@stacksjs/components 0.2.93 → 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 (187) hide show
  1. package/dist/index.js +4 -4
  2. package/package.json +5 -6
  3. package/src/components/CodeBlock.stx +0 -54
  4. package/src/components/Footer.stx +0 -66
  5. package/src/components/Hero.stx +0 -25
  6. package/src/components/Installation.stx +0 -37
  7. package/src/components/index.ts +0 -4
  8. package/src/composables/index.ts +0 -4
  9. package/src/composables/useCopyCode.ts +0 -73
  10. package/src/composables/useDarkMode.ts +0 -100
  11. package/src/composables/useSEO.ts +0 -230
  12. package/src/composables/utilities/index.ts +0 -7
  13. package/src/composables/utilities/useClickOutside.ts +0 -72
  14. package/src/composables/utilities/useFocusTrap.ts +0 -159
  15. package/src/composables/utilities/useKeyboard.ts +0 -124
  16. package/src/composables/utilities/useLocalStorage.ts +0 -132
  17. package/src/composables/utilities/useMediaQuery.ts +0 -118
  18. package/src/index.ts +0 -99
  19. package/src/stx.d.ts +0 -4
  20. package/src/ui/accordion/Accordion.stx +0 -146
  21. package/src/ui/accordion/AccordionItem.stx +0 -37
  22. package/src/ui/accordion/index.ts +0 -47
  23. package/src/ui/audio/Audio.stx +0 -50
  24. package/src/ui/audio/README.md +0 -41
  25. package/src/ui/audio/index.ts +0 -13
  26. package/src/ui/auth/Login.stx +0 -161
  27. package/src/ui/auth/README.md +0 -142
  28. package/src/ui/auth/Signup.stx +0 -159
  29. package/src/ui/auth/TwoFactorChallenge.stx +0 -111
  30. package/src/ui/auth/index.ts +0 -32
  31. package/src/ui/avatar/Avatar.stx +0 -77
  32. package/src/ui/avatar/index.ts +0 -12
  33. package/src/ui/badge/Badge.stx +0 -62
  34. package/src/ui/badge/index.ts +0 -10
  35. package/src/ui/breadcrumb/Breadcrumb.stx +0 -79
  36. package/src/ui/breadcrumb/index.ts +0 -15
  37. package/src/ui/button/Button.stx +0 -74
  38. package/src/ui/button/README.md +0 -80
  39. package/src/ui/button/index.ts +0 -85
  40. package/src/ui/calendar/Calendar.stx +0 -189
  41. package/src/ui/calendar/README.md +0 -254
  42. package/src/ui/calendar/index.ts +0 -14
  43. package/src/ui/card/Card.stx +0 -68
  44. package/src/ui/card/index.ts +0 -13
  45. package/src/ui/checkbox/Checkbox.stx +0 -86
  46. package/src/ui/checkbox/index.ts +0 -16
  47. package/src/ui/combobox/Combobox.stx +0 -96
  48. package/src/ui/combobox/ComboboxButton.stx +0 -25
  49. package/src/ui/combobox/ComboboxInput.stx +0 -32
  50. package/src/ui/combobox/ComboboxOption.stx +0 -49
  51. package/src/ui/combobox/ComboboxOptions.stx +0 -16
  52. package/src/ui/combobox/README.md +0 -150
  53. package/src/ui/combobox/index.ts +0 -40
  54. package/src/ui/command-palette/CommandPalette.stx +0 -81
  55. package/src/ui/command-palette/CommandPaletteItem.stx +0 -27
  56. package/src/ui/command-palette/README.md +0 -42
  57. package/src/ui/command-palette/index.ts +0 -15
  58. package/src/ui/dialog/Dialog.stx +0 -41
  59. package/src/ui/dialog/DialogBackdrop.stx +0 -9
  60. package/src/ui/dialog/DialogDescription.stx +0 -11
  61. package/src/ui/dialog/DialogPanel.stx +0 -16
  62. package/src/ui/dialog/DialogTitle.stx +0 -11
  63. package/src/ui/dialog/README.md +0 -121
  64. package/src/ui/dialog/index.ts +0 -32
  65. package/src/ui/drawer/Drawer.stx +0 -120
  66. package/src/ui/drawer/README.md +0 -90
  67. package/src/ui/drawer/index.ts +0 -9
  68. package/src/ui/dropdown/Dropdown.stx +0 -82
  69. package/src/ui/dropdown/DropdownButton.stx +0 -29
  70. package/src/ui/dropdown/DropdownItem.stx +0 -35
  71. package/src/ui/dropdown/DropdownItems.stx +0 -18
  72. package/src/ui/dropdown/README.md +0 -114
  73. package/src/ui/dropdown/index.ts +0 -29
  74. package/src/ui/form/Form.stx +0 -95
  75. package/src/ui/form/index.ts +0 -67
  76. package/src/ui/heatmap/Heatmap.stx +0 -294
  77. package/src/ui/image/Image.stx +0 -165
  78. package/src/ui/image/README.md +0 -164
  79. package/src/ui/image/index.ts +0 -22
  80. package/src/ui/input/EmailInput.stx +0 -30
  81. package/src/ui/input/NumberInput.stx +0 -126
  82. package/src/ui/input/PasswordInput.stx +0 -143
  83. package/src/ui/input/SearchInput.stx +0 -44
  84. package/src/ui/input/TextInput.stx +0 -132
  85. package/src/ui/input/index.ts +0 -180
  86. package/src/ui/listbox/Listbox.stx +0 -101
  87. package/src/ui/listbox/ListboxButton.stx +0 -28
  88. package/src/ui/listbox/ListboxLabel.stx +0 -11
  89. package/src/ui/listbox/ListboxOption.stx +0 -49
  90. package/src/ui/listbox/ListboxOptions.stx +0 -16
  91. package/src/ui/listbox/README.md +0 -135
  92. package/src/ui/listbox/index.ts +0 -39
  93. package/src/ui/navigator/Navigator.stx +0 -113
  94. package/src/ui/navigator/README.md +0 -352
  95. package/src/ui/navigator/index.ts +0 -20
  96. package/src/ui/notification/Notification.stx +0 -117
  97. package/src/ui/notification/README.md +0 -114
  98. package/src/ui/notification/index.ts +0 -12
  99. package/src/ui/pagination/Pagination.stx +0 -150
  100. package/src/ui/pagination/index.ts +0 -11
  101. package/src/ui/payment/Checkout.stx +0 -31
  102. package/src/ui/payment/DefaultPaymentMethod.stx +0 -62
  103. package/src/ui/payment/PaymentMethods.stx +0 -104
  104. package/src/ui/payment/README.md +0 -345
  105. package/src/ui/payment/SubscriptionCheckout.stx +0 -323
  106. package/src/ui/payment/index.ts +0 -59
  107. package/src/ui/popover/Popover.stx +0 -60
  108. package/src/ui/popover/PopoverButton.stx +0 -29
  109. package/src/ui/popover/PopoverPanel.stx +0 -23
  110. package/src/ui/popover/README.md +0 -91
  111. package/src/ui/popover/index.ts +0 -22
  112. package/src/ui/portal/Portal.stx +0 -57
  113. package/src/ui/portal/index.ts +0 -6
  114. package/src/ui/progress/Progress.stx +0 -131
  115. package/src/ui/progress/index.ts +0 -12
  116. package/src/ui/radio/Radio.stx +0 -77
  117. package/src/ui/radio/index.ts +0 -15
  118. package/src/ui/radio-group/README.md +0 -139
  119. package/src/ui/radio-group/RadioGroup.stx +0 -60
  120. package/src/ui/radio-group/RadioGroupDescription.stx +0 -11
  121. package/src/ui/radio-group/RadioGroupLabel.stx +0 -11
  122. package/src/ui/radio-group/RadioGroupOption.stx +0 -58
  123. package/src/ui/radio-group/index.ts +0 -30
  124. package/src/ui/select/README.md +0 -180
  125. package/src/ui/select/Select.stx +0 -82
  126. package/src/ui/select/index.ts +0 -21
  127. package/src/ui/sidebar/Sidebar.stx +0 -476
  128. package/src/ui/sidebar/SidebarFooter.stx +0 -71
  129. package/src/ui/sidebar/SidebarHeader.stx +0 -103
  130. package/src/ui/sidebar/SidebarItem.stx +0 -86
  131. package/src/ui/sidebar/SidebarSection.stx +0 -83
  132. package/src/ui/sidebar/index.ts +0 -153
  133. package/src/ui/sidebar/themes.ts +0 -240
  134. package/src/ui/skeleton/Skeleton.stx +0 -48
  135. package/src/ui/skeleton/index.ts +0 -11
  136. package/src/ui/spinner/Spinner.stx +0 -109
  137. package/src/ui/spinner/index.ts +0 -9
  138. package/src/ui/stepper/README.md +0 -36
  139. package/src/ui/stepper/Stepper.stx +0 -17
  140. package/src/ui/stepper/StepperStep.stx +0 -57
  141. package/src/ui/stepper/index.ts +0 -19
  142. package/src/ui/storage/README.md +0 -193
  143. package/src/ui/storage/index.ts +0 -347
  144. package/src/ui/switch/README.md +0 -114
  145. package/src/ui/switch/Switch.stx +0 -72
  146. package/src/ui/switch/index.ts +0 -10
  147. package/src/ui/table/README.md +0 -39
  148. package/src/ui/table/Table.stx +0 -14
  149. package/src/ui/table/TableBody.stx +0 -10
  150. package/src/ui/table/TableCell.stx +0 -10
  151. package/src/ui/table/TableHead.stx +0 -10
  152. package/src/ui/table/TableHeader.stx +0 -20
  153. package/src/ui/table/TableRow.stx +0 -11
  154. package/src/ui/table/index.ts +0 -35
  155. package/src/ui/tabs/TabPanel.stx +0 -25
  156. package/src/ui/tabs/Tabs.stx +0 -202
  157. package/src/ui/tabs/index.ts +0 -50
  158. package/src/ui/teleport/Teleport.stx +0 -65
  159. package/src/ui/teleport/index.ts +0 -7
  160. package/src/ui/textarea/Textarea.stx +0 -108
  161. package/src/ui/textarea/index.ts +0 -20
  162. package/src/ui/tooltip/Tooltip.stx +0 -71
  163. package/src/ui/tooltip/index.ts +0 -10
  164. package/src/ui/transition/README.md +0 -30
  165. package/src/ui/transition/Transition.stx +0 -102
  166. package/src/ui/transition/index.ts +0 -25
  167. package/src/ui/video/README.md +0 -47
  168. package/src/ui/video/Video.stx +0 -45
  169. package/src/ui/video/index.ts +0 -16
  170. package/src/ui/virtual-list/VirtualList.stx +0 -67
  171. package/src/ui/virtual-list/index.ts +0 -10
  172. package/src/ui/virtual-table/VirtualTable.stx +0 -103
  173. package/src/ui/virtual-table/index.ts +0 -21
  174. package/src/utils/PROP_VALIDATION.md +0 -458
  175. package/src/utils/THEME_SYSTEM.md +0 -702
  176. package/src/utils/accessibility.ts +0 -841
  177. package/src/utils/animation/easing.ts +0 -368
  178. package/src/utils/animation/helpers.ts +0 -223
  179. package/src/utils/animation/index.ts +0 -5
  180. package/src/utils/animation/keyframes.ts +0 -230
  181. package/src/utils/error-handling.ts +0 -475
  182. package/src/utils/highlighter.ts +0 -93
  183. package/src/utils/i18n.ts +0 -634
  184. package/src/utils/keep-alive.ts +0 -819
  185. package/src/utils/lazy-loading.ts +0 -530
  186. package/src/utils/prop-validation.ts +0 -478
  187. package/src/utils/theme.ts +0 -626
