Skip to content

Commit 6a027ed

Browse files
committed
feat: improve UI and accessibility across cardsboard layout; enhance color scheme and shadows
1 parent 9a84d53 commit 6a027ed

File tree

13 files changed

+184
-98
lines changed

13 files changed

+184
-98
lines changed

CHANGELOG.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,14 @@ Diese Datei ist die kompakte Stakeholder-Ansicht.
88

99
## Unreleased
1010

11-
- UI & Layout: Farbschema-Default fuer neue Settings und Fallback wurde von `stil` auf `rpi` umgestellt (Option `Stil` bleibt weiterhin manuell waehlbar).
11+
- Boards-Liste (Light): Board-Kacheln nutzen jetzt denselben sehr hellen Hintergrund wie die Board-Flaeche (`--board-bg`), Dark Mode bleibt bei `--card`.
12+
- Test-Runner (Windows): `test:e2e` ruft das Shell-Skript jetzt explizit ueber `bash` auf; zusaetzlich wurden Zeilenenden des Skripts auf LF normalisiert.
13+
- DX/Editor: VS-Code CSS-`unknownAtRules` Warnungen fuer Tailwind-v4 Direktiven (`@config`, `@custom-variant`) im Workspace unterdrueckt.
14+
- Boards-Liste (A11y): Status-/Aktions-Icons sind jetzt immer sichtbar und als kleine, rechts angepinnte Kreis-Badges umgesetzt; der Inhaltsbereich der Board-Kachel wurde rechts reduziert.
15+
- UI Light Mode: Cards nutzen jetzt einen weissen Hintergrund, der Board-Hintergrund ist auf ein sehr helles Grau angepasst.
16+
- UI Karten: Karten-Schatten wurde verstaerkt und auf feste RGBA-Werte umgestellt; Schattenfall ist jetzt konsistent nach rechts/unten (Light und Dark).
17+
- Navigation: Klick auf das Sidebar-Logo `Kanban-Editor` leitet jetzt auf die Basis-URL der App (`base`) weiter.
18+
- UI Tiefenwirkung: Rechte Sidebar (Desktop) erhielt einen rechten Kanten-Schatten, Topbar einen unteren Schatten fuer klarere Layer-Trennung im Board-Layout.
1219
- AMB Publishing: `a`-Tag im Kind-30142 Event nutzt jetzt das kanonische Address-Format `30301:<pubkey>:<d-tag>` (optional mit Relay-Hint) statt `naddr`, damit Referenzen NIP-konform und robuster aufloesbar sind.
1320
- AMB Publishing: Optionaler `r`-Tag mit oeffentlicher Board-Web-URL (naddr-Pfad) wird zu Snapshot- und AMB-Events hinzugefuegt; lokale/private Origins (`localhost`, private IP-Ranges) werden dabei automatisch ausgeschlossen.
1421
- Sidebar-Branding: App-Name `Kanban-Editor` mit periodischem Accent-Shine (links→rechts) und statischem Gradient-Finish (light: foreground→accent, dark: foreground→accent) in `cardsboard` Layout.

docs/CHANGELOG/2026-Q1.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,17 @@ Q1/2026 war kein einzelner Release, sondern ein schneller Stabilitaets- und Ausb
154154
## Direkte Commits (ohne PR)
155155

