@stacksjs/components 0.2.92 → 0.2.94

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 (188) hide show
  1. package/dist/{Sidebar-yb115a2w.stx → Sidebar-4hn7vw4n.stx} +18 -0
  2. package/dist/index.js +5 -5
  3. package/package.json +5 -6
  4. package/src/components/CodeBlock.stx +0 -54
  5. package/src/components/Footer.stx +0 -66
  6. package/src/components/Hero.stx +0 -25
  7. package/src/components/Installation.stx +0 -37
  8. package/src/components/index.ts +0 -4
  9. package/src/composables/index.ts +0 -4
  10. package/src/composables/useCopyCode.ts +0 -73
  11. package/src/composables/useDarkMode.ts +0 -100
  12. package/src/composables/useSEO.ts +0 -230
  13. package/src/composables/utilities/index.ts +0 -7
  14. package/src/composables/utilities/useClickOutside.ts +0 -72
  15. package/src/composables/utilities/useFocusTrap.ts +0 -159
  16. package/src/composables/utilities/useKeyboard.ts +0 -124
  17. package/src/composables/utilities/useLocalStorage.ts +0 -132
  18. package/src/composables/utilities/useMediaQuery.ts +0 -118
  19. package/src/index.ts +0 -99
  20. package/src/stx.d.ts +0 -4
  21. package/src/ui/accordion/Accordion.stx +0 -146
  22. package/src/ui/accordion/AccordionItem.stx +0 -37
  23. package/src/ui/accordion/index.ts +0 -47
  24. package/src/ui/audio/Audio.stx +0 -50
  25. package/src/ui/audio/README.md +0 -41
  26. package/src/ui/audio/index.ts +0 -13
  27. package/src/ui/auth/Login.stx +0 -161
  28. package/src/ui/auth/README.md +0 -142
  29. package/src/ui/auth/Signup.stx +0 -159
  30. package/src/ui/auth/TwoFactorChallenge.stx +0 -111
  31. package/src/ui/auth/index.ts +0 -32
  32. package/src/ui/avatar/Avatar.stx +0 -77
  33. package/src/ui/avatar/index.ts +0 -12
  34. package/src/ui/badge/Badge.stx +0 -62
  35. package/src/ui/badge/index.ts +0 -10
  36. package/src/ui/breadcrumb/Breadcrumb.stx +0 -79
  37. package/src/ui/breadcrumb/index.ts +0 -15
  38. package/src/ui/button/Button.stx +0 -74
  39. package/src/ui/button/README.md +0 -80
  40. package/src/ui/button/index.ts +0 -85
  41. package/src/ui/calendar/Calendar.stx +0 -189
  42. package/src/ui/calendar/README.md +0 -254
  43. package/src/ui/calendar/index.ts +0 -14
  44. package/src/ui/card/Card.stx +0 -68
  45. package/src/ui/card/index.ts +0 -13
  46. package/src/ui/checkbox/Checkbox.stx +0 -86
  47. package/src/ui/checkbox/index.ts +0 -16
  48. package/src/ui/combobox/Combobox.stx +0 -96
  49. package/src/ui/combobox/ComboboxButton.stx +0 -25
  50. package/src/ui/combobox/ComboboxInput.stx +0 -32
  51. package/src/ui/combobox/ComboboxOption.stx +0 -49
  52. package/src/ui/combobox/ComboboxOptions.stx +0 -16
  53. package/src/ui/combobox/README.md +0 -150
  54. package/src/ui/combobox/index.ts +0 -40
  55. package/src/ui/command-palette/CommandPalette.stx +0 -81
  56. package/src/ui/command-palette/CommandPaletteItem.stx +0 -27
  57. package/src/ui/command-palette/README.md +0 -42
  58. package/src/ui/command-palette/index.ts +0 -15
  59. package/src/ui/dialog/Dialog.stx +0 -41
  60. package/src/ui/dialog/DialogBackdrop.stx +0 -9
  61. package/src/ui/dialog/DialogDescription.stx +0 -11
  62. package/src/ui/dialog/DialogPanel.stx +0 -16
  63. package/src/ui/dialog/DialogTitle.stx +0 -11
  64. package/src/ui/dialog/README.md +0 -121
  65. package/src/ui/dialog/index.ts +0 -32
  66. package/src/ui/drawer/Drawer.stx +0 -120
  67. package/src/ui/drawer/README.md +0 -90
  68. package/src/ui/drawer/index.ts +0 -9
  69. package/src/ui/dropdown/Dropdown.stx +0 -82
  70. package/src/ui/dropdown/DropdownButton.stx +0 -29
  71. package/src/ui/dropdown/DropdownItem.stx +0 -35
  72. package/src/ui/dropdown/DropdownItems.stx +0 -18
  73. package/src/ui/dropdown/README.md +0 -114
  74. package/src/ui/dropdown/index.ts +0 -29
  75. package/src/ui/form/Form.stx +0 -95
  76. package/src/ui/form/index.ts +0 -67
  77. package/src/ui/heatmap/Heatmap.stx +0 -294
  78. package/src/ui/image/Image.stx +0 -165
  79. package/src/ui/image/README.md +0 -164
  80. package/src/ui/image/index.ts +0 -22
  81. package/src/ui/input/EmailInput.stx +0 -30
  82. package/src/ui/input/NumberInput.stx +0 -126
  83. package/src/ui/input/PasswordInput.stx +0 -143
  84. package/src/ui/input/SearchInput.stx +0 -44
  85. package/src/ui/input/TextInput.stx +0 -132
  86. package/src/ui/input/index.ts +0 -180
  87. package/src/ui/listbox/Listbox.stx +0 -101
  88. package/src/ui/listbox/ListboxButton.stx +0 -28
  89. package/src/ui/listbox/ListboxLabel.stx +0 -11
  90. package/src/ui/listbox/ListboxOption.stx +0 -49
  91. package/src/ui/listbox/ListboxOptions.stx +0 -16
  92. package/src/ui/listbox/README.md +0 -135
  93. package/src/ui/listbox/index.ts +0 -39
  94. package/src/ui/navigator/Navigator.stx +0 -113
  95. package/src/ui/navigator/README.md +0 -352
  96. package/src/ui/navigator/index.ts +0 -20
  97. package/src/ui/notification/Notification.stx +0 -117
  98. package/src/ui/notification/README.md +0 -114
  99. package/src/ui/notification/index.ts +0 -12
  100. package/src/ui/pagination/Pagination.stx +0 -150
  101. package/src/ui/pagination/index.ts +0 -11
  102. package/src/ui/payment/Checkout.stx +0 -31
  103. package/src/ui/payment/DefaultPaymentMethod.stx +0 -62
  104. package/src/ui/payment/PaymentMethods.stx +0 -104
  105. package/src/ui/payment/README.md +0 -345
  106. package/src/ui/payment/SubscriptionCheckout.stx +0 -323
  107. package/src/ui/payment/index.ts +0 -59
  108. package/src/ui/popover/Popover.stx +0 -60
  109. package/src/ui/popover/PopoverButton.stx +0 -29
  110. package/src/ui/popover/PopoverPanel.stx +0 -23
  111. package/src/ui/popover/README.md +0 -91
  112. package/src/ui/popover/index.ts +0 -22
  113. package/src/ui/portal/Portal.stx +0 -57
  114. package/src/ui/portal/index.ts +0 -6
  115. package/src/ui/progress/Progress.stx +0 -131
  116. package/src/ui/progress/index.ts +0 -12
  117. package/src/ui/radio/Radio.stx +0 -77
  118. package/src/ui/radio/index.ts +0 -15
  119. package/src/ui/radio-group/README.md +0 -139
  120. package/src/ui/radio-group/RadioGroup.stx +0 -60
  121. package/src/ui/radio-group/RadioGroupDescription.stx +0 -11
  122. package/src/ui/radio-group/RadioGroupLabel.stx +0 -11
  123. package/src/ui/radio-group/RadioGroupOption.stx +0 -58
  124. package/src/ui/radio-group/index.ts +0 -30
  125. package/src/ui/select/README.md +0 -180
  126. package/src/ui/select/Select.stx +0 -82
  127. package/src/ui/select/index.ts +0 -21
  128. package/src/ui/sidebar/Sidebar.stx +0 -458
  129. package/src/ui/sidebar/SidebarFooter.stx +0 -71
  130. package/src/ui/sidebar/SidebarHeader.stx +0 -103
  131. package/src/ui/sidebar/SidebarItem.stx +0 -86
  132. package/src/ui/sidebar/SidebarSection.stx +0 -83
  133. package/src/ui/sidebar/index.ts +0 -153
  134. package/src/ui/sidebar/themes.ts +0 -240
  135. package/src/ui/skeleton/Skeleton.stx +0 -48
  136. package/src/ui/skeleton/index.ts +0 -11
  137. package/src/ui/spinner/Spinner.stx +0 -109
  138. package/src/ui/spinner/index.ts +0 -9
  139. package/src/ui/stepper/README.md +0 -36
  140. package/src/ui/stepper/Stepper.stx +0 -17
  141. package/src/ui/stepper/StepperStep.stx +0 -57
  142. package/src/ui/stepper/index.ts +0 -19
  143. package/src/ui/storage/README.md +0 -193
  144. package/src/ui/storage/index.ts +0 -347
  145. package/src/ui/switch/README.md +0 -114
  146. package/src/ui/switch/Switch.stx +0 -72
  147. package/src/ui/switch/index.ts +0 -10
  148. package/src/ui/table/README.md +0 -39
  149. package/src/ui/table/Table.stx +0 -14
  150. package/src/ui/table/TableBody.stx +0 -10
  151. package/src/ui/table/TableCell.stx +0 -10
  152. package/src/ui/table/TableHead.stx +0 -10
  153. package/src/ui/table/TableHeader.stx +0 -20
  154. package/src/ui/table/TableRow.stx +0 -11
  155. package/src/ui/table/index.ts +0 -35
  156. package/src/ui/tabs/TabPanel.stx +0 -25
  157. package/src/ui/tabs/Tabs.stx +0 -202
  158. package/src/ui/tabs/index.ts +0 -50
  159. package/src/ui/teleport/Teleport.stx +0 -65
  160. package/src/ui/teleport/index.ts +0 -7
  161. package/src/ui/textarea/Textarea.stx +0 -108
  162. package/src/ui/textarea/index.ts +0 -20
  163. package/src/ui/tooltip/Tooltip.stx +0 -71
  164. package/src/ui/tooltip/index.ts +0 -10
  165. package/src/ui/transition/README.md +0 -30
  166. package/src/ui/transition/Transition.stx +0 -102
  167. package/src/ui/transition/index.ts +0 -25
  168. package/src/ui/video/README.md +0 -47
  169. package/src/ui/video/Video.stx +0 -45
  170. package/src/ui/video/index.ts +0 -16
  171. package/src/ui/virtual-list/VirtualList.stx +0 -67
  172. package/src/ui/virtual-list/index.ts +0 -10
  173. package/src/ui/virtual-table/VirtualTable.stx +0 -103
  174. package/src/ui/virtual-table/index.ts +0 -21
  175. package/src/utils/PROP_VALIDATION.md +0 -458
  176. package/src/utils/THEME_SYSTEM.md +0 -702
  177. package/src/utils/accessibility.ts +0 -841
  178. package/src/utils/animation/easing.ts +0 -368
  179. package/src/utils/animation/helpers.ts +0 -223
  180. package/src/utils/animation/index.ts +0 -5
  181. package/src/utils/animation/keyframes.ts +0 -230
  182. package/src/utils/error-handling.ts +0 -475
  183. package/src/utils/highlighter.ts +0 -93
  184. package/src/utils/i18n.ts +0 -634
  185. package/src/utils/keep-alive.ts +0 -819
  186. package/src/utils/lazy-loading.ts +0 -530
  187. package/src/utils/prop-validation.ts +0 -478
  188. package/src/utils/theme.ts +0 -626
