From 35877ae8acf4cd937da054647824617075dec4d3 Mon Sep 17 00:00:00 2001
From: Fred Boniface
Date: Mon, 16 Mar 2026 20:31:28 +0000
Subject: [PATCH] Add LocationSearchCard and add to homepage for testing.
Run `npm run format`
---
.gitea/workflows/build-push.yaml | 4 +-
.../components/ui/LocationSearchBox.svelte | 283 ++++++++++++------
src/lib/components/ui/Textbox.svelte | 152 +++++-----
src/lib/components/ui/cards/BaseCard.svelte | 163 +++++-----
.../ui/cards/LocationBoardCard.svelte | 25 ++
src/routes/+error.svelte | 2 +-
src/routes/+layout.svelte | 16 +-
src/routes/+layout.ts | 2 +-
src/routes/+page.svelte | 32 +-
src/routes/about/+page.svelte | 5 +-
svelte.config.js | 26 +-
11 files changed, 427 insertions(+), 283 deletions(-)
create mode 100644 src/lib/components/ui/cards/LocationBoardCard.svelte
diff --git a/.gitea/workflows/build-push.yaml b/.gitea/workflows/build-push.yaml
index 78f4a53..44bbcbc 100644
--- a/.gitea/workflows/build-push.yaml
+++ b/.gitea/workflows/build-push.yaml
@@ -3,7 +3,7 @@ run-name: ${{ gitea.actor }} is building and pushing
on:
create:
- tags: "*"
+ tags: '*'
env:
GITEA_DOMAIN: git.fjla.uk
@@ -36,4 +36,4 @@ jobs:
push: true
tags: |
${{ env.GITEA_DOMAIN }}/${{ env.RESULT_IMAGE_NAME }}:${{ gitea.ref_name }}
- ${{ env.GITEA_DOMAIN }}/${{ env.RESULT_IMAGE_NAME }}:latest
\ No newline at end of file
+ ${{ env.GITEA_DOMAIN }}/${{ env.RESULT_IMAGE_NAME }}:latest
diff --git a/src/lib/components/ui/LocationSearchBox.svelte b/src/lib/components/ui/LocationSearchBox.svelte
index 2cdc2f4..1fd33c6 100644
--- a/src/lib/components/ui/LocationSearchBox.svelte
+++ b/src/lib/components/ui/LocationSearchBox.svelte
@@ -1,112 +1,221 @@
-
showResults = true}
- onkeydown={handleKey}
- capital
- />
+ (showResults = true)}
+ onkeydown={handleKey}
+ capital
+ />
- {#if showResults && results.length}
-
- {#each results as loc, i}
- choose(loc)}
- >
- {loc.n}
-
- {#if loc.c}
- {loc.c}
- {/if}
-
- {/each}
-
- {/if}
+ {#if showResults && results.length}
+
+ {/if}
\ No newline at end of file
+ .location-search {
+ position: relative;
+ width: 100%;
+ }
+
+ .suggestions[popover] {
+ position: absolute;
+ inset: unset;
+ margin: 0;
+ margin-top: 3px;
+ border: none;
+ border-radius: 5px;
+ padding: 0;
+ width: 100%;
+ max-height: 350px;
+ top: 100%;
+ background-color: var(--color-title);
+ color: var(--color-bg-dark);
+ box-shadow: var(--shadow-std);
+ display: block;
+ z-index: 9999;
+ }
+
+ .suggestions:not([popover]) {
+ display: none;
+ }
+
+ .result-item {
+ font-family: 'URW Gothic', sans-serif;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 0.5rem 1rem;
+ cursor: pointer;
+ min-height: 48px;
+ transition: all 0.15s;
+ border-bottom: 1px solid rgba(0, 0, 0, 0.4);
+ }
+
+ .result-item.selected,
+ .result-item:hover {
+ background-color: var(--color-accent);
+ color: var(--color-title);
+ }
+
+ .crs-badge {
+ font-family: ui-monospace, monospace;
+ font-size: 1.1rem;
+ font-weight: 700;
+ background: var(--color-accent);
+ color: var(--color-title);
+ padding: 3px 6px;
+ border-radius: 10px;
+ transition: all 0.1s;
+ }
+
+ .crs-badge.empty {
+ filter: opacity(0);
+ }
+
+ .result-item:hover .crs-badge {
+ filter: brightness(1.3);
+ }
+
+ .details {
+ display: flex;
+ flex-direction: column;
+ }
+
+ .name {
+ font-size: 1.1rem;
+ font-weight: 700;
+ text-align: right;
+ }
+
+ .tiploc {
+ text-align: right;
+ font-size: 0.8rem;
+ }
+
diff --git a/src/lib/components/ui/Textbox.svelte b/src/lib/components/ui/Textbox.svelte
index 3f38d5a..2b1c472 100644
--- a/src/lib/components/ui/Textbox.svelte
+++ b/src/lib/components/ui/Textbox.svelte
@@ -1,94 +1,94 @@
- {#if label}
- {label}
- {/if}
+ {#if label}
+ {label}
+ {/if}
- isFocussed = true}
- onblur={() => isFocussed = false}
- {...rest}
- />
+ (isFocussed = true)}
+ onblur={() => (isFocussed = false)}
+ {...rest}
+ />
- {#if error}
- {error}
- {/if}
+ {#if error}
+ {error}
+ {/if}
\ No newline at end of file
+ .error-message {
+ color: #ff4d4d;
+ font-size: 1rem;
+ text-align: center;
+ }
+
diff --git a/src/lib/components/ui/cards/BaseCard.svelte b/src/lib/components/ui/cards/BaseCard.svelte
index 87a1a68..f593a84 100644
--- a/src/lib/components/ui/cards/BaseCard.svelte
+++ b/src/lib/components/ui/cards/BaseCard.svelte
@@ -1,94 +1,101 @@
- {#if header || helpText}
-
+ {#if header || helpText}
+
- {#if showHelp && helpText}
-
- {/if}
- {/if}
+ {#if showHelp && helpText}
+
+ {/if}
+ {/if}
-
- {@render children?.()}
-
+
+ {@render children?.()}
+
\ No newline at end of file
+ .help-drawer {
+ background-color: var(--color-accent);
+ padding: 4px 16px;
+ font-size: 0.95rem;
+ line-height: 1.2;
+ margin: auto;
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
+ color: var(--color-title);
+ }
+
diff --git a/src/lib/components/ui/cards/LocationBoardCard.svelte b/src/lib/components/ui/cards/LocationBoardCard.svelte
new file mode 100644
index 0000000..9ef7e01
--- /dev/null
+++ b/src/lib/components/ui/cards/LocationBoardCard.svelte
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/routes/+error.svelte b/src/routes/+error.svelte
index 5a69b2c..779f0e5 100644
--- a/src/routes/+error.svelte
+++ b/src/routes/+error.svelte
@@ -58,7 +58,7 @@
font-size: 1.1rem;
color: var(--color-title);
max-width: 300px;
- margin-top: 5px;
+ margin-top: 5px;
margin-bottom: 30px;
}
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index a98f5c2..9d531c5 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -34,7 +34,7 @@
if (navWidth === 0) return navItems.length;
const available = navWidth;
const totalItems = navItems.length;
- const countWithoutMore = Math.floor(available/ ITEM_WIDTH);
+ const countWithoutMore = Math.floor(available / ITEM_WIDTH);
if (countWithoutMore >= totalItems) return totalItems;
@@ -128,10 +128,11 @@
-
+
Narrow Gauge Detected
- Just as trains need the right track width, our data needs a bit more room to stay on the rails. Please expand your view to at least 300px to view the app.
+ Just as trains need the right track width, our data needs a bit more room to stay on the rails.
+ Please expand your view to at least 300px to view the app.
@@ -193,7 +194,8 @@
box-shadow: var(--shadow-up);
}
- .nav-item, .more-menu-wrapper {
+ .nav-item,
+ .more-menu-wrapper {
display: flex;
flex: 1;
flex-direction: column;
@@ -317,8 +319,10 @@
margin: auto;
padding-top: 30px;
}
-
- header, main, nav {
+
+ header,
+ main,
+ nav {
display: none;
}
}
diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts
index cf088e3..e285259 100644
--- a/src/routes/+layout.ts
+++ b/src/routes/+layout.ts
@@ -1,3 +1,3 @@
export const prerender = true;
export const trailingSlash = 'always';
-export const csr = true;
\ No newline at end of file
+export const csr = true;
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index d307e7a..6ec1a92 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -1,22 +1,18 @@
-
-Default
-Brand
-Accent
-
+
+
+
-Hello
-
-
-
-OwlBoard
+
diff --git a/src/routes/about/+page.svelte b/src/routes/about/+page.svelte
index aafe7fa..d77c5fa 100644
--- a/src/routes/about/+page.svelte
+++ b/src/routes/about/+page.svelte
@@ -29,7 +29,10 @@
daily basis.
-Why OwlBoard? The name was chosen as an evolution of its predecessor, 'Athena'; owls are associated with the Roman Goddess as well as with wisdom. The name also links to Bath, where the app has been built and is run, representing the 'Minerva Owl' sculpture trail in the city, with many of the sculptures still in the area.
+ Why OwlBoard? The name was chosen as an evolution of its predecessor, 'Athena'; owls are
+ associated with the Roman Goddess as well as with wisdom. The name also links to Bath, where the
+ app has been built and is run, representing the 'Minerva Owl' sculpture trail in the city, with
+ many of the sculptures still in the area.
Some components that combine to form OwlBoard are open-source, see the