156156
### 2026-03-05
157+
- **Boards-Liste Light-Background angeglichen:** Die Board-Kacheln in der linken Boards-Liste verwenden im Light-Mode nun `--board-bg` statt `--card`, damit die Flaechenwirkung dem Board-Hintergrund entspricht. Im Dark-Mode bleibt `--card` aktiv (`dark:bg-[var(--card)]`) fuer Kontrast/Lesbarkeit. Betroffene Datei: `src/routes/cardsboard/BoardsList.svelte`.
158+
- **E2E-Runner Windows-kompatibel gemacht:** Das NPM-Script `test:e2e` fuehrt den Shell-Runner nun explizit mit `bash` aus (`package.json`), und `scripts/test-e2e-with-ci-config.sh` wurde auf LF-Zeilenenden normalisiert. Dadurch scheitert der Aufruf unter PowerShell nicht mehr an Script-Start/CRLF, sondern laeuft bis zum fachlichen Precheck (lokaler Relay auf Port 7000 erforderlich).
159+
- **Editor-DX: CSS At-Rule Warnungen bereinigt:** Fuer das Workspace wurden VS-Code-Lint-Settings ergaenzt, damit Tailwind-v4-spezifische Direktiven (`@config`, `@custom-variant`) in `src/app.css` nicht mehr als `unknownAtRules` markiert werden. Umsetzung in `.vscode/settings.json` via `css/scss/less.lint.unknownAtRules = ignore`.
160+
- **Boards-Liste A11y verbessert (Icons immer sichtbar):** Die bisher hover-abhaengigen Board-Icons wurden auf eine dauerhaft sichtbare, rechts angepinnte Icon-Leiste umgestellt. Status-/Rollen-/Aktions-Icons werden als kleine Kreis-Badges am rechten Rand der Board-Kachel angezeigt. Zur Vermeidung von Ueberlappungen wurde der klickbare Inhaltsbereich rechts verschmaelert (`pr-16`). Betroffene Datei: `src/routes/cardsboard/BoardsList.svelte`.
161+
- **Light-Mode Flaechen angepasst (Cards/Board):** Kartenflaechen wurden im Light-Mode auf reines Weiss gesetzt (`--card`), waehrend die Board-Flaeche auf ein sehr helles Grau umgestellt wurde (`--board-bg`) fuer bessere Layer-Trennung. Die Anpassung gilt fuer `:root` und `:root.rpi`. Zusaetzlich wurde ein Tippfehler in der RPI-Light-Variable korrigiert (`---board-bg``--board-bg`). Betroffene Datei: `src/app.css`.
162+
- **Karten-Schatten verstaerkt (theme-unabhaengig):** Die Card-Komponente verwendet jetzt feste RGBA-Schattenwerte statt generischer Utility-Schatten (`shadow-md`/`hover:shadow-lg`), damit die Tiefenwirkung in Light- und Dark-Theme gleichmaessig stark bleibt. Der Schattenwurf ist dabei explizit nach rechts/unten ausgerichtet (positive X/Y-Offsets) fuer einen konsistenten "Licht von links oben"-Eindruck. Umsetzung in `src/routes/cardsboard/Card.svelte` ueber `shadow-[...]` und `hover:shadow-[...]`.
163+
- **Logo-Navigation zur Basis-URL:** Das Sidebar-Logo `Kanban-Editor` ist nun sowohl im mobilen als auch im Desktop-Header als Link auf die Basis-URL der App umgesetzt (`${base}/`). Dadurch fuehrt ein Klick konsistent zur Startseite, auch bei Deployments mit konfiguriertem SvelteKit-`base`-Pfad. Betroffene Datei: `src/routes/cardsboard/+layout.svelte`.
164+
- **OER-Finder Local-Dev Fallback fuer private Registry:** `src/lib/components/OerImagePicker.svelte` verwendet keine statischen TypeScript-Imports von `@edufeed-org/oer-finder-plugin` mehr, sondern laedt das Plugin optional clientseitig via dynamischem Import. Damit schlagen lokale Editor-/Type-Checks ohne gesetzten `NODE_AUTH_TOKEN` nicht mehr mit `TS2307` fehl. Wenn das Paket nicht installiert ist, zeigt die Komponente stattdessen einen klaren Hinweis (`fehlender NODE_AUTH_TOKEN`) und beendet den Picker-Flow kontrolliert.
165+
- **OER-Finder Plugin Kompatibilitaetsfix (`Missing "./adapters" specifier`):** `src/lib/components/OerImagePicker.svelte` wurde auf die tatsaechlich exportierte API von `@edufeed-org/oer-finder-plugin@0.1.0` umgestellt. Der nicht exportierte Deep-Import `@edufeed-org/oer-finder-plugin/adapters` wurde entfernt. Zusaetzlich wurden veraltete Typen/APIs (`SourceConfig`, `LoadMoreElement`, `searchEl.sources`) auf aktuelle Plugin-Typen (`SourceOption`, `searchEl.availableSources`) migriert sowie Event-Casts auf `CustomEvent<...>` korrigiert (`search-results`, `card-click`). Der Build-/Dev-Blocker in Vite ist damit beseitigt und `pnpm run check` laeuft wieder fehlerfrei.
166+
- **Layout-Tiefe verbessert (Sidebar/Topbar):** Im `cardsboard`-Layout wurde die rechte Desktop-Sidebar um einen sichtbaren rechten Kanten-Schatten erweitert (inset-shadow fuer robuste Darstellung trotz `overflow-hidden`). Die Topbar erhielt zusaetzlich einen unteren Schatten fuer eine klarere visuelle Trennung zwischen Header und Board-Inhalt. Betroffene Dateien: `src/routes/cardsboard/+layout.svelte`, `src/routes/cardsboard/Topbar.svelte`.
167+
- **RPI-Farbspezifikation umgesetzt (Hex-vorgaben):** Das RPI-Theme in `src/app.css` wurde auf die vorgegebenen Farben aus dem Design-Briefing abgestimmt: Light `Primaer #203A8F` und `Sekundaer #FFA500`, Dark `Primaer #4C68C4` und `Sekundaer #FFA500`. Die Werte wurden konsistent auf die relevanten Theme-Tokens gemappt (`--primary`, `--accent`, `--ring`, `--sidebar-primary`, `--sidebar-ring`, `--chart-1`, `--chart-2`) und die RPI-Board-Hintergrundverlaeufe entsprechend angepasst. Zusaetzlich wurde die RPI-Farbvorschau im SettingsPanel auf `#203A8F` vereinheitlicht (`src/lib/components/settings/SettingsPanel.svelte`).
157168
- **UI & Layout Farbschema-Default auf RPI gesetzt:** In den globalen UI-Einstellungen wurde `colorScheme` standardmaessig auf `rpi` gesetzt. Zusaetzlich nutzt `applyTheme()` jetzt `rpi` als Fallback, wenn kein Farbschema vorhanden ist. Damit starten neue Installationen und ungefuellte Settings konsistent mit dem RPI-Farbschema; das Schema `stil` bleibt als manuell waehlbare Option unveraendert verfuegbar. Betroffene Datei: `src/lib/stores/settingsStore.svelte.ts`.
158169