@@ -1,135 +0,0 @@
1
- # Listbox Component
2
-
3
- A custom select component for choosing one or multiple values from a list.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- bun add @stacksjs/components
9
- ```
10
-
11
- ## Usage
12
-
13
- ```stx
14
- <script server>
15
- const people = [
16
- { id: 1, name: 'Wade Cooper' },
17
- { id: 2, name: 'Arlene Mccoy' },
18
- { id: 3, name: 'Devon Webb' }
19
- ]
20
-
21
- let selected = people[0]
22
-
23
- function handleChange(person) {
24
- selected = person
25
- }
26
- </script>
27
-
28
- <Listbox :value="selected" :onChange="handleChange">
29
- <ListboxLabel>Assign to</ListboxLabel>
30
-
31
- <ListboxButton>{{ selected.name }}</ListboxButton>
32
-
33
- <ListboxOptions>
34
- @foreach(person in people)
35
- <ListboxOption :value="person" :currentValue="selected" :onChange="handleChange">
36
- {{ person.name }}
37
- </ListboxOption>
38
- @endforeach
39
- </ListboxOptions>
40
- </Listbox>
41
- ```
42
-
43
- ## Props
44
-
45
- ### Listbox
46
- | Prop | Type | Default | Description |
47
- |------|------|---------|-------------|
48
- | `value` | `any` | - | Currently selected value(s) |
49
- | `onChange` | `(value: any) => void` | - | Change handler |
50
- | `multiple` | `boolean` | `false` | Allow multiple selection |
51
- | `className` | `string` | `''` | Additional CSS classes |
52
- | `as` | `string` | `'div'` | HTML element to render |
53
-
54
- ### ListboxButton
55
- | Prop | Type | Default | Description |
56
- |------|------|---------|-------------|
57
- | `className` | `string` | `''` | Additional CSS classes |
58
- | `as` | `string` | `'button'` | HTML element to render |
59
- | `disabled` | `boolean` | `false` | Disable the button |
60
-
61
- ### ListboxOptions
62
- | Prop | Type | Default | Description |
63
- |------|------|---------|-------------|
64
- | `className` | `string` | `''` | Additional CSS classes |
65
- | `as` | `string` | `'ul'` | HTML element to render |
66
- | `static` | `boolean` | `false` | Keep visible regardless of state |
67
-
68
- ### ListboxOption
69
- | Prop | Type | Default | Description |
70
- |------|------|---------|-------------|
71
- | `value` | `any` | - | Option value |
72
- | `disabled` | `boolean` | `false` | Disable the option |
73
- | `className` | `string` | `''` | Additional CSS classes |
74
- | `as` | `string` | `'li'` | HTML element to render |
75
- | `currentValue` | `any` | - | Current selected value(s) |
76
- | `onChange` | `(value: any) => void` | - | Change handler |
77
-
78
- ### ListboxLabel
79
- | Prop | Type | Default | Description |
80
- |------|------|---------|-------------|
81
- | `className` | `string` | `''` | Additional CSS classes |
82
- | `as` | `string` | `'label'` | HTML element to render |
83
-
84
- ## Examples
85
-
86
- ### Multiple Selection
87
-
88
- ```stx
89
- <script server>
90
- let selectedPeople = [people[0], people[1]]
91
-
92
- function handleChange(person) {
93
- if (selectedPeople.includes(person)) {
94
- selectedPeople = selectedPeople.filter(p => p !== person)
95
- } else {
96
- selectedPeople = [...selectedPeople, person]
97
- }
98
- }
99
- </script>
100
-
101
- <Listbox :value="selectedPeople" :onChange="handleChange" multiple>
102
- <!-- ... -->
103
- </Listbox>
104
- ```
105
-
106
- ### With Avatars
107
-
108
- ```stx
109
- <ListboxOption :value="person">
110
- <div class="flex items-center">
111
- <img src="{{ person.avatar }}" alt="" class="h-6 w-6 rounded-full mr-2" />
112
- {{ person.name }}
113
- </div>
114
- </ListboxOption>
115
- ```
116
-
117
- ### Disabled Option
118
-
119
- ```stx
120
- <ListboxOption :value="person" disabled>
121
- {{ person.name }} (unavailable)
122
- </ListboxOption>
123
- ```
124
-
125
- ## Features
126
-
127
- - Single or multiple selection
128
- - Keyboard navigation
129
- - Search/filter support
130
- - Dark mode support
131
- - Accessible (WAI-ARIA)
132
- - Disabled state
133
- - Active state on hover
134
- - Check icon for selected items
135
- - Customizable styling
@@ -1,39 +0,0 @@
1
- export { default as Listbox } from './Listbox.stx'
2
- export { default as ListboxButton } from './ListboxButton.stx'
3
- export { default as ListboxLabel } from './ListboxLabel.stx'
4
- export { default as ListboxOption } from './ListboxOption.stx'
5
- export { default as ListboxOptions } from './ListboxOptions.stx'
6
-
7
- export interface ListboxProps {
8
- value?: any
9
- onChange?: (value: any) => void
10
- multiple?: boolean
11
- className?: string
12
- as?: string
13
- }
14
-
15
- export interface ListboxButtonProps {
16
- className?: string
17
- as?: string
18
- disabled?: boolean
19
- }
20
-
21
- export interface ListboxOptionsProps {
22
- className?: string
23
- as?: string
24
- static?: boolean
25
- }
26
-
27
- export interface ListboxOptionProps {
28
- value: any
29
- disabled?: boolean
30
- className?: string
31
- as?: string
32
- currentValue?: any
33
- onChange?: (value: any) => void
34
- }
35
-
36
- export interface ListboxLabelProps {
37
- className?: string
38
- as?: string
39
- }
@@ -1,113 +0,0 @@
1
- <script server>
2
- export const items = $props.items || []
3
- export const active = $props.active || ''
4
- export const orientation = $props.orientation || 'horizontal'
5
- export const variant = $props.variant || 'default'
6
- export const size = $props.size || 'md'
7
- export const className = $props.className || ''
8
-
9
- const containerBaseClasses = orientation === 'horizontal' ? 'flex items-center' : 'flex flex-col'
10
- export const containerClasses = `${containerBaseClasses} ${className}`.trim()
11
- export const gapClasses = orientation === 'horizontal' ? 'gap-1' : 'gap-0.5'
12
- </script>
13
-
14
- <script client>
15
- const emit = defineEmits()
16
- const items = {{ items }}
17
- const variant = {{ variant }}
18
- const size = {{ size }}
19
- const initialActive = {{ active }}
20
- const activeKey = state(initialActive)
21
-
22
- function isActive(item) {
23
- const a = activeKey()
24
- if (typeof item.href === 'string' && typeof a === 'string') {
25
- if (item.href === a) return true
26
- if (a.startsWith(item.href)) return true
27
- }
28
- if (item.id && item.id === a) return true
29
- return false
30
- }
31
-
32
- function getItemClasses(item) {
33
- const isActiveItem = isActive(item)
34
- const sizeClasses = { sm: 'px-2 py-1 text-sm', md: 'px-3 py-2 text-base', lg: 'px-4 py-3 text-lg' }
35
- let cls = sizeClasses[size] || sizeClasses.md
36
- if (variant === 'default') {
37
- cls += isActiveItem
38
- ? ' text-gray-900 dark:text-gray-100 font-medium'
39
- : ' text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100'
40
- }
41
- else if (variant === 'pills') {
42
- cls += isActiveItem
43
- ? ' bg-blue-600 text-white font-medium rounded-full'
44
- : ' text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-full'
45
- }
46
- else if (variant === 'underline') {
47
- cls += isActiveItem
48
- ? ' text-blue-600 dark:text-blue-400 font-medium border-b-2 border-blue-600 dark:border-blue-400'
49
- : ' text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 border-b-2 border-transparent'
50
- }
51
- else if (variant === 'sidebar') {
52
- cls += isActiveItem
53
- ? ' bg-blue-50 dark:bg-blue-900/20 text-blue-600 dark:text-blue-400 font-medium border-l-4 border-blue-600 dark:border-blue-400'
54
- : ' text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 border-l-4 border-transparent'
55
- }
56
- cls += ' transition-all duration-200 cursor-pointer flex items-center gap-2'
57
- if (item.disabled) cls += ' opacity-50 cursor-not-allowed pointer-events-none'
58
- return cls.trim()
59
- }
60
-
61
- function onClickItem(item, event) {
62
- if (item.disabled) {
63
- event.preventDefault()
64
- return
65
- }
66
- event.preventDefault()
67
- activeKey.set(item.href || item.id || activeKey())
68
- emit('navigate', item)
69
- }
70
-
71
- defineExpose({ activeKey })
72
- </script>
73
-
74
- <nav class="{{ containerClasses }} {{ gapClasses }}" role="navigation" aria-label="Main navigation">
75
- @foreach(item in items)
76
- @if(item.href)
77
- <a
78
- href="{{ item.href }}"
79
- :class="getItemClasses({{ JSON.stringify(item) }})"
80
- @click="onClickItem({{ JSON.stringify(item) }}, $event)"
81
- :aria-current="isActive({{ JSON.stringify(item) }}) ? 'page' : null"
82
- @if(item.disabled)aria-disabled="true" tabindex="-1"@endif
83
- >
84
- @if(item.icon)
85
- <span class="flex-shrink-0">{!! item.icon !!}</span>
86
- @endif
87
- <span>{{ item.label }}</span>
88
- @if(item.badge)
89
- <span class="ml-auto px-2 py-0.5 text-xs font-semibold rounded-full bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300">
90
- {{ item.badge }}
91
- </span>
92
- @endif
93
- </a>
94
- @else
95
- <button
96
- type="button"
97
- :class="getItemClasses({{ JSON.stringify(item) }})"
98
- @click="onClickItem({{ JSON.stringify(item) }}, $event)"
99
- @if(item.disabled)disabled aria-disabled="true"@endif
100
- >
101
- @if(item.icon)
102
- <span class="flex-shrink-0">{!! item.icon !!}</span>
103
- @endif
104
- <span>{{ item.label }}</span>
105
- @if(item.badge)
106
- <span class="ml-auto px-2 py-0.5 text-xs font-semibold rounded-full bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300">
107
- {{ item.badge }}
108
- </span>
109
- @endif
110
- </button>
111
- @endif
112
- @endforeach
113
- </nav>
@@ -1,352 +0,0 @@
1
- # Navigator Component
2
-
3
- A versatile navigation component that supports multiple orientations, variants, and styles. Perfect for main navigation, sidebars, tabs, and more.
4
-
5
- ## Features
6
-
7
- - ✅ Multiple variants (default, pills, underline, sidebar)
8
- - ✅ Horizontal and vertical orientations
9
- - ✅ Active state handling
10
- - ✅ Icon support
11
- - ✅ Badge support
12
- - ✅ Disabled states
13
- - ✅ Multiple sizes (sm, md, lg)
14
- - ✅ Custom navigation handlers
15
- - ✅ Dark mode support
16
- - ✅ Accessible with ARIA labels
17
- - ✅ Keyboard navigation support
18
-
19
- ## Usage
20
-
21
- ### Basic Horizontal Navigation
22
-
23
- ```stx
24
- <script>
25
- import { Navigator } from '@stacksjs/components'
26
-
27
- const items = [
28
- { id: 'home', label: 'Home', href: '/' },
29
- { id: 'about', label: 'About', href: '/about' },
30
- { id: 'contact', label: 'Contact', href: '/contact' },
31
- ]
32
-
33
- let activeItem = 'home'
34
- </script>
35
-
36
- <Navigator items={items} active={activeItem} />
37
- ```
38
-
39
- ### Vertical Sidebar Navigation
40
-
41
- ```stx
42
- <script>
43
- import { Navigator } from '@stacksjs/components'
44
-
45
- const items = [
46
- { id: 'dashboard', label: 'Dashboard', href: '/dashboard' },
47
- { id: 'projects', label: 'Projects', href: '/projects' },
48
- { id: 'team', label: 'Team', href: '/team' },
49
- { id: 'settings', label: 'Settings', href: '/settings' },
50
- ]
51
- </script>
52
-
53
- <Navigator
54
- items={items}
55
- active="dashboard"
56
- orientation="vertical"
57
- variant="sidebar"
58
- />
59
- ```
60
-
61
- ### Pills Navigation
62
-
63
- ```stx
64
- <script>
65
- import { Navigator } from '@stacksjs/components'
66
-
67
- const items = [
68
- { id: 'overview', label: 'Overview', href: '/overview' },
69
- { id: 'analytics', label: 'Analytics', href: '/analytics' },
70
- { id: 'reports', label: 'Reports', href: '/reports' },
71
- ]
72
- </script>
73
-
74
- <Navigator
75
- items={items}
76
- active="overview"
77
- variant="pills"
78
- />
79
- ```
80
-
81
- ### Underline Tabs
82
-
83
- ```stx
84
- <script>
85
- import { Navigator } from '@stacksjs/components'
86
-
87
- const tabs = [
88
- { id: 'profile', label: 'Profile', href: '#profile' },
89
- { id: 'security', label: 'Security', href: '#security' },
90
- { id: 'notifications', label: 'Notifications', href: '#notifications' },
91
- ]
92
- </script>
93
-
94
- <Navigator
95
- items={tabs}
96
- active="profile"
97
- variant="underline"
98
- />
99
- ```
100
-
101
- ### With Icons
102
-
103
- ```stx
104
- <script>
105
- import { Navigator } from '@stacksjs/components'
106
-
107
- const items = [
108
- {
109
- id: 'home',
110
- label: 'Home',
111
- href: '/',
112
- icon: '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" /></svg>',
113
- },
114
- {
115
- id: 'search',
116
- label: 'Search',
117
- href: '/search',
118
- icon: '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" /></svg>',
119
- },
120
- ]
121
- </script>
122
-
123
- <Navigator items={items} active="home" />
124
- ```
125
-
126
- ### With Badges
127
-
128
- ```stx
129
- <script>
130
- import { Navigator } from '@stacksjs/components'
131
-
132
- const items = [
133
- { id: 'inbox', label: 'Inbox', href: '/inbox', badge: '12' },
134
- { id: 'drafts', label: 'Drafts', href: '/drafts', badge: '3' },
135
- { id: 'sent', label: 'Sent', href: '/sent' },
136
- ]
137
- </script>
138
-
139
- <Navigator items={items} active="inbox" variant="sidebar" orientation="vertical" />
140
- ```
141
-
142
- ### With Disabled Items
143
-
144
- ```stx
145
- <script>
146
- import { Navigator } from '@stacksjs/components'
147
-
148
- const items = [
149
- { id: 'enabled', label: 'Enabled', href: '/enabled' },
150
- { id: 'disabled', label: 'Disabled (Coming Soon)', href: '/disabled', disabled: true },
151
- { id: 'another', label: 'Another Link', href: '/another' },
152
- ]
153
- </script>
154
-
155
- <Navigator items={items} active="enabled" />
156
- ```
157
-
158
- ### With Custom Navigation Handler
159
-
160
- ```stx
161
- <script>
162
- import { Navigator } from '@stacksjs/components'
163
-
164
- const items = [
165
- { id: 'tab1', label: 'Tab 1' },
166
- { id: 'tab2', label: 'Tab 2' },
167
- { id: 'tab3', label: 'Tab 3' },
168
- ]
169
-
170
- let activeTab = 'tab1'
171
-
172
- function handleNavigate(item) {
173
- activeTab = item.id
174
- console.log('Navigated to:', item.label)
175
- // Custom logic here (e.g., switch content, fetch data, etc.)
176
- }
177
- </script>
178
-
179
- <Navigator
180
- items={items}
181
- active={activeTab}
182
- onNavigate={handleNavigate}
183
- variant="underline"
184
- />
185
- ```
186
-
187
- ## Props
188
-
189
- | Prop | Type | Default | Description |
190
- |------|------|---------|-------------|
191
- | `items` | `NavigatorItem[]` | `[]` | Array of navigation items |
192
- | `active` | `string` | `''` | ID or href of the currently active item |
193
- | `orientation` | `'horizontal' \| 'vertical'` | `'horizontal'` | Layout orientation |
194
- | `variant` | `'default' \| 'pills' \| 'underline' \| 'sidebar'` | `'default'` | Visual style variant |
195
- | `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Size of navigation items |
196
- | `onNavigate` | `(item: NavigatorItem) => void` | - | Custom navigation handler (prevents default link behavior) |
197
- | `className` | `string` | `''` | Additional CSS classes |
198
-
199
- ### NavigatorItem Interface
200
-
201
- ```typescript
202
- interface NavigatorItem {
203
- id?: string // Unique identifier
204
- label: string // Display text
205
- href?: string // Link URL (renders as <a> if provided, <button> otherwise)
206
- icon?: string // SVG icon HTML
207
- badge?: string | number // Badge text/number
208
- disabled?: boolean // Whether the item is disabled
209
- }
210
- ```
211
-
212
- ## Variants
213
-
214
- ### Default
215
- Clean, simple navigation with subtle hover effects.
216
-
217
- ### Pills
218
- Rounded pill-style navigation with filled active state.
219
-
220
- ### Underline
221
- Tab-style navigation with bottom border indicator.
222
-
223
- ### Sidebar
224
- Left-bordered navigation optimized for vertical sidebars.
225
-
226
- ## Sizes
227
-
228
- - **sm**: Compact padding and text
229
- - **md**: Default comfortable size
230
- - **lg**: Large padding and text
231
-
232
- ## Examples
233
-
234
- ### App Header Navigation
235
-
236
- ```stx
237
- <script>
238
- import { Navigator } from '@stacksjs/components'
239
-
240
- const mainNav = [
241
- { id: 'products', label: 'Products', href: '/products' },
242
- { id: 'pricing', label: 'Pricing', href: '/pricing' },
243
- { id: 'docs', label: 'Docs', href: '/docs' },
244
- { id: 'blog', label: 'Blog', href: '/blog' },
245
- ]
246
- </script>
247
-
248
- <header class="bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700">
249
- <div class="max-w-7xl mx-auto px-4 py-4">
250
- <Navigator items={mainNav} active="/products" />
251
- </div>
252
- </header>
253
- ```
254
-
255
- ### Dashboard Sidebar
256
-
257
- ```stx
258
- <script>
259
- import { Navigator } from '@stacksjs/components'
260
-
261
- const sidebarNav = [
262
- {
263
- id: 'dashboard',
264
- label: 'Dashboard',
265
- href: '/dashboard',
266
- icon: '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" /></svg>',
267
- },
268
- {
269
- id: 'projects',
270
- label: 'Projects',
271
- href: '/projects',
272
- badge: '5',
273
- icon: '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z" /></svg>',
274
- },
275
- {
276
- id: 'team',
277
- label: 'Team',
278
- href: '/team',
279
- icon: '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z" /></svg>',
280
- },
281
- ]
282
- </script>
283
-
284
- <aside class="w-64 bg-white dark:bg-gray-800 border-r border-gray-200 dark:border-gray-700 h-full">
285
- <Navigator
286
- items={sidebarNav}
287
- active="/dashboard"
288
- orientation="vertical"
289
- variant="sidebar"
290
- />
291
- </aside>
292
- ```
293
-
294
- ### Settings Tabs
295
-
296
- ```stx
297
- <script>
298
- import { Navigator } from '@stacksjs/components'
299
-
300
- const settingsTabs = [
301
- { id: 'general', label: 'General', href: '#general' },
302
- { id: 'security', label: 'Security', href: '#security' },
303
- { id: 'notifications', label: 'Notifications', href: '#notifications' },
304
- { id: 'billing', label: 'Billing', href: '#billing' },
305
- ]
306
-
307
- let activeTab = 'general'
308
- </script>
309
-
310
- <div class="border-b border-gray-200 dark:border-gray-700 mb-6">
311
- <Navigator
312
- items={settingsTabs}
313
- active={activeTab}
314
- variant="underline"
315
- />
316
- </div>
317
- ```
318
-
319
- ## Styling
320
-
321
- The navigator uses utility-first CSS classes and supports dark mode. Customize appearance by passing additional classes:
322
-
323
- ```stx
324
- <Navigator
325
- className="bg-gray-50 dark:bg-gray-900 rounded-lg p-2"
326
- items={items}
327
- active="home"
328
- />
329
- ```
330
-
331
- ## Accessibility
332
-
333
- - Semantic HTML (`<nav>`, `<a>`, `<button>`)
334
- - ARIA labels for navigation role
335
- - `aria-current="page"` for active items
336
- - `aria-disabled` for disabled items
337
- - Keyboard navigation support
338
- - Focus indicators
339
-
340
- ## Browser Support
341
-
342
- Works in all modern browsers that support:
343
- - CSS Flexbox
344
- - CSS custom properties
345
- - ES6+ JavaScript
346
-
347
- ## Related Components
348
-
349
- - **Breadcrumb**: Hierarchical navigation trail
350
- - **Tabs**: Content switching interface
351
- - **Sidebar**: Full sidebar layout with navigation
352
- - **Menu**: Dropdown menu navigation
@@ -1,20 +0,0 @@
1
- export { default as Navigator } from './Navigator.stx'
2
-
3
- export interface NavigatorItem {
4
- id?: string
5
- label: string
6
- href?: string
7
- icon?: string
8
- badge?: string | number
9
- disabled?: boolean
10
- }
11
-
12
- export interface NavigatorProps {
13
- items: NavigatorItem[]
14
- active?: string // ID or href of active item
15
- orientation?: 'horizontal' | 'vertical'
16
- variant?: 'default' | 'pills' | 'underline' | 'sidebar'
17
- size?: 'sm' | 'md' | 'lg'
18
- onNavigate?: (item: NavigatorItem) => void
19
- className?: string
20
- }