1c0a7cb850
Phase 4 — New Widget Types: - Clock/Weather, System Stats, RSS/Feed, Calendar, Markdown, Metric/Counter, Link Group, Camera/Stream widgets - Backend services with caching for each data source - Full creation form with dynamic config fields per type Phase 5 — Visual & Styling Enhancements: - Glassmorphism card style (solid/glass/outline) - Board-level themes with per-board hue/saturation - Animated SVG status rings replacing static dots - Card size options (compact/medium/large) - Custom CSS injection (admin + per-board, sanitized) - Wallpaper backgrounds with blur/overlay/parallax Phase 6 — Functional Features: - Favorites bar with drag-and-drop reordering - Recent apps tracking with privacy toggle - Uptime dashboard page (/status, guest-accessible) - Notifications system (Discord/Slack/Telegram/HTTP webhooks) - App tags with filtering in board view - Multi-URL app cards with expandable sub-links - Personal API tokens with scoped permissions - Audit log with retention and admin viewer Phase 7 — Quality of Life: - Onboarding wizard (5-step first-launch setup) - App URL health preview with favicon/title detection - Board templates (4 built-in + custom import/export) - Keyboard shortcut overlay (j/k nav, 1-9 boards, ? help) 212 files changed, 15641 insertions, 980 deletions. Build, lint, type check, and 222 tests all pass.
163 lines
10 KiB
Markdown
163 lines
10 KiB
Markdown
# Phase 4: Visual & Styling Enhancements
|
|
|
|
**Status:** ✅ Complete
|
|
**Parent plan:** [PLAN.md](./PLAN.md)
|
|
**Domain:** frontend
|
|
|
|
## Objective
|
|
|
|
Implement all 6 visual/styling features: glassmorphism cards, board-level themes, animated status rings, card size options, custom CSS injection, and wallpaper backgrounds.
|
|
|
|
## Tasks
|
|
|
|
### 4.1 Glassmorphism Card Style
|
|
|
|
- [x] Add card style system to theme store — extend `src/lib/stores/theme.svelte.ts`:
|
|
- New property: `cardStyle: 'solid' | 'glass' | 'outline'` (default: 'solid')
|
|
- Persist to localStorage, broadcast across tabs
|
|
- [x] Add CSS classes in `src/app.css`:
|
|
- `.card-solid` — current default card style
|
|
- `.card-glass` — `backdrop-filter: blur(12px); background: hsl(var(--card) / 0.6); border: 1px solid hsl(var(--border) / 0.3)`
|
|
- `.card-outline` — `background: transparent; border: 1px solid hsl(var(--border))`
|
|
- [x] Update widget/card components to use dynamic card style class
|
|
- [x] Add card style picker to theme settings UI (3-way toggle: solid/glass/outline)
|
|
|
|
### 4.2 Board-Level Themes
|
|
|
|
- [x] Create `src/lib/components/board/BoardThemeProvider.svelte`
|
|
- Reads board's themeHue, themeSaturation, backgroundType from board data
|
|
- Overrides CSS variables when viewing that board (--primary-h, --primary-s)
|
|
- Smooth transition when switching boards (CSS transition on :root variables)
|
|
- Restores global theme when navigating away from the board
|
|
- [x] Update board edit form to include theme settings:
|
|
- Hue slider (0-360 with color preview)
|
|
- Saturation slider (0-100)
|
|
- Background type selector (mesh/particles/aurora/none/wallpaper)
|
|
- [x] Update board data loading to include theme fields
|
|
- [x] Fix updateBoard server action to extract theme fields from formData
|
|
- [x] Fix backgroundType validator to accept all background types (mesh/particles/aurora/wallpaper/none)
|
|
|
|
### 4.3 Animated SVG Status Ring
|
|
|
|
- [x] Create `src/lib/components/app/AnimatedStatusRing.svelte`
|
|
- SVG circle around app icon with status-dependent animation:
|
|
- Online: animated green fill sweep (stroke-dashoffset animation)
|
|
- Offline: pulsing red ring (opacity animation)
|
|
- Degraded: partial yellow arc (75% fill, subtle pulse)
|
|
- Unknown: gray dashed ring (rotating dash pattern)
|
|
- Props: status, size (scales with card size), animated (boolean)
|
|
- [x] Replace static status dots in AppWidget.svelte with AnimatedStatusRing
|
|
- [x] Ensure ring scales appropriately with compact/medium/large card sizes
|
|
|
|
### 4.4 Card Size Options
|
|
|
|
- [x] Add `CardSize` support to section and board levels:
|
|
- Per-section: `section.cardSize` overrides board default
|
|
- Per-board: `board.cardSize` as fallback
|
|
- Global default: 'medium'
|
|
- [x] Create card size variants in widget components:
|
|
- `compact` — icon + name only, smaller padding, single row grid
|
|
- `medium` — current default (icon + name + status + description on hover)
|
|
- `large` — icon + name + description + sparkline + tags, more padding
|
|
- [x] Add card size picker to section edit form (DraggableSection) and board settings
|
|
- [x] Update WidgetGrid to adjust grid columns based on card size
|
|
- [x] Wire up onUpdateSection handler through DraggableBoard to board edit page
|
|
|
|
### 4.5 Custom CSS Injection
|
|
|
|
- [x] Create `src/lib/components/settings/CustomCssEditor.svelte`
|
|
- Textarea with monospace font for custom CSS
|
|
- Live preview toggle
|
|
- Sanitization: strip `<script>` tags, limit selectors to `.app-scope` or descendant selectors
|
|
- [x] Add custom CSS field to admin system settings form (SettingsForm.svelte)
|
|
- [x] Add per-board custom CSS field to board edit form
|
|
- [x] Create `src/lib/components/layout/CustomCssInjector.svelte`
|
|
- Injects `<style>` tag with sanitized CSS from system settings + current board
|
|
- Wraps CSS in `.custom-css-scope` to prevent breaking critical UI
|
|
- [x] Add CustomCssInjector to root layout
|
|
|
|
### 4.6 Wallpaper Backgrounds
|
|
|
|
- [x] Create `src/lib/components/background/WallpaperBackground.svelte`
|
|
- Displays uploaded image or Unsplash URL as board background
|
|
- Configurable: blur amount (0-20px), overlay opacity (0-1), parallax (boolean), position (fixed/scroll)
|
|
- Fallback to procedural background if wallpaper fails to load
|
|
- [x] Add wallpaper upload endpoint: `src/routes/api/wallpaper/+server.ts`
|
|
- Accept image upload (PNG, JPG, WebP), save to `static/uploads/wallpapers/`
|
|
- Return URL path
|
|
- Max file size: 5MB
|
|
- [x] Add wallpaper configuration to board edit form:
|
|
- Image upload button or URL input
|
|
- Blur slider, overlay opacity slider
|
|
- Parallax toggle
|
|
- [x] Integrate WallpaperBackground into AmbientBackground component (new background type)
|
|
- [ ] Optional Unsplash integration (deferred — requires external API key infrastructure)
|
|
|
|
## Files to Modify/Create
|
|
|
|
- `src/lib/stores/theme.svelte.ts` — extend with cardStyle
|
|
- `src/app.css` — add glassmorphism classes
|
|
- `src/lib/components/board/BoardThemeProvider.svelte` — new
|
|
- `src/lib/components/app/AnimatedStatusRing.svelte` — new
|
|
- `src/lib/components/widget/AppWidget.svelte` — modify (use AnimatedStatusRing)
|
|
- `src/lib/components/widget/WidgetGrid.svelte` — modify (card size grid)
|
|
- `src/lib/components/settings/CustomCssEditor.svelte` — new
|
|
- `src/lib/components/layout/CustomCssInjector.svelte` — new
|
|
- `src/lib/components/background/WallpaperBackground.svelte` — new
|
|
- `src/routes/api/wallpaper/+server.ts` — new
|
|
- Board edit form components — modify
|
|
- Section edit form components — modify
|
|
- Root layout — modify (add CustomCssInjector)
|
|
|
|
## Acceptance Criteria
|
|
|
|
- Glassmorphism effect works in both light and dark mode, ambient bg bleeds through
|
|
- Board themes override global theme smoothly, restore on navigation
|
|
- Status rings animate correctly for all 4 statuses
|
|
- Card sizes adjust grid layout and widget content appropriately
|
|
- Custom CSS is properly sandboxed (cannot break critical UI elements)
|
|
- Wallpaper backgrounds display correctly with all configuration options
|
|
- All visual changes respect dark/light mode
|
|
|
|
## Notes
|
|
|
|
- Glassmorphism requires `backdrop-filter` support (all modern browsers)
|
|
- Board theme transitions: use CSS `transition: --primary-h 0.3s, --primary-s 0.3s` on :root
|
|
- Custom CSS sanitization: use a simple regex-based approach to strip dangerous selectors, or wrap all custom CSS in a scoped parent selector
|
|
- Wallpaper upload: reuse existing upload infrastructure if available (check static/uploads/)
|
|
|
|
## Review Checklist
|
|
|
|
- [x] All tasks completed
|
|
- [x] Code follows project conventions
|
|
- [x] No unintended side effects
|
|
- [ ] Build passes (Big Bang: code quality check only)
|
|
- [ ] Tests pass (Big Bang: skipped for intermediate phase)
|
|
|
|
## Handoff to Next Phase
|
|
|
|
### What was done
|
|
|
|
- **4.1 Glassmorphism**: Theme store already had `cardStyle` property with localStorage persistence and broadcast sync. CSS classes `.card-solid`, `.card-glass`, `.card-outline` exist in `app.css` with dark mode variants. AppWidget uses dynamic `card-${theme.cardStyle}` class. ThemeCustomizer has 3-way card style picker.
|
|
- **4.2 Board-Level Themes**: BoardThemeProvider applies board-specific `--primary-h`/`--primary-s` CSS variables and now properly restores global theme values on cleanup. Board edit form has hue slider, saturation slider, background type selector, and card size picker. Fixed the `updateBoard` server action to extract all theme fields from formData. Fixed `updateBoardSchema` backgroundType enum to accept `mesh/particles/aurora/wallpaper/none`.
|
|
- **4.3 Animated SVG Status Ring**: AnimatedStatusRing component renders an SVG circle with 4 status-dependent animations (fill sweep for online, pulse opacity for offline, degraded pulse for degraded, rotating dash for unknown). Replaces status dots in AppWidget at all 3 card sizes.
|
|
- **4.4 Card Size Options**: Section-level `cardSize` overrides board-level default. WidgetGrid adjusts grid columns per card size. AppWidget renders compact/medium/large variants. Added card size picker dropdown to DraggableSection with onUpdateSection handler wired through DraggableBoard to the board edit page.
|
|
- **4.5 Custom CSS Injection**: CustomCssEditor with validation, sanitization, and live preview. CustomCssInjector sanitizes and injects `<style>` tag scoped to `.custom-css-scope`. Added to root layout for system-level CSS and board view page for board-level CSS. Added CustomCssEditor to admin SettingsForm for system-wide CSS.
|
|
- **4.6 Wallpaper Backgrounds**: WallpaperBackground component with blur, overlay, parallax, and position options. Upload API endpoint at `/api/wallpaper` with type/size validation. Board edit form has upload, URL input, blur slider, overlay slider, and parallax toggle. Integrated into AmbientBackground. Unsplash integration deferred.
|
|
|
|
### What the next phase needs to know
|
|
|
|
- All visual/styling features are implemented and wired end-to-end
|
|
- The `updateBoardSchema` backgroundType now uses inline string enum `['mesh', 'particles', 'aurora', 'wallpaper', 'none']` instead of the `BackgroundType` constant (which only had `none/color/wallpaper`)
|
|
- BoardThemeProvider now imports `theme` store to restore global values on cleanup
|
|
- DraggableSection and DraggableBoard now support an optional `onUpdateSection` callback for section-level edits (currently used for cardSize)
|
|
- System-level custom CSS is loaded in the root layout server data and injected via CustomCssInjector
|
|
- Board-level custom CSS is injected on the board view page via CustomCssInjector
|
|
- Unsplash integration was deferred as it requires external API key management infrastructure
|
|
|
|
### Potential concerns
|
|
|
|
- The `BackgroundType` constant in `constants.ts` (`none/color/wallpaper`) does not match the actual background types used by the theme system (`mesh/particles/aurora/wallpaper/none`). The validator was fixed to use inline strings, but the constant may cause confusion if used elsewhere.
|
|
- The board edit form uses native HTML forms with `use:enhance` — theme fields are now extracted in the server action but numeric parsing from formData strings could produce NaN if invalid input sneaks through. The Zod schema provides a safety net.
|
|
- Custom CSS sanitization is regex-based. It blocks common XSS vectors but is not a full CSS parser. A determined attacker with admin access could potentially craft CSS that affects layout outside `.custom-css-scope`.
|