159170
### 2026-02-23

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"lint": "eslint .",
1515
"test:unit": "vitest",
1616
"test": "npm run test:unit -- --run && npm run test:e2e",
17-
"test:e2e": "./scripts/test-e2e-with-ci-config.sh"
17+
"test:e2e": "bash ./scripts/test-e2e-with-ci-config.sh"
1818
},
1919
"files": [
2020
"dist",

scripts/test-e2e-with-ci-config.sh

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,19 @@ BACKUP_FILE="${CONFIG_DIR}/config.json.backup"
2020
# Function to restore config on exit
2121
cleanup() {
2222
local exit_code=$?
23-
23+
2424
if [ -f "$BACKUP_FILE" ]; then
2525
echo -e "\n${BLUE}🔄 Restoring original config.json...${NC}"
2626
mv "$BACKUP_FILE" "$CONFIG_FILE"
2727
echo -e "${GREEN}✅ Original config.json restored${NC}"
2828
fi
29-
29+
3030
if [ $exit_code -ne 0 ]; then
3131
echo -e "${RED}❌ Tests failed with exit code: $exit_code${NC}"
3232
else
3333
echo -e "${GREEN}✅ Tests completed successfully${NC}"
3434
fi
35-
35+
3636
exit $exit_code
3737
}
3838

@@ -56,7 +56,7 @@ if ! nc -z localhost 7000 2>/dev/null && ! lsof -i:7000 >/dev/null 2>&1 && ! ss
5656
echo -e ""
5757
echo -e "Once the relay is running, try this command again."
5858
echo -e "${RED}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
59-
59+
6060
# Unset trap to avoid cleanup on this error exit
6161
trap - EXIT INT TERM
6262
exit 1

src/app.css

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
/* Core Colors — FOERBICO "stil" */
2323
--background: oklch(100% 0 0);
2424
--foreground: oklch(38% .02 250);
25-
--card: oklch(97% 0 0);
25+
--card: oklch(100% 0 0);
2626
--card-hover: oklch(94% 0 0);
2727
--card-foreground: oklch(38% .02 250);
2828
--popover: oklch(97% 0 0);
@@ -69,6 +69,7 @@
6969
/* Board */
7070
--column-border: oklch(85% .01 250);
7171
--button: oklch(88% 0 0);
72+
--board-bg: oklch(97.8% 0.002 250);
7273

7374
/* Card Colors for Color Picker */
7475
--color-slate: oklch(88.734% 0.02327 285.861 / 0.945);
@@ -153,24 +154,24 @@
153154
/* Core Colors — FOERBICO "rpi" */
154155
--background: oklch(100% 0 0);
155156
--foreground: oklch(25% .02 264);
156-
--card: oklch(97% .005 264);
157+
--card: oklch(100% 0 0);
157158
--card-hover: oklch(94% .01 264);
158159
--card-foreground: oklch(25% .02 264);
159160
--popover: oklch(97% .005 264);
160161
--popover-foreground: oklch(25% .02 264);
161-
--primary: oklch(35% .16 264);
162+
--primary: #203a8f;
162163
--primary-foreground: oklch(100% 0 0);
163164
--secondary: oklch(94% .01 264);
164165
--secondary-foreground: oklch(25% .02 264);
165166
--muted: oklch(94% .01 264);
166167
--muted-foreground: oklch(55% .01 264);
167-
--accent: oklch(79% .17 70);
168+
--accent: #ffa500;
168169
--accent-foreground: oklch(20% 0 0);
169170
--destructive: oklch(65% .2 25);
170171
--destructive-foreground: oklch(100% 0 0);
171172
--border: oklch(88% .005 264);
172173
--input: oklch(91% .005 264);
173-
--ring: oklch(35% .16 264);
174+
--ring: #203a8f;
174175

175176
/* Semantic Status Colors */
176177
--info: oklch(72% .11 230);
@@ -181,34 +182,29 @@
181182
--warning-foreground: oklch(20% 0 0);
182183

183184
/* Chart Colors */
184-
--chart-1: oklch(35% .16 264);
185-
--chart-2: oklch(79% .17 70);
185+
--chart-1: #203a8f;
186+
--chart-2: #ffa500;
186187
--chart-3: oklch(72% .11 230);
187188
--chart-4: oklch(82% .17 85);
188189
--chart-5: oklch(65% .2 25);
190+
--color-slate: var(--card);
189191

190192
/* Sidebar */
191193
--sidebar: oklch(97% .005 264);
192194
--sidebar-foreground: oklch(25% .02 264);
193-
--sidebar-primary: oklch(35% .16 264);
195+
--sidebar-primary: #203a8f;
194196
--sidebar-primary-foreground: oklch(100% 0 0);
195197
--sidebar-accent: oklch(94% .01 264);
196198
--sidebar-accent-foreground: oklch(25% .02 264);
197199
--sidebar-border: oklch(88% .005 264);
198-
--sidebar-ring: oklch(35% .16 264);
200+
--sidebar-ring: #203a8f;
199201

200202
/* Board */
201203
--column-border: oklch(85% .01 264);
202204
--button: oklch(88% .005 264);
203205

204206
/* Board Background — primary (blue) → accent (gold) diagonal */
205-
--board-bg: linear-gradient(
206-
to bottom right,
207-
oklch(72.577% 0.14152 265.272 / 0.534) 0%,
208-
oklch(54.98% 0.16067 264.173 / 0.192) 60%,
209-
oklch(89.946% 0.02229 74.012 / 0.562) 85%,
210-
oklch(78.807% 0.16987 69.733 / 0.534) 98%
211-
);
207+
--board-bg: oklch(97.6% 0.004 264);
212208
}
213209

