@xleddyl/443-components-vue 0.11.0 → 0.12.1
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/CATALOG.md +45 -40
- package/README.md +62 -4
- package/dist/components/layout/Sidebar.vue +8 -3
- package/dist/components/layout/Sidebar.vue.d.ts +6 -1
- package/dist/components/layout/types.d.ts +1 -0
- package/dist/components/templates/DashboardLayout.vue +11 -1
- package/dist/components/templates/DashboardLayout.vue.d.ts +5 -2
- package/dist/components/templates/SettingsModal.vue +95 -4
- package/dist/components/templates/SettingsModal.vue.d.ts +6 -1
- package/dist/components/templates/types.d.ts +2 -0
- package/dist/composables/layout.d.ts +1 -0
- package/dist/composables/layout.mjs +1 -0
- package/dist/composables/useRouteState.d.ts +13 -0
- package/dist/composables/useRouteState.mjs +37 -0
- package/dist/grid/DataGrid.vue +7 -1
- package/dist/grid/DataGrid.vue.d.ts +8 -1
- package/dist/grid/GridToolbar.vue +57 -2
- package/dist/grid/GridToolbar.vue.d.ts +13 -2
- package/dist/grid/data-grid.css +33 -0
- package/dist/grid/types.d.ts +1 -0
- package/dist/icons/builtin.d.ts +2 -0
- package/dist/icons/builtin.mjs +2 -0
- package/dist/internal/layout/query.d.ts +6 -0
- package/dist/internal/layout/query.mjs +64 -0
- package/dist/internal/layout/route.d.ts +9 -2
- package/dist/locale/de.mjs +4 -0
- package/dist/locale/en.mjs +4 -0
- package/dist/locale/it.mjs +4 -0
- package/dist/locale/types.d.ts +4 -0
- package/dist/nuxt/runtime/layouts/dashboard.vue +1 -0
- package/dist/styles/layout/app-shell.css +12 -6
- package/dist/styles/layout/sidebar.css +11 -2
- package/dist/styles/templates/settings-modal.css +5 -1
- package/package.json +1 -1
package/CATALOG.md
CHANGED
|
@@ -65,6 +65,8 @@ Playground paths in this file are relative to `playground/nuxt/app/pages/compone
|
|
|
65
65
|
| Toast after saving in an open Drawer | `toast` (the stack moves beside the drawer or above its footer) |
|
|
66
66
|
| Detail or edit panel from the side | `Drawer` (or `useDrawer().open`) |
|
|
67
67
|
| Dialog with a form or content | `Modal` (or `useModal().open` to get the result as a promise) |
|
|
68
|
+
| Buttons in a Modal or Drawer header | `#actions` slot of `Modal` / `Drawer` (right side, before the close button) |
|
|
69
|
+
| Deep link to a drawer or modal (`?family=fam_1`, `?family=new`) | `useRouteState('family')` + `:open="!!familyId"`; settings: `route` on `SettingsModal`, `settingsRoute` on `DashboardLayout` |
|
|
68
70
|
| Menu opened by a button | `DropdownMenu` |
|
|
69
71
|
| Right click menu | `ContextMenu` |
|
|
70
72
|
| Small floating panel with content or a form | `Popover` |
|
|
@@ -73,6 +75,7 @@ Playground paths in this file are relative to `playground/nuxt/app/pages/compone
|
|
|
73
75
|
| Global search, command menu (Cmd+K) | `CommandPalette` (the `DashboardLayout` has it with `search`) |
|
|
74
76
|
| Small table, simple sort | `Table` (+ `useTableSort` for client sort) |
|
|
75
77
|
| Big table, many rows, editing, Excel-like | `DataGrid` (+ `spreadsheet` prop for Excel-like editing) |
|
|
78
|
+
| Filters for a grid (selects, dates in a modal from the toolbar) | `DataGrid` `#filters` slot with `filterCount` and `@filters-reset` |
|
|
76
79
|
| Several tags or statuses in one grid cell | `BadgeCell` with an array value (`max` adds a `+N` badge) |
|
|
77
80
|
| Whole list page: search, filters, table, pagination | `ListPage` |
|
|
78
81
|
| Page numbers and page size | `Pagination` |
|
|
@@ -95,6 +98,7 @@ Playground paths in this file are relative to `playground/nuxt/app/pages/compone
|
|
|
95
98
|
| Page title, description, breadcrumbs, actions | `PageHeader` (or a page template) |
|
|
96
99
|
| Breadcrumbs only | `Breadcrumbs` |
|
|
97
100
|
| Dashboard layout with sidebar, search, account and settings | `DashboardLayout` (or the Nuxt layout `k-dashboard`) |
|
|
101
|
+
| Actions in a settings section header ("Add user") | `#actions-<id>` on `SettingsModal`, `#settings-actions-<id>` on `DashboardLayout` (gets `page`, `openPage`, `back`) |
|
|
98
102
|
| Page that fills the panel height (a full height grid) | `content="fill"` or `"centered"` on `DashboardLayout` / `AppShell`, `definePageMeta({ content: 'fill' })` |
|
|
99
103
|
| Custom app frame with your own sidebar | `AppShell` + `Sidebar` + `SidebarNav` |
|
|
100
104
|
| Login, sign up, reset password page | `AuthLayout` (or the Nuxt layout `k-auth`) |
|
|
@@ -172,20 +176,20 @@ All field components work inside `FormField` and take `invalid`, `disabled`, `re
|
|
|
172
176
|
|
|
173
177
|
Mount `OverlayHost` once for the imperative hooks (see [Composables](#composables)).
|
|
174
178
|
|
|
175
|
-
| Component | Purpose and when to use it | Main props, models, slots, events
|
|
176
|
-
| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
177
|
-
| `Modal` | Centered dialog for forms and content. Use `Drawer` for a side panel, `useConfirm` for a yes or no question. | Model: `v-model:open`. Props: `title`, `description`, `size` (sm to xl, full, fit, fullscreen), `width`, `minHeight`, `dismissible`, `hideClose`, `sheet`, `flush`, `loading`, `beforeClose(reason)`. Slots: default, `header`, `footer`, `title-trailing`. Events: `open`, `close`, `afterLeave`.
|
|
178
|
-
| `Drawer` | Panel from the side or bottom for details and edit forms. Use `Modal` for short focused dialogs. | Model: `v-model:open`. Props: `title`, `description`, `side` (left, right, bottom), `size` (sm to xl, full), `dismissible`, `hideClose`, `flush`, `loading`, `beforeClose(reason)`. Slots like `Modal`. Events: `open`, `close`, `afterLeave`.
|
|
179
|
-
| `ConfirmDialog` | Declarative confirm dialog. Prefer `useConfirm()`. Use this one only when the dialog state lives in the template. | Model: `v-model:open`. Props: `title`, `description`, `confirmLabel`, `cancelLabel`, `tone`, `icon`, `hideCancel`, `onConfirm`. Events: `resolve(confirmed)`, `cancel`, `afterLeave`.
|
|
180
|
-
| `ConfirmHost` | Renders the dialogs of `useConfirm`, `useAlert`, `usePrompt`. `OverlayHost` includes it. Do not mount it alone. | None.
|
|
181
|
-
| `OverlayHost` | One mount point for toasts, confirm dialogs, programmatic modals and loading indicators. | Props: `toaster` (true or options), `confirm`, `modals`, `loading` (true or `{ bar, delay, label }`).
|
|
182
|
-
| `Toaster` | Renders toasts. `OverlayHost` includes it. Use it directly only for custom options. The stack moves out of the way of an open side Drawer (beside it, or above its footer). | Props: `position`, `max`, `duration`, `gap`, `expand`, `progress`, `hotkey`.
|
|
183
|
-
| `DropdownMenu` | Menu opened by its trigger. Items can have icons, shortcuts, checkboxes, radios, sub menus and links. | Model: `v-model:open`. Props: `items` (`label`, `icon`, `to`, `href`, `tone: danger`, `shortcut`, `disabled`, `children`, `onSelect`; also `type`: checkbox, radio, label, separator), `placement`, `offset`, `matchTriggerWidth`, `minWidth`. Slot: default (the trigger). Event: `select`.
|
|
184
|
-
| `ContextMenu` | Menu on right click of the wrapped area. | Model: `v-model:open`. Props: `items` (same as `DropdownMenu`), `disabled`. Slot: default (the area). Event: `select`.
|
|
185
|
-
| `Popover` | Floating panel with any content (a form, filters) opened by its trigger. Use `DropdownMenu` for a list of actions. | Model: `v-model:open`. Props: `placement`, `offset`, `arrow`, `label`, `initialFocus`. Slots: default (the trigger), `content`.
|
|
186
|
-
| `HoverCard` | Rich preview on hover or focus (user card, link preview). Use `Tooltip` for plain text. | Model: `v-model:open`. Props: `placement`, `openDelay`, `closeDelay`, `arrow`, `disabled`. Slots: default (trigger), `content`.
|
|
187
|
-
| `Tooltip` | Short text on hover or focus. Optional shortcut. | Props: `text`, `placement`, `openDelay`, `closeDelay`, `arrow`, `shortcut`, `disabled`. Slots: default (trigger), `content`.
|
|
188
|
-
| `CommandPalette` | Search and command dialog (Cmd+K) with groups, recent items, async search and typed item data. | Models: `v-model:open`, `v-model:query`. Props: `groups` (items with `id`, `label`, `description`, `icon`, `shortcut`, `keywords`, `to`, `data`, `onSelect`), `search(query, signal)`, `shortcut`, `trigger`, `recentKey`, `emptyText`, `notice`. Slots: `item`, `empty`, `group-label`, `after-results`. Events: `select`, `open`, `close`.
|
|
179
|
+
| Component | Purpose and when to use it | Main props, models, slots, events | Playground |
|
|
180
|
+
| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ |
|
|
181
|
+
| `Modal` | Centered dialog for forms and content. Use `Drawer` for a side panel, `useConfirm` for a yes or no question. | Model: `v-model:open`. Props: `title`, `description`, `size` (sm to xl, full, fit, fullscreen), `width`, `minHeight`, `dismissible`, `hideClose`, `sheet`, `flush`, `loading`, `beforeClose(reason)`. Slots: default, `header`, `actions` (header, before the close button), `footer`, `title-trailing`. Events: `open`, `close`, `afterLeave`. | `overlays/modal.vue` |
|
|
182
|
+
| `Drawer` | Panel from the side or bottom for details and edit forms. Use `Modal` for short focused dialogs. | Model: `v-model:open`. Props: `title`, `description`, `side` (left, right, bottom), `size` (sm to xl, full), `dismissible`, `hideClose`, `flush`, `loading`, `beforeClose(reason)`. Slots like `Modal`. Events: `open`, `close`, `afterLeave`. | `overlays/drawer.vue` |
|
|
183
|
+
| `ConfirmDialog` | Declarative confirm dialog. Prefer `useConfirm()`. Use this one only when the dialog state lives in the template. | Model: `v-model:open`. Props: `title`, `description`, `confirmLabel`, `cancelLabel`, `tone`, `icon`, `hideCancel`, `onConfirm`. Events: `resolve(confirmed)`, `cancel`, `afterLeave`. | `overlays/confirm-dialog.vue` |
|
|
184
|
+
| `ConfirmHost` | Renders the dialogs of `useConfirm`, `useAlert`, `usePrompt`. `OverlayHost` includes it. Do not mount it alone. | None. | - |
|
|
185
|
+
| `OverlayHost` | One mount point for toasts, confirm dialogs, programmatic modals and loading indicators. | Props: `toaster` (true or options), `confirm`, `modals`, `loading` (true or `{ bar, delay, label }`). | `overlays/hooks.vue` |
|
|
186
|
+
| `Toaster` | Renders toasts. `OverlayHost` includes it. Use it directly only for custom options. The stack moves out of the way of an open side Drawer (beside it, or above its footer). | Props: `position`, `max`, `duration`, `gap`, `expand`, `progress`, `hotkey`. | `overlays/toast.vue` |
|
|
187
|
+
| `DropdownMenu` | Menu opened by its trigger. Items can have icons, shortcuts, checkboxes, radios, sub menus and links. | Model: `v-model:open`. Props: `items` (`label`, `icon`, `to`, `href`, `tone: danger`, `shortcut`, `disabled`, `children`, `onSelect`; also `type`: checkbox, radio, label, separator), `placement`, `offset`, `matchTriggerWidth`, `minWidth`. Slot: default (the trigger). Event: `select`. | `overlays/dropdown-menu.vue` |
|
|
188
|
+
| `ContextMenu` | Menu on right click of the wrapped area. | Model: `v-model:open`. Props: `items` (same as `DropdownMenu`), `disabled`. Slot: default (the area). Event: `select`. | `overlays/context-menu.vue` |
|
|
189
|
+
| `Popover` | Floating panel with any content (a form, filters) opened by its trigger. Use `DropdownMenu` for a list of actions. | Model: `v-model:open`. Props: `placement`, `offset`, `arrow`, `label`, `initialFocus`. Slots: default (the trigger), `content`. | `overlays/popover.vue` |
|
|
190
|
+
| `HoverCard` | Rich preview on hover or focus (user card, link preview). Use `Tooltip` for plain text. | Model: `v-model:open`. Props: `placement`, `openDelay`, `closeDelay`, `arrow`, `disabled`. Slots: default (trigger), `content`. | `overlays/hover-card.vue` |
|
|
191
|
+
| `Tooltip` | Short text on hover or focus. Optional shortcut. | Props: `text`, `placement`, `openDelay`, `closeDelay`, `arrow`, `shortcut`, `disabled`. Slots: default (trigger), `content`. | `overlays/tooltip.vue` |
|
|
192
|
+
| `CommandPalette` | Search and command dialog (Cmd+K) with groups, recent items, async search and typed item data. | Models: `v-model:open`, `v-model:query`. Props: `groups` (items with `id`, `label`, `description`, `icon`, `shortcut`, `keywords`, `to`, `data`, `onSelect`), `search(query, signal)`, `shortcut`, `trigger`, `recentKey`, `emptyText`, `notice`. Slots: `item`, `empty`, `group-label`, `after-results`. Events: `select`, `open`, `close`. | `overlays/command-palette.vue` |
|
|
189
193
|
|
|
190
194
|
## Data
|
|
191
195
|
|
|
@@ -224,7 +228,7 @@ Mount `OverlayHost` once for the imperative hooks (see [Composables](#composable
|
|
|
224
228
|
| `ThemeSwitch` | Light, dark and system switch. | Props: `variant` (segmented, icon), `size`, `showLabels`. | `layout/theme-switch.vue` |
|
|
225
229
|
| `NavLink` | One navigation link with icon, badge and active state. | Props: `label`, `to`, `href`, `icon`, `badge`, `active`, `match` (exact, prefix), `external`, `disabled`. Slots: default, `icon`. | `layout/nav-link.vue` |
|
|
226
230
|
| `AppShell` | App frame: sidebar, topbar, mobile menu, collapse, skip link. Use it for a custom frame. Use `DashboardLayout` for the ready one. | Models: `v-model:collapsed`, `v-model:open`. Props: `variant` (inset, sidebar, floating), `content` (`page`, `fill`, `centered`, `bleed`), `fluid`, `fill`, `topbar`, `storageKey`, `shortcut`. Slots: default, `sidebar`, `topbar`, `overlays`. | `layout/app-shell.vue` |
|
|
227
|
-
| `Sidebar` | Sidebar content with header, collapse button and footer. Goes in the `sidebar` slot of `AppShell`. | Props: `label`, `collapsible
|
|
231
|
+
| `Sidebar` | Sidebar content with header, collapse button and footer. Goes in the `sidebar` slot of `AppShell`. | Props: `label`, `collapsible`, `collapseLabel`, `brandAlign` (`start`, `center`). Icons `sidebar-collapse` and `sidebar-expand` for the collapse button. Slots: default, `header`, `top`, `footer`. | `layout/app-shell.vue` |
|
|
228
232
|
| `SidebarNav` | Navigation list from data, with groups and children. | Props: `items` (`NavItem[]` or `NavSection[]`: `label`, `to`, `icon`, `badge`, `children`), `currentPath`. | `layout/app-shell.vue` |
|
|
229
233
|
| `SidebarSection` | Labelled block inside a sidebar for hand written links. | Prop: `label`. Slot: default. | `layout/app-shell.vue` |
|
|
230
234
|
|
|
@@ -244,25 +248,25 @@ Mount `OverlayHost` once for the imperative hooks (see [Composables](#composable
|
|
|
244
248
|
|
|
245
249
|
Templates combine core parts into whole pages and layouts. Start from them for new pages.
|
|
246
250
|
|
|
247
|
-
| Component | Purpose and when to use it | Main props, models, slots, events
|
|
248
|
-
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
249
|
-
| `DashboardLayout` | Ready app frame: brand, navigation, command search, account menu, settings modal, breadcrumbs, theme switch. Put it in `layouts/default.vue`. | Models: `v-model:collapsed`, `v-model:open`, `v-model:settingsOpen`, `v-model:settingsSection`. Props: `navigation` (`NavItem[]` or `NavSection[]`), `account` (`name`, `email`, `avatar`, `role`, `menu`), `brandName`, `brandIcon`, `brandLogo`, `breadcrumbs`, `search` (true, groups or function), `settingsSections`, `variant`, `content` (`page`, `fill`, `centered`, `bleed`; per page with `definePageMeta({ content })` in `k-dashboard`), `fluid`, `fill`, `onSignOut`. Slots: default, `actions`, `brand`, `sidebar`, `sidebar-footer`, `account`, `topbar`, `search-item`, `settings-account-fields
|
|
250
|
-
| `AuthLayout` | Login, sign up and reset password frame. Centered card or split with aside. | Props: `variant` (centered, split), `title`, `description`, `footer`, `brandName`, `brandIcon`, `brandLogo`, `asideTitle`, `asideDescription`, `themeSwitch`. Slots: default, `links`, `footer`, `brand`, `aside`, `corner`.
|
|
251
|
-
| `ListPage` | Whole list page: header, search, filters, table, pagination, bulk actions, loading, empty, no results and error states. Client or server mode (`total`). | Models: `page`, `pageSize`, `search`, `filter`, `sort`, `selected`. Props: `title`, `rows`, `columns`, `rowKey`, `rowTo`, `selectable`, `loading`, `error`, `total`, `paginate`, `searchable`, `searchKeys`, `filters`, `filterKey`, `filterMultiple`, `emptyTitle`. Slots: `actions`, `toolbar`, `toolbar-end`, `bulk`, `empty`, `empty-actions`, `no-results`, `error`, `cell-<key>`, `table`. Events: `retry`, `clear`, `rowClick`.
|
|
252
|
-
| `DetailPage` | Record page: back link, title, status, actions, tabs, main column and aside with description lists. | Model: `v-model:tab`. Props: `title`, `backTo`, `backLabel`, `status` (`label`, `tone`, `dot`), `tabs`, `sections` (`title`, `items`), `loading`, `error`. Slots: default, `actions`, `badge`, `meta`, `aside`, `aside-before`, `panel-<value>`.
|
|
253
|
-
| `FormPage` | Form page: header, cards in a `Form`, sticky submit and cancel footer, dirty guard. | Props: `title`, `backTo`, `form` (from `useForm`), `dirty`, `saving`, `guard`, `requireDirty`, `submitLabel`, `cancelLabel`, `cancelTo`, `width`, `sticky`. Slots: default, `actions`, `footer`, `status`. Events: `submit`, `submitted`, `invalid`, `reset`, `cancel`.
|
|
254
|
-
| `DashboardPage` | Overview page: header, stat grid, content grid. | Props: `title`, `eyebrow`, `description`, `stats` (`PageStat[]`), `statsColumns`, `columns`, `loading`. Slots: default, `actions`, `stats`, `sparkline`, `before`, `after`, `eyebrow`.
|
|
255
|
-
| `SettingsPage` | Settings as a page: section nav, panels, floating save bar when `dirty`. | Model: `v-model:section`. Props: `title`, `sections` (`value`, `label`, `icon`, `to`), `dirty`, `saving`, `saveBar`, `form`. Slots: `section-<value>`, `actions`, `nav-footer`. Events: `save`, `discard`.
|
|
256
|
-
| `SettingsSection` | Card of one settings section with a save footer. | Props: `title`, `description`, `icon`, `hint`, `saveable`, `saving`, `saveDisabled`, `saveLabel`, `form`. Slots: default, `actions`, `footer`, `hint`. Event: `save`.
|
|
257
|
-
| `SettingsGroup` | Block with label, description and actions inside a settings section. | Props: `label`, `description`, `level`, `row`. Slots: default, `label`, `description`, `actions`.
|
|
258
|
-
| `SettingsModal` | Settings dialog with nav, built-in account and appearance sections, your own sections and subpages. | Models: `v-model:open`, `v-model:section`, `v-model:pages`. Props: `sections` (`id`, `label`, `icon`, `group`, `badge`, `to`), `account`, `presets`, `title`, `onSignOut`, `hideSession`, `beforeClose`. Slots: `section-<id>`, `actions-<id
|
|
259
|
-
| `AppearanceSettings` | Theme (light, dark, system) and preset cards. Used by `SettingsModal`. Use alone in a settings page. | Props: `presets` (list or false), `themes`, `level`.
|
|
260
|
-
| `SaveBar` | Floating bar with save and discard for unsaved changes. | Props: `visible`, `saving`, `message`, `saveLabel`, `discardLabel`, `form`. Slots: default, `actions`. Events: `save`, `discard`.
|
|
261
|
-
| `EmptyPage` | First run screen with illustration, actions and onboarding steps. | Props: `title`, `description`, `icon`, `actionLabel`, `actionTo`, `onAction`, `secondaryLabel`, `steps` (`title`, `description`, `done`, `to`), `fill`. Slots: default, `illustration`, `title`, `description`, `actions`.
|
|
262
|
-
| `ErrorPage` | Error screen. Reads a Nuxt `error`. Use it in `app/error.vue`. | Props: `error`, `statusCode`, `title`, `message`, `homeTo`, `homeLabel`, `retryLabel`, `brandName`, `fill`, `onHome`, `onRetry`. Slots: default, `title`, `message`, `actions`, `brand`.
|
|
263
|
-
| `NotFoundPage` | 404 screen. | Props: `title`, `message`, `homeTo`, `homeLabel`, `backLabel`, `brandName`, `fill`, `onHome`. Slots: default, `actions`, `brand`.
|
|
264
|
-
| `Brand` | Logo and name block (image URL, inline SVG or component). | Props: `name`, `subtitle`, `icon`, `logo`, `to`, `size`, `accent`, `hideText`, `showName`. Slots: default, `logo`, `mark`, `subtitle`.
|
|
265
|
-
| `AccountMenu` | Account button with avatar, name and a dropdown menu. Used by `DashboardLayout`. | Props: `name`, `email`, `avatar`, `menu` (menu items), `placement`, `icon`. Event: `select`.
|
|
251
|
+
| Component | Purpose and when to use it | Main props, models, slots, events | Playground |
|
|
252
|
+
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------- |
|
|
253
|
+
| `DashboardLayout` | Ready app frame: brand, navigation, command search, account menu, settings modal, breadcrumbs, theme switch. Put it in `layouts/default.vue`. | Models: `v-model:collapsed`, `v-model:open`, `v-model:settingsOpen`, `v-model:settingsSection`. Props: `navigation` (`NavItem[]` or `NavSection[]`), `account` (`name`, `email`, `avatar`, `role`, `menu`), `brandName`, `brandIcon`, `brandLogo`, `breadcrumbs`, `search` (true, groups or function), `settingsSections`, `settingsRoute`, `settingsResolvePage`, `variant`, `content` (`page`, `fill`, `centered`, `bleed`; per page with `definePageMeta({ content })` in `k-dashboard`), `fluid`, `fill`, `onSignOut`. Slots: default, `actions`, `brand`, `sidebar`, `sidebar-footer`, `account`, `topbar`, `search-item`, `settings-account-fields`, `settings-section-<id>`, `settings-actions-<id>`. Event: `accountSelect`. | `templates/dashboard-layout.vue` |
|
|
254
|
+
| `AuthLayout` | Login, sign up and reset password frame. Centered card or split with aside. | Props: `variant` (centered, split), `title`, `description`, `footer`, `brandName`, `brandIcon`, `brandLogo`, `asideTitle`, `asideDescription`, `themeSwitch`. Slots: default, `links`, `footer`, `brand`, `aside`, `corner`. | `templates/auth-layout.vue` |
|
|
255
|
+
| `ListPage` | Whole list page: header, search, filters, table, pagination, bulk actions, loading, empty, no results and error states. Client or server mode (`total`). | Models: `page`, `pageSize`, `search`, `filter`, `sort`, `selected`. Props: `title`, `rows`, `columns`, `rowKey`, `rowTo`, `selectable`, `loading`, `error`, `total`, `paginate`, `searchable`, `searchKeys`, `filters`, `filterKey`, `filterMultiple`, `emptyTitle`. Slots: `actions`, `toolbar`, `toolbar-end`, `bulk`, `empty`, `empty-actions`, `no-results`, `error`, `cell-<key>`, `table`. Events: `retry`, `clear`, `rowClick`. | `templates/list-page.vue` |
|
|
256
|
+
| `DetailPage` | Record page: back link, title, status, actions, tabs, main column and aside with description lists. | Model: `v-model:tab`. Props: `title`, `backTo`, `backLabel`, `status` (`label`, `tone`, `dot`), `tabs`, `sections` (`title`, `items`), `loading`, `error`. Slots: default, `actions`, `badge`, `meta`, `aside`, `aside-before`, `panel-<value>`. | `templates/detail-page.vue` |
|
|
257
|
+
| `FormPage` | Form page: header, cards in a `Form`, sticky submit and cancel footer, dirty guard. | Props: `title`, `backTo`, `form` (from `useForm`), `dirty`, `saving`, `guard`, `requireDirty`, `submitLabel`, `cancelLabel`, `cancelTo`, `width`, `sticky`. Slots: default, `actions`, `footer`, `status`. Events: `submit`, `submitted`, `invalid`, `reset`, `cancel`. | `templates/form-page.vue` |
|
|
258
|
+
| `DashboardPage` | Overview page: header, stat grid, content grid. | Props: `title`, `eyebrow`, `description`, `stats` (`PageStat[]`), `statsColumns`, `columns`, `loading`. Slots: default, `actions`, `stats`, `sparkline`, `before`, `after`, `eyebrow`. | `templates/dashboard-page.vue` |
|
|
259
|
+
| `SettingsPage` | Settings as a page: section nav, panels, floating save bar when `dirty`. | Model: `v-model:section`. Props: `title`, `sections` (`value`, `label`, `icon`, `to`), `dirty`, `saving`, `saveBar`, `form`. Slots: `section-<value>`, `actions`, `nav-footer`. Events: `save`, `discard`. | `templates/settings-page.vue` |
|
|
260
|
+
| `SettingsSection` | Card of one settings section with a save footer. | Props: `title`, `description`, `icon`, `hint`, `saveable`, `saving`, `saveDisabled`, `saveLabel`, `form`. Slots: default, `actions`, `footer`, `hint`. Event: `save`. | `templates/settings-page.vue` |
|
|
261
|
+
| `SettingsGroup` | Block with label, description and actions inside a settings section. | Props: `label`, `description`, `level`, `row`. Slots: default, `label`, `description`, `actions`. | `templates/settings-modal.vue` |
|
|
262
|
+
| `SettingsModal` | Settings dialog with nav, built-in account and appearance sections, your own sections and subpages. | Models: `v-model:open`, `v-model:section`, `v-model:pages`. Props: `sections` (`id`, `label`, `icon`, `group`, `badge`, `to`), `account`, `presets`, `title`, `onSignOut`, `hideSession`, `beforeClose`, `route` (sync with `?settings=<section>/<page>`), `resolvePage(section, id, parents)`. Slots: `section-<id>`, `actions-<id>` (right of the header row, also on a subpage), `account-fields`. | `templates/settings-modal.vue` |
|
|
263
|
+
| `AppearanceSettings` | Theme (light, dark, system) and preset cards. Used by `SettingsModal`. Use alone in a settings page. | Props: `presets` (list or false), `themes`, `level`. | `presets.vue` (pages root) |
|
|
264
|
+
| `SaveBar` | Floating bar with save and discard for unsaved changes. | Props: `visible`, `saving`, `message`, `saveLabel`, `discardLabel`, `form`. Slots: default, `actions`. Events: `save`, `discard`. | `templates/settings-page.vue` |
|
|
265
|
+
| `EmptyPage` | First run screen with illustration, actions and onboarding steps. | Props: `title`, `description`, `icon`, `actionLabel`, `actionTo`, `onAction`, `secondaryLabel`, `steps` (`title`, `description`, `done`, `to`), `fill`. Slots: default, `illustration`, `title`, `description`, `actions`. | `templates/empty-page.vue` |
|
|
266
|
+
| `ErrorPage` | Error screen. Reads a Nuxt `error`. Use it in `app/error.vue`. | Props: `error`, `statusCode`, `title`, `message`, `homeTo`, `homeLabel`, `retryLabel`, `brandName`, `fill`, `onHome`, `onRetry`. Slots: default, `title`, `message`, `actions`, `brand`. | `templates/error-page.vue` |
|
|
267
|
+
| `NotFoundPage` | 404 screen. | Props: `title`, `message`, `homeTo`, `homeLabel`, `backLabel`, `brandName`, `fill`, `onHome`. Slots: default, `actions`, `brand`. | `templates/error-page.vue` |
|
|
268
|
+
| `Brand` | Logo and name block (image URL, inline SVG or component). | Props: `name`, `subtitle`, `icon`, `logo`, `to`, `size`, `accent`, `hideText`, `showName`. Slots: default, `logo`, `mark`, `subtitle`. | `templates/dashboard-layout.vue` |
|
|
269
|
+
| `AccountMenu` | Account button with avatar, name and a dropdown menu. Used by `DashboardLayout`. | Props: `name`, `email`, `avatar`, `menu` (menu items), `placement`, `icon`. Event: `select`. | `templates/dashboard-layout.vue` |
|
|
266
270
|
|
|
267
271
|
Nuxt ready layouts: with `k: { layouts: true }` the module registers the layouts `k-dashboard` and `k-auth`. They read brand, navigation, account and settings from `app.config.ts` (`k` key). `useDashboard()` gives the runtime account, breadcrumbs and badges for `k-dashboard`. See README, section "Nuxt: ready layouts".
|
|
268
272
|
|
|
@@ -270,12 +274,12 @@ Nuxt ready layouts: with `k: { layouts: true }` the module registers the layouts
|
|
|
270
274
|
|
|
271
275
|
Import from `@xleddyl/443-components-vue/grid`. It wraps AG Grid Community.
|
|
272
276
|
|
|
273
|
-
| Component | Purpose and when to use it | Main props, models, slots, events
|
|
274
|
-
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
275
|
-
| `DataGrid` | Big table: virtual scroll, column menu, search, CSV export, selection, server sort and paging, inline editing. For small tables use `Table`. | Models: `v-model:query`, `v-model:page`, `v-model:pageSize`, `v-model:sort` (`{ column, direction }`). Props: `rows`, `columns` (AG Grid `ColDef`), `rowIdKey` or `getRowId`, `storageKey`, `density`, `selectable`, `loading`, `height`, `fill`, `autoHeight`, `toolbar`, `searchable`, `columnMenu`, `exportable`, `serverSort`, `pagination`, `serverPagination`, `total`, `filterable`, `editable`, `spreadsheet`, `gridOptions`, `messages`.
|
|
276
|
-
| `DataGrid` with `spreadsheet` | Excel-like editing: cell range selection, copy and paste (TSV), fill down and right, clear, undo and redo, dirty cell tracking. Set `rowIdKey` or `getRowId`. | Template ref methods (`GridSpreadsheetMethods`): `getRange`, `getSelectedCells`, `selectRange`, `selectAll`, `setRangeValue`, `copyRange`, `paste`, `fillDown`, `fillRight`, `clearCells`, `undo`, `redo`, `getDirtyCells`, `clearDirty`. The `actions` slot gets the same methods plus `range`, `selectedCellCount`, `dirtyCount`, `canUndo`, `canRedo`. Use `cellsChange` to save edits, `cellsInvalid` for rejected input.
|
|
277
|
-
| `GridToolbar` | Toolbar of `DataGrid` (search, column menu, export). `DataGrid` already renders it. Use it alone only for a custom grid setup. | Props: `api`, `searchable`, `columnMenu`, `exportable`, `exportFileName`, `debounce`. Model: `v-model` (query).
|
|
278
|
-
| Cell renderers | Use as `cellRenderer` in a column definition, with `cellRendererParams`. | `BadgeCell` (`tones`, `labels`, `defaultTone`, `variant`; array values render one badge each, `max` adds a `+N` badge, `wrap`), `BooleanCell` (`trueLabel`, `falseLabel`), `DateCell` (`locale`, `options`, `relative`), `EmptyCell` (placeholder for empty values), `ImageCell` (`alt`, `rounded`, `fit`, `size`), `LinkCell` (`href`, `label`, `target`).
|
|
277
|
+
| Component | Purpose and when to use it | Main props, models, slots, events | Playground |
|
|
278
|
+
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- |
|
|
279
|
+
| `DataGrid` | Big table: virtual scroll, column menu, search, CSV export, selection, server sort and paging, inline editing. For small tables use `Table`. | Models: `v-model:query`, `v-model:page`, `v-model:pageSize`, `v-model:sort` (`{ column, direction }`). Props: `rows`, `columns` (AG Grid `ColDef`), `rowIdKey` or `getRowId`, `storageKey`, `density`, `selectable`, `loading`, `height`, `fill`, `autoHeight`, `toolbar`, `searchable`, `columnMenu`, `exportable`, `serverSort`, `pagination`, `serverPagination`, `total`, `filterable`, `editable`, `spreadsheet`, `gridOptions`, `messages`, `filterCount`. Slots: `actions`, `filters` (`{ close, count }`, hosted in a modal opened by a funnel button next to the search). Events: `filtersReset`, `rowClick`, `selectionChange`, `sortChange`, `filterChange`, `cellsChange`, `cellsInvalid`, `dirtyChange`, `rangeChange`, `copy`. | `grid/data-grid.vue` |
|
|
280
|
+
| `DataGrid` with `spreadsheet` | Excel-like editing: cell range selection, copy and paste (TSV), fill down and right, clear, undo and redo, dirty cell tracking. Set `rowIdKey` or `getRowId`. | Template ref methods (`GridSpreadsheetMethods`): `getRange`, `getSelectedCells`, `selectRange`, `selectAll`, `setRangeValue`, `copyRange`, `paste`, `fillDown`, `fillRight`, `clearCells`, `undo`, `redo`, `getDirtyCells`, `clearDirty`. The `actions` slot gets the same methods plus `range`, `selectedCellCount`, `dirtyCount`, `canUndo`, `canRedo`. Use `cellsChange` to save edits, `cellsInvalid` for rejected input. | `grid/spreadsheet.vue` |
|
|
281
|
+
| `GridToolbar` | Toolbar of `DataGrid` (search, column menu, export). `DataGrid` already renders it. Use it alone only for a custom grid setup. | Props: `api`, `searchable`, `columnMenu`, `exportable`, `exportFileName`, `debounce`, `filterCount`. Model: `v-model` (query). Slots: default (actions), `filters`. Events: `resetColumns`, `filtersReset`. | - |
|
|
282
|
+
| Cell renderers | Use as `cellRenderer` in a column definition, with `cellRendererParams`. | `BadgeCell` (`tones`, `labels`, `defaultTone`, `variant`; array values render one badge each, `max` adds a `+N` badge, `wrap`), `BooleanCell` (`trueLabel`, `falseLabel`), `DateCell` (`locale`, `options`, `relative`), `EmptyCell` (placeholder for empty values), `ImageCell` (`alt`, `rounded`, `fit`, `size`), `LinkCell` (`href`, `label`, `target`). | `grid/data-grid.vue` |
|
|
279
283
|
|
|
280
284
|
Grid helpers: `registerGridModules`, `registerGridEditorModules`, `registerGridFilterModules`, `registerGridSpreadsheetModules` (register AG Grid modules by hand), `createGridTheme`, `parseTsv`, `formatTsv`.
|
|
281
285
|
|
|
@@ -325,6 +329,7 @@ All are exported from `@xleddyl/443-components-vue` and auto-imported in Nuxt.
|
|
|
325
329
|
| `useTheme` | Read or set the theme preference (system, light, dark). | `const { preference, resolved, set } = useTheme()`. Nuxt module stores it in a cookie. | `layout/theme-switch.vue` |
|
|
326
330
|
| `usePreset` | Read or set the visual preset. | `presetOptions` lists the presets. | `presets.vue` (pages root) |
|
|
327
331
|
| `useAppShell` | Read the `AppShell` state (collapsed, open) from a child component. | Returns the shell context or `null` outside a shell. | `layout/app-shell.vue` |
|
|
332
|
+
| `useRouteState` | Bind a ref to a URL query parameter: deep links to drawers and modals, back button closes them, filters in the URL. | `useRouteState(key, { parse, serialize, default, history: 'push' \| 'replace' })`. Returns a ref; `undefined` or `''` removes the parameter. No-op without a router. | `overlays/drawer.vue` |
|
|
328
333
|
| `useScrollLock` | Lock the page scroll while something is open. | `useScrollLock(activeRef)`. | - |
|
|
329
334
|
| `useLocale` | Translate component texts and read the active locale (en, it, de). | `const { locale, t } = useLocale()`. `provideLocale` and `createLocale` set it. Nuxt follows `k.locale`. | `languages.vue` (pages root) |
|
|
330
335
|
| `useIcons` helpers, `createIcons`, `provideIcons` | Register your own icons by name. | Nuxt: option `k.icons: { dir: '~/assets/icons' }`. | `components/core/icon.vue` |
|
package/README.md
CHANGED
|
@@ -136,7 +136,7 @@ A few component tokens are unset by default and only exist to be overridden on a
|
|
|
136
136
|
| Fields | `--k-field-padding-x` |
|
|
137
137
|
| Overlays | `--k-modal-radius`, `--k-modal-shadow`, `--k-drawer-radius`, `--k-drawer-shadow`, `--k-popover-radius`, `--k-popover-shadow`, `--k-toast-radius`, `--k-toast-shadow`, `--k-scrim-blur` (3px) |
|
|
138
138
|
| Tooltip | `--k-tooltip-background`, `--k-tooltip-text`, `--k-tooltip-border`, `--k-tooltip-radius`, `--k-tooltip-shadow`, `--k-tooltip-padding` |
|
|
139
|
-
| Shell | `--k-sidebar-width` (
|
|
139
|
+
| Shell | `--k-sidebar-width` (16.5rem), `--k-sidebar-rail-width`, `--k-topbar-height` (3rem), `--k-shell-inset`, `--k-shell-padding`, `--k-shell-content` |
|
|
140
140
|
| Switch | `--k-switch-track-width`, `--k-switch-track-height`, `--k-switch-thumb-size` (md size) |
|
|
141
141
|
| Separator | `--k-separator-heading-font-size` (0.9375rem), `--k-separator-heading-color` (`--k-text`), `--k-separator-label-font-size` (0.75rem) |
|
|
142
142
|
| Calendar | `--k-calendar-day-radius`, `--k-calendar-unavailable-color`, `--k-calendar-unavailable-decoration` (line-through), `--k-calendar-unavailable-opacity` (0.6), `--k-calendar-out-of-range-color`, `--k-calendar-out-of-range-decoration`, `--k-calendar-out-of-range-opacity` (each defaults to its unavailable token) |
|
|
@@ -358,7 +358,7 @@ Several controls in one `FormField`. Only the primary control takes the field id
|
|
|
358
358
|
| editor | RichTextEditor |
|
|
359
359
|
| chart | ChartPanel, ChartLegend, LineChart, BarChart, DoughnutChart |
|
|
360
360
|
|
|
361
|
-
Composables: `useTheme`, `usePreset`, `useForm`, `useField`, `useFieldControl`, `useToast` (and `toast`), `useConfirm`, `useAlert`, `usePrompt`, `useModal`, `useDrawer`, `useOverlay`, `useModalContext`, `useLoading` (and `withLoading`), `useLoadingState`, `useHotkey`, `useCopy`, `useFileDrop` (with `readDroppedFiles`), `useSortable`, `usePasswordStrength`, `useTableSort`, `useAppShell`, `useScrollLock`, `useDirtyGuard`, `useIcons` helpers and `useLinkComponent`, `provideFieldBoundary`, `provideAuxiliaryControls`, `provideForm`, `useLocale`. With the Nuxt module also `useDashboard()` (runtime account, breadcrumbs and badges for the `k-dashboard` layout).
|
|
361
|
+
Composables: `useTheme`, `usePreset`, `useForm`, `useField`, `useFieldControl`, `useToast` (and `toast`), `useConfirm`, `useAlert`, `usePrompt`, `useModal`, `useDrawer`, `useOverlay`, `useModalContext`, `useLoading` (and `withLoading`), `useLoadingState`, `useHotkey`, `useCopy`, `useFileDrop` (with `readDroppedFiles`), `useSortable`, `usePasswordStrength`, `useTableSort`, `useAppShell`, `useRouteState`, `useScrollLock`, `useDirtyGuard`, `useIcons` helpers and `useLinkComponent`, `provideFieldBoundary`, `provideAuxiliaryControls`, `provideForm`, `useLocale`. With the Nuxt module also `useDashboard()` (runtime account, breadcrumbs and badges for the `k-dashboard` layout).
|
|
362
362
|
|
|
363
363
|
### Lists, trees and uploads
|
|
364
364
|
|
|
@@ -475,9 +475,47 @@ const confirmDiscard = () => !dirty.value || confirm({ title: 'Discard changes?'
|
|
|
475
475
|
```
|
|
476
476
|
|
|
477
477
|
- `#title-trailing` puts badges or a status next to the title without replacing `#header`.
|
|
478
|
+
- `#actions` (`{ close }`) puts buttons in the header, on the right before the close button (an edit or a more menu), without replacing `#header`.
|
|
478
479
|
- `size="fullscreen"` on a Modal fills the viewport edge to edge (no radius, no outer padding, safe area insets inside the panel) and never turns into a bottom sheet.
|
|
479
480
|
- Overlays reset the field context: controls inside a Modal, Drawer, CommandPalette, menu, Popover or HoverCard panel do not inherit the id, description or invalid state of a `FormField` that contains the trigger. Call `provideFieldBoundary()` in your own overlay components to do the same.
|
|
480
481
|
|
|
482
|
+
### Deep links
|
|
483
|
+
|
|
484
|
+
`useRouteState(key, options?)` binds a ref to one query parameter of the current URL, so any Drawer or Modal can be opened from a link, survives a reload and closes with the browser back button. It reads the router through `$router` (vue-router or Nuxt, no import of either); without a router it is a plain ref.
|
|
485
|
+
|
|
486
|
+
```ts
|
|
487
|
+
const familyId = useRouteState('family')
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
```vue
|
|
491
|
+
<KButton icon="plus" @click="familyId = 'new'">New family</KButton>
|
|
492
|
+
<KDrawer
|
|
493
|
+
:open="!!familyId"
|
|
494
|
+
:title="familyId === 'new' ? 'New family' : family?.name"
|
|
495
|
+
@update:open="familyId = undefined"
|
|
496
|
+
>
|
|
497
|
+
<FamilyForm :id="familyId === 'new' ? undefined : familyId" />
|
|
498
|
+
</KDrawer>
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
- Reading: the initial value comes from the URL (on the server too, so SSR renders the same state), and the ref follows every later route change (back, forward, links).
|
|
502
|
+
- Writing: setting the ref navigates with `router.push` (default) or `router.replace` (`history: 'replace'`, for filters or tabs that should not add history entries). The path and the other query parameters stay. `undefined`, `null` and `''` remove the parameter. Several refs changed in the same tick make one navigation. A push that returns to the previous history entry goes back instead (`router.back()`), so opening then closing a drawer leaves the history as it was, and the browser back button and the in-app close button agree.
|
|
503
|
+
- Types: `parse(value)` and `serialize(value)` convert the string (`parse` returning `undefined` means no value). `default` gives the value when the parameter is missing, and setting the default removes the parameter:
|
|
504
|
+
|
|
505
|
+
```ts
|
|
506
|
+
const page = useRouteState('page', { parse: Number, default: 1, history: 'replace' })
|
|
507
|
+
const archived = useRouteState('archived', {
|
|
508
|
+
parse: (value) => value === '1',
|
|
509
|
+
serialize: (value) => (value ? '1' : undefined),
|
|
510
|
+
default: false,
|
|
511
|
+
})
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
- Create forms: use a reserved value (`?family=new`) and branch on it, like above.
|
|
515
|
+
- Nested views inside one overlay: keep the path in one parameter (`?settings=users/usr_123`, `?family=fam_1/variants`) and split it on `/` in a computed. One parameter keeps every step in one history entry and avoids two refs racing. Encode ids that may contain `/` with `encodeURIComponent` per segment.
|
|
516
|
+
- Pages that set `definePageMeta({ key: (route) => route.fullPath })` remount on every query change; keep the default page key for pages with deep links.
|
|
517
|
+
- To leave the page from inside an overlay, navigate (a link or `router.push`): the new route has no parameter, so the overlay closes. Do not set the ref to `undefined` and navigate in the same tick: the later navigation cancels the earlier one.
|
|
518
|
+
|
|
481
519
|
`CommandPalette`: items take typed `data` (`CommandItem<T>`, `CommandGroup<T>`), which reaches the `#item` slot and the `select` event typed; `emptyText` also takes `(query) => string`. Groups take a `description` (shown after the label), the `#group-label` slot (`{ group, label, description, recent }`) replaces the label, and `notice` or the `#after-results` slot (`{ query, count }`) adds a line under the results, for example "Showing the first results".
|
|
482
520
|
|
|
483
521
|
- `Brand`: `logo` takes an image URL, trusted inline SVG markup (`'<svg ...>'`) or a component; the `#logo` slot replaces the boxed mark; `show-name` keeps the name visible next to a logo.
|
|
@@ -510,9 +548,10 @@ Ready defaults to start a dashboard project: an app frame, an auth frame and pag
|
|
|
510
548
|
| `variant` | `'inset'` | `inset` (canvas sidebar, inset content panel), `sidebar` (bordered sidebar, full bleed content), `floating` (raised sidebar card on the canvas). |
|
|
511
549
|
| `navigation` | | `NavItem[]` or `NavSection[]` (`{ label?, items }`). Items: `label`, `to`/`href`, `icon`, `badge`, `exact`, `active`, `external`, `disabled`, `children`. |
|
|
512
550
|
| `currentPath` | router path | Active state is computed from the router (`$route`) with prefix matching (`/` and `exact` items match exactly). |
|
|
513
|
-
| `brandName`, `brandSubtitle`, `brandIcon`, `brandLogo`, `brandShowName`, `brandTo` | `brandTo: '/'` | `brandLogo` takes an image URL, inline SVG markup or a component; the name is hidden next to a logo unless `brandShowName`. Or the `#brand` slot.
|
|
551
|
+
| `brandName`, `brandSubtitle`, `brandIcon`, `brandLogo`, `brandShowName`, `brandTo` | `brandTo: '/'` | `brandLogo` takes an image URL, inline SVG markup or a component; the name is hidden next to a logo unless `brandShowName`. Or the `#brand` slot. `brandAlign` (`'start'` or `'center'`) centers the brand in the expanded sidebar, with the collapse button on the right. The collapse button uses the icons `sidebar-collapse` and `sidebar-expand` (chevrons by default), so `k.icons.aliases: { 'sidebar-collapse': 'lucide:panel-left-close', 'sidebar-expand': 'lucide:panel-left-open' }` changes only that button. |
|
|
514
552
|
| `account` | | `{ name, email?, avatar?, role?, menu? }`. Shown as a row (avatar, name, email, chevron) at the bottom of the sidebar. |
|
|
515
553
|
| `accountAction` | `'settings'` | `settings`: the row opens a `SettingsModal` (`settingsSections`, `settingsPresets`, `v-model:settings-open`, `v-model:settings-section`, `@sign-out`). `menu`: a DropdownMenu with `account.menu`, selections emit `account-select`. Or replace it with the `#account` slot. |
|
|
554
|
+
| `settingsRoute`, `settingsResolvePage` | `false` | Sync the settings modal with the URL (`?settings=users/usr_123`): `true` uses the key `settings`, a string sets the key. `settingsResolvePage(section, id, parents)` gives the label of a subpage restored from the URL. See SettingsModal. |
|
|
516
555
|
| `breadcrumbs` | | Rendered in the desktop topbar. `#topbar` replaces them, `#actions` adds buttons on the right. |
|
|
517
556
|
| `search` | `false` | `true` adds a CommandPalette with every navigation item, an array adds your own command groups, an async function `(query, signal) => CommandGroup<T>[]` searches on your server (item `data` reaches `#search-item` typed) (matching navigation items come first unless `searchNavigation` is `false`). `#search` replaces it. |
|
|
518
557
|
| `searchProps` | | Options for the built-in CommandPalette: `minQueryLength`, `debounce`, `placeholder`, `label`, `emptyText` (a string or `(query) => string`), `minQueryText`, `errorText`, `loadingText`, `resultsText`, `notice`, `recentKey`, footer labels. Slots `#search-item`, `#search-empty`, `#search-group-label` and `#search-after-results` reach the palette. |
|
|
@@ -559,7 +598,9 @@ A large dialog (60rem) with a section nav on the left and the content on the rig
|
|
|
559
598
|
- Built-in sections, used when no `#section-<id>` slot fills them: `account` (profile card, your `#account-fields`, a sign out button) and `appearance` (`AppearanceSettings`: theme cards light, dark, system and preset cards; `presets` limits or hides them).
|
|
560
599
|
- `@sign-out` adds a Sign out item at the bottom of the nav and in the account section.
|
|
561
600
|
- Labels: `title` (accessible name of the dialog, default `Settings`), `closeLabel`, `navLabel`, `signOutLabel`, `accountLabel`, `accountText`, `appearanceLabel`, `appearanceText`, `sessionLabel`, `sessionText`, `themeLabel`, `themeText`, `presetLabel`, `presetText`.
|
|
601
|
+
- Header actions: `#actions-<id>` renders buttons on the right of the section header row (an "Add user" button), next to the title instead of on a row of its own in the body. It stays there when a subpage is open, so render different actions per page from its `page` prop. When the content is too narrow, the actions wrap under the title. On `DashboardLayout` the slot is `#settings-actions-<id>`.
|
|
562
602
|
- Subpages: `#section-<id>` and `#actions-<id>` get `page`, `pages`, `openPage({ id, label })` and `back()`. With a page open, the header title becomes the path (`Members > Grace Hopper`, same size, only the last part in the text color, earlier parts are buttons that go back to them), the section description stays, and a Back button (`backLabel`, default `common.back`) shows on the right before `#actions-<id>`. `v-model:pages` binds the stack (it also works unbound). Changing section clears it. Render the detail when `page` is set, the list otherwise.
|
|
603
|
+
- Deep links: `route` (`true` for the key `settings`, or your own query key, default `false`) syncs the open state, the section and the subpage stack with the URL: `?settings=users` for a section, `?settings=users/usr_123` for a subpage, deeper pages add segments. Opening, switching section, opening a subpage, Back and the crumbs push history entries, so the browser back button steps back through them and finally closes the dialog; closing removes the parameter. Loading a URL with the parameter opens the dialog at that section and subpage after mount. A section id that is not selectable falls back to the first section and the URL is corrected with `replace`. The URL holds only page ids, so `resolvePage(section, id, parents)` returns the label of a page restored from the URL: a string, `undefined` (the page and the ones after it are dropped, the URL is corrected) or a promise of either (the page opens at once with an empty label, then the label fills in). Without `resolvePage` the label is the id. Pages opened with `openPage` keep their own label. Link sections (`to`) do not close the dialog themselves when the route is synced: the navigation drops the parameter and closes it. On `DashboardLayout` the props are `settingsRoute` and `settingsResolvePage`; in the `k-dashboard` layout `settings.route` in `app.config`.
|
|
563
604
|
- `hide-session` hides the Session group (sign out) in the account section; the Sign out item in the nav stays. `beforeClose` works as on Modal.
|
|
564
605
|
- Accessibility: native modal `<dialog>` (focus trap, Escape, focus returns to the trigger), the nav is a labelled `nav` of buttons with `aria-current` and `aria-controls`, the content is a `section` labelled by its heading.
|
|
565
606
|
|
|
@@ -661,7 +702,7 @@ export default defineAppConfig({
|
|
|
661
702
|
})
|
|
662
703
|
```
|
|
663
704
|
|
|
664
|
-
The account row opens the SettingsModal (`account.action: 'menu'` with `account.menu` for a dropdown instead). Sections from `app.config` can be built-ins or links (`to`); `settings.presets` limits the preset cards, `settings.signOutTo` adds Sign out.
|
|
705
|
+
The account row opens the SettingsModal (`account.action: 'menu'` with `account.menu` for a dropdown instead). Sections from `app.config` can be built-ins or links (`to`); `settings.presets` limits the preset cards, `settings.signOutTo` adds Sign out, `settings.route` (`true` or a query key) syncs the modal with the URL (see SettingsModal, deep links).
|
|
665
706
|
|
|
666
707
|
Pages pick them with `definePageMeta({ layout: 'k-dashboard', title: 'Items' })` or `layout: 'k-auth'` (the auth card shows `title` and `description` from the page meta). Both layouts set the document title from `meta.title` and the brand name (`Items · Acme`; a page's own `useHead({ title })` wins) and announce route changes through a polite live region, unless the app already renders `<NuxtRouteAnnouncer />`. Breadcrumbs come from `meta.breadcrumbs`, otherwise from the matching navigation item (plus `meta.title` on deeper pages). At runtime `useDashboard().value = { account, breadcrumbs, badges: { '/items': 12 } }` overrides the account, the breadcrumbs and the badges. Set it in route middleware (`definePageMeta({ middleware })`) or a plugin, not in the page `setup`: the layout renders the sidebar and breadcrumbs before the page, so a value set during the page render would differ between the server HTML and hydration.
|
|
667
708
|
|
|
@@ -708,6 +749,23 @@ Accessibility related props and defaults:
|
|
|
708
749
|
- `DataGrid` sort is a model: `v-model:sort` (`{ column, direction } | null`) sets the sorted column from outside (server side sort, a sort restored from the URL) and follows header clicks. Leave it unset for an uncontrolled grid. `sortChange` still fires with `serverSort`.
|
|
709
750
|
- `DataGrid` takes `rowHeight` and `headerHeight` (pixels) for an exact row size on top of `density`, and `headerText: (field, column) => string | undefined` to name every column that has a `field` and no `headerName` (from your i18n).
|
|
710
751
|
- `DataGrid` `filterable` registers the AG Grid text, number and date filters (`registerGridFilterModules()` does it without the prop) and turns `filter` on for every column. `filterChange(model, event)` fires with `api.getFilterModel()` whenever a column filter changes, also when the filters come from `gridOptions` or your own registered modules.
|
|
752
|
+
- `DataGrid` `#filters` slot: put your own filter controls (Select, Combobox, DateInput bound with `v-model`) in it and the toolbar shows a square funnel button right after the search input (at the start with `:searchable="false"`), before the `actions`. The button opens a `Modal` titled "Filters" that hosts the slot, so the filters still apply live; its footer has "Reset filters" (emits `filtersReset`, disabled while `filterCount` is 0) and "Show results" (closes it). `filterCount` shows the number of active filters as a badge on the button and in its accessible name ("Filters, 2 active", `grid.filtersActive`). Slot props: `{ close, count }`. Focus returns to the button on close, and the modal becomes a bottom sheet on small screens. `GridToolbar` takes the same slot, prop and event.
|
|
753
|
+
|
|
754
|
+
```vue
|
|
755
|
+
<KDataGrid
|
|
756
|
+
:rows="rows"
|
|
757
|
+
:columns="columns"
|
|
758
|
+
toolbar
|
|
759
|
+
:filter-count="[status, owner].filter(Boolean).length"
|
|
760
|
+
@filters-reset="status = owner = null"
|
|
761
|
+
>
|
|
762
|
+
<template #filters>
|
|
763
|
+
<KFormField label="Status"><KSelect v-model="status" :options="statuses" /></KFormField>
|
|
764
|
+
<KFormField label="Owner"><KSelect v-model="owner" :options="owners" /></KFormField>
|
|
765
|
+
</template>
|
|
766
|
+
</KDataGrid>
|
|
767
|
+
```
|
|
768
|
+
|
|
711
769
|
- `DateCell` takes `relative: true` (or `Intl.RelativeTimeFormatOptions`) in `cellRendererParams` for "3 days ago"; the absolute date stays in the `title`. `relativeWithin` (milliseconds, default unset: always relative) shows the absolute date instead once the value is further than that from now, in the past or the future (`relativeWithin: 7 * 86_400_000` keeps "3 days ago" and prints older dates in full).
|
|
712
770
|
- `DataGrid` takes `gridOptions` for any AG Grid option it does not wrap (`rowHeight`, `onCellEditingStopped`, `onFilterChanged`, ...). A prop of `DataGrid` wins only when it is set: `getRowId`, `rowSelection` (when `selectable` is off), `autoSizeStrategy` (also `undefined` to turn it off), `tooltipShowDelay`, `overlayNoRowsTemplate` and `overlayLoadingTemplate` from `gridOptions` are used otherwise; `defaultColDef` and `localeText` are merged over the component defaults, and `context` is merged under the cell context. Handlers from both run.
|
|
713
771
|
- `DataGrid` row ids: `getRowId: (params) => string` (wins), `rowIdKey` (a field of the row), or `gridOptions.getRowId`.
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="k-sidebar">
|
|
3
|
-
<div
|
|
3
|
+
<div
|
|
4
|
+
v-if="$slots.header || collapsible"
|
|
5
|
+
class="k-sidebar-header"
|
|
6
|
+
:class="{ 'is-brand-center': brandAlign === 'center' && !isCollapsed }"
|
|
7
|
+
>
|
|
4
8
|
<div class="k-sidebar-brand">
|
|
5
9
|
<slot name="header" :collapsed="isCollapsed" />
|
|
6
10
|
</div>
|
|
@@ -10,7 +14,7 @@
|
|
|
10
14
|
variant="ghost"
|
|
11
15
|
tone="neutral"
|
|
12
16
|
size="xs"
|
|
13
|
-
icon="
|
|
17
|
+
:icon="isCollapsed ? 'sidebar-expand' : 'sidebar-collapse'"
|
|
14
18
|
:aria-label="collapseText"
|
|
15
19
|
:aria-expanded="isCollapsed ? 'false' : 'true'"
|
|
16
20
|
:aria-controls="shell.sidebarId"
|
|
@@ -43,7 +47,8 @@ import Button from "../core/Button.vue";
|
|
|
43
47
|
const props = defineProps({
|
|
44
48
|
label: { type: String, required: false },
|
|
45
49
|
collapsible: { type: Boolean, required: false },
|
|
46
|
-
collapseLabel: { type: String, required: false }
|
|
50
|
+
collapseLabel: { type: String, required: false },
|
|
51
|
+
brandAlign: { type: String, required: false, default: "start" }
|
|
47
52
|
});
|
|
48
53
|
const { t } = useLocale();
|
|
49
54
|
const navText = computed(() => props.label ?? t("shell.main"));
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { SidebarBrandAlign } from './types';
|
|
1
2
|
declare var __VLS_1: {
|
|
2
3
|
collapsed: boolean;
|
|
3
4
|
}, __VLS_10: {
|
|
@@ -20,6 +21,7 @@ declare const __VLS_base: import("vue").DefineComponent<{
|
|
|
20
21
|
label?: string;
|
|
21
22
|
collapsible?: boolean;
|
|
22
23
|
collapseLabel?: string;
|
|
24
|
+
brandAlign?: SidebarBrandAlign;
|
|
23
25
|
innerHTML?: string | undefined | undefined;
|
|
24
26
|
class?: import("vue").ClassValue;
|
|
25
27
|
style?: import("vue").StyleValue;
|
|
@@ -216,6 +218,7 @@ declare const __VLS_base: import("vue").DefineComponent<{
|
|
|
216
218
|
label?: string;
|
|
217
219
|
collapsible?: boolean;
|
|
218
220
|
collapseLabel?: string;
|
|
221
|
+
brandAlign?: SidebarBrandAlign;
|
|
219
222
|
innerHTML?: string | undefined | undefined;
|
|
220
223
|
class?: import("vue").ClassValue;
|
|
221
224
|
style?: import("vue").StyleValue;
|
|
@@ -408,7 +411,9 @@ declare const __VLS_base: import("vue").DefineComponent<{
|
|
|
408
411
|
ref?: import("vue").VNodeRef | undefined;
|
|
409
412
|
ref_for?: boolean | undefined | undefined;
|
|
410
413
|
ref_key?: string | undefined | undefined;
|
|
411
|
-
}> & Readonly<{}>, {
|
|
414
|
+
}> & Readonly<{}>, {
|
|
415
|
+
brandAlign: SidebarBrandAlign;
|
|
416
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
412
417
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
413
418
|
declare const _default: typeof __VLS_export;
|
|
414
419
|
export default _default;
|
|
@@ -3,6 +3,7 @@ import type { LinkTarget, Tone } from '../core/types';
|
|
|
3
3
|
export type LayoutGap = 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
4
4
|
export type LayoutAlign = 'start' | 'center' | 'end' | 'stretch' | 'baseline';
|
|
5
5
|
export type LayoutJustify = 'start' | 'center' | 'end' | 'between' | 'around';
|
|
6
|
+
export type SidebarBrandAlign = 'start' | 'center';
|
|
6
7
|
export interface GridColumns {
|
|
7
8
|
base?: number;
|
|
8
9
|
sm?: number;
|
|
@@ -18,7 +18,12 @@
|
|
|
18
18
|
:view-transition="viewTransition"
|
|
19
19
|
>
|
|
20
20
|
<template #sidebar="{ collapsed: isCollapsed }">
|
|
21
|
-
<Sidebar
|
|
21
|
+
<Sidebar
|
|
22
|
+
:label="navLabel"
|
|
23
|
+
:collapsible="collapsible"
|
|
24
|
+
:collapse-label="collapseLabel"
|
|
25
|
+
:brand-align="brandAlign"
|
|
26
|
+
>
|
|
22
27
|
<template #header>
|
|
23
28
|
<slot name="brand" :collapsed="isCollapsed">
|
|
24
29
|
<Brand
|
|
@@ -140,6 +145,8 @@
|
|
|
140
145
|
:presets="settingsPresets"
|
|
141
146
|
:title="settingsTitleText"
|
|
142
147
|
:on-sign-out="onSignOut"
|
|
148
|
+
:route="settingsRoute"
|
|
149
|
+
:resolve-page="settingsResolvePage"
|
|
143
150
|
>
|
|
144
151
|
<template v-if="$slots['settings-account-fields']" #account-fields="scope">
|
|
145
152
|
<slot name="settings-account-fields" v-bind="scope" />
|
|
@@ -176,11 +183,14 @@ const props = defineProps({
|
|
|
176
183
|
brandLogo: { type: null, required: false },
|
|
177
184
|
brandShowName: { type: Boolean, required: false },
|
|
178
185
|
brandTo: { type: [String, Object], required: false, default: "/" },
|
|
186
|
+
brandAlign: { type: String, required: false },
|
|
179
187
|
account: { type: Object, required: false },
|
|
180
188
|
accountAction: { type: String, required: false, default: "settings" },
|
|
181
189
|
settingsSections: { type: Array, required: false, default: void 0 },
|
|
182
190
|
settingsPresets: { type: [Array, Boolean], required: false, default: void 0 },
|
|
183
191
|
settingsTitle: { type: String, required: false },
|
|
192
|
+
settingsRoute: { type: [String, Boolean], required: false, default: false },
|
|
193
|
+
settingsResolvePage: { type: Function, required: false },
|
|
184
194
|
onSignOut: { type: Function, required: false },
|
|
185
195
|
breadcrumbs: { type: Array, required: false },
|
|
186
196
|
search: { type: [Boolean, Array, Function], required: false },
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { IconName } from '../../composables/useIcons';
|
|
2
|
-
import type { BreadcrumbItem, ShellContent } from '../layout/types';
|
|
2
|
+
import type { BreadcrumbItem, ShellContent, SidebarBrandAlign } from '../layout/types';
|
|
3
3
|
import type { CommandGroupLabelSlotProps, CommandItem, MenuItem } from '../overlays/types';
|
|
4
4
|
import type { ThemePreset } from '../../composables/usePreset';
|
|
5
5
|
import type { LinkTarget } from '../core/types';
|
|
6
|
-
import type { AccountAction, BrandLogo, DashboardAccount, DashboardNavigation, DashboardSearch, DashboardSearchProps, DashboardVariant, SettingsModalAccount, SettingsModalSection, SettingsSectionSlotProps, ThemeSwitchPlacement } from './types';
|
|
6
|
+
import type { AccountAction, BrandLogo, DashboardAccount, DashboardNavigation, DashboardSearch, DashboardSearchProps, DashboardVariant, SettingsModalAccount, SettingsModalSection, SettingsPageResolver, SettingsSectionSlotProps, ThemeSwitchPlacement } from './types';
|
|
7
7
|
declare const __VLS_export: <T = unknown>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
|
|
8
8
|
props: import("vue").PublicProps & __VLS_PrettifyLocal<({
|
|
9
9
|
variant?: DashboardVariant;
|
|
@@ -15,11 +15,14 @@ declare const __VLS_export: <T = unknown>(__VLS_props: NonNullable<Awaited<typeo
|
|
|
15
15
|
brandLogo?: BrandLogo;
|
|
16
16
|
brandShowName?: boolean;
|
|
17
17
|
brandTo?: LinkTarget;
|
|
18
|
+
brandAlign?: SidebarBrandAlign;
|
|
18
19
|
account?: DashboardAccount;
|
|
19
20
|
accountAction?: AccountAction;
|
|
20
21
|
settingsSections?: SettingsModalSection[];
|
|
21
22
|
settingsPresets?: readonly ThemePreset[] | false;
|
|
22
23
|
settingsTitle?: string;
|
|
24
|
+
settingsRoute?: string | boolean;
|
|
25
|
+
settingsResolvePage?: SettingsPageResolver;
|
|
23
26
|
onSignOut?: () => void;
|
|
24
27
|
breadcrumbs?: BreadcrumbItem[];
|
|
25
28
|
search?: DashboardSearch<T>;
|