@urbicon-ui/design-content 6.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -0
- package/content/auth/components/account-settings/llm.txt +33 -0
- package/content/auth/components/forgot-password-page/llm.txt +25 -0
- package/content/auth/components/invitation-manager/llm.txt +28 -0
- package/content/auth/components/login-page/llm.txt +34 -0
- package/content/auth/components/notification-badge/llm.txt +21 -0
- package/content/auth/components/notification-center/llm.txt +33 -0
- package/content/auth/components/notification-listener/llm.txt +24 -0
- package/content/auth/components/passkey-manager/llm.txt +27 -0
- package/content/auth/components/push-permission-prompt/llm.txt +32 -0
- package/content/auth/components/register-page/llm.txt +35 -0
- package/content/auth/components/reset-password-page/llm.txt +26 -0
- package/content/auth/components/session-manager/llm.txt +32 -0
- package/content/auth/components/two-factor-manager/llm.txt +40 -0
- package/content/auth/components/verify-email-page/llm.txt +25 -0
- package/content/blocks/components/area-chart/llm.txt +46 -0
- package/content/blocks/components/bar-chart/llm.txt +44 -0
- package/content/blocks/components/calendar/llm.txt +105 -0
- package/content/blocks/components/chart-frame/llm.txt +38 -0
- package/content/blocks/components/command-palette/llm.txt +60 -0
- package/content/blocks/components/composition-bar/llm.txt +69 -0
- package/content/blocks/components/currency-input/llm.txt +65 -0
- package/content/blocks/components/date-picker/llm.txt +90 -0
- package/content/blocks/components/donut-chart/llm.txt +45 -0
- package/content/blocks/components/empty-state/llm.txt +43 -0
- package/content/blocks/components/file-upload/llm.txt +76 -0
- package/content/blocks/components/guide/llm.txt +49 -0
- package/content/blocks/components/guide-article/llm.txt +30 -0
- package/content/blocks/components/guide-beacon/llm.txt +38 -0
- package/content/blocks/components/guide-hint/llm.txt +41 -0
- package/content/blocks/components/guide-marker/llm.txt +36 -0
- package/content/blocks/components/guide-mention/llm.txt +31 -0
- package/content/blocks/components/guide-panel/llm.txt +42 -0
- package/content/blocks/components/guide-provider/llm.txt +31 -0
- package/content/blocks/components/line-chart/llm.txt +45 -0
- package/content/blocks/components/locale-switcher/llm.txt +44 -0
- package/content/blocks/components/planner/llm.txt +68 -0
- package/content/blocks/components/sankey/llm.txt +72 -0
- package/content/blocks/components/sidebar-layout/llm.txt +87 -0
- package/content/blocks/components/sparkline/llm.txt +33 -0
- package/content/blocks/components/theme-switcher/llm.txt +40 -0
- package/content/blocks/primitives/accordion/llm.txt +57 -0
- package/content/blocks/primitives/alert/llm.txt +54 -0
- package/content/blocks/primitives/avatar/llm.txt +61 -0
- package/content/blocks/primitives/badge/llm.txt +60 -0
- package/content/blocks/primitives/breadcrumb/llm.txt +47 -0
- package/content/blocks/primitives/button/llm.txt +80 -0
- package/content/blocks/primitives/button-group/llm.txt +65 -0
- package/content/blocks/primitives/card/llm.txt +68 -0
- package/content/blocks/primitives/checkbox/llm.txt +61 -0
- package/content/blocks/primitives/collapsible/llm.txt +66 -0
- package/content/blocks/primitives/combobox/llm.txt +86 -0
- package/content/blocks/primitives/confirm-dialog/llm.txt +47 -0
- package/content/blocks/primitives/dialog/llm.txt +59 -0
- package/content/blocks/primitives/drawer/llm.txt +54 -0
- package/content/blocks/primitives/form-field/llm.txt +43 -0
- package/content/blocks/primitives/input/llm.txt +73 -0
- package/content/blocks/primitives/menu/llm.txt +81 -0
- package/content/blocks/primitives/pagination/llm.txt +68 -0
- package/content/blocks/primitives/popover/llm.txt +72 -0
- package/content/blocks/primitives/progress/llm.txt +55 -0
- package/content/blocks/primitives/radio-group/llm.txt +53 -0
- package/content/blocks/primitives/segment-group/llm.txt +51 -0
- package/content/blocks/primitives/select/llm.txt +130 -0
- package/content/blocks/primitives/separator/llm.txt +45 -0
- package/content/blocks/primitives/sidebar/llm.txt +79 -0
- package/content/blocks/primitives/skeleton/llm.txt +54 -0
- package/content/blocks/primitives/slider/llm.txt +82 -0
- package/content/blocks/primitives/spinner/llm.txt +46 -0
- package/content/blocks/primitives/stepper/llm.txt +60 -0
- package/content/blocks/primitives/tab/llm.txt +72 -0
- package/content/blocks/primitives/textarea/llm.txt +61 -0
- package/content/blocks/primitives/toast/llm.txt +45 -0
- package/content/blocks/primitives/toggle/llm.txt +62 -0
- package/content/blocks/primitives/toolbar/llm.txt +60 -0
- package/content/blocks/primitives/tooltip/llm.txt +54 -0
- package/content/component-catalog.json +5010 -0
- package/content/design-system/patterns/dashboard.md +55 -0
- package/content/design-system/patterns/form-page.md +69 -0
- package/content/design-system/patterns/onboarding-guide.md +50 -0
- package/content/design-system/patterns/planning-board.md +46 -0
- package/content/design-system/patterns/settings-page.md +48 -0
- package/content/design-system/patterns/tab-navigation.md +136 -0
- package/content/design-system/principles.md +260 -0
- package/content/docs/components/api-reference/llm.txt +32 -0
- package/content/docs/components/code-example/llm.txt +44 -0
- package/content/docs/components/code-panel/llm.txt +26 -0
- package/content/docs/components/docs-layout/llm.txt +61 -0
- package/content/docs/components/info-card/llm.txt +31 -0
- package/content/docs/components/playground-configurator/llm.txt +49 -0
- package/content/docs/components/section/llm.txt +46 -0
- package/content/docs/components/table-of-contents/llm.txt +48 -0
- package/content/docs/components/types-reference/llm.txt +38 -0
- package/content/guides/llms-full-template.md +1019 -0
- package/content/icons.json +4834 -0
- package/content/meta.json +5 -0
- package/content/table/table/llm.txt +110 -0
- package/content/verbs/adopt.md +33 -0
- package/content/verbs/audit.md +29 -0
- package/content/verbs/compose.md +38 -0
- package/content/verbs/critique.md +27 -0
- package/content/verbs/fix.md +29 -0
- package/content/verbs/migrate.md +30 -0
- package/content/verbs/onboard.md +33 -0
- package/content/verbs/polish.md +25 -0
- package/content/verbs/redesign.md +29 -0
- package/content/verbs/retheme.md +29 -0
- package/package.json +45 -0
- package/src/content-loader.test.ts +78 -0
- package/src/content-loader.ts +97 -0
- package/src/index.ts +23 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Dashboard
|
|
2
|
+
|
|
3
|
+
Data-rich overview page with metrics, charts, and action shortcuts.
|
|
4
|
+
|
|
5
|
+
## Layout
|
|
6
|
+
|
|
7
|
+
- **Structure:** full-width content area, optionally within `SidebarLayout` for app navigation
|
|
8
|
+
- **Grid:** CSS grid with responsive columns. Desktop: 3-4 columns for stat tiles, 2 columns for charts/tables. Mobile: single column stack.
|
|
9
|
+
- **Content:** no max-width constraint (data-dense view). Cards fill available space.
|
|
10
|
+
- **Spacing:** `gap-4` between grid items, `gap-6` between sections (stats row, charts row, table row)
|
|
11
|
+
|
|
12
|
+
## Component Selection
|
|
13
|
+
|
|
14
|
+
| UI Need | Component | Configuration |
|
|
15
|
+
|---|---|---|
|
|
16
|
+
| Stat/KPI tile | `Card` | Compact padding, prominent number + label + trend indicator |
|
|
17
|
+
| Trend direction | `Badge` | `intent="success"` for up, `intent="danger"` for down |
|
|
18
|
+
| Proportional data | `CompositionBar` | Horizontal bar with legend |
|
|
19
|
+
| Flow visualization | `Sankey` | Multi-level relationship flows |
|
|
20
|
+
| Data table | `Table` | With sorting, filtering; limit visible rows (5-10), link to full view |
|
|
21
|
+
| Quick actions | `ButtonGroup` or `Toolbar` | Top-right of page or section |
|
|
22
|
+
| Date range filter | `DatePicker` or `Select` | Top of page, controls all widgets below |
|
|
23
|
+
| Empty widget | `EmptyState` | In Card, with action to configure/populate |
|
|
24
|
+
| Loading state | `Skeleton` | Match widget dimensions, not generic spinners |
|
|
25
|
+
| Notifications | `Alert` | Persistent, at page top, for system status |
|
|
26
|
+
|
|
27
|
+
## Section Ordering
|
|
28
|
+
|
|
29
|
+
1. **Page header:** title + date range filter + quick actions
|
|
30
|
+
2. **Stat tiles:** 3-4 KPI cards in a single row
|
|
31
|
+
3. **Charts / visualizations:** 2 cards side-by-side (e.g., CompositionBar + trend chart)
|
|
32
|
+
4. **Activity table:** recent activity or transactions, with link to full view
|
|
33
|
+
5. **Secondary widgets:** lower-priority info, may be collapsed or tabbed
|
|
34
|
+
|
|
35
|
+
## Behavioral Rules
|
|
36
|
+
|
|
37
|
+
- All widgets should show `Skeleton` during data loading, matching the widget's final dimensions.
|
|
38
|
+
- Date range filter at the top controls all widgets — changing the range refreshes everything.
|
|
39
|
+
- Stat tiles: show current value, trend (% change), and a subtle trend indicator (Badge with intent).
|
|
40
|
+
- Tables: show only 5-10 rows on the dashboard. Provide a "View all" link to the full table view.
|
|
41
|
+
- Auto-refresh: if data is live, use `Table` live-update capabilities (`pushInsert`, `pushUpdate`). Show a subtle timestamp ("Last updated: 2 min ago").
|
|
42
|
+
- Error states: per-widget errors, not a page-level error. Show `Alert` within the `Card` that failed.
|
|
43
|
+
|
|
44
|
+
## Anti-Patterns
|
|
45
|
+
|
|
46
|
+
- Do not use full-featured `Table` with all controls (grouping, column reorder, etc.) on the dashboard. Keep it compact.
|
|
47
|
+
- Do not mix different Card styles within the same section. Stat tiles should look uniform.
|
|
48
|
+
- Do not stack more than 3 vertical sections without scroll anchoring or navigation.
|
|
49
|
+
- Do not use `Dialog` for drill-down. Use `Drawer` or navigate to a detail page.
|
|
50
|
+
- Do not show raw numbers without context. Always pair a number with a label and, where applicable, a trend.
|
|
51
|
+
|
|
52
|
+
## Related
|
|
53
|
+
|
|
54
|
+
- Recipe: `dashboard` — complete production-ready code example
|
|
55
|
+
- Pattern: `settings-page` — for admin dashboards with settings navigation
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Form Page
|
|
2
|
+
|
|
3
|
+
Standalone form for data entry — registration, creation, multi-step wizards.
|
|
4
|
+
|
|
5
|
+
## Layout
|
|
6
|
+
|
|
7
|
+
- **Structure:** centered content area with constrained width
|
|
8
|
+
- **Content:** max-width 560px for simple forms, 720px for complex forms with side context
|
|
9
|
+
- **Spacing:** `gap-6` between form groups, `gap-4` between fields within a group
|
|
10
|
+
- **Responsive:** single-column stack. On desktop, short related fields (first/last name, city/zip) can sit side-by-side in a 2-column grid.
|
|
11
|
+
- **Actions:** bottom of form, right-aligned. Primary action first (right), secondary (Cancel/Back) second (left).
|
|
12
|
+
|
|
13
|
+
## Component Selection
|
|
14
|
+
|
|
15
|
+
| UI Need | Component | Configuration |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| Text input | `Input` | Wrapped in `FormField` |
|
|
18
|
+
| Multi-line text | `Textarea` | Wrapped in `FormField`, with character count if limited |
|
|
19
|
+
| Email/password | `Input` | `type="email"` / `type="password"`, wrapped in `FormField` |
|
|
20
|
+
| Enum selection | `Select` or `RadioGroup` | Select for 4+, RadioGroup for 2-3 visible options |
|
|
21
|
+
| Searchable selection | `Combobox` | 7+ options, wrapped in `FormField` |
|
|
22
|
+
| Boolean consent | `Checkbox` | For agreements ("I accept the terms") |
|
|
23
|
+
| Boolean toggle | `Toggle` | For preference settings within a form |
|
|
24
|
+
| Date input | `DatePicker` | Wrapped in `FormField` |
|
|
25
|
+
| Currency | `CurrencyInput` | Locale-aware, wrapped in `FormField` |
|
|
26
|
+
| File | `FileUpload` | Drag-and-drop zone, clear accepted formats |
|
|
27
|
+
| Form group | `Card` or visual separator | Card for distinct sections, `Separator` for light division |
|
|
28
|
+
| Submit action | `Button intent="primary"` | Loading state during submission |
|
|
29
|
+
| Multi-step | `Stepper` | Shows progress, validates per step |
|
|
30
|
+
| Validation feedback | `FormField` error prop | Inline, under the field |
|
|
31
|
+
| Submit feedback | `Toast` | Success/error after submission |
|
|
32
|
+
|
|
33
|
+
## Validation Rules
|
|
34
|
+
|
|
35
|
+
- Validate on blur for individual fields (immediate feedback).
|
|
36
|
+
- Validate on submit for cross-field rules (password confirmation, date ranges).
|
|
37
|
+
- Show error text below the field via `FormField` error prop, not in a `Toast` or `Alert`.
|
|
38
|
+
- Required fields: mark optional fields with "(optional)" label suffix instead of marking required with asterisks.
|
|
39
|
+
- Disable submit button only while submission is in-flight (spinner), not while fields are invalid — let users click and see validation errors.
|
|
40
|
+
|
|
41
|
+
## Multi-Step Forms
|
|
42
|
+
|
|
43
|
+
- Use `Stepper` to show progress.
|
|
44
|
+
- Validate the current step before allowing navigation to the next.
|
|
45
|
+
- Allow backward navigation without losing data.
|
|
46
|
+
- Show a summary/review step before final submission for important forms.
|
|
47
|
+
- Keep step count visible (e.g., "Step 2 of 4"), not just a progress bar.
|
|
48
|
+
|
|
49
|
+
## Behavioral Rules
|
|
50
|
+
|
|
51
|
+
- Pre-fill known data (from user profile, previous entries, URL params).
|
|
52
|
+
- Persist draft state for long forms (localStorage or server-side draft).
|
|
53
|
+
- Show unsaved-changes warning on navigation away (`ConfirmDialog`).
|
|
54
|
+
- Group related fields together. Use `Card` with a heading for distinct sections (Personal Info, Payment, Shipping).
|
|
55
|
+
- Place help text in `FormField` description, not in `Tooltip`. Tooltips are hidden by default.
|
|
56
|
+
|
|
57
|
+
## Anti-Patterns
|
|
58
|
+
|
|
59
|
+
- Do not use `Dialog` for forms with more than 3 fields. Use a dedicated page or `Drawer`.
|
|
60
|
+
- Do not use horizontal multi-column layouts for unrelated fields. Side-by-side only for naturally paired fields (first + last name, city + zip).
|
|
61
|
+
- Do not put the submit button above the form. Actions go at the bottom, where the user ends.
|
|
62
|
+
- Do not use `placeholder` as the only label. Always use `FormField` with a visible label.
|
|
63
|
+
- Do not auto-submit on field change without explicit user instruction.
|
|
64
|
+
|
|
65
|
+
## Related
|
|
66
|
+
|
|
67
|
+
- Recipe: `login` — login/registration form example
|
|
68
|
+
- Recipe: `wizard` — multi-step form wizard example
|
|
69
|
+
- Pattern: `settings-page` — for forms embedded in settings sections
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Onboarding & In-App Help
|
|
2
|
+
|
|
3
|
+
Guide a first-run user and keep help available in context, using the Guide system over one
|
|
4
|
+
headless controller — without a modal wizard that blocks the app. Guide is the library's
|
|
5
|
+
sequential, system-driven overlay pattern (it decides *when*, *in what order*, and *in what
|
|
6
|
+
mode* help appears), unlike the spatial, event-driven overlays (`Dialog`, `Popover`, `Tooltip`).
|
|
7
|
+
|
|
8
|
+
## Layout
|
|
9
|
+
|
|
10
|
+
- **Provider:** one `GuideProvider` near the app root, holding one `GuideController` you create yourself for programmatic control.
|
|
11
|
+
- **Tour renderer:** one `<Guide />` inside the provider — invisible until a tour starts; it owns the top-layer spotlight + bubble.
|
|
12
|
+
- **Help panel:** one `GuidePanel` — non-modal, docks to a screen edge at `--z-sidebar`; the app stays interactive behind it.
|
|
13
|
+
- **Entry point:** a `GuideBeacon` placed inline or absolutely over a "new" feature — the gentle, opt-in tour entry. Never auto-start.
|
|
14
|
+
- **Targets:** mark each referenced element once with `data-guide="<id>"`; tours, hints, markers, and mentions all resolve through that one namespace.
|
|
15
|
+
|
|
16
|
+
## Component Selection
|
|
17
|
+
|
|
18
|
+
| UI Need | Component | Configuration |
|
|
19
|
+
|---|---|---|
|
|
20
|
+
| First-run walkthrough | `Guide` + a `GuideTour` | Opt-in, 3–5 steps; spotlight each step `target` |
|
|
21
|
+
| Gentle tour entry | `GuideBeacon` | `tour={...}`; hides itself once the tour is seen |
|
|
22
|
+
| Always-available help | `GuidePanel` + `GuideArticle` | Non-modal; controller-driven `openPanel(article?)` |
|
|
23
|
+
| "What does this do?" affordance | `GuideMarker` | `for="<id>"` → opens the panel at the article (UI → guide) |
|
|
24
|
+
| Point an article at the UI | `GuideMention` | `for="<id>"` inside an article; highlights on hover **and** focus (guide → UI) |
|
|
25
|
+
| One-off contextual nudge | `GuideHint` | `trigger="mount"`, or `"manual"` + `open`; `once` persists "seen" |
|
|
26
|
+
| Onboarding analytics | `onStep` / `onComplete` / `onSkip` | On the `GuideTour` — the funnel + drop-off signal |
|
|
27
|
+
|
|
28
|
+
## Behavioral Rules
|
|
29
|
+
|
|
30
|
+
- **Helpful, not intrusive.** Default to the callable panel and the waiting hint. The scrim tour is the most aggressive mode and stays opt-in (beacon or explicit button) — never auto-started.
|
|
31
|
+
- **One controller, many surfaces.** Create the `GuideController`, pass it to `GuideProvider`, and drive everything (`startTour`, `openPanel`, `hasSeen`) from it.
|
|
32
|
+
- **Persist "seen."** Tours and `once` hints mark themselves seen on end, so a returning user is not nagged. `stopTour()` (route change / unmount) deliberately does NOT mark seen and is analytics-silent.
|
|
33
|
+
- **Track the funnel.** Wire `onStep` / `onComplete` / `onSkip` — `onStep.via` distinguishes `start` vs `next`/`prev`, and `onSkip.index` is the drop-off step. This is the real business value of onboarding.
|
|
34
|
+
- **Cross-route tours are app-driven.** The controller survives client navigation and the renderer re-anchors once the new route's `data-guide` target appears; the app navigates in `tour.onStep` (e.g. `goto(stepRoutes[index])`). Mount `Guide` in the layout — a route-local renderer unmounts mid-tour. Full recipe: `docs/GUIDE.md` §9.
|
|
35
|
+
- **Learning-by-doing steps:** `GuideStep.advance: 'action'` (paired with `interactive: true`) disables Next; the user performs the real action and the app advances via `controller.next()`.
|
|
36
|
+
- **Content lives in the app**, not the library: steps, article text, and `data-guide` selectors are app-owned (and i18n'd by the app).
|
|
37
|
+
- **Reduced motion** is honored automatically (panel slide, beacon pulse, step fade) — no extra work.
|
|
38
|
+
|
|
39
|
+
## Anti-Patterns
|
|
40
|
+
|
|
41
|
+
- Do not auto-start a tour on page load. Onboarding that hijacks the screen before the user acts is exactly why product tours earned a bad reputation.
|
|
42
|
+
- Do not use a modal `Dialog` / `Drawer` as the help panel. The panel must be non-modal so a `GuideMention` can highlight a UI element while the panel is open (the bidirectional link breaks otherwise).
|
|
43
|
+
- Do not build a multi-step **form wizard** with `Guide`. That is a `Stepper` + form pattern; `Guide` overlays *existing* UI, it does not collect input.
|
|
44
|
+
- Do not invent `data-guide` ids with `Math.random()` — they are author-chosen, stable strings shared across surfaces.
|
|
45
|
+
- Do not duplicate help copy across a tour step and an article; point both at the same `data-guide` topic instead.
|
|
46
|
+
|
|
47
|
+
## Related
|
|
48
|
+
|
|
49
|
+
- Recipe: `onboarding-flow` — complete production-ready Guide-system example
|
|
50
|
+
- Guide: `docs/GUIDE.md` — full architecture and the cross-route tour recipe (§9)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Planning Board
|
|
2
|
+
|
|
3
|
+
Date-indexed board that lays domain items — meals, shifts, bookings, content slots — onto calendar days across a week, month or custom range.
|
|
4
|
+
|
|
5
|
+
## Layout
|
|
6
|
+
|
|
7
|
+
- **Structure:** `Planner` is the whole board. It buckets `items` by day and renders each cell via your `cell` snippet — no manual date math, no per-day grid.
|
|
8
|
+
- **View:** `view="week"` for a column-per-day plan (the default), `view="month"` for a compact 6×7 overview, `view="range"` for an arbitrary span. Week stacks to one column per day on mobile automatically.
|
|
9
|
+
- **Cells:** put a small stack of cards or rows inside `cell`. Keep each item to one or two lines (icon + label); the cell is narrow.
|
|
10
|
+
- **Spacing:** week cells get `gap-1`–`gap-2` between items; month cells stay terse — show counts or 1–2 items, not the full list.
|
|
11
|
+
- **Server alignment:** load the week on the server with `@urbicon-ui/blocks/date` (`startOfWeek` / `toIso`) so the SSR range and the client grid agree — no UTC drift.
|
|
12
|
+
|
|
13
|
+
## Component Selection
|
|
14
|
+
|
|
15
|
+
| UI Need | Component | Configuration |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| The board itself | `Planner` | `view`, `items`, `getDate`; `sort` for intra-day order |
|
|
18
|
+
| Per-day content | `cell` snippet | Receives typed `items: T[]`, `isoDate`, `isToday`, `selectDate()` |
|
|
19
|
+
| An item card | `Card` or a plain `div` | One per item, kept to a line or two |
|
|
20
|
+
| Item category / status | `Badge` | `intent` per category (`success`/`warning`/`primary`…) |
|
|
21
|
+
| Add-on-a-day affordance | `Button variant="ghost" size="sm"` | Inside `cell` — rendered for empty days too |
|
|
22
|
+
| Empty-day placeholder | `empty` snippet | Optional; omit it to let `cell` handle empty days |
|
|
23
|
+
| Custom toolbar | `header` snippet | Replaces prev/next/today/title |
|
|
24
|
+
| Timed appointments instead | `Calendar` | Use Calendar, not Planner, when items have a clock time |
|
|
25
|
+
|
|
26
|
+
## Behavioral Rules
|
|
27
|
+
|
|
28
|
+
- `getDate` returns a `Date` or a local ISO date string (`'2026-06-16'`); strings are taken verbatim, so a day never shifts across timezones. Pass a `Date` for UTC instants.
|
|
29
|
+
- The `cell` snippet runs for **every** day, empty ones included — keep the "add" button there so it is reachable on blank days.
|
|
30
|
+
- Drive data loading from `onNavigate(date, range)`: fetch `range.start … range.end`, not the whole month.
|
|
31
|
+
- `bind:value` is the reference date; `bind:selectedDate` is the active day. Clicking a cell's body selects its day; clicks on interactive cell content keep their own behaviour.
|
|
32
|
+
- Sort within a day via `sort` (e.g. breakfast → lunch → dinner), not by reordering `items`.
|
|
33
|
+
|
|
34
|
+
## Anti-Patterns
|
|
35
|
+
|
|
36
|
+
- Do not reach for `Calendar` for uhrzeit-lose day content — its model is timed `CalendarEvent`s with bars and recurrence. Planner is single-date bucketing of your own type.
|
|
37
|
+
- Do not rebuild the week/month grid by hand with `getWeekDates` + a `{#each}`. That is exactly what Planner removes.
|
|
38
|
+
- Do not stuff a full item list into a month cell. Summarise (count or top item) and switch to `view="week"` for detail.
|
|
39
|
+
- Do not parse a plain date string through `new Date()` before handing it to `getDate` — you reintroduce the UTC off-by-one Planner avoids.
|
|
40
|
+
- Do not gate the add affordance behind "has items". Empty days are where you add most.
|
|
41
|
+
|
|
42
|
+
## Related
|
|
43
|
+
|
|
44
|
+
- Component: `Planner` — the board; see also `Calendar` for timed events
|
|
45
|
+
- Recipe: `meal-planner` — complete production-ready weekly plan
|
|
46
|
+
- Pattern: `dashboard` — when the board is one panel among analytics
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Settings Page
|
|
2
|
+
|
|
3
|
+
Multi-section user preferences with sidebar navigation and grouped content areas.
|
|
4
|
+
|
|
5
|
+
## Layout
|
|
6
|
+
|
|
7
|
+
- **Structure:** `SidebarLayout` with sidebar navigation + scrollable content area
|
|
8
|
+
- **Sidebar:** 240-280px width, grouped navigation links via `Sidebar` with `Accordion` for groups
|
|
9
|
+
- **Content:** max-width 720px, vertically stacked sections
|
|
10
|
+
- **Responsive:** below 768px, sidebar collapses; use a `Select` or horizontal scrollable navigation to switch sections
|
|
11
|
+
- **Spacing:** `gap-8` between sections, `gap-4` within sections
|
|
12
|
+
|
|
13
|
+
## Component Selection
|
|
14
|
+
|
|
15
|
+
| UI Need | Component | Configuration |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| Section navigation | `Sidebar` + `Accordion` | Grouped links, highlight active section |
|
|
18
|
+
| Section container | `Card` | `variant="outlined"` |
|
|
19
|
+
| Section heading | Native `h2` | `text-text-primary font-semibold text-lg` |
|
|
20
|
+
| Subsection heading | Native `h3` | `text-text-secondary font-medium text-base` |
|
|
21
|
+
| Boolean setting | `Toggle` | With label, not `Checkbox` |
|
|
22
|
+
| Enum setting (3-6) | `Select` | Labeled via `FormField` |
|
|
23
|
+
| Enum setting (7+) | `Combobox` | Searchable, labeled via `FormField` |
|
|
24
|
+
| Free text | `Input` or `Textarea` | Labeled via `FormField` |
|
|
25
|
+
| Save/cancel | `Button` pair | Sticky bottom bar when form exceeds viewport |
|
|
26
|
+
| Destructive action | `Button intent="danger"` | Separated at bottom, requires `ConfirmDialog` |
|
|
27
|
+
| Status feedback | `Toast` | On save success/failure |
|
|
28
|
+
|
|
29
|
+
## Behavioral Rules
|
|
30
|
+
|
|
31
|
+
- Group related settings in Cards. One Card per conceptual group (Account, Notifications, Privacy).
|
|
32
|
+
- Save button shows loading state (spinner) during save.
|
|
33
|
+
- Warn on unsaved changes: intercept navigation, show `ConfirmDialog`.
|
|
34
|
+
- Reset/Cancel returns to last saved state, not initial page load state.
|
|
35
|
+
- Destructive settings (delete account, revoke access) separated at the bottom of the page, visually distinct from other settings.
|
|
36
|
+
- Default values: show the active value, not "unchanged". Users should see what is currently configured.
|
|
37
|
+
|
|
38
|
+
## Anti-Patterns
|
|
39
|
+
|
|
40
|
+
- Do not use `Tab` for settings groups. Tabs imply peer sections at the same hierarchy; settings are hierarchical.
|
|
41
|
+
- Do not put all settings in a single scrollable list without navigation.
|
|
42
|
+
- Do not use modals for inline editing. Edit in place, save with the section's save action.
|
|
43
|
+
- Do not auto-save without explicit user signal. Settings changes should be intentional.
|
|
44
|
+
|
|
45
|
+
## Related
|
|
46
|
+
|
|
47
|
+
- Recipe: `settings` — complete production-ready code example
|
|
48
|
+
- Pattern: `form-page` — for standalone forms within settings sections
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Tab Navigation
|
|
2
|
+
|
|
3
|
+
URL-based tab navigation for SvelteKit routes — each tab maps to a route segment.
|
|
4
|
+
|
|
5
|
+
## When to Use
|
|
6
|
+
|
|
7
|
+
Use this pattern when:
|
|
8
|
+
- Peer sections of a detail view need their own URL (bookmarkable, shareable)
|
|
9
|
+
- Each section has distinct content that justifies a separate route
|
|
10
|
+
- The user navigates between sections without losing page context (e.g., project detail with Overview, Settings, Logs)
|
|
11
|
+
|
|
12
|
+
Do NOT use when:
|
|
13
|
+
- Sections share state that would be lost on navigation — use client-side `Tab` with `bind:value` instead
|
|
14
|
+
- There are only 2 sections — consider a simple toggle or inline layout
|
|
15
|
+
- Sections are hierarchical — use `Sidebar` navigation instead (see `settings-page` pattern)
|
|
16
|
+
|
|
17
|
+
## Layout
|
|
18
|
+
|
|
19
|
+
- **Structure:** shared layout (`+layout.svelte`) with `Tab` or `SegmentGroup` + nested `+page.svelte` per section
|
|
20
|
+
- **Placement:** tabs directly below the page header / breadcrumb, above the content area
|
|
21
|
+
- **Content:** each `+page.svelte` renders its own section content below the shared tab bar
|
|
22
|
+
- **Responsive:** on mobile, consider horizontal scroll for the tab bar, or collapse to a `Select` dropdown for 5+ tabs
|
|
23
|
+
|
|
24
|
+
## SvelteKit Route Structure
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
routes/
|
|
28
|
+
project/[id]/
|
|
29
|
+
+layout.svelte ← shared tab bar
|
|
30
|
+
+page.svelte ← "Overview" (default tab)
|
|
31
|
+
settings/
|
|
32
|
+
+page.svelte ← "Settings" tab
|
|
33
|
+
logs/
|
|
34
|
+
+page.svelte ← "Logs" tab
|
|
35
|
+
hooks/
|
|
36
|
+
+page.svelte ← "Hooks" tab
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Implementation
|
|
40
|
+
|
|
41
|
+
### Shared Layout with Tab Navigation
|
|
42
|
+
|
|
43
|
+
```svelte
|
|
44
|
+
<script lang="ts">
|
|
45
|
+
import { page } from '$app/state';
|
|
46
|
+
import { Tab } from '@urbicon-ui/blocks';
|
|
47
|
+
|
|
48
|
+
const { children } = $props();
|
|
49
|
+
|
|
50
|
+
const tabs = [
|
|
51
|
+
{ label: 'Overview', href: `/project/${page.params.id}` },
|
|
52
|
+
{ label: 'Settings', href: `/project/${page.params.id}/settings` },
|
|
53
|
+
{ label: 'Logs', href: `/project/${page.params.id}/logs` },
|
|
54
|
+
{ label: 'Hooks', href: `/project/${page.params.id}/hooks` },
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
const activeTab = $derived(
|
|
58
|
+
tabs.findIndex((t) => page.url.pathname === t.href) ?? 0
|
|
59
|
+
);
|
|
60
|
+
</script>
|
|
61
|
+
|
|
62
|
+
<div class="flex flex-col gap-6">
|
|
63
|
+
<Tab.Root value={tabs[activeTab]?.label}>
|
|
64
|
+
{#each tabs as tab}
|
|
65
|
+
<Tab.Trigger value={tab.label}>
|
|
66
|
+
<a href={tab.href}>{tab.label}</a>
|
|
67
|
+
</Tab.Trigger>
|
|
68
|
+
{/each}
|
|
69
|
+
</Tab.Root>
|
|
70
|
+
|
|
71
|
+
{@render children()}
|
|
72
|
+
</div>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Alternative: SegmentGroup (Compact)
|
|
76
|
+
|
|
77
|
+
For fewer tabs (2-4) where a more compact visual is preferred:
|
|
78
|
+
|
|
79
|
+
```svelte
|
|
80
|
+
<script lang="ts">
|
|
81
|
+
import { page } from '$app/state';
|
|
82
|
+
import { goto } from '$app/navigation';
|
|
83
|
+
import { SegmentGroup } from '@urbicon-ui/blocks';
|
|
84
|
+
|
|
85
|
+
const segments = [
|
|
86
|
+
{ value: 'overview', label: 'Overview', href: `/project/${page.params.id}` },
|
|
87
|
+
{ value: 'settings', label: 'Settings', href: `/project/${page.params.id}/settings` },
|
|
88
|
+
];
|
|
89
|
+
|
|
90
|
+
const current = $derived(
|
|
91
|
+
segments.find((s) => page.url.pathname === s.href)?.value ?? 'overview'
|
|
92
|
+
);
|
|
93
|
+
</script>
|
|
94
|
+
|
|
95
|
+
<SegmentGroup
|
|
96
|
+
value={current}
|
|
97
|
+
onValueChange={(v) => {
|
|
98
|
+
const seg = segments.find((s) => s.value === v);
|
|
99
|
+
if (seg) goto(seg.href);
|
|
100
|
+
}}
|
|
101
|
+
>
|
|
102
|
+
{#each segments as seg}
|
|
103
|
+
<SegmentGroup.Item value={seg.value}>{seg.label}</SegmentGroup.Item>
|
|
104
|
+
{/each}
|
|
105
|
+
</SegmentGroup>
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Component Selection
|
|
109
|
+
|
|
110
|
+
| UI Need | Component | When |
|
|
111
|
+
|---|---|---|
|
|
112
|
+
| 3+ peer sections | `Tab` | Standard horizontal tabs |
|
|
113
|
+
| 2-4 compact options | `SegmentGroup` | Tighter visual, pill-style |
|
|
114
|
+
| 5+ sections on mobile | `Select` | Dropdown fallback for narrow screens |
|
|
115
|
+
| Hierarchical subsections | `Sidebar` | Use `settings-page` pattern instead |
|
|
116
|
+
|
|
117
|
+
## Behavioral Rules
|
|
118
|
+
|
|
119
|
+
- The default route (`+page.svelte` at the layout level) is the first/primary tab.
|
|
120
|
+
- Active tab is derived from `page.url.pathname`, not from component state — the URL is the source of truth.
|
|
121
|
+
- Use `<a href>` for navigation, not `goto()`, to preserve browser history and link behavior.
|
|
122
|
+
- Breadcrumbs above the tab bar should show the entity context (e.g., "Projects / My Project"), not the tab name.
|
|
123
|
+
- Each tab page should be independently loadable via URL (deep linking).
|
|
124
|
+
|
|
125
|
+
## Anti-Patterns
|
|
126
|
+
|
|
127
|
+
- Do not store active tab in `$state` — derive it from the URL. Client-side state and URL will drift.
|
|
128
|
+
- Do not use `Tab` with `bind:value` for route-based navigation — use `<a href>` inside tab triggers.
|
|
129
|
+
- Do not duplicate the tab bar in every `+page.svelte` — put it in the shared `+layout.svelte`.
|
|
130
|
+
- Do not use this pattern for settings with save/cancel — use the `settings-page` pattern with `Sidebar` instead.
|
|
131
|
+
|
|
132
|
+
## Related
|
|
133
|
+
|
|
134
|
+
- Pattern: `settings-page` — for hierarchical settings navigation
|
|
135
|
+
- Component: `Tab` — the underlying tab component API
|
|
136
|
+
- Component: `SegmentGroup` — compact alternative for few sections
|