214210
/* ============================================
@@ -224,19 +220,19 @@
224220
--card-foreground: oklch(90% 0 0);
225221
--popover: oklch(18% .02 264);
226222
--popover-foreground: oklch(90% 0 0);
227-
--primary: oklch(54.98% 0.16067 264.173);
223+
--primary: #4c68c4;
228224
--primary-foreground: oklch(100% 0 0);
229225
--secondary: oklch(50% .02 264);
230226
--secondary-foreground: oklch(100% 0 0);
231227
--muted: oklch(30% .01 264);
232228
--muted-foreground: oklch(65% .01 264);
233-
--accent: oklch(79% .17 70);
229+
--accent: #ffa500;
234230
--accent-foreground: oklch(15% 0 0);
235231
--destructive: oklch(65% .2 25);
236232
--destructive-foreground: oklch(100% 0 0);
237233
--border: oklch(35% .01 264);
238234
--input: oklch(26% .02 264);
239-
--ring: oklch(55% .16 264);
235+
--ring: #4c68c4;
240236

241237
/* Semantic Status Colors */
242238
--info: oklch(72% .11 230);
@@ -247,21 +243,21 @@
247243
--warning-foreground: oklch(15% 0 0);
248244

249245
/* Chart Colors */
250-
--chart-1: oklch(55% .16 264);
251-
--chart-2: oklch(79% .17 70);
246+
--chart-1: #4c68c4;
247+
--chart-2: #ffa500;
252248
--chart-3: oklch(72% .11 230);
253249
--chart-4: oklch(82% .17 85);
254250
--chart-5: oklch(65% .2 25);
255251

