entasis 0.5.0 → 0.7.0

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.
Files changed (80) hide show
  1. package/dist/components/AIAskUserQuestion/aiAskUserQuestion.theme.js +1 -1
  2. package/dist/components/AIChat/aiChat.theme.js +2 -2
  3. package/dist/components/AIComposer/aiComposer.theme.js +2 -2
  4. package/dist/components/AIContext/aiContext.theme.js +2 -2
  5. package/dist/components/AIFilePreview/aiFilePreview.theme.js +1 -1
  6. package/dist/components/AIMarker/aiMarker.theme.js +2 -2
  7. package/dist/components/AIMessage/aiMessage.theme.js +2 -2
  8. package/dist/components/AIMessageActions/aiMessageActions.theme.js +1 -1
  9. package/dist/components/AIModelSelector/aiModelSelector.theme.js +1 -1
  10. package/dist/components/AIReasoning/aiReasoning.theme.js +1 -1
  11. package/dist/components/AISuggestion/aiSuggestion.theme.js +1 -1
  12. package/dist/components/AIThread/aiThread.theme.js +2 -2
  13. package/dist/components/AIThreadToc/aiThreadToc.theme.js +1 -1
  14. package/dist/components/AITool/aiTool.theme.js +2 -2
  15. package/dist/components/AudioPlayer/audioPlayer.theme.js +2 -2
  16. package/dist/components/Avatar/avatarGroup.theme.js +1 -1
  17. package/dist/components/Button/button.mcp.d.ts +1 -1
  18. package/dist/components/Button/button.mcp.js +2 -2
  19. package/dist/components/ButtonGroup/buttonGroup.theme.js +1 -1
  20. package/dist/components/DocumentViewer/documentViewer.theme.js +1 -1
  21. package/dist/components/EventCalendar/eventCalendar.theme.js +1 -1
  22. package/dist/components/Form/ColorInput/colorInput.theme.js +2 -2
  23. package/dist/components/Form/ColorPicker/colorPicker.theme.js +2 -2
  24. package/dist/components/Form/DateInput/dateInput.theme.js +2 -2
  25. package/dist/components/Form/DateSelector/dateSelector.theme.js +1 -1
  26. package/dist/components/Form/File/fileInput.theme.js +2 -2
  27. package/dist/components/Form/Form/form.state.svelte.d.ts +4 -4
  28. package/dist/components/Form/Form/visibility.d.ts +54 -54
  29. package/dist/components/Form/KeyValueInput/keyValueInput.theme.js +2 -2
  30. package/dist/components/Form/MultiStepForm/multiStepForm.state.svelte.d.ts +4 -4
  31. package/dist/components/Form/MultiStepForm/multiStepForm.theme.js +1 -1
  32. package/dist/components/Form/NumberInput/numberInput.theme.js +2 -2
  33. package/dist/components/Form/PasswordInput/passwordInput.theme.js +2 -2
  34. package/dist/components/Form/PhoneInput/phoneInput.theme.js +2 -2
  35. package/dist/components/Form/PinInput/pinInput.theme.js +2 -2
  36. package/dist/components/Form/TagsInput/tagsInput.theme.js +2 -2
  37. package/dist/components/Form/TextArea/textArea.theme.js +2 -2
  38. package/dist/components/Form/TextInput/textInput.theme.js +2 -2
  39. package/dist/components/Form/TimeInput/timeInput.theme.js +2 -2
  40. package/dist/components/Form/VoiceInput/voiceInput.theme.js +2 -2
  41. package/dist/components/GanttChart/ganttChart.theme.js +2 -2
  42. package/dist/components/Grid/gridSpan.theme.js +2 -2
  43. package/dist/components/MediaVolume/mediaVolumeControl.theme.js +1 -1
  44. package/dist/components/MenuBar/menuBar.theme.js +2 -2
  45. package/dist/components/MenuOption/menuOption.theme.js +2 -2
  46. package/dist/components/MetadataList/metadataList.theme.js +2 -2
  47. package/dist/components/MiniCalendar/miniCalendar.theme.js +2 -2
  48. package/dist/components/NetworkIndicator/networkIndicator.mcp.d.ts +1 -1
  49. package/dist/components/NetworkIndicator/networkIndicator.mcp.js +1 -1
  50. package/dist/components/NetworkIndicator/networkIndicator.theme.js +2 -2
  51. package/dist/components/QRCode/qrCode.theme.js +2 -2
  52. package/dist/components/RichTextInput/richTextInput.theme.js +2 -2
  53. package/dist/components/ScrollArea/scrollArea.theme.js +2 -2
  54. package/dist/components/SegmentedControl/segmentedControl.theme.js +1 -1
  55. package/dist/components/SelectionMenu/selectionMenu.theme.js +1 -1
  56. package/dist/components/Sidebar/Sidebar.svelte +8 -2
  57. package/dist/components/Sidebar/SidebarDesktopShell.svelte +3 -0
  58. package/dist/components/Sidebar/SidebarDesktopShell.svelte.d.ts +1 -0
  59. package/dist/components/Sidebar/SidebarMobileDrawer.svelte +3 -1
  60. package/dist/components/Sidebar/SidebarMobileDrawer.svelte.d.ts +1 -0
  61. package/dist/components/Sidebar/sidebar.mcp.d.ts +1 -1
  62. package/dist/components/Sidebar/sidebar.mcp.js +24 -1
  63. package/dist/components/Sidebar/sidebar.props.d.ts +2 -0
  64. package/dist/components/Sidebar/sidebar.theme.d.ts +30 -0
  65. package/dist/components/Sidebar/sidebar.theme.js +46 -43
  66. package/dist/components/SortableList/sortableList.theme.js +2 -2
  67. package/dist/components/SpinnerText/spinnerText.mcp.d.ts +1 -1
  68. package/dist/components/SpinnerText/spinnerText.mcp.js +1 -1
  69. package/dist/components/SpinnerText/spinnerText.theme.js +2 -2
  70. package/dist/components/ToggleButton/toggleButton.theme.js +1 -1
  71. package/dist/components/ToggleButtonGroup/toggleButtonGroup.theme.js +1 -1
  72. package/dist/components/ToggleMenu/toggleMenu.theme.js +2 -2
  73. package/dist/components/VideoPlayer/videoPlayer.theme.js +2 -2
  74. package/dist/generated/componentMcpRegistry.d.ts +5 -5
  75. package/dist/tailwind/global.js +4 -1
  76. package/dist/tailwind/theme.mcp.d.ts +1 -1
  77. package/dist/tailwind/theme.mcp.js +1 -1
  78. package/dist/utils/cva/merge.d.ts +108 -0
  79. package/dist/utils/cva/merge.js +6 -2
  80. package/package.json +1 -1
@@ -87,5 +87,5 @@ export const keyValueInputTheme = {
87
87
  removeButton: defaultRemoveButton,
88
88
  addButton: defaultAddButton
89
89
  };