@@ -1,86 +0,0 @@
1
- <script server>
2
- import { resolveIconColor, resolveSidebarTheme } from './themes'
3
-
4
- export const id = $props.id || ''
5
- export const label = $props.label || ''
6
- export const icon = $props.icon || ''
7
- export const iconColor = $props.iconColor || ''
8
- export const image = $props.image || ''
9
- export const href = $props.href || ''
10
- export const count = $props.count ?? $props.badge ?? ''
11
- export const active = $props.active ?? false
12
- export const disabled = $props.disabled ?? false
13
- export const expandable = $props.expandable ?? false
14
- export const expanded = $props.expanded ?? true
15
- export const depth = $props.depth || 0
16
- export const parents = $props.parents || ''
17
- export const theme = $props.theme || $props.variant || 'macos'
18
-
19
- const themeStyle = resolveSidebarTheme(theme).item
20
-
21
- export const rowClasses = [
22
- themeStyle.base,
23
- disabled ? themeStyle.disabled : themeStyle.hover,
24
- disabled ? '' : themeStyle.pressed,
25
- active ? themeStyle.active : '',
26
- ].filter(Boolean).join(' ')
27
-
28
- export const disclosureClasses = themeStyle.disclosure
29
- export const chevronClasses = themeStyle.chevron
30
- export const iconSlotClasses = themeStyle.iconSlot
31
- export const iconClasses = `${icon} ${themeStyle.icon}`
32
- export const imageClasses = themeStyle.image
33
- export const labelClasses = themeStyle.label
34
- export const countClasses = themeStyle.count
35
-
36
- // Nested rows are indented; the icon tint accepts macOS system color names
37
- // ("blue", "yellow", …) or any CSS color.
38
- export const indentStyle = depth > 0 ? `padding-left: ${depth * themeStyle.indentPerLevel}px` : ''
39
- const tint = resolveIconColor(iconColor)
40
- export const iconStyle = tint ? `color: ${tint}` : ''
41
- export const isLink = Boolean(href) && !disabled
42
- </script>
43
-
44
- <div
45
- data-sidebar-row
46
- data-item-id="{{ id }}"
47
- @if(parents)data-parents="{{ parents }}"@endif
48
- @if(expandable)data-expanded="{{ expanded ? 'true' : 'false' }}"@endif
49
- @if(indentStyle)style="{{ indentStyle }}"@endif
50
- >
51
- @if(isLink)
52
- <a href="{{ href }}" data-sidebar-item data-label="{{ label }}" class="{{ rowClasses }}" @if(active)data-active="true" aria-current="page"@endif>
53
- <span class="{{ disclosureClasses }}" @if(expandable)data-sidebar-disclosure role="button" aria-label="Toggle {{ label }}"@endif>
54
- @if(expandable)
55
- <span class="{{ chevronClasses }}" aria-hidden="true"></span>
56
- @endif
57
- </span>
58
- @if(image)
59
- <span class="{{ iconSlotClasses }}"><img src="{{ image }}" alt="" class="{{ imageClasses }}" /></span>
60
- @elseif(icon)
61
- <span class="{{ iconSlotClasses }}"><span class="{{ iconClasses }}" @if(iconStyle)style="{{ iconStyle }}"@endif aria-hidden="true"></span></span>
62
- @endif
63
- <span class="{{ labelClasses }}">{{ label }}</span>
64
- @if(count !== '' && count !== null && count !== undefined)
65
- <span class="{{ countClasses }}">{{ count }}</span>
66
- @endif
67
- </a>
68
- @else
69
- <button type="button" data-sidebar-item data-label="{{ label }}" class="{{ rowClasses }}" @if(active)data-active="true" aria-current="page"@endif @if(disabled)data-disabled disabled aria-disabled="true"@endif>
70
- <span class="{{ disclosureClasses }}" @if(expandable)data-sidebar-disclosure role="button" aria-label="Toggle {{ label }}"@endif>
71
- @if(expandable)
72
- <span class="{{ chevronClasses }}" aria-hidden="true"></span>
73
- @endif
74
- </span>
75
- @if(image)
76
- <span class="{{ iconSlotClasses }}"><img src="{{ image }}" alt="" class="{{ imageClasses }}" /></span>
77
- @elseif(icon)
78
- <span class="{{ iconSlotClasses }}"><span class="{{ iconClasses }}" @if(iconStyle)style="{{ iconStyle }}"@endif aria-hidden="true"></span></span>
79
- @endif
80
- <span class="{{ labelClasses }}">{{ label }}</span>
81
- @if(count !== '' && count !== null && count !== undefined)
82
- <span class="{{ countClasses }}">{{ count }}</span>
83
- @endif
84
- </button>
85
- @endif
86
- </div>
@@ -1,83 +0,0 @@
1
- <script server>
2
- import { resolveSidebarTheme } from './themes'
3
-
4
- export const id = $props.id || ''
5
- export const label = $props.label || ''
6
- export const items = $props.items || []
7
- export const collapsible = $props.collapsible ?? true
8
- export const collapsed = $props.collapsed ?? false
9
- export const theme = $props.theme || $props.variant || 'macos'
10
-
11
- const themeStyle = resolveSidebarTheme(theme)
12
- export const headerClasses = themeStyle.sectionHeader + (collapsible ? ' cursor-default' : '')
13
- export const chevronClasses = themeStyle.sectionChevron
14
- export const groupClasses = themeStyle.sectionGroup
15
-
16
- // Components can't render themselves recursively, so the item tree is
17
- // flattened into ready-to-render rows here. Each row remembers its depth
18
- // and ancestor ids — the Sidebar controller uses those to collapse whole
19
- // subtrees.
20
- function flatten(list, depth = 0, parents = []) {
21
- return list.flatMap((item) => {
22
- const children = item.children || []
23
- const row = {
24
- id: item.id,
25
- label: item.label,
26
- icon: item.icon || '',
27
- iconColor: item.iconColor || '',
28
- image: item.image || '',
29
- href: item.href || '',
30
- count: item.count ?? item.badge ?? '',
31
- active: item.active === true,
32
- disabled: item.disabled === true,
33
- expandable: children.length > 0 || item.expandable === true,
34
- expanded: item.expanded !== false,
35
- depth,
36
- parents: parents.join('/'),
37
- }
38
- return [row, ...flatten(children, depth + 1, [...parents, item.id])]
39
- })
40
- }
41
-
42
- export const rows = flatten(items)
43
- </script>
44
-
45
- <section
46
- data-sidebar-section
47
- data-section-id="{{ id }}"
48
- data-expanded="{{ collapsed ? 'false' : 'true' }}"
49
- >
50
- @if(label)
51
- @if(collapsible)
52
- <button type="button" data-sidebar-section-header class="{{ headerClasses }}" aria-expanded="{{ collapsed ? 'false' : 'true' }}">
53
- <span class="truncate">{{ label }}</span>
54
- <span data-sidebar-section-chevron class="{{ chevronClasses }}" aria-hidden="true"></span>
55
- </button>
56
- @else
57
- <div class="{{ headerClasses }}">
58
- <span class="truncate">{{ label }}</span>
59
- </div>
60
- @endif
61
- @endif
62
-
63
- <div class="{{ groupClasses }}" role="group" @if(label)aria-label="{{ label }}"@endif>
64
- @foreach(rows as row)
65
- <SidebarItem
66
- :id="row.id"
67
- :label="row.label"
68
- :icon="row.icon"
69
- :iconColor="row.iconColor"
70
- :image="row.image"
71
- :href="row.href"
72
- :count="row.count"
73
- :active="row.active"
74
- :disabled="row.disabled"
75
- :expandable="row.expandable"
76
- :expanded="row.expanded"
77
- :depth="row.depth"
78
- :parents="row.parents"
79
- :theme="theme"
80
- />
81
- @endforeach
82
- </div>
83
- </section>
@@ -1,153 +0,0 @@
1
- export { default as Sidebar } from './Sidebar.stx'
2
- export { default as SidebarFooter } from './SidebarFooter.stx'
3
- export { default as SidebarHeader } from './SidebarHeader.stx'
4
- export { default as SidebarItem } from './SidebarItem.stx'
5
- export { default as SidebarSection } from './SidebarSection.stx'
6
- export * from './themes'
7
-
8
- /**
9
- * One navigation row.
10
- *
11
- * ```ts
12
- * { id: 'icloud', label: 'iCloud', icon: 'i-f7-tray', iconColor: 'blue', count: 248, active: true }
13
- * ```
14
- */
15
- export interface SidebarItemData {
16
- id: string
17
- label: string
18
- /** Iconify utility class, e.g. `i-f7-tray`. F7 icons mirror SF Symbols. */
19
- icon?: string
20
- /** macOS system color name (`"blue"`, `"red"`, `"yellow"`, …) or any CSS color. */
21
- iconColor?: string
22
- /** Image URL rendered instead of an icon (album art, avatars). */
23
- image?: string
24
- href?: string
25
- /** Right-aligned count — rendered as plain gray text like native macOS. */
26
- count?: string | number
27
- /** @deprecated Use `count`. */
28
- badge?: string | number
29
- active?: boolean
30
- disabled?: boolean
31
- /** Nested rows, indented and collapsible under this one. */
32
- children?: SidebarItemData[]
33
- /** Show a disclosure chevron even without children. */
34
- expandable?: boolean
35
- /** Initial disclosure state when the item has children. Defaults to true. */
36
- expanded?: boolean
37
- }
38
-
39
- /** A titled group of rows (e.g. "Favorites"). Untitled when `label` is empty. */
40
- export interface SidebarSectionData {
41
- id: string
42
- label?: string
43
- items: SidebarItemData[]
44
- /** Section headers collapse their group on click. Defaults to true. */
45
- collapsible?: boolean
46
- /** Initial collapse state. Defaults to false (expanded). */
47
- collapsed?: boolean
48
- }
49
-
50
- /**
51
- * Sidebar themes. `macos` recreates the sidebar of the latest macOS
52
- * (Tahoe, macOS 26/27) — translucent material, Liquid Glass edge shimmer,
53
- * 30px rows with 9px-radius highlights and plain gray counts. `tahoe`,
54
- * `macos-tahoe` and `macos-latest` are aliases of `macos`. The remaining
55
- * names are legacy looks kept for backwards compatibility.
56
- */
57
- export type SidebarThemeChoice =
58
- | 'macos'
59
- | 'macos-tahoe'
60
- | 'macos-latest'
61
- | 'tahoe'
62
- | 'vibrancy'
63
- | 'solid'
64
- | 'transparent'
65
- | 'workspace'
66
- | 'desktop'
67
-
68
- export interface SidebarProps {
69
- /** Sections with their items. Omit to compose children via the default slot. */
70
- sections?: SidebarSectionData[]
71
- /** Visual theme. Defaults to `macos`. */
72
- theme?: SidebarThemeChoice
73
- /** @deprecated Use `theme`. */
74
- variant?: SidebarThemeChoice
75
- /** Expanded width in pixels. Defaults to 250 (native macOS default). */
76
- width?: number
77
- position?: 'left' | 'right'
78
- /** Layout placement for app shells. Defaults to `fixed`. */
79
- placement?: 'fixed' | 'sticky' | 'static'
80
- bordered?: boolean
81
- /** Whether the sidebar starts collapsed. */
82
- collapsed?: boolean
83
- collapsible?: boolean
84
- /** `hidden` slides away entirely (macOS); `rail` keeps a compact strip. */
85
- collapseMode?: 'hidden' | 'rail'
86
- /** Rail width when `collapseMode` is `rail`. */
87
- minWidth?: number
88
- /** localStorage key that persists collapse state. */
89
- persistKey?: string
90
- /** App-shell selector whose width CSS variable tracks the sidebar. */
91
- shellSelector?: string
92
- widthVar?: string
93
- collapsedClass?: string
94
- className?: string
95
- onCollapse?: (collapsed: boolean) => void
96
- onSectionToggle?: (sectionId: string) => void
97
- onItemToggle?: (event: { id: string, expanded: boolean }) => void
98
- onItemClick?: (item: SidebarItemData, event: Event) => void
99
- }
100
-
101
- export interface SidebarSectionProps {
102
- id: string
103
- label?: string
104
- items: SidebarItemData[]
105
- collapsible?: boolean
106
- collapsed?: boolean
107
- theme?: SidebarThemeChoice
108
- }
109
-
110
- export interface SidebarItemProps extends SidebarItemData {
111
- /** Nesting depth — set by SidebarSection when flattening the tree. */
112
- depth?: number
113
- /** Slash-joined ancestor ids — set by SidebarSection. */
114
- parents?: string
115
- theme?: SidebarThemeChoice
116
- }
117
-
118
- /** A floating toolbar or footer action button. */
119
- export interface SidebarActionData {
120
- id: string
121
- /** Iconify utility class. */
122
- icon: string
123
- /** Accessible label. */
124
- label: string
125
- }
126
-
127
- export interface SidebarHeaderProps {
128
- theme?: SidebarThemeChoice
129
- /** Render traffic lights (wired to Craft's window API when present). */
130
- showWindowControls?: boolean
131
- /** Floating Liquid Glass toolbar buttons on the right. */
132
- actions?: SidebarActionData[]
133
- showSearch?: boolean
134
- searchPlaceholder?: string
135
- /** Legacy (non-macos) header content. */
136
- title?: string
137
- subtitle?: string
138
- logo?: string
139
- onAction?: (actionId: string) => void
140
- onSearch?: (value: string) => void
141
- onWindowControl?: (action: 'close' | 'minimize' | 'zoom') => void
142
- }
143
-
144
- export interface SidebarFooterProps {
145
- theme?: SidebarThemeChoice
146
- /** Account row, like Music's profile footer. */
147
- avatar?: string
148
- name?: string
149
- detail?: string
150
- actions?: SidebarActionData[]
151
- onProfileClick?: () => void
152
- onAction?: (actionId: string) => void
153
- }
@@ -1,240 +0,0 @@
1
- /**
2
- * Sidebar theme registry
3
- *
4
- * Every visual decision the sidebar makes lives here, expressed as utility
5
- * classes, so a theme can be read top-to-bottom like a spec sheet.
6
- *
7
- * The flagship theme is `macos` — a faithful recreation of the sidebar in
8
- * the latest macOS (Tahoe, macOS 26/27 "Liquid Glass"). Its metrics were
9
- * measured from native apps (Mail, Music, Notes) at @2x:
10
- *
11
- * row pitch 32px = 30px row + 2px gap · highlight radius 9px
12
- * label 13px · count 13px secondary gray · section header 11px semibold
13
- * icon 17px in a fixed 22px slot · disclosure gutter 18px · child indent 16px
14
- *
15
- * Legacy themes (`workspace`, `desktop`, `solid`, `transparent`, `vibrancy`)
16
- * are preserved verbatim from the previous variant maps. `tahoe` now aliases
17
- * `macos` — it always meant "look like macOS", and now it actually does.
18
- */
19
-
20
- /** macOS system colors (light appearance) for tinting sidebar icons. */
21
- export const macosColors = {
22
- blue: '#0088ff',
23
- red: '#ff383c',
24
- pink: '#ff2d55',
25
- orange: '#ff8d28',
26
- yellow: '#ffcc00',
27
- green: '#34c759',
28
- teal: '#00c3d0',
29
- cyan: '#00c0e8',
30
- indigo: '#6155f5',
31
- purple: '#cb30e0',
32
- brown: '#ac7f5e',
33
- gray: '#8e8e93',
34
- } as const
35
-
36
- export type MacosColor = keyof typeof macosColors
37
-
38
- /** Class groups a sidebar theme provides. All values are utility classes. */
39
- export interface SidebarTheme {
40
- /** The <aside> pane itself: material, text color, borders. */
41
- pane: string
42
- /** Extra overlay layers rendered inside the pane (visual only). */
43
- layers: {
44
- /** Liquid Glass edge highlight — a bright rim that subtly shimmers. */
45
- shimmerRim?: boolean
46
- /** Soft tint gradient blended over the material. */
47
- tint?: string
48
- }
49
- /** Scrollable content area between header and footer. */
50
- scrollArea: string
51
- /** Section header row (e.g. "Favorites", "iCloud"). */
52
- sectionHeader: string
53
- /** Chevron inside the section header (revealed on hover). */
54
- sectionChevron: string
55
- /** Wrapper around a section's items. */
56
- sectionGroup: string
57
- /** One navigation row, layout + typography. State styles live below. */
58
- item: {
59
- base: string
60
- hover: string
61
- active: string
62
- pressed: string
63
- disabled: string
64
- /** Fixed-width leading slot the disclosure chevron sits in. */
65
- disclosure: string
66
- /** Chevron glyph itself (rotates 90° when expanded). */
67
- chevron: string
68
- /** Fixed-width slot that centers the 17px icon. */
69
- iconSlot: string
70
- icon: string
71
- /** Thumbnail images (album art, avatars) rendered instead of an icon. */
72
- image: string
73
- label: string
74
- /** Right-aligned unread/item count — plain gray text on macOS. */
75
- count: string
76
- /** Indentation added per nesting depth. */
77
- indentPerLevel: number
78
- }
79
- }
80
-
81
- const macos: SidebarTheme = {
82
- pane: [
83
- // Frosted sidebar material. In a Craft window with `webSidebarMaterial`
84
- // the native vibrancy shows through; in a browser the backdrop blur
85
- // approximates it over whatever sits behind the pane.
86
- 'bg-white/55 dark:bg-[#1e1e23]/55',
87
- 'backdrop-blur-[60px] backdrop-saturate-[1.8]',
88
- 'text-black dark:text-white',
89
- 'select-none',
90
- ].join(' '),
91
- layers: {
92
- shimmerRim: true,
93
- },
94
- scrollArea: 'flex-1 overflow-y-auto overflow-x-hidden px-[10px] pb-[10px]',
95
- sectionHeader: [
96
- 'group/section flex w-full items-center',
97
- 'pl-[8px] pr-[6px] pt-[16px] pb-[5px]',
98
- 'text-[11px] font-semibold leading-[13px]',
99
- 'text-[#3c3c43]/60 dark:text-[#ebebf5]/60',
100
- ].join(' '),
101
- sectionChevron: [
102
- 'i-f7-chevron-down h-[11px] w-[11px] ml-auto',
103
- 'text-[#3c3c43]/45 dark:text-[#ebebf5]/45',
104
- 'opacity-0 group-hover/section:opacity-100 transition-opacity duration-150',
105
- 'transition-transform duration-200',
106
- ].join(' '),
107
- sectionGroup: 'flex flex-col gap-[2px]',
108
- item: {
109
- base: [
110
- 'flex w-full items-center',
111
- 'h-[30px] rounded-[9px] pl-[4px] pr-[8px]',
112
- 'text-[13px] leading-[16px] font-normal',
113
- 'text-black dark:text-white',
114
- 'transition-colors duration-150 ease-out',
115
- 'cursor-default',
116
- ].join(' '),
117
- hover: 'hover:bg-black/4 dark:hover:bg-white/6',
118
- active: 'bg-black/8 dark:bg-white/14',
119
- pressed: 'active:bg-black/10 dark:active:bg-white/18',
120
- disabled: 'opacity-40 pointer-events-none',
121
- disclosure: 'flex h-[16px] w-[18px] shrink-0 items-center justify-center',
122
- chevron: [
123
- 'i-f7-chevron-right h-[11px] w-[11px]',
124
- 'text-[#3c3c43]/55 dark:text-[#ebebf5]/55',
125
- 'transition-transform duration-200 ease-out',
126
- ].join(' '),
127
- iconSlot: 'flex h-[20px] w-[22px] shrink-0 items-center justify-center mr-[7px]',
128
- icon: 'h-[17px] w-[17px]',
129
- image: 'h-[20px] w-[20px] rounded-[4px] object-cover shadow-sm',
130
- label: 'flex-1 truncate text-left',
131
- count: [
132
- 'ml-[8px] shrink-0 tabular-nums',
133
- 'text-[13px] leading-[16px]',
134
- 'text-[#3c3c43]/60 dark:text-[#ebebf5]/60',
135
- ].join(' '),
136
- indentPerLevel: 16,
137
- },
138
- }
139
-
140
- /**
141
- * Legacy themes carried over from the old per-component variant maps so
142
- * existing apps keep rendering identically. New work should use `macos`.
143
- */
144
- const workspace: SidebarTheme = {
145
- pane: 'bg-[#f4f4f3] dark:bg-neutral-950 text-zinc-950 dark:text-white select-none',
146
- layers: {},
147
- scrollArea: 'flex-1 overflow-y-auto overflow-x-hidden px-5 py-5',
148
- sectionHeader: 'group/section flex w-full items-center gap-2.5 px-4 pb-2 pt-5 text-[13px] font-semibold uppercase tracking-[0.12em] text-zinc-400 dark:text-zinc-500',
149
- sectionChevron: 'i-f7-chevron-down h-3 w-3 ml-auto opacity-0 group-hover/section:opacity-100 transition-opacity duration-150 transition-transform duration-200',
150
- sectionGroup: 'flex flex-col space-y-1',
151
- item: {
152
- base: 'flex w-full items-center gap-3 rounded-[16px] px-3.5 py-2 text-[14px] leading-tight transition-colors duration-150',
153
- hover: 'hover:bg-[#ececea] hover:text-zinc-950 dark:hover:bg-white/10',
154
- active: 'bg-[#e7e7e5] text-zinc-950 dark:bg-white/12 dark:text-white',
155
- pressed: 'active:bg-[#e2e2e0] dark:active:bg-white/15',
156
- disabled: 'opacity-50 pointer-events-none',
157
- disclosure: 'flex h-4 w-4 shrink-0 items-center justify-center',
158
- chevron: 'i-f7-chevron-right h-3 w-3 opacity-50 transition-transform duration-200',
159
- iconSlot: 'flex h-5 w-5 shrink-0 items-center justify-center',
160
- icon: 'h-[18px] w-[18px] text-zinc-500 dark:text-zinc-500',
161
- image: 'h-5 w-5 rounded object-cover',
162
- label: 'flex-1 truncate text-left text-zinc-700 dark:text-zinc-300',
163
- count: 'ml-auto grid h-5 min-w-5 place-items-center rounded-full bg-white/70 px-1.5 text-[11px] font-medium text-zinc-500 shadow-sm dark:bg-white/10 dark:text-zinc-400',
164
- indentPerLevel: 12,
165
- },
166
- }
167
-
168
- const desktop: SidebarTheme = {
169
- pane: 'bg-[#f3f3f1]/48 dark:bg-neutral-950/32 backdrop-blur-3xl backdrop-saturate-150 text-zinc-950 dark:text-white select-none',
170
- layers: {
171
- tint: 'bg-[linear-gradient(112deg,rgba(255,255,255,0.20)_0%,rgba(255,255,255,0.04)_45%,rgba(226,226,222,0.16)_100%)] dark:bg-[linear-gradient(112deg,rgba(255,255,255,0.08)_0%,rgba(255,255,255,0.02)_46%,rgba(255,255,255,0.06)_100%)]',
172
- },
173
- scrollArea: 'flex-1 overflow-y-auto overflow-x-hidden px-5 py-2',
174
- sectionHeader: 'group/section flex w-full items-center gap-2.5 px-3 pb-1.5 pt-3 rounded-[14px] text-[12px] font-semibold uppercase tracking-[0.10em] text-zinc-500/80 dark:text-zinc-400/80',
175
- sectionChevron: 'i-f7-chevron-down h-3 w-3 ml-auto opacity-0 group-hover/section:opacity-100 transition-opacity duration-150 transition-transform duration-200',
176
- sectionGroup: 'flex flex-col space-y-1',
177
- item: {
178
- base: 'flex w-full items-center gap-3 rounded-[14px] px-3 py-1.5 text-[13.5px] leading-tight transition-colors duration-150',
179
- hover: 'hover:bg-white/38 hover:text-zinc-950 dark:hover:bg-white/10',
180
- active: 'bg-[#e8e8e6]/90 text-zinc-950 dark:bg-white/12 dark:text-white',
181
- pressed: 'active:bg-white/50 dark:active:bg-white/15',
182
- disabled: 'opacity-50 pointer-events-none',
183
- disclosure: 'flex h-4 w-4 shrink-0 items-center justify-center',
184
- chevron: 'i-f7-chevron-right h-3 w-3 opacity-50 transition-transform duration-200',
185
- iconSlot: 'flex h-5 w-5 shrink-0 items-center justify-center',
186
- icon: 'h-[18px] w-[18px] text-zinc-600 dark:text-zinc-400',
187
- image: 'h-5 w-5 rounded object-cover',
188
- label: 'flex-1 truncate text-left text-zinc-700 dark:text-zinc-300',
189
- count: 'ml-auto grid h-5 min-w-5 place-items-center rounded-full bg-white/72 px-1.5 text-[11px] font-medium text-zinc-500 shadow-sm dark:bg-white/10 dark:text-zinc-400',
190
- indentPerLevel: 12,
191
- },
192
- }
193
-
194
- const solid: SidebarTheme = {
195
- ...macos,
196
- pane: 'bg-stone-100 dark:bg-neutral-900 text-black dark:text-white select-none',
197
- layers: {},
198
- }
199
-
200
- const transparent: SidebarTheme = {
201
- ...macos,
202
- pane: 'bg-transparent text-black dark:text-white select-none',
203
- layers: {},
204
- }
205
-
206
- const vibrancy: SidebarTheme = {
207
- ...macos,
208
- pane: 'bg-white/50 dark:bg-black/40 backdrop-blur-3xl backdrop-saturate-200 text-black dark:text-white select-none',
209
- layers: {},
210
- }
211
-
212
- export const sidebarThemes: Record<string, SidebarTheme> = {
213
- macos,
214
- // Historical names people may still pass — all render the macOS look.
215
- 'tahoe': macos,
216
- 'macos-tahoe': macos,
217
- 'macos-latest': macos,
218
- workspace,
219
- desktop,
220
- solid,
221
- transparent,
222
- vibrancy,
223
- }
224
-
225
- export type SidebarThemeName = keyof typeof sidebarThemes
226
-
227
- export function resolveSidebarTheme(name?: string): SidebarTheme {
228
- return sidebarThemes[name || 'macos'] || sidebarThemes.macos
229
- }
230
-
231
- /**
232
- * Resolve an item's icon tint. Accepts a macOS system color name
233
- * (`"blue"`, `"red"`, …) or any CSS color, and falls back to the
234
- * theme's default icon color when unset.
235
- */
236
- export function resolveIconColor(color?: string): string | undefined {
237
- if (!color)
238
- return undefined
239
- return macosColors[color as MacosColor] || color
240
- }
@@ -1,48 +0,0 @@
1
- <script server>
2
- export const variant = $props.variant || 'text'
3
- export const count = $props.count || 1
4
- export const width = $props.width || ''
5
- export const height = $props.height || ''
6
- export const circle = $props.circle || false
7
- export const className = $props.className || ''
8
- export const animate = $props.animate ?? true
9
-
10
- // Variant classes
11
- const variantClasses = {
12
- text: 'h-4 rounded',
13
- title: 'h-8 rounded',
14
- avatar: 'w-10 h-10 rounded-full',
15
- thumbnail: 'w-24 h-24 rounded-md',
16
- button: 'h-10 w-32 rounded-md',
17
- card: 'h-64 rounded-lg',
18
- rect: 'rounded-md',
19
- }
20
-
21
- // Animation classes
22
- const animationClasses = animate ? 'animate-pulse' : ''
23
-
24
- // Build base classes
25
- const baseClasses = circle ? 'rounded-full' : variantClasses[variant]
26
-
27
- // Build style object
28
- let styleString = ''
29
- if (width) {
30
- styleString += `width: ${typeof width === 'number' ? width + 'px' : width};`
31
- }
32
- if (height) {
33
- styleString += `height: ${typeof height === 'number' ? height + 'px' : height};`
34
- }
35
-
36
- export const skeletonClasses = `bg-gray-200 dark:bg-gray-700 ${baseClasses} ${animationClasses} ${className}`.trim()
37
- export const containerClasses = count > 1 ? 'space-y-3' : ''
38
- </script>
39
-
40
- @if(count > 1)
41
- <div class="{{ containerClasses }}">
42
- @for(i = 0; i < count; i++)
43
- <div class="{{ skeletonClasses }}" style="{{ styleString }}" aria-busy="true" aria-live="polite"></div>
44
- @endfor
45
- </div>
46
- @else
47
- <div class="{{ skeletonClasses }}" style="{{ styleString }}" aria-busy="true" aria-live="polite"></div>
48
- @endif
@@ -1,11 +0,0 @@
1
- export { default as Skeleton } from './Skeleton.stx'
2
-
3
- export interface SkeletonProps {
4
- variant?: 'text' | 'title' | 'avatar' | 'thumbnail' | 'button' | 'card' | 'rect'
5
- count?: number
6
- width?: string | number
7
- height?: string | number
8
- circle?: boolean
9
- animate?: boolean
10
- className?: string
11
- }