256252
/* Sidebar */
257253
--sidebar: oklch(18% .02 264);
258254
--sidebar-foreground: oklch(90% 0 0);
259-
--sidebar-primary: oklch(55% .16 264);
255+
--sidebar-primary: #4c68c4;
260256
--sidebar-primary-foreground: oklch(100% 0 0);
261257
--sidebar-accent: oklch(30% .01 264);
262258
--sidebar-accent-foreground: oklch(90% 0 0);
263259
--sidebar-border: oklch(35% .01 264);
264-
--sidebar-ring: oklch(55% .16 264);
260+
--sidebar-ring: #4c68c4;
265261

266262
/* Board */
267263
--column-border: oklch(35% .01 264);
@@ -271,14 +267,14 @@
271267
/* Board Background — primary (blue) → accent (gold) diagonal */
272268
--board-bg: linear-gradient(
273269
to bottom right,
274-
oklch(54.98% 0.16067 264.173) 0%,
275-
oklch(54.98% 0.16067 264.173 / 0.150) 50%,
276-
oklch(69.137% 0.09057 73.175 / 0.108) 85%,
277-
oklch(78.807% 0.16987 69.733 / 0.534) 98%
270+
rgba(76, 104, 196, 0.46) 0%,
271+
rgba(76, 104, 196, 0.16) 50%,
272+
rgba(255, 165, 0, 0.14) 85%,
273+
rgba(255, 165, 0, 0.36) 98%
278274
);
279275

280276
/* Card Colors for Color Picker - Dark Mode */
281-
--color-slate: oklch(32.579% 0.00353 286.054 / 0.945);
277+
--color-slate: var(--card);
282278
--color-blue: oklch(36.012% 0.24863 264.466);
283279
--color-green: #0ef347;
284280
--color-orange: oklch(76.57% 0.15684 77.795);
@@ -469,3 +465,8 @@
469465
outline-offset: 2px;
470466
box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 40%, transparent);
471467
}
468+
469+
.add-board-button:hover {
470+
background: var(--primary);
471+
color: var(--primary-foreground);
472+
}

src/lib/components/OerImagePicker.svelte