90
- export const setKeyValueInputTheme = setComponentTheme('keyValueInput');
91
- export const useKeyValueInputTheme = useComponentTheme('keyValueInput', keyValueInputTheme);
90
+ export const setKeyValueInputTheme = setComponentTheme('key-value-input');
91
+ export const useKeyValueInputTheme = useComponentTheme('key-value-input', keyValueInputTheme);
@@ -533,9 +533,9 @@ export declare class MultiStepFormState<I extends MultiStepFormItems = FormStep[
533
533
  disabled?: boolean | undefined;
534
534
  error?: import("../../Slot/slot.js").Slot<undefined> | undefined;
535
535
  class?: string | undefined;
536
+ prefix?: import("../../Slot/slot.js").Slot<undefined> | undefined;
536
537
  size?: import("../../../types/theme.js").Sizes | undefined;
537
538
  value?: string | null | undefined;
538
- prefix?: import("../../Slot/slot.js").Slot<undefined> | undefined;
539
539
  suffix?: import("../../Slot/slot.js").Slot<undefined> | undefined;
540
540
  name?: string | undefined;
541
541
  label?: import("../../Slot/slot.js").Slot<undefined> | undefined;
@@ -1304,9 +1304,9 @@ export declare class MultiStepFormState<I extends MultiStepFormItems = FormStep[
1304
1304
  disabled?: boolean | undefined;
1305
1305
  error?: import("../../Slot/slot.js").Slot<undefined> | undefined;
1306
1306
  class?: string | undefined;
1307
+ prefix?: import("../../Slot/slot.js").Slot<undefined> | undefined;
1307
1308
  size?: import("../../../types/theme.js").Sizes | undefined;
1308
1309
  value?: string | null | undefined;
1309
- prefix?: import("../../Slot/slot.js").Slot<undefined> | undefined;
1310
1310
  suffix?: import("../../Slot/slot.js").Slot<undefined> | undefined;
1311
1311
  name?: string | undefined;
1312
1312
  label?: import("../../Slot/slot.js").Slot<undefined> | undefined;
@@ -2109,9 +2109,9 @@ export declare class MultiStepFormState<I extends MultiStepFormItems = FormStep[
2109
2109
  disabled?: boolean | undefined;
2110
2110
  error?: import("../../Slot/slot.js").Slot<undefined> | undefined;
2111
2111
  class?: string | undefined;
2112
+ prefix?: import("../../Slot/slot.js").Slot<undefined> | undefined;
2112
2113
  size?: import("../../../types/theme.js").Sizes | undefined;
2113
2114
  value?: string | null | undefined;
2114
- prefix?: import("../../Slot/slot.js").Slot<undefined> | undefined;
2115
2115
  suffix?: import("../../Slot/slot.js").Slot<undefined> | undefined;
2116
2116
  name?: string | undefined;
2117
2117
  label?: import("../../Slot/slot.js").Slot<undefined> | undefined;
@@ -2880,9 +2880,9 @@ export declare class MultiStepFormState<I extends MultiStepFormItems = FormStep[
2880
2880
  disabled?: boolean | undefined;
2881
2881
  error?: import("../../Slot/slot.js").Slot<undefined> | undefined;
2882
2882
  class?: string | undefined;
2883
+ prefix?: import("../../Slot/slot.js").Slot<undefined> | undefined;
2883
2884
  size?: import("../../../types/theme.js").Sizes | undefined;
2884
2885
  value?: string | null | undefined;
2885
- prefix?: import("../../Slot/slot.js").Slot<undefined> | undefined;
2886
2886
  suffix?: import("../../Slot/slot.js").Slot<undefined> | undefined;
2887
2887
  name?: string | undefined;
2888
2888
  label?: import("../../Slot/slot.js").Slot<undefined> | undefined;
@@ -48,5 +48,5 @@ export const multiStepFormTheme = {
48
48
  multiStepFormContent: defaultMultiStepContent,
49
49
  multiStepFormFooter: defaultMultiStepFooter
50
50
  };
51
- export const setMultiStepFormTheme = setComponentTheme('multiStepForm');
51
+ export const setMultiStepFormTheme = setComponentTheme('multi-step-form');
52
52
  export const useMultiStepFormTheme = useComponentTheme('multiStepForm', multiStepFormTheme);
@@ -38,5 +38,5 @@ export const numberInputTheme = {
38
38
  input: defaultInput,
39
39
  inputContainer: defaultInputContainer
40
40
  };
41
- export const setNumberInputTheme = setComponentTheme('numberInput');
42
- export const useNumberInputTheme = useComponentTheme('numberInput', numberInputTheme);
41
+ export const setNumberInputTheme = setComponentTheme('number-input');
42
+ export const useNumberInputTheme = useComponentTheme('number-input', numberInputTheme);
@@ -38,5 +38,5 @@ export const passwordInputTheme = {
38
38
  input: defaultInput,
39
39
  inputContainer: defaultInputContainer
40
40
  };
41
- export const setPasswordInputTheme = setComponentTheme('passwordInput');
42
- export const usePasswordInputTheme = useComponentTheme('passwordInput', passwordInputTheme);
41
+ export const setPasswordInputTheme = setComponentTheme('password-input');
42
+ export const usePasswordInputTheme = useComponentTheme('password-input', passwordInputTheme);
@@ -217,5 +217,5 @@ export const phoneInputTheme = {
217
217
  countryCheck: defaultCountryCheck,
218
218
  countryEmpty: defaultCountryEmpty
219
219
  };
220
- export const setPhoneInputTheme = setComponentTheme('phoneInput');
221
- export const usePhoneInputTheme = useComponentTheme('phoneInput', phoneInputTheme);
220
+ export const setPhoneInputTheme = setComponentTheme('phone-input');
221
+ export const usePhoneInputTheme = useComponentTheme('phone-input', phoneInputTheme);
@@ -66,5 +66,5 @@ export const pinInputTheme = {
66
66
  character: defaultCharacter,
67
67
  caret: defaultCaret
68
68
  };
69
- export const setPinInputTheme = setComponentTheme('pinInput');
70
- export const usePinInputTheme = useComponentTheme('pinInput', pinInputTheme);
69
+ export const setPinInputTheme = setComponentTheme('pin-input');
70
+ export const usePinInputTheme = useComponentTheme('pin-input', pinInputTheme);
@@ -87,5 +87,5 @@ export const tagsInputTheme = {
87
87
  error: defaultError,
88
88
  noOptions: defaultNoOptions
89
89
  };
90
- export const setTagsInputTheme = setComponentTheme('tagsInput');
91
- export const useTagsInputTheme = useComponentTheme('tagsInput', tagsInputTheme);
90
+ export const setTagsInputTheme = setComponentTheme('tags-input');
91
+ export const useTagsInputTheme = useComponentTheme('tags-input', tagsInputTheme);
@@ -38,5 +38,5 @@ export const textAreaTheme = {
38
38
  input: defaultTextArea,
39
39
  inputContainer: defaultTextAreaContainer
40
40
  };
41
- export const setTextAreaTheme = setComponentTheme('textArea');
42
- export const useTextAreaTheme = useComponentTheme('textArea', textAreaTheme);
41
+ export const setTextAreaTheme = setComponentTheme('text-area');
42
+ export const useTextAreaTheme = useComponentTheme('text-area', textAreaTheme);
@@ -38,5 +38,5 @@ export const textInputTheme = {
38
38
  input: defaultInput,
39
39
  inputContainer: defaultInputContainer
40
40
  };
41
- export const setTextInputTheme = setComponentTheme('textInput');
42
- export const useTextInputTheme = useComponentTheme('textInput', textInputTheme);
41
+ export const setTextInputTheme = setComponentTheme('text-input');
42
+ export const useTextInputTheme = useComponentTheme('text-input', textInputTheme);
@@ -88,5 +88,5 @@ export const timeInputTheme = {
88
88
  pickerScrollArea: defaultPickerScrollArea,
89
89
  pickerOption: defaultPickerOption
90
90
  };
91
- export const setTimeInputTheme = setComponentTheme('timeInput');
92
- export const useTimeInputTheme = useComponentTheme('timeInput', timeInputTheme);
91
+ export const setTimeInputTheme = setComponentTheme('time-input');
92
+ export const useTimeInputTheme = useComponentTheme('time-input', timeInputTheme);
@@ -346,5 +346,5 @@ export const voiceInputTheme = {
346
346
  timer: defaultTimer,
347
347
  error: defaultError
348
348
  };
349
- export const setVoiceInputTheme = setComponentTheme('voiceInput');
350
- export const useVoiceInputTheme = useComponentTheme('voiceInput', voiceInputTheme);
349
+ export const setVoiceInputTheme = setComponentTheme('voice-input');
350
+ export const useVoiceInputTheme = useComponentTheme('voice-input', voiceInputTheme);
@@ -267,5 +267,5 @@ export const ganttChartTheme = {
267
267
  empty,
268
268
  liveRegion
269
269
  };
270
- export const setGanttChartTheme = setComponentTheme('ganttChart');
271
- export const useGanttChartTheme = useComponentTheme('ganttChart', ganttChartTheme);
270
+ export const setGanttChartTheme = setComponentTheme('gantt-chart');
271
+ export const useGanttChartTheme = useComponentTheme('gantt-chart', ganttChartTheme);
@@ -28,5 +28,5 @@ const defaultGridSpan = cva({
28
28
  export const gridSpanTheme = {
29
29
  root: defaultGridSpan
30
30
  };
31
- export const setGridSpanTheme = setComponentTheme('gridSpan');
32
- export const useGridSpanTheme = useComponentTheme('gridSpan', gridSpanTheme);
31
+ export const setGridSpanTheme = setComponentTheme('grid-span');
32
+ export const useGridSpanTheme = useComponentTheme('grid-span', gridSpanTheme);
@@ -45,5 +45,5 @@ export const mediaVolumeControlTheme = {
45
45
  panel: defaultMediaVolumeControlPanel,
46
46
  slider: defaultMediaVolumeControlSlider
47
47
  };
48
- export const setMediaVolumeControlTheme = setComponentTheme('mediaVolumeControl');
48
+ export const setMediaVolumeControlTheme = setComponentTheme('media-volume-control');
49
49
  export const useMediaVolumeControlTheme = useComponentTheme('mediaVolumeControl', mediaVolumeControlTheme);
@@ -30,5 +30,5 @@ export const menuBarTheme = {
30
30
  root: defaultMenuBar,
31
31
  trigger: defaultMenuBarTrigger
32
32
  };
33
- export const setMenuBarTheme = setComponentTheme('menuBar');
34
- export const useMenuBarTheme = useComponentTheme('menuBar', menuBarTheme);
33
+ export const setMenuBarTheme = setComponentTheme('menu-bar');
34
+ export const useMenuBarTheme = useComponentTheme('menu-bar', menuBarTheme);
@@ -139,5 +139,5 @@ export const menuOptionTheme = {
139
139
  suffix: defaultMenuOptionSuffix,
140
140
  content: defaultMenuOptionContent
141
141
  };
142
- export const setMenuOptionTheme = setComponentTheme('menuOption');
143
- export const useMenuOptionTheme = useComponentTheme('menuOption', menuOptionTheme);
142
+ export const setMenuOptionTheme = setComponentTheme('menu-option');
143
+ export const useMenuOptionTheme = useComponentTheme('menu-option', menuOptionTheme);
@@ -189,5 +189,5 @@ export const metadataListTheme = {
189
189
  toggle: defaultToggle,
190
190
  toggleIcon: defaultToggleIcon
191
191
  };
192
- export const setMetadataListTheme = setComponentTheme('metadataList');
193
- export const useMetadataListTheme = useComponentTheme('metadataList', metadataListTheme);
192
+ export const setMetadataListTheme = setComponentTheme('metadata-list');
193
+ export const useMetadataListTheme = useComponentTheme('metadata-list', metadataListTheme);
@@ -175,5 +175,5 @@ export const miniCalendarTheme = {
175
175
  dayMonth: defaultDayMonth,
176
176
  dayNumber: defaultDayNumber
177
177
  };
178
- export const setMiniCalendarTheme = setComponentTheme('miniCalendar');
179
- export const useMiniCalendarTheme = useComponentTheme('miniCalendar', miniCalendarTheme);
178
+ export const setMiniCalendarTheme = setComponentTheme('mini-calendar');
179
+ export const useMiniCalendarTheme = useComponentTheme('mini-calendar', miniCalendarTheme);
@@ -1 +1 @@
1
- export declare const networkIndicatorDescription = "\n# NetworkIndicator Component\n\nNetworkIndicator is a fixed top loading bar for SvelteKit navigation and explicit async work. Mount one instance near the root layout. It shows automatically during SvelteKit route transitions, can be driven by a controlled `loading` prop, and exposes imperative helpers for request lifecycles.\n\n## Import\n\n```svelte\n<script lang=\"ts\">\n\timport { NetworkIndicator } from 'entasis/network-indicator';\n</script>\n```\n\n## Basic Usage\n\n```svelte\n<!-- +layout.svelte -->\n<script lang=\"ts\">\n\timport { NetworkIndicator } from 'entasis/network-indicator';\n</script>\n\n<NetworkIndicator />\n\n{@render children()}\n```\n\n## Props\n\n- **loading**: boolean = false\n - Controlled visibility. Use this when the owner already has request state or when rendering examples/previews.\n- **variant**: 'bar' | 'trail' | 'trail-bounce' = 'bar'\n - `bar` progressively grows one indicator. `trail` renders one randomly sized moving segment at a time. `trail-bounce` sends that random trail fully off one edge, then returns from the opposite edge.\n- **trailGap**: number = 0\n - Pause between trail passes in milliseconds. Only applies to `variant=\"trail\"`.\n- **color**: 'primary' | 'secondary' | 'neutral' | 'danger' | 'success' | 'warning' | 'info' = 'neutral'\n - Applies the semantic color token to the bar.\n- **height**: number = 3\n - Height in pixels. Keep most navigation indicators between 2 and 6.\n- Animation duration and easing come from the `motion` theme slot \u2014 `theme={{ motion: { duration: 450, easing: 'expoOut' } }}` \u2014 not from props; see Motion below.\n- **label**: string = 'Loading'\n - Accessible label for the indeterminate `role=\"progressbar\"`.\n- **ref**: HTMLDivElement | null\n - Bindable root element reference while the indicator is visible.\n- **class**: string\n - Additional classes for the root bar.\n- **theme**: NetworkIndicatorThemeProps\n - Theme override for the root bar.\n\n## Helper API\n\n```ts\nimport {\n\thideNetworkIndicator,\n\tshowNetworkIndicator,\n\ttoggleNetworkIndicator\n} from 'entasis/network-indicator';\n```\n\nPrefer `showNetworkIndicator()` and `hideNetworkIndicator()` for async work. `toggleNetworkIndicator()` is available for simple demos or manual toggles, but it is easier to desynchronize in request lifecycles.\n\n## Patterns\n\n### Controlled Loading\n\n```svelte\n<script lang=\"ts\">\n\timport { NetworkIndicator } from 'entasis/network-indicator';\n\n\tlet loading = $state(false);\n</script>\n\n<NetworkIndicator {loading} color=\"primary\" label=\"Saving changes\" />\n```\n\n### Async Request\n\n```svelte\n<script lang=\"ts\">\n\timport { Button } from 'entasis/button';\n\timport {\n\t\thideNetworkIndicator,\n\t\tshowNetworkIndicator\n\t} from 'entasis/network-indicator';\n\n\tasync function save() {\n\t\tshowNetworkIndicator();\n\t\ttry {\n\t\t\tawait fetch('/api/save', { method: 'POST' });\n\t\t} finally {\n\t\t\thideNetworkIndicator();\n\t\t}\n\t}\n</script>\n\n<Button onclick={save}>Save</Button>\n```\n\n### Color Variations\n\n```svelte\n<NetworkIndicator loading color=\"primary\" />\n<NetworkIndicator loading color=\"success\" />\n<NetworkIndicator loading color=\"warning\" />\n<NetworkIndicator loading color=\"danger\" />\n```\n\n### Trail Variant\n\n```svelte\n<NetworkIndicator loading variant=\"trail\" color=\"primary\" theme={{ motion: { duration: 650 } }} trailGap={0} />\n<NetworkIndicator loading variant=\"trail\" color=\"success\" height={5} theme={{ motion: { duration: 450 } }} trailGap={120} />\n<NetworkIndicator loading variant=\"trail-bounce\" color=\"info\" theme={{ motion: { duration: 700 } }} trailGap={80} />\n```\n\n### Height Variations\n\n```svelte\n<NetworkIndicator loading height={2} />\n<NetworkIndicator loading height={4} color=\"primary\" />\n<NetworkIndicator loading height={6} color=\"info\" />\n```\n\n### Motion Variations\n\n```svelte\n<NetworkIndicator loading theme={{ motion: { duration: 300, easing: 'cubicInOut' } }} />\n<NetworkIndicator loading theme={{ motion: { duration: 450, easing: 'expoOut' } }} />\n<NetworkIndicator loading theme={{ motion: { duration: 500, easing: 'backOut' } }} />\n```\n\n### Theme Override\n\n```svelte\n<NetworkIndicator\n\tloading\n\tcolor=\"success\"\n\theight={5}\n\ttheme={{\n\t\troot: {\n\t\t\tbase: 'ui-network-indicator fixed top-0 left-0 w-full z-[9999] origin-left rounded-none lift-4'\n\t\t}\n\t}}\n/>\n```\n\n## Theme\n\nThe theme has two parts:\n\n- **root**: the fixed top bar.\n - `base`: positioning, origin, radius, z-index, and shared bar classes.\n - `variant`: `bar`, `trail`, or `trail-bounce` container styling.\n - `color`: semantic color variants.\n- **segment**: trail segment styling.\n - `base`: segment positioning, radius, opacity, shadow, and transform hints.\n - `color`: semantic color variants for each trail segment.\n\nThe default root base includes `ui-network-indicator`; keep that class if overriding the base because `toggleNetworkIndicator()` uses it to read current state.\n\n## Accessibility\n\nThe visible bar renders `role=\"progressbar\"` without a value because progress is indeterminate. Use a specific `label` when the loading context matters, such as \"Uploading files\" or \"Saving changes\". If screen readers need richer lifecycle announcements, pair the indicator with app-level live region text.\n\n## Motion\n\n- **motion** theme slot, keyed by `variant`: one growth step of the `bar` loop (`slow`), or\n one pass of the `trail` / `trail-bounce` variants (the `slower` token, 500ms). Only `duration` / `easing` are read.\n- Ladder: `<Theme components={{ networkIndicator: { motion } }}>` \u2192\n `setNetworkIndicatorTheme({ motion })` \u2192 `theme={{ motion: { duration, easing } }}`.\n- A resolved duration of 0 (reduced motion) holds the indicator still instead of looping.\n";
1
+ export declare const networkIndicatorDescription = "\n# NetworkIndicator Component\n\nNetworkIndicator is a fixed top loading bar for SvelteKit navigation and explicit async work. Mount one instance near the root layout. It shows automatically during SvelteKit route transitions, can be driven by a controlled `loading` prop, and exposes imperative helpers for request lifecycles.\n\n## Import\n\n```svelte\n<script lang=\"ts\">\n\timport { NetworkIndicator } from 'entasis/network-indicator';\n</script>\n```\n\n## Basic Usage\n\n```svelte\n<!-- +layout.svelte -->\n<script lang=\"ts\">\n\timport { NetworkIndicator } from 'entasis/network-indicator';\n</script>\n\n<NetworkIndicator />\n\n{@render children()}\n```\n\n## Props\n\n- **loading**: boolean = false\n - Controlled visibility. Use this when the owner already has request state or when rendering examples/previews.\n- **variant**: 'bar' | 'trail' | 'trail-bounce' = 'bar'\n - `bar` progressively grows one indicator. `trail` renders one randomly sized moving segment at a time. `trail-bounce` sends that random trail fully off one edge, then returns from the opposite edge.\n- **trailGap**: number = 0\n - Pause between trail passes in milliseconds. Only applies to `variant=\"trail\"`.\n- **color**: 'primary' | 'secondary' | 'neutral' | 'danger' | 'success' | 'warning' | 'info' = 'neutral'\n - Applies the semantic color token to the bar.\n- **height**: number = 3\n - Height in pixels. Keep most navigation indicators between 2 and 6.\n- Animation duration and easing come from the `motion` theme slot \u2014 `theme={{ motion: { duration: 450, easing: 'expoOut' } }}` \u2014 not from props; see Motion below.\n- **label**: string = 'Loading'\n - Accessible label for the indeterminate `role=\"progressbar\"`.\n- **ref**: HTMLDivElement | null\n - Bindable root element reference while the indicator is visible.\n- **class**: string\n - Additional classes for the root bar.\n- **theme**: NetworkIndicatorThemeProps\n - Theme override for the root bar.\n\n## Helper API\n\n```ts\nimport {\n\thideNetworkIndicator,\n\tshowNetworkIndicator,\n\ttoggleNetworkIndicator\n} from 'entasis/network-indicator';\n```\n\nPrefer `showNetworkIndicator()` and `hideNetworkIndicator()` for async work. `toggleNetworkIndicator()` is available for simple demos or manual toggles, but it is easier to desynchronize in request lifecycles.\n\n## Patterns\n\n### Controlled Loading\n\n```svelte\n<script lang=\"ts\">\n\timport { NetworkIndicator } from 'entasis/network-indicator';\n\n\tlet loading = $state(false);\n</script>\n\n<NetworkIndicator {loading} color=\"primary\" label=\"Saving changes\" />\n```\n\n### Async Request\n\n```svelte\n<script lang=\"ts\">\n\timport { Button } from 'entasis/button';\n\timport {\n\t\thideNetworkIndicator,\n\t\tshowNetworkIndicator\n\t} from 'entasis/network-indicator';\n\n\tasync function save() {\n\t\tshowNetworkIndicator();\n\t\ttry {\n\t\t\tawait fetch('/api/save', { method: 'POST' });\n\t\t} finally {\n\t\t\thideNetworkIndicator();\n\t\t}\n\t}\n</script>\n\n<Button onclick={save}>Save</Button>\n```\n\n### Color Variations\n\n```svelte\n<NetworkIndicator loading color=\"primary\" />\n<NetworkIndicator loading color=\"success\" />\n<NetworkIndicator loading color=\"warning\" />\n<NetworkIndicator loading color=\"danger\" />\n```\n\n### Trail Variant\n\n```svelte\n<NetworkIndicator loading variant=\"trail\" color=\"primary\" theme={{ motion: { duration: 650 } }} trailGap={0} />\n<NetworkIndicator loading variant=\"trail\" color=\"success\" height={5} theme={{ motion: { duration: 450 } }} trailGap={120} />\n<NetworkIndicator loading variant=\"trail-bounce\" color=\"info\" theme={{ motion: { duration: 700 } }} trailGap={80} />\n```\n\n### Height Variations\n\n```svelte\n<NetworkIndicator loading height={2} />\n<NetworkIndicator loading height={4} color=\"primary\" />\n<NetworkIndicator loading height={6} color=\"info\" />\n```\n\n### Motion Variations\n\n```svelte\n<NetworkIndicator loading theme={{ motion: { duration: 300, easing: 'cubicInOut' } }} />\n<NetworkIndicator loading theme={{ motion: { duration: 450, easing: 'expoOut' } }} />\n<NetworkIndicator loading theme={{ motion: { duration: 500, easing: 'backOut' } }} />\n```\n\n### Theme Override\n\n```svelte\n<NetworkIndicator\n\tloading\n\tcolor=\"success\"\n\theight={5}\n\ttheme={{\n\t\troot: {\n\t\t\tbase: 'ui-network-indicator fixed top-0 left-0 w-full z-[9999] origin-left rounded-none lift-4'\n\t\t}\n\t}}\n/>\n```\n\n## Theme\n\nThe theme has two parts:\n\n- **root**: the fixed top bar.\n - `base`: positioning, origin, radius, z-index, and shared bar classes.\n - `variant`: `bar`, `trail`, or `trail-bounce` container styling.\n - `color`: semantic color variants.\n- **segment**: trail segment styling.\n - `base`: segment positioning, radius, opacity, shadow, and transform hints.\n - `color`: semantic color variants for each trail segment.\n\nThe default root base includes `ui-network-indicator`; keep that class if overriding the base because `toggleNetworkIndicator()` uses it to read current state.\n\n## Accessibility\n\nThe visible bar renders `role=\"progressbar\"` without a value because progress is indeterminate. Use a specific `label` when the loading context matters, such as \"Uploading files\" or \"Saving changes\". If screen readers need richer lifecycle announcements, pair the indicator with app-level live region text.\n\n## Motion\n\n- **motion** theme slot, keyed by `variant`: one growth step of the `bar` loop (`slow`), or\n one pass of the `trail` / `trail-bounce` variants (the `slower` token, 500ms). Only `duration` / `easing` are read.\n- Ladder: `<Theme components={{ 'network-indicator': { motion } }}>` \u2192\n `setNetworkIndicatorTheme({ motion })` \u2192 `theme={{ motion: { duration, easing } }}`.\n- A resolved duration of 0 (reduced motion) holds the indicator still instead of looping.\n";
@@ -165,7 +165,7 @@ The visible bar renders \`role="progressbar"\` without a value because progress
165
165
 
166
166
  - **motion** theme slot, keyed by \`variant\`: one growth step of the \`bar\` loop (\`slow\`), or
167
167
  one pass of the \`trail\` / \`trail-bounce\` variants (the \`slower\` token, 500ms). Only \`duration\` / \`easing\` are read.
168
- - Ladder: \`<Theme components={{ networkIndicator: { motion } }}>\` →
168
+ - Ladder: \`<Theme components={{ 'network-indicator': { motion } }}>\` →
169
169
  \`setNetworkIndicatorTheme({ motion })\` → \`theme={{ motion: { duration, easing } }}\`.
170
170
  - A resolved duration of 0 (reduced motion) holds the indicator still instead of looping.
171
171
  `;
@@ -77,6 +77,6 @@ export const networkIndicatorTheme = {
77
77
  root: defaultNetworkIndicator,
78
78
  segment: defaultNetworkIndicatorSegment
79
79
  };
80
- export const setNetworkIndicatorTheme = setComponentTheme('networkIndicator');
80
+ export const setNetworkIndicatorTheme = setComponentTheme('network-indicator');
81
81
  export const useNetworkIndicatorTheme = useComponentTheme('networkIndicator', networkIndicatorTheme);
82
- export const useNetworkIndicatorMotion = () => useComponentMotion('networkIndicator', defaultNetworkIndicatorMotion);
82
+ export const useNetworkIndicatorMotion = () => useComponentMotion('network-indicator', defaultNetworkIndicatorMotion);
@@ -26,5 +26,5 @@ const defaultQRCode = cva({
26
26
  export const qrCodeTheme = {
27
27
  root: defaultQRCode
28
28
  };
29
- export const setQRCodeTheme = setComponentTheme('qrCode');
30
- export const useQRCodeTheme = useComponentTheme('qrCode', qrCodeTheme);
29
+ export const setQRCodeTheme = setComponentTheme('qr-code');
30
+ export const useQRCodeTheme = useComponentTheme('qr-code', qrCodeTheme);
@@ -289,5 +289,5 @@ export const richTextInputTheme = {
289
289
  suggestionsStatus: defaultRichTextInputSuggestionsStatus,
290
290
  suggestionsError: defaultRichTextInputSuggestionsError
291
291
  };
292
- export const setRichTextInputTheme = setComponentTheme('richTextInput');
293
- export const useRichTextInputTheme = useComponentTheme('richTextInput', richTextInputTheme);
292
+ export const setRichTextInputTheme = setComponentTheme('rich-text-input');
293
+ export const useRichTextInputTheme = useComponentTheme('rich-text-input', richTextInputTheme);
@@ -41,5 +41,5 @@ export const scrollAreaTheme = {
41
41
  scrollbarX: defaultScrollAreaScrollbarX,
42
42
  scrollbarThumb: defaultScrollAreaScrollbarThumb
43
43
  };
44
- export const setScrollAreaTheme = setComponentTheme('scrollArea');
45
- export const useScrollAreaTheme = useComponentTheme('scrollArea', scrollAreaTheme);
44
+ export const setScrollAreaTheme = setComponentTheme('scroll-area');
45
+ export const useScrollAreaTheme = useComponentTheme('scroll-area', scrollAreaTheme);
@@ -126,5 +126,5 @@ export const segmentedControlTheme = {
126
126
  indicator: defaultIndicator,
127
127
  staticIndicator: defaultStaticIndicator
128
128
  };
129
- export const setSegmentedControlTheme = setComponentTheme('segmentedControl');
129
+ export const setSegmentedControlTheme = setComponentTheme('segmented-control');
130
130
  export const useSegmentedControlTheme = useComponentTheme('segmentedControl', segmentedControlTheme);
@@ -10,5 +10,5 @@ export const selectionMenuTheme = {
10
10
  popover: defaultSelectionMenuPopover,
11
11
  content: defaultSelectionMenuContent
12
12
  };
13
- export const setSelectionMenuTheme = setComponentTheme('selectionMenu');
13
+ export const setSelectionMenuTheme = setComponentTheme('selection-menu');
14
14
  export const useSelectionMenuTheme = useComponentTheme('selectionMenu', selectionMenuTheme);
@@ -30,6 +30,7 @@
30
30
  side = 'left',
31
31
  variant = 'admin',
32
32
  size = 'normal',
33
+ iconSize,
33
34
  activeVariant = 'soft',
34
35
  density = 'normal',
35
36
  collapsible = 'offcanvas',
@@ -268,7 +269,10 @@
268
269
  style:--sidebar-width={panelWidth}
269
270
  style:--sidebar-width-icon={widthIcon}
270
271
  style:--sidebar-width-mobile={widthMobile}
271
- class={cx('group', classes.panel({ variant, placement: 'panel', size, density, className }))}
272
+ class={cx(
273
+ 'group',
274
+ classes.panel({ variant, placement: 'panel', size, iconSize, density, className })
275
+ )}
272
276
  {...attachments}
273
277
  >
274
278
  {@render panel()}
@@ -307,6 +311,7 @@
307
311
  {widthMobile}
308
312
  {dir}
309
313
  {size}
314
+ {iconSize}
310
315
  {density}
311
316
  label={navLabel}
312
317
  {theme}
@@ -333,7 +338,7 @@
333
338
  data-sidebar="sidebar"
334
339
  data-color={resolvedColor}
335
340
  data-side={side}
336
- class={classes.panel({ variant, placement: 'static', size, density })}
341
+ class={classes.panel({ variant, placement: 'static', size, iconSize, density })}
337
342
  >
338
343
  {@render panel()}
339
344
  </div>
@@ -349,6 +354,7 @@
349
354
  {side}
350
355
  {frame}
351
356
  {size}
357
+ {iconSize}
352
358
  {density}
353
359
  {rail}
354
360
  {edgeReveal}
@@ -35,6 +35,7 @@
35
35
  side,
36
36
  frame,
37
37
  size,
38
+ iconSize,
38
39
  density,
39
40
  rail,
40
41
  edgeReveal,
@@ -60,6 +61,7 @@
60
61
  side: SidebarSide;
61
62
  frame: SidebarFrame;
62
63
  size: SidebarSize;
64
+ iconSize?: SidebarSize;
63
65
  density: SidebarDensity;
64
66
  rail: SidebarRail;
65
67
  edgeReveal: boolean;
@@ -308,6 +310,7 @@
308
310
  variant,
309
311
  placement: 'positioned',
310
312
  size,
313
+ iconSize,
311
314
  density,
312
315
  className: getSidebarPanelPeekClass(variant)
313
316
  })}
@@ -10,6 +10,7 @@ type $$ComponentProps = {
10
10
  side: SidebarSide;
11
11
  frame: SidebarFrame;
12
12
  size: SidebarSize;
13
+ iconSize?: SidebarSize;
13
14
  density: SidebarDensity;
14
15
  rail: SidebarRail;
15
16
  edgeReveal: boolean;
@@ -13,6 +13,7 @@
13
13
  widthMobile,
14
14
  dir,
15
15
  size,
16
+ iconSize,
16
17
  density,
17
18
  label,
18
19
  theme,
@@ -24,6 +25,7 @@
24
25
  widthMobile: string;
25
26
  dir?: 'ltr' | 'rtl';
26
27
  size: SidebarSize;
28
+ iconSize?: SidebarSize;
27
29
  density: SidebarDensity;
28
30
  label: string;
29
31
  theme?: SidebarThemeProps;
@@ -57,7 +59,7 @@
57
59
  data-density={density}
58
60
  style:--sidebar-width-mobile={widthMobile}
59
61
  {dir}
60
- class={classes.mobilePanel({ side, size, density })}
62
+ class={classes.mobilePanel({ side, size, iconSize, density })}
61
63
  >
62
64
  {@render children()}
63
65
  </div>
@@ -8,6 +8,7 @@ type $$ComponentProps = {
8
8
  widthMobile: string;
9
9
  dir?: 'ltr' | 'rtl';
10
10
  size: SidebarSize;
11
+ iconSize?: SidebarSize;
11
12
  density: SidebarDensity;
12
13
  label: string;
13
14
  theme?: SidebarThemeProps;
@@ -1 +1 @@
1
- export declare const sidebarDescription = "\n# Sidebar Component\n\nSidebar navigation with data-driven groups, icon collapse, mobile drawer behavior,\nrecursive tree groups, header/footer rows, search, actions, and snippet escape hatches.\n\n## Import\n\n```svelte\n<script lang=\"ts\">\n\timport { Sidebar, type SidebarGroup } from 'entasis/sidebar';\n</script>\n```\n\n## Basic Usage\n\n```svelte\n<script lang=\"ts\">\n\timport { Sidebar, type SidebarGroup } from 'entasis/sidebar';\n\timport { houseIcon } from 'entasis/icons/house';\n\timport { gearIcon } from 'entasis/icons/gear';\n\n\tconst items: SidebarGroup[] = [\n\t\t{\n\t\t\tlabel: 'Workspace',\n\t\t\titems: [\n\t\t\t\t{ label: 'Dashboard', href: '/', icon: houseIcon, isActive: true },\n\t\t\t\t{ label: 'Settings', href: '/settings', icon: gearIcon }\n\t\t\t]\n\t\t}\n\t];\n</script>\n\n<Sidebar items={items}>\n\t{#snippet children({ toggle })}\n\t\t<header>\n\t\t\t<button type=\"button\" onclick={toggle}>Toggle</button>\n\t\t</header>\n\t\t<main>Page content</main>\n\t{/snippet}\n</Sidebar>\n```\n\n## AI-Safe Usage Contract\n\n1. Use `items` for normal navigation. Use `content` only when data-driven rows cannot express the layout.\n2. Use local Entasis icon snippets such as `houseIcon`, not Lucide component constructors.\n3. Use `MenuItem[]` from `entasis/menu` for `menu` and action dropdowns.\n4. Do not combine `menu` with `href` or `onclick` on the same row; use `action` for a trailing row menu.\n5. Keep `children`, `header`, `content`, `footer`, `banner`, and action snippets pure; they receive `SidebarApi`.\n6. Use `collapsible=\"icon\"` for icon rail behavior, `collapsible=\"offcanvas\"` for hidden desktop panels, and `collapsible=\"none\"` for fixed sidebars. Icon collapse automatically falls back to offcanvas when any data-driven row lacks an icon.\n7. Offcanvas sidebars reveal over the content from the screen edge by default when hidden; set `edgeReveal={false}` to disable that. A revealed hidden sidebar keeps its resize handle and dismisses through a small rectangular pointer tolerance.\n8. Set `keyboardShortcut={false}` when embedding Sidebar inside another shortcut-heavy surface.\n9. Sidebar owns navigation, resize mechanics, the lower application wall, and variant surface geometry. AppShell forwards its variant and composes PageShell inside that surface.\n10. Use `size` for typography, icon scale, and item height. Use `density` independently for section padding, gaps, and submenu spacing.\n11. Use `activityBar` for a persistent icon rail outside the panel (section switching, workspaces). Every item needs an `icon` and a `label`; the label is the accessible name and the tooltip. It is layout mode only: `mode=\"panel\"` renders the navigation panel alone.\n12. Use `expandOnHover` only with `collapsible=\"icon\"`. It is a temporary peek, not a toggle: the persisted collapsed state never changes, while the peeked panel renders with expanded semantics.\n\n## Data Model\n\n### SidebarGroup\n- **label**: string - Group label, hidden in icon-collapsed mode.\n- **items**: SidebarMenuEntry[] - Menu rows.\n- **tree**: SidebarTreeNode[] - Recursive tree rows instead of menu items.\n- **action**: SidebarMenuActionDescriptor | SidebarMenuActionDescriptor[] | Snippet<[SidebarApi]> - Top-right group actions. Pass an array to pin several affordances (a `+` and a drag handle) to one group header; each renders as its own icon-only ghost button.\n- **collapsible**: boolean - Makes the group label a toggle.\n- **defaultOpen**: boolean - Initial collapsible group state.\n- **separator**: boolean - Divider before the group.\n\n### SidebarMenuEntry\n- **label**: string - Visible row label.\n- **icon**: SidebarIcon - Entasis icon snippet or string.\n- **iconColor**: Colors - Role tint for the leading icon, applied through `data-color`.\n- **iconVariant**: 'bare' | 'tile' - Leading icon treatment. `tile` paints a rounded square (`bg-color-muted text-color-muted-readable`) around the glyph, so per-project colour chips come from the role scale instead of hand-built markup.\n- **href**: string - Render as an anchor. Mutually exclusive with menu.\n- **onclick**: (event: MouseEvent) => void - Native click handler for button or anchor rows. Mutually exclusive with menu.\n- **isActive**: boolean - Adds active styling and `aria-current=\"page\"`.\n- **disabled**: boolean - Disables button rows and marks anchor rows disabled.\n- **badge**: string | number - Trailing count/status, hidden in icon mode.\n- **tooltip**: string - Entasis Tooltip content in icon mode. Defaults to label.\n- **items**: SidebarMenuSubEntry[] - Inline nested menu.\n- **collapsible**: boolean - Set false for an always-open submenu.\n- **defaultOpen**: boolean - Initial nested menu state.\n- **menu**: MenuItem[] - Popup menu opened from the full row. Mutually exclusive with href/onclick.\n- **action**: SidebarMenuActionDescriptor | Snippet<[SidebarApi]> - Hover/focus trailing action.\n\n### SidebarActivityBar\nIcon rail pinned to the outer edge of the sidebar, visible in every display state.\n- **items**: SidebarActivityBarItem[] - Items rendered from the top.\n- **footerItems**: SidebarActivityBarItem[] - Items pinned to the end of the column.\n- **header** / **footer**: Snippet - Custom content before the first item and after the pinned ones.\n- **width**: string (default '3rem') - Column thickness, published as `--sidebar-width-activity`.\n- **label**: string - Accessible name for the column landmark. Set it whenever the panel also renders navigation.\n- **onSelect**: ({ item, index }) => void - Fires after an item is activated. `index` counts `items` then `footerItems`.\n\n### SidebarActivityBarItem\n- **icon**: SidebarIcon (required) - Icon rendered in the square.\n- **label**: string (required) - Accessible name and default tooltip; the square shows no text.\n- **id**: string - Stable render key.\n- **href** / **target** / **rel** - Render an anchor instead of a button.\n- **onclick**: (event: MouseEvent) => void - Native click handler.\n- **isActive**: boolean - Adds active styling and `aria-current=\"page\"`.\n- **badge**: string | number | Snippet - Corner badge pinned to the outer top corner. An empty string renders a bare dot. A string or number badge joins the accessible name (`\"Alerts, 3\"`); a dot and a Snippet badge are decorative, so put their meaning in `label`.\n- **disabled**: boolean - Blocks activation and skips the item during keyboard navigation.\n- **tooltip**: string | false - Tooltip override; `false` suppresses it.\n\n### SidebarMenuButtonItem\nUse for `headerButton`, `footerButton`, or direct `<SidebarMenuButton />` rows.\n- **icon**: SidebarIcon - Leading logo/icon.\n- **avatar**: { src?: string; alt?: string; fallback?: string } - Leading avatar.\n- **variant**: 'default' | 'brand' | 'compact'.\n- **title**: string - Primary text.\n- **subtitle**: string - Secondary text.\n- **trailing**: SidebarIcon | false | SidebarMenuActionDescriptor - Trailing content. An icon is decorative; an action descriptor (`{ icon, label, onclick }`, the same shape as a group action) renders its own icon-only ghost button beside the row, so a workspace card can carry its own collapse control without a custom `header` snippet. Descriptor handlers are `onclick(event, api)`, so `api.toggle()` is reachable.\n- **href** / **onclick** / **menu** - Choose link, button, or popup behavior. `onclick(event, api)` receives the SidebarApi beside the event, so `api.toggle()` is reachable from the row itself.\n- **menuIconClass**: string - Class override for option icons inside the popup menu.\n\n## Props\n\n### State\n- **open**: boolean (bindable, default true) - Desktop expanded state.\n- **defaultOpen**: boolean (default true) - Initial desktop state when `open` is omitted.\n- **onOpenChange**: (open: boolean) => void - Called once for a library-originated desktop state change. Repeated requests and parent prop updates stay silent.\n- **onDisplayStateChange**: (state: SidebarDisplayState) => void - Called once for a library-originated semantic display-state change.\n- **api.displayState**: 'expanded' | 'collapsed' | 'hidden' - Semantic desktop state; hidden means closed offcanvas. A hover peek does not change it.\n- **api.isPeeking**: boolean - True while a hover peek renders the collapsed panel at full width. Read it alongside `displayState` when a snippet hides content in icon mode.\n- **keyboardShortcut**: string | false (default 'b') - Ctrl/Cmd shortcut key.\n\n### Layout\n- **side**: 'left' | 'right' - Desktop and mobile side.\n- **variant**: 'admin' | 'floating' | 'inset' | 'split' | 'framed' - Sidebar geometry. `framed` is the admin geometry for a sidebar hosted inside a raised card (AppShell variant framed), with a `surface-recessed` well. `admin` renders the conventional full-height navigation column; `inset` integrates navigation into the lower wall with an inset content surface; `split` renders detached sidebar and content surfaces.\n- **size**: 'small' | 'normal' | 'large' (default 'normal') - Typography, icon, avatar, badge, leading-media, item-height, and search-height scale.\n- **activeVariant**: 'soft' | 'outline' | 'solid' (default 'soft') - How active rows are painted. `soft` is the shared selected recipe (`selectedSoft`: `bg-selected-muted text-selected-muted-readable`), `solid` its loud counterpart (`selectedSolid`: `bg-selected text-selected-contrast`), `outline` a bordered surface card (`bg-surface border border-neutral-muted text-neutral`) that reads as a raised card on a tinted well. Each row carries the choice as `data-active-variant`, so no descendant selector is needed to restyle selection.\n- **density**: 'compact' | 'normal' | 'comfortable' (default 'normal') - Section padding, group padding, gaps, horizontal inset, and submenu spacing.\n- **collapsible**: 'offcanvas' | 'icon' | 'none' - Collapse behavior. Icon mode requires icons on every data-driven row and otherwise resolves to offcanvas.\n- **collapseIcon**: DisclosureIndicator \u2014 'chevron' | 'plus-minus' | 'none' (default 'chevron') - Disclosure indicator drawn on collapsible menu rows. 'none' renders no indicator.\n- **mode**: 'layout' | 'panel' - Full resizing layout or only the visible navigation panel.\n- **frame**: 'viewport' | 'contained' - Standalone Sidebar positioning. Viewport mode uses Theme's dynamic window-height token; contained mode fills a positioned parent.\n- **width**: string - Expanded width.\n- **widthIcon**: string - Icon-collapsed width.\n- **widthMobile**: string - Mobile drawer width.\n- **rail**: boolean | 'line' | 'thumb' - Edge toggle rail. `true` keeps the thin line style; `thumb` renders a short visible handle with the same full-height hitbox. The appearance is preserved when the rail shares the resize control.\n- **activityBar**: SidebarActivityBar - Icon rail pinned outside the panel, in layout mode only (`mode=\"panel\"` renders the panel alone and ignores it). It never slides off screen: only the panel takes the offcanvas offset, and the reserved layout column is the panel width plus the rail width. On mobile it renders as a horizontal row at the top of the drawer.\n- **expandOnHover**: boolean (default false) - With `collapsible=\"icon\"`, hovering or focusing into the collapsed panel expands it to `width` over the page (`data-peek=\"true\"`) while the reserved column stays at `widthIcon`, so page content does not reflow. The persisted collapsed state is untouched, and the peeked panel renders exactly like an expanded one: group headers, badges, search, inline submenus, and inline tree branches all come back, and the rail or resize handle travels to its inner edge.\n- **edgeReveal**: boolean (default true) - Pointer/focus edge preview for hidden offcanvas sidebars. Hover reveal overlays content, remains resizable when configured, and re-hides after the pointer leaves its small rectangular tolerance. Dragging the sidebar closed suppresses immediate hover reopening until the pointer leaves the edge trigger; toggle/click opens persistently.\n- **resizable**: boolean | SidebarResizableOptions - Enables pointer and keyboard resizing while expanded, icon-collapsed, or temporarily edge-revealed. By default, collapse requires dragging 75% of `minWidth` beyond the minimum; override `collapseThreshold` for a custom boundary. Use `storageKey` to restore and persist the expanded width across sessions.\n - `onWidthChange({ width, isUserInteraction })` reports every expanded-width change with one named payload: continuously while the user resizes (`isUserInteraction: true`) and once when a stored width is restored (`isUserInteraction: false`).\n\n### Content\n- **items**: SidebarGroup[] - Data-driven body navigation.\n- **headerButton** / **footerButton**: SidebarMenuButtonItem - Sticky large rows.\n- **search**: SidebarSearch - Header search input; use its native `oninput` handler.\n- **headerMenu** / **footerMenu**: SidebarMenuEntry[] - Sticky quick menus.\n- Menu entries and nested entries accept `size: 'small' | 'normal' | 'large'` for row geometry.\n- **header**, **content**, **footer**, **children**, **banner**: Snippet<[SidebarApi]> - Escape hatches. The `header` snippet renders **first** in the header region, above `headerButton`, `search` and `headerMenu`.\n\n### Styling\n- **class**: string - Classes applied to the Sidebar root.\n- **theme**: SidebarThemeProps - Semantic part overrides such as `panel`, `header`, `nav`, `footer`, menu, search, rail, and mobile drawer parts.\n\n## Motion\n\n- **motion** theme slot: the y-axis slide shared by collapsible groups, inline submenus, and\n tree branches. Takes `in` / `out` slide params plus a `duration` / `easing` motion token.\n- Ladder: `<Theme components={{ sidebar: { motion } }}>` \u2192 `setSidebarTheme({ motion })` \u2192\n `theme.motion`. Reduced motion collapses it to 0.\n\n## Accessibility\n\n- The body navigation renders inside a named `<nav>` landmark (`data-sidebar=\"nav\"`), so assistive tech can jump straight to it and tell it apart from the activity bar's own landmark.\n- Active links set `aria-current=\"page\"`.\n- Collapsible rows and groups set `aria-expanded`.\n- Disabled buttons use `disabled`; disabled links omit `href`, use `aria-disabled` and `tabindex=-1`, and block activation.\n- Mobile drawer includes a backdrop button labelled \"Close Sidebar\".\n- Icon-collapsed rows keep their labels mounted and visually fade them, preserving accessible names and stable icon geometry.\n- Search, group controls, actions, and nested rows become inert before collapse can remove or hide them; focus returns to the owning visible row.\n- Nested groups, tree branches, and inline submenus use reversible height transitions for open, close, and sidebar-collapse changes.\n- Tree roots use menu-row styling and nested tree nodes use submenu-row styling. In desktop icon mode, root folders open a PopupMenu and descendants remain navigable through recursive Menu submenu popovers; root leaves retain direct navigation and tooltips.\n- When `rail` and `resizable` are both enabled, one edge control owns click-to-toggle, drag resize, and keyboard resize without overlapping hitboxes.\n- Hidden offcanvas sidebars keep that combined edge control while temporarily revealed. Resizing does not pin the sidebar open; leaving the panel, trigger, and handle tolerance re-hides it without discarding the configured width.\n- Both peeks (edge reveal and `expandOnHover`) stay open while focus is inside the panel or while an overlay opened from inside it is open, including nested submenus. They release about 120ms after the pointer, focus, and every such overlay are gone.\n- The activity bar is its own `<nav>` landmark with a `<ul>` of items, a roving tabindex, and ArrowUp/ArrowDown/Home/End navigation that loops and skips disabled items. Tab lands on the `isActive` item. Each square takes its accessible name from `label`, with a string or number `badge` appended to it, and shows `label` as a tooltip on hover and focus.\n- A hidden offcanvas panel is `inert`, so Tab never lands in a panel parked off screen; a peek makes it interactive again.\n\n## Notes\n\n- Dropdown menus use Entasis `PopupMenu` and `MenuItem[]`.\n- The component uses semantic Entasis tokens. Do not add shadcn `sidebar-*` color tokens.\n- Snippet icons from `entasis/icons/*` are the preferred icon format.\n";
1
+ export declare const sidebarDescription = "\n# Sidebar Component\n\nSidebar navigation with data-driven groups, icon collapse, mobile drawer behavior,\nrecursive tree groups, header/footer rows, search, actions, and snippet escape hatches.\n\n## Import\n\n```svelte\n<script lang=\"ts\">\n\timport { Sidebar, type SidebarGroup } from 'entasis/sidebar';\n</script>\n```\n\n## Basic Usage\n\n```svelte\n<script lang=\"ts\">\n\timport { Sidebar, type SidebarGroup } from 'entasis/sidebar';\n\timport { houseIcon } from 'entasis/icons/house';\n\timport { gearIcon } from 'entasis/icons/gear';\n\n\tconst items: SidebarGroup[] = [\n\t\t{\n\t\t\tlabel: 'Workspace',\n\t\t\titems: [\n\t\t\t\t{ label: 'Dashboard', href: '/', icon: houseIcon, isActive: true },\n\t\t\t\t{ label: 'Settings', href: '/settings', icon: gearIcon }\n\t\t\t]\n\t\t}\n\t];\n</script>\n\n<Sidebar items={items}>\n\t{#snippet children({ toggle })}\n\t\t<header>\n\t\t\t<button type=\"button\" onclick={toggle}>Toggle</button>\n\t\t</header>\n\t\t<main>Page content</main>\n\t{/snippet}\n</Sidebar>\n```\n\n## AI-Safe Usage Contract\n\n1. Use `items` for normal navigation. Use `content` only when data-driven rows cannot express the layout.\n2. Use local Entasis icon snippets such as `houseIcon`, not Lucide component constructors.\n3. Use `MenuItem[]` from `entasis/menu` for `menu` and action dropdowns.\n4. Do not combine `menu` with `href` or `onclick` on the same row; use `action` for a trailing row menu.\n5. Keep `children`, `header`, `content`, `footer`, `banner`, and action snippets pure; they receive `SidebarApi`.\n6. Use `collapsible=\"icon\"` for icon rail behavior, `collapsible=\"offcanvas\"` for hidden desktop panels, and `collapsible=\"none\"` for fixed sidebars. Icon collapse automatically falls back to offcanvas when any data-driven row lacks an icon.\n7. Offcanvas sidebars reveal over the content from the screen edge by default when hidden; set `edgeReveal={false}` to disable that. A revealed hidden sidebar keeps its resize handle and dismisses through a small rectangular pointer tolerance.\n8. Set `keyboardShortcut={false}` when embedding Sidebar inside another shortcut-heavy surface.\n9. Sidebar owns navigation, resize mechanics, the lower application wall, and variant surface geometry. AppShell forwards its variant and composes PageShell inside that surface.\n10. Use `size` for typography, icon scale, and item height. Use `density` independently for section padding, gaps, and submenu spacing.\n11. Use `activityBar` for a persistent icon rail outside the panel (section switching, workspaces). Every item needs an `icon` and a `label`; the label is the accessible name and the tooltip. It is layout mode only: `mode=\"panel\"` renders the navigation panel alone.\n12. Use `expandOnHover` only with `collapsible=\"icon\"`. It is a temporary peek, not a toggle: the persisted collapsed state never changes, while the peeked panel renders with expanded semantics.\n\n## Data Model\n\n### SidebarGroup\n- **label**: string - Group label, hidden in icon-collapsed mode.\n- **items**: SidebarMenuEntry[] - Menu rows.\n- **tree**: SidebarTreeNode[] - Recursive tree rows instead of menu items.\n- **action**: SidebarMenuActionDescriptor | SidebarMenuActionDescriptor[] | Snippet<[SidebarApi]> - Top-right group actions. Pass an array to pin several affordances (a `+` and a drag handle) to one group header; each renders as its own icon-only ghost button.\n- **collapsible**: boolean - Makes the group label a toggle.\n- **defaultOpen**: boolean - Initial collapsible group state.\n- **separator**: boolean - Divider before the group.\n\n### SidebarMenuEntry\n- **label**: string - Visible row label.\n- **icon**: SidebarIcon - Entasis icon snippet or string.\n- **iconColor**: Colors - Role tint for the leading icon, applied through `data-color`.\n- **iconVariant**: 'bare' | 'tile' - Leading icon treatment. `tile` paints a rounded square (`bg-color-muted text-color-muted-readable`) around the glyph, so per-project colour chips come from the role scale instead of hand-built markup.\n- **href**: string - Render as an anchor. Mutually exclusive with menu.\n- **onclick**: (event: MouseEvent) => void - Native click handler for button or anchor rows. Mutually exclusive with menu.\n- **isActive**: boolean - Adds active styling and `aria-current=\"page\"`.\n- **disabled**: boolean - Disables button rows and marks anchor rows disabled.\n- **badge**: string | number - Trailing count/status, hidden in icon mode.\n- **tooltip**: string - Entasis Tooltip content in icon mode. Defaults to label.\n- **items**: SidebarMenuSubEntry[] - Inline nested menu.\n- **collapsible**: boolean - Set false for an always-open submenu.\n- **defaultOpen**: boolean - Initial nested menu state.\n- **menu**: MenuItem[] - Popup menu opened from the full row. Mutually exclusive with href/onclick.\n- **action**: SidebarMenuActionDescriptor | Snippet<[SidebarApi]> - Hover/focus trailing action.\n\n### SidebarActivityBar\nIcon rail pinned to the outer edge of the sidebar, visible in every display state.\n- **items**: SidebarActivityBarItem[] - Items rendered from the top.\n- **footerItems**: SidebarActivityBarItem[] - Items pinned to the end of the column.\n- **header** / **footer**: Snippet - Custom content before the first item and after the pinned ones.\n- **width**: string (default '3rem') - Column thickness, published as `--sidebar-width-activity`.\n- **label**: string - Accessible name for the column landmark. Set it whenever the panel also renders navigation.\n- **onSelect**: ({ item, index }) => void - Fires after an item is activated. `index` counts `items` then `footerItems`.\n\n### SidebarActivityBarItem\n- **icon**: SidebarIcon (required) - Icon rendered in the square.\n- **label**: string (required) - Accessible name and default tooltip; the square shows no text.\n- **id**: string - Stable render key.\n- **href** / **target** / **rel** - Render an anchor instead of a button.\n- **onclick**: (event: MouseEvent) => void - Native click handler.\n- **isActive**: boolean - Adds active styling and `aria-current=\"page\"`.\n- **badge**: string | number | Snippet - Corner badge pinned to the outer top corner. An empty string renders a bare dot. A string or number badge joins the accessible name (`\"Alerts, 3\"`); a dot and a Snippet badge are decorative, so put their meaning in `label`.\n- **disabled**: boolean - Blocks activation and skips the item during keyboard navigation.\n- **tooltip**: string | false - Tooltip override; `false` suppresses it.\n\n### SidebarMenuButtonItem\nUse for `headerButton`, `footerButton`, or direct `<SidebarMenuButton />` rows.\n- **icon**: SidebarIcon - Leading logo/icon.\n- **avatar**: { src?: string; alt?: string; fallback?: string } - Leading avatar.\n- **variant**: 'default' | 'brand' | 'compact'.\n- **title**: string - Primary text.\n- **subtitle**: string - Secondary text.\n- **trailing**: SidebarIcon | false | SidebarMenuActionDescriptor - Trailing content. An icon is decorative; an action descriptor (`{ icon, label, onclick }`, the same shape as a group action) renders its own icon-only ghost button beside the row, so a workspace card can carry its own collapse control without a custom `header` snippet. Descriptor handlers are `onclick(event, api)`, so `api.toggle()` is reachable.\n- **href** / **onclick** / **menu** - Choose link, button, or popup behavior. `onclick(event, api)` receives the SidebarApi beside the event, so `api.toggle()` is reachable from the row itself.\n- **menuIconClass**: string - Class override for option icons inside the popup menu.\n\n## Props\n\n### State\n- **open**: boolean (bindable, default true) - Desktop expanded state.\n- **defaultOpen**: boolean (default true) - Initial desktop state when `open` is omitted.\n- **onOpenChange**: (open: boolean) => void - Called once for a library-originated desktop state change. Repeated requests and parent prop updates stay silent.\n- **onDisplayStateChange**: (state: SidebarDisplayState) => void - Called once for a library-originated semantic display-state change.\n- **api.displayState**: 'expanded' | 'collapsed' | 'hidden' - Semantic desktop state; hidden means closed offcanvas. A hover peek does not change it.\n- **api.isPeeking**: boolean - True while a hover peek renders the collapsed panel at full width. Read it alongside `displayState` when a snippet hides content in icon mode.\n- **keyboardShortcut**: string | false (default 'b') - Ctrl/Cmd shortcut key.\n\n### Layout\n- **side**: 'left' | 'right' - Desktop and mobile side.\n- **variant**: 'admin' | 'floating' | 'inset' | 'split' | 'framed' - Sidebar geometry. `framed` is the admin geometry for a sidebar hosted inside a raised card (AppShell variant framed), with a `surface-recessed` well. `admin` renders the conventional full-height navigation column; `inset` integrates navigation into the lower wall with an inset content surface; `split` renders detached sidebar and content surfaces.\n- **size**: 'small' | 'normal' | 'large' (default 'normal') - Typography, icon, avatar, badge, leading-media, item-height, and search-height scale.\n- **iconSize**: 'small' | 'normal' | 'large' - Icon and leading-media scale inside the panel on its own; defaults to `size`. Menu rows, sub rows, group labels and the header button follow it; the activity bar keeps `size`.\n- **activeVariant**: 'soft' | 'outline' | 'solid' (default 'soft') - How active rows are painted. `soft` is the shared selected recipe (`selectedSoft`: `bg-selected-muted text-selected-muted-readable`), `solid` its loud counterpart (`selectedSolid`: `bg-selected text-selected-contrast`), `outline` a bordered surface card (`bg-surface border border-neutral-muted text-neutral`) that reads as a raised card on a tinted well. Each row carries the choice as `data-active-variant`, so no descendant selector is needed to restyle selection.\n- **density**: 'compact' | 'normal' | 'comfortable' (default 'normal') - Section padding, group padding, gaps, horizontal inset, and submenu spacing.\n- **collapsible**: 'offcanvas' | 'icon' | 'none' - Collapse behavior. Icon mode requires icons on every data-driven row and otherwise resolves to offcanvas.\n- **collapseIcon**: DisclosureIndicator \u2014 'chevron' | 'plus-minus' | 'none' (default 'chevron') - Disclosure indicator drawn on collapsible menu rows. 'none' renders no indicator.\n- **mode**: 'layout' | 'panel' - Full resizing layout or only the visible navigation panel.\n- **frame**: 'viewport' | 'contained' - Standalone Sidebar positioning. Viewport mode uses Theme's dynamic window-height token; contained mode fills a positioned parent.\n- **width**: string - Expanded width.\n- **widthIcon**: string - Icon-collapsed width.\n- **widthMobile**: string - Mobile drawer width.\n- **rail**: boolean | 'line' | 'thumb' - Edge toggle rail. `true` keeps the thin line style; `thumb` renders a short visible handle with the same full-height hitbox. The appearance is preserved when the rail shares the resize control.\n- **activityBar**: SidebarActivityBar - Icon rail pinned outside the panel, in layout mode only (`mode=\"panel\"` renders the panel alone and ignores it). It never slides off screen: only the panel takes the offcanvas offset, and the reserved layout column is the panel width plus the rail width. On mobile it renders as a horizontal row at the top of the drawer.\n- **expandOnHover**: boolean (default false) - With `collapsible=\"icon\"`, hovering or focusing into the collapsed panel expands it to `width` over the page (`data-peek=\"true\"`) while the reserved column stays at `widthIcon`, so page content does not reflow. The persisted collapsed state is untouched, and the peeked panel renders exactly like an expanded one: group headers, badges, search, inline submenus, and inline tree branches all come back, and the rail or resize handle travels to its inner edge.\n- **edgeReveal**: boolean (default true) - Pointer/focus edge preview for hidden offcanvas sidebars. Hover reveal overlays content, remains resizable when configured, and re-hides after the pointer leaves its small rectangular tolerance. Dragging the sidebar closed suppresses immediate hover reopening until the pointer leaves the edge trigger; toggle/click opens persistently.\n- **resizable**: boolean | SidebarResizableOptions - Enables pointer and keyboard resizing while expanded, icon-collapsed, or temporarily edge-revealed. By default, collapse requires dragging 75% of `minWidth` beyond the minimum; override `collapseThreshold` for a custom boundary. Use `storageKey` to restore and persist the expanded width across sessions.\n - `onWidthChange({ width, isUserInteraction })` reports every expanded-width change with one named payload: continuously while the user resizes (`isUserInteraction: true`) and once when a stored width is restored (`isUserInteraction: false`).\n\n### Content\n- **items**: SidebarGroup[] - Data-driven body navigation.\n- **headerButton** / **footerButton**: SidebarMenuButtonItem - Sticky large rows.\n- **search**: SidebarSearch - Header search input; use its native `oninput` handler.\n- **headerMenu** / **footerMenu**: SidebarMenuEntry[] - Sticky quick menus.\n- Menu entries and nested entries accept `size: 'small' | 'normal' | 'large'` for row geometry.\n- **header**, **content**, **footer**, **children**, **banner**: Snippet<[SidebarApi]> - Escape hatches. The `header` snippet renders **first** in the header region, above `headerButton`, `search` and `headerMenu`.\n\n### Styling\n- **class**: string - Classes applied to the Sidebar root.\n- **theme**: SidebarThemeProps - Semantic part overrides such as `panel`, `header`, `nav`, `footer`, menu, search, rail, and mobile drawer parts. Every part, with the element it lands on, its variants and their default classes, is listed in the entasis skill's `theme-parts/sidebar.md`; the registry key is `sidebar`.\n\n## Motion\n\n- **motion** theme slot: the y-axis slide shared by collapsible groups, inline submenus, and\n tree branches. Takes `in` / `out` slide params plus a `duration` / `easing` motion token.\n- Ladder: `<Theme components={{ sidebar: { motion } }}>` \u2192 `setSidebarTheme({ motion })` \u2192\n `theme.motion`. Reduced motion collapses it to 0.\n\n## Restyle recipes\n\nThe five asks that come up first, as the override to copy. Each one is rendered and asserted by\n`sidebar-recipes.svelte.test.ts`, so it cannot drift from the component. One rule behind them: a\ndefault written under a variant prefix (`data-[active-variant=solid]:data-active:bg-selected`,\n`data-[side=left]:border-r`) is only replaced by an override carrying the same prefixes; an\nunprefixed class coexists with it and loses on specificity. `theme-parts/sidebar.md` shows every\ndefault verbatim, prefixes included.\n\n- **Dark panel.** `dark` scopes the dark theme's variables to the panel, so every neutral ink inside\n flips with it (every theme also emits its variables on `.<name>`, so the class scopes the dark theme to one subtree); needs a theme named `dark`, which the documented setup declares.\n `theme={{ panel: { base: 'dark bg-slate-900' }, mobilePanel: { base: 'dark bg-slate-900' } }}`\n- **Active row in your colour.** `activeVariant=\"solid\"` plus the same prefix chain as the default:\n `theme={{ menuButton: { base: 'rounded-full', activeVariant: { solid: 'data-[active-variant=solid]:data-active:bg-indigo-600 data-[active-variant=solid]:data-active:text-white' } } }}`\n- **No hover change.** The overlay is a `::before` and the default also brightens the ink on hover:\n `theme={{ menuButton: { base: 'state-layer-none hover:text-inherit' }, subButton: { base: 'state-layer-none hover:text-neutral/70' } }}`\n- **Flat panel.** The edge is a prefixed `border-r` / `border-l` on the admin variant, the shadow a\n `raised-*` on the floating ones:\n `theme={{ panel: { base: 'raised-none', variant: { admin: 'data-[side=left]:border-r-0 data-[side=right]:border-l-0' } } }}`\n- **Row height.** A plain height beats the compound `h-control-*`: `theme={{ menuButton: { base: 'h-11' } }}`\n- **Bigger icons.** A prop, not a theme: `iconSize=\"large\"`.\n\n## Accessibility\n\n- The body navigation renders inside a named `<nav>` landmark (`data-sidebar=\"nav\"`), so assistive tech can jump straight to it and tell it apart from the activity bar's own landmark.\n- Active links set `aria-current=\"page\"`.\n- Collapsible rows and groups set `aria-expanded`.\n- Disabled buttons use `disabled`; disabled links omit `href`, use `aria-disabled` and `tabindex=-1`, and block activation.\n- Mobile drawer includes a backdrop button labelled \"Close Sidebar\".\n- Icon-collapsed rows keep their labels mounted and visually fade them, preserving accessible names and stable icon geometry.\n- Search, group controls, actions, and nested rows become inert before collapse can remove or hide them; focus returns to the owning visible row.\n- Nested groups, tree branches, and inline submenus use reversible height transitions for open, close, and sidebar-collapse changes.\n- Tree roots use menu-row styling and nested tree nodes use submenu-row styling. In desktop icon mode, root folders open a PopupMenu and descendants remain navigable through recursive Menu submenu popovers; root leaves retain direct navigation and tooltips.\n- When `rail` and `resizable` are both enabled, one edge control owns click-to-toggle, drag resize, and keyboard resize without overlapping hitboxes.\n- Hidden offcanvas sidebars keep that combined edge control while temporarily revealed. Resizing does not pin the sidebar open; leaving the panel, trigger, and handle tolerance re-hides it without discarding the configured width.\n- Both peeks (edge reveal and `expandOnHover`) stay open while focus is inside the panel or while an overlay opened from inside it is open, including nested submenus. They release about 120ms after the pointer, focus, and every such overlay are gone.\n- The activity bar is its own `<nav>` landmark with a `<ul>` of items, a roving tabindex, and ArrowUp/ArrowDown/Home/End navigation that loops and skips disabled items. Tab lands on the `isActive` item. Each square takes its accessible name from `label`, with a string or number `badge` appended to it, and shows `label` as a tooltip on hover and focus.\n- A hidden offcanvas panel is `inert`, so Tab never lands in a panel parked off screen; a peek makes it interactive again.\n\n## Notes\n\n- Dropdown menus use Entasis `PopupMenu` and `MenuItem[]`.\n- The component uses semantic Entasis tokens. Do not add shadcn `sidebar-*` color tokens.\n- Snippet icons from `entasis/icons/*` are the preferred icon format.\n";
@@ -130,6 +130,7 @@ Use for \`headerButton\`, \`footerButton\`, or direct \`<SidebarMenuButton />\`
130
130
  - **side**: 'left' | 'right' - Desktop and mobile side.
131
131
  - **variant**: 'admin' | 'floating' | 'inset' | 'split' | 'framed' - Sidebar geometry. \`framed\` is the admin geometry for a sidebar hosted inside a raised card (AppShell variant framed), with a \`surface-recessed\` well. \`admin\` renders the conventional full-height navigation column; \`inset\` integrates navigation into the lower wall with an inset content surface; \`split\` renders detached sidebar and content surfaces.
132
132
  - **size**: 'small' | 'normal' | 'large' (default 'normal') - Typography, icon, avatar, badge, leading-media, item-height, and search-height scale.
133
+ - **iconSize**: 'small' | 'normal' | 'large' - Icon and leading-media scale inside the panel on its own; defaults to \`size\`. Menu rows, sub rows, group labels and the header button follow it; the activity bar keeps \`size\`.
133
134
  - **activeVariant**: 'soft' | 'outline' | 'solid' (default 'soft') - How active rows are painted. \`soft\` is the shared selected recipe (\`selectedSoft\`: \`bg-selected-muted text-selected-muted-readable\`), \`solid\` its loud counterpart (\`selectedSolid\`: \`bg-selected text-selected-contrast\`), \`outline\` a bordered surface card (\`bg-surface border border-neutral-muted text-neutral\`) that reads as a raised card on a tinted well. Each row carries the choice as \`data-active-variant\`, so no descendant selector is needed to restyle selection.
134
135
  - **density**: 'compact' | 'normal' | 'comfortable' (default 'normal') - Section padding, group padding, gaps, horizontal inset, and submenu spacing.
135
136
  - **collapsible**: 'offcanvas' | 'icon' | 'none' - Collapse behavior. Icon mode requires icons on every data-driven row and otherwise resolves to offcanvas.
@@ -156,7 +157,7 @@ Use for \`headerButton\`, \`footerButton\`, or direct \`<SidebarMenuButton />\`
156
157
 
157
158
  ### Styling
158
159
  - **class**: string - Classes applied to the Sidebar root.
159
- - **theme**: SidebarThemeProps - Semantic part overrides such as \`panel\`, \`header\`, \`nav\`, \`footer\`, menu, search, rail, and mobile drawer parts.
160
+ - **theme**: SidebarThemeProps - Semantic part overrides such as \`panel\`, \`header\`, \`nav\`, \`footer\`, menu, search, rail, and mobile drawer parts. Every part, with the element it lands on, its variants and their default classes, is listed in the entasis skill's \`theme-parts/sidebar.md\`; the registry key is \`sidebar\`.
160
161
 
161
162
  ## Motion
162
163
 
@@ -165,6 +166,28 @@ Use for \`headerButton\`, \`footerButton\`, or direct \`<SidebarMenuButton />\`
165
166
  - Ladder: \`<Theme components={{ sidebar: { motion } }}>\` → \`setSidebarTheme({ motion })\` →
166
167
  \`theme.motion\`. Reduced motion collapses it to 0.
167
168
 
169
+ ## Restyle recipes
170
+
171
+ The five asks that come up first, as the override to copy. Each one is rendered and asserted by
172
+ \`sidebar-recipes.svelte.test.ts\`, so it cannot drift from the component. One rule behind them: a
173
+ default written under a variant prefix (\`data-[active-variant=solid]:data-active:bg-selected\`,
174
+ \`data-[side=left]:border-r\`) is only replaced by an override carrying the same prefixes; an
175
+ unprefixed class coexists with it and loses on specificity. \`theme-parts/sidebar.md\` shows every
176
+ default verbatim, prefixes included.
177
+
178
+ - **Dark panel.** \`dark\` scopes the dark theme's variables to the panel, so every neutral ink inside
179
+ flips with it (every theme also emits its variables on \`.<name>\`, so the class scopes the dark theme to one subtree); needs a theme named \`dark\`, which the documented setup declares.
180
+ \`theme={{ panel: { base: 'dark bg-slate-900' }, mobilePanel: { base: 'dark bg-slate-900' } }}\`
181
+ - **Active row in your colour.** \`activeVariant="solid"\` plus the same prefix chain as the default:
182
+ \`theme={{ menuButton: { base: 'rounded-full', activeVariant: { solid: 'data-[active-variant=solid]:data-active:bg-indigo-600 data-[active-variant=solid]:data-active:text-white' } } }}\`
183
+ - **No hover change.** The overlay is a \`::before\` and the default also brightens the ink on hover:
184
+ \`theme={{ menuButton: { base: 'state-layer-none hover:text-inherit' }, subButton: { base: 'state-layer-none hover:text-neutral/70' } }}\`
185
+ - **Flat panel.** The edge is a prefixed \`border-r\` / \`border-l\` on the admin variant, the shadow a
186
+ \`raised-*\` on the floating ones:
187
+ \`theme={{ panel: { base: 'raised-none', variant: { admin: 'data-[side=left]:border-r-0 data-[side=right]:border-l-0' } } }}\`
188
+ - **Row height.** A plain height beats the compound \`h-control-*\`: \`theme={{ menuButton: { base: 'h-11' } }}\`
189
+ - **Bigger icons.** A prop, not a theme: \`iconSize="large"\`.
190
+
168
191
  ## Accessibility
169
192
 
170
193
  - The body navigation renders inside a named \`<nav>\` landmark (\`data-sidebar="nav"\`), so assistive tech can jump straight to it and tell it apart from the activity bar's own landmark.
@@ -344,6 +344,8 @@ type SidebarOwnProps = {
344
344
  variant?: SidebarVariant;
345
345
  /** Typography, icon, and item-height scale. */
346
346
  size?: SidebarSize;
347
+ /** Icon and leading-media scale inside the panel, on its own. Defaults to `size`. */
348
+ iconSize?: SidebarSize;
347
349
  /** How active rows are painted. Defaults to 'soft', the shared selected recipe. */
348
350
  activeVariant?: SidebarActiveVariant;
349
351
  /** Spacing density for section padding, gaps, and nested navigation. */