Lines changed: 68 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,52 @@
11
<script lang="ts">
2-
import type {
3-
OerSearchResultEvent,
4-
OerSearchElement,
5-
OerListElement,
6-
OerCardClickEvent,
7-
SourceConfig,
8-
LoadMoreElement
9-
} from '@edufeed-org/oer-finder-plugin';
102
import { onMount } from 'svelte';
113
import { settingsStore } from '$lib/stores/settingsStore.svelte';
12-
import { registerAllBuiltInAdapters } from '@edufeed-org/oer-finder-plugin/adapters';
4+
5+
// Keep these local fallback types so TS stays happy when the optional
6+
// private plugin package is not installed in local environments.
7+
type SourceConfig = {
8+
id: string;
9+
label: string;
10+
checked?: boolean;
11+
baseUrl?: string;
12+
};
13+
14+
type OerData = {
15+
extensions?: {
16+
images?: {
17+
high?: string;
18+
medium?: string;
19+
small?: string;
20+
};
21+
};
22+
amb?: {
23+
id?: string;
24+
};
25+
};
26+
27+
type OerSearchResultEvent = CustomEvent<{
28+
data: OerData[];
29+
meta: unknown;
30+
}>;
31+
32+
type OerCardClickEvent = CustomEvent<{
33+
oer: OerData;
34+
}>;
35+
36+
type OerSearchElement = HTMLElement & {
37+
sources: SourceConfig[];
38+
};
39+
40+
type OerListElement = HTMLElement & {
41+
loading: boolean;
42+
oers: OerData[];
43+
error: string | null;
44+
};
45+
46+
type LoadMoreElement = HTMLElement & {
47+
loading: boolean;
48+
metadata: unknown;
49+
};
1350
1451
interface Props {
1552
onSelect: (imageUrl: string) => void;
@@ -20,8 +57,6 @@
2057
const language = $state(settingsStore.settings.language)
2158
const { onSelect }: Props = $props();
2259
23-
registerAllBuiltInAdapters();
24-
2560
const availableSources: SourceConfig[] = [
2661
{ id: 'arasaac', label: 'ARASAAC' },
2762
{ id: 'openverse', label: 'Openverse', checked: true },
@@ -35,8 +70,28 @@
3570
let loadMoreElement: LoadMoreElement;
3671
3772
onMount(async () => {
38-
// Dynamically import the plugin only on the client side to avoid SSR issues
39-
await import('@edufeed-org/oer-finder-plugin');
73+
// Dynamically import the plugin only on the client side to avoid SSR issues.
74+
// Using an indirection avoids hard TS module resolution in environments
75+
// where the private package is not available.
76+
const pluginPackage = '@edufeed-org/oer-finder-plugin';
77+
const plugin = await import(pluginPackage).catch(() => null);
78+
if (!plugin) {
79+
console.warn(
80+
'[OerImagePicker] Optional package "@edufeed-org/oer-finder-plugin" fehlt lokal. ' +
81+
'Bitte NODE_AUTH_TOKEN setzen/erneuern und danach "pnpm install" ausfuehren.'
82+
);
83+
listEl.loading = false;
84+
listEl.error = 'OER plugin fehlt lokal. Bitte NODE_AUTH_TOKEN aktualisieren und pnpm install ausfuehren.';
85+
loadMoreElement.loading = false;
86+
loadMoreElement.metadata = null;
87+
return;
88+
}
89+
90+
const maybeRegisterAdapters = (plugin as { registerAllBuiltInAdapters?: () => void })
91+
.registerAllBuiltInAdapters;
92+
if (typeof maybeRegisterAdapters === 'function') {
93+
maybeRegisterAdapters();
94+
}
4095
4196
// Set sources as a JS property (not HTML attribute)
4297
searchEl.sources = availableSources;

src/lib/components/settings/SettingsPanel.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@
209209
onclick={() => settingsStore.setColorScheme('rpi')}
210210
class="flex-1 gap-2 {settings.colorScheme === 'rpi' ? 'ring-2 ring-primary ring-offset-background' : 'text-muted-foreground'}"
211211
>
212-
<span class="inline-block h-4 w-4 rounded-full" style="background: oklch(35% .16 264);"></span>
212+
<span class="inline-block h-4 w-4 rounded-full" style="background: #203A8F;"></span>
213213
RPI
214214
</Button>
215215
</div>

0 commit comments

Comments
 (0)