@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,41 +0,0 @@
1
- <script server>
2
- export const open = $props.open || false
3
- export const className = $props.className || ''
4
-
5
- const baseClasses = 'relative z-50'
6
- export const dialogClasses = `${baseClasses} ${className}`.trim()
7
- </script>
8
-
9
- <script client>
10
- const emit = defineEmits()
11
- // useReactiveProp wires `:open="parentSignal()"` from the parent into our
12
- // local `isOpen` signal — when the parent's signal changes, bindAttr
13
- // updates the root's `open` attribute, our MutationObserver picks it up,
14
- // and isOpen flips. See stacksjs/stx#1704.
15
- const isOpen = useReactiveProp('open', {{ open }})
16
-
17
- function close() {
18
- isOpen.set(false)
19
- emit('close')
20
- }
21
-
22
- function onBackdropKey(event) {
23
- if (event.key === 'Escape') close()
24
- }
25
-
26
- defineExpose({
27
- open: () => isOpen.set(true),
28
- close,
29
- isOpen,
30
- })
31
- </script>
32
-
33
- <div
34
- :show="isOpen()"
35
- class="{{ dialogClasses }}"
36
- role="dialog"
37
- aria-modal="true"
38
- @keydown="onBackdropKey($event)"
39
- >
40
- <slot />
41
- </div>
@@ -1,9 +0,0 @@
1
- <script server>
2
- export const className = $props.className || ''
3
- export const as = $props.as || 'div'
4
-
5
- const baseClasses = 'fixed inset-0 bg-black bg-opacity-25 dark:bg-opacity-50 transition-opacity'
6
- const backdropClasses = `${baseClasses} ${className}`.trim()
7
- </script>
8
-
9
- <component :is="{{ as }}" class="{{ backdropClasses }}" aria-hidden="true" />
@@ -1,11 +0,0 @@
1
- <script server>
2
- export const className = $props.className || ''
3
- export const as = $props.as || 'p'
4
-
5
- const baseClasses = 'mt-2 text-sm text-neutral-500 dark:text-neutral-400'
6
- const descriptionClasses = `${baseClasses} ${className}`.trim()
7
- </script>
8
-
9
- <component :is="{{ as }}" class="{{ descriptionClasses }}">
10
- <slot />
11
- </component>
@@ -1,16 +0,0 @@
1
- <script server>
2
- export const className = $props.className || ''
3
- export const as = $props.as || 'div'
4
-
5
- const baseClasses = 'fixed inset-0 overflow-y-auto'
6
- const panelWrapperClasses = 'flex min-h-full items-center justify-center p-4 text-center'
7
- const panelClasses = `transform overflow-hidden rounded-lg bg-white dark:bg-neutral-800 p-6 text-left align-middle shadow-xl transition-all ${className}`.trim()
8
- </script>
9
-
10
- <component :is="{{ as }}" class="{{ baseClasses }}">
11
- <div class="{{ panelWrapperClasses }}">
12
- <div class="{{ panelClasses }}">
13
- <slot />
14
- </div>
15
- </div>
16
- </component>
@@ -1,11 +0,0 @@
1
- <script server>
2
- export const className = $props.className || ''
3
- export const as = $props.as || 'h3'
4
-
5
- const baseClasses = 'text-lg font-medium leading-6 text-neutral-900 dark:text-white'
6
- const titleClasses = `${baseClasses} ${className}`.trim()
7
- </script>
8
-
9
- <component :is="{{ as }}" class="{{ titleClasses }}">
10
- <slot />
11
- </component>
@@ -1,121 +0,0 @@
1
- # Dialog Component
2
-
3
- A modal dialog component for overlays, alerts, and confirmations. Built with STX and headwind.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- bun add @stacksjs/components
9
- ```
10
-
11
- ## Usage
12
-
13
- ```stx
14
- <script server>
15
- let isOpen = false
16
-
17
- function closeModal() {
18
- isOpen = false
19
- }
20
-
21
- function openModal() {
22
- isOpen = true
23
- }
24
- </script>
25
-
26
- <Dialog :open="isOpen" :onClose="closeModal">
27
- <DialogBackdrop />
28
-
29
- <DialogPanel className="max-w-md">
30
- <DialogTitle>Payment successful</DialogTitle>
31
-
32
- <DialogDescription>
33
- Your payment has been successfully submitted.
34
- </DialogDescription>
35
-
36
- <div class="mt-4">
37
- <Button :onClick="closeModal">Got it, thanks!</Button>
38
- </div>
39
- </DialogPanel>
40
- </Dialog>
41
- ```
42
-
43
- ## Props
44
-
45
- ### Dialog
46
- | Prop | Type | Default | Description |
47
- |------|------|---------|-------------|
48
- | `open` | `boolean` | `false` | Whether dialog is open |
49
- | `onClose` | `(value: boolean) => void` | - | Close handler |
50
- | `className` | `string` | `''` | Additional CSS classes |
51
- | `as` | `string` | `'div'` | HTML element to render |
52
-
53
- ### DialogBackdrop
54
- | Prop | Type | Default | Description |
55
- |------|------|---------|-------------|
56
- | `className` | `string` | `''` | Additional CSS classes |
57
- | `as` | `string` | `'div'` | HTML element to render |
58
-
59
- ### DialogPanel
60
- | Prop | Type | Default | Description |
61
- |------|------|---------|-------------|
62
- | `className` | `string` | `''` | Additional CSS classes |
63
- | `as` | `string` | `'div'` | HTML element to render |
64
-
65
- ### DialogTitle
66
- | Prop | Type | Default | Description |
67
- |------|------|---------|-------------|
68
- | `className` | `string` | `''` | Additional CSS classes |
69
- | `as` | `string` | `'h3'` | HTML element to render |
70
-
71
- ### DialogDescription
72
- | Prop | Type | Default | Description |
73
- |------|------|---------|-------------|
74
- | `className` | `string` | `''` | Additional CSS classes |
75
- | `as` | `string` | `'p'` | HTML element to render |
76
-
77
- ## Examples
78
-
79
- ### Confirmation Dialog
80
-
81
- ```stx
82
- <Dialog :open="isOpen" :onClose="closeModal">
83
- <DialogBackdrop />
84
-
85
- <DialogPanel className="max-w-md">
86
- <DialogTitle>Delete account</DialogTitle>
87
-
88
- <DialogDescription>
89
- Are you sure you want to delete your account? This action cannot be undone.
90
- </DialogDescription>
91
-
92
- <div class="mt-4 flex gap-2">
93
- <Button variant="danger" :onClick="handleDelete">Delete</Button>
94
- <Button variant="secondary" :onClick="closeModal">Cancel</Button>
95
- </div>
96
- </DialogPanel>
97
- </Dialog>
98
- ```
99
-
100
- ### Large Dialog
101
-
102
- ```stx
103
- <DialogPanel className="max-w-4xl">
104
- <DialogTitle>Terms and Conditions</DialogTitle>
105
-
106
- <div class="mt-4 max-h-96 overflow-y-auto">
107
- <!-- Long content -->
108
- </div>
109
- </DialogPanel>
110
- ```
111
-
112
- ## Features
113
-
114
- - Focus trap
115
- - Backdrop overlay
116
- - Keyboard support (ESC to close)
117
- - Dark mode support
118
- - Accessible (WAI-ARIA)
119
- - Customizable with headwind classes
120
- - Multiple sizes
121
- - Scrollable content support
@@ -1,32 +0,0 @@
1
- export { default as Dialog } from './Dialog.stx'
2
- export { default as DialogBackdrop } from './DialogBackdrop.stx'
3
- export { default as DialogDescription } from './DialogDescription.stx'
4
- export { default as DialogPanel } from './DialogPanel.stx'
5
- export { default as DialogTitle } from './DialogTitle.stx'
6
-
7
- export interface DialogProps {
8
- open?: boolean
9
- onClose?: (value: boolean) => void
10
- className?: string
11
- as?: string
12
- }
13
-
14
- export interface DialogBackdropProps {
15
- className?: string
16
- as?: string
17
- }
18
-
19
- export interface DialogPanelProps {
20
- className?: string
21
- as?: string
22
- }
23
-
24
- export interface DialogTitleProps {
25
- className?: string
26
- as?: string
27
- }
28
-
29
- export interface DialogDescriptionProps {
30
- className?: string
31
- as?: string
32
- }
@@ -1,120 +0,0 @@
1
- <script server>
2
- export const open = $props.open ?? false
3
- export const position = $props.position || 'right'
4
- export const title = $props.title || ''
5
- export const className = $props.className || ''
6
-
7
- const positionClasses = {
8
- right: 'inset-y-0 right-0 pl-10 sm:pl-16',
9
- left: 'inset-y-0 left-0 pr-10 sm:pr-16',
10
- top: 'inset-x-0 top-0 pb-10',
11
- bottom: 'inset-x-0 bottom-0 pt-10',
12
- }
13
-
14
- const sizeClasses = {
15
- right: 'max-w-md w-screen',
16
- left: 'max-w-md w-screen',
17
- top: 'max-h-[90vh] w-full',
18
- bottom: 'max-h-[90vh] w-full',
19
- }
20
-
21
- const closeButtonPosition = {
22
- right: 'left-0 -ml-8 sm:-ml-10',
23
- left: 'right-0 -mr-8 sm:-mr-10',
24
- top: 'right-0 -mr-8',
25
- bottom: 'right-0 -mr-8',
26
- }
27
-
28
- export const containerClasses = `pointer-events-none fixed ${positionClasses[position]} flex max-w-full`.trim()
29
- export const panelClasses = `pointer-events-auto relative ${sizeClasses[position]} ${className}`.trim()
30
- export const closeButtonClasses = `absolute top-0 ${closeButtonPosition[position]} flex pt-4 pr-2 sm:pr-4`.trim()
31
- </script>
32
-
33
- <script client>
34
- const emit = defineEmits()
35
- // useReactiveProp lets the parent drive `open` via signals
36
- // (`:open="drawerOpen()"`) instead of the prop being captured once.
37
- // See stacksjs/stx#1704.
38
- const isOpen = useReactiveProp('open', {{ open }})
39
-
40
- function close() {
41
- isOpen.set(false)
42
- emit('close')
43
- }
44
-
45
- function onBackdropClick() {
46
- close()
47
- }
48
-
49
- function onPanelKey(event) {
50
- if (event.key === 'Escape') close()
51
- }
52
-
53
- defineExpose({
54
- open: () => isOpen.set(true),
55
- close,
56
- isOpen,
57
- })
58
- </script>
59
-
60
- <div :show="isOpen()">
61
- <div
62
- class="fixed inset-0 z-50 bg-gray-500/75 dark:bg-gray-900/75 transition-opacity duration-500"
63
- style="animation: fadeIn 0.5s ease-in-out"
64
- @click="onBackdropClick()"
65
- ></div>
66
-
67
- <div class="fixed inset-0 z-50 overflow-hidden" @keydown="onPanelKey($event)">
68
- <div class="absolute inset-0 overflow-hidden">
69
- <div class="{{ containerClasses }}">
70
- <div
71
- class="{{ panelClasses }}"
72
- style="animation: slideIn 0.5s ease-in-out"
73
- >
74
- <div class="{{ closeButtonClasses }}">
75
- <button
76
- type="button"
77
- class="relative rounded-md text-gray-300 dark:text-gray-400 hover:text-white dark:hover:text-white focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
78
- @click="close()"
79
- >
80
- <span class="absolute -inset-2.5"></span>
81
- <span class="sr-only">Close panel</span>
82
- <svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
83
- <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
84
- </svg>
85
- </button>
86
- </div>
87
-
88
- <div class="relative flex h-full flex-col overflow-y-auto bg-white dark:bg-blue-gray-800 py-6 shadow-xl">
89
- @if(title)
90
- <div class="px-4 sm:px-6">
91
- <h2 class="text-base font-semibold text-gray-900 dark:text-gray-100">
92
- {{ title }}
93
- </h2>
94
- </div>
95
- @endif
96
- <div class="relative mt-6 flex-1 px-4 sm:px-6">
97
- <slot />
98
- </div>
99
- </div>
100
- </div>
101
- </div>
102
- </div>
103
- </div>
104
- </div>
105
-
106
- <style>
107
- @keyframes fadeIn {
108
- from { opacity: 0; }
109
- to { opacity: 1; }
110
- }
111
-
112
- @keyframes slideIn {
113
- from {
114
- transform: {{ position === 'right' ? 'translateX(100%)' : position === 'left' ? 'translateX(-100%)' : position === 'top' ? 'translateY(-100%)' : 'translateY(100%)' }};
115
- }
116
- to {
117
- transform: translate(0, 0);
118
- }
119
- }
120
- </style>
@@ -1,90 +0,0 @@
1
- # Drawer Component
2
-
3
- A slide-out panel component that can appear from any side of the screen.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- bun add @stacksjs/components
9
- ```
10
-
11
- ## Usage
12
-
13
- ```stx
14
- <script server>
15
- let drawerOpen = false
16
- </script>
17
-
18
- <button
19
- class="rounded-md bg-gray-950/5 px-2.5 py-1.5 text-sm font-semibold text-gray-900 hover:bg-gray-950/10"
20
- onclick="drawerOpen = true"
21
- >
22
- Open drawer
23
- </button>
24
-
25
- <Drawer
26
- :open="drawerOpen"
27
- :onClose="() => drawerOpen = false"
28
- position="right"
29
- title="Panel title"
30
- >
31
- <p class="text-sm text-gray-500 dark:text-gray-400">
32
- Your drawer content goes here.
33
- </p>
34
- </Drawer>
35
- ```
36
-
37
- ## Props
38
-
39
- | Prop | Type | Default | Description |
40
- |------|------|---------|-------------|
41
- | `open` | `boolean` | `false` | Controls drawer visibility |
42
- | `onClose` | `function` | - | Callback when drawer should close |
43
- | `position` | `'right' \| 'left' \| 'top' \| 'bottom'` | `'right'` | Position of the drawer |
44
- | `title` | `string` | `''` | Optional title for the drawer |
45
- | `className` | `string` | `''` | Additional CSS classes |
46
-
47
- ## Positions
48
-
49
- ### Right (default)
50
- ```stx
51
- <Drawer open position="right">Content</Drawer>
52
- ```
53
-
54
- ### Left
55
- ```stx
56
- <Drawer open position="left">Content</Drawer>
57
- ```
58
-
59
- ### Top
60
- ```stx
61
- <Drawer open position="top">Content</Drawer>
62
- ```
63
-
64
- ### Bottom
65
- ```stx
66
- <Drawer open position="bottom">Content</Drawer>
67
- ```
68
-
69
- ## Features
70
-
71
- - **4 positions** - Slide from right, left, top, or bottom
72
- - **Smooth animations** - CSS transitions for slide and fade effects
73
- - **Backdrop click** - Closes drawer when clicking outside
74
- - **Close button** - Positioned appropriately for each direction
75
- - **Dark mode** - Full dark mode support
76
- - **Accessible** - Screen reader support and focus management
77
- - **Responsive** - Mobile-friendly with adjusted spacing
78
- - **Modern ES modules** - Clean export syntax
79
- - **Headwind styling** - Utility-first CSS classes
80
-
81
- ## Accessibility
82
-
83
- - Close button includes `sr-only` text for screen readers
84
- - Backdrop and close button have proper ARIA labels
85
- - Keyboard accessible (ESC key closes drawer - handled by parent)
86
- - Focus management for modal behavior
87
-
88
- ## Customization
89
-
90
- The drawer accepts a `className` prop for additional styling and supports slot content for complete customization of the drawer body.
@@ -1,9 +0,0 @@
1
- export { default as Drawer } from './Drawer.stx'
2
-
3
- export interface DrawerProps {
4
- open?: boolean
5
- onClose?: () => void
6
- position?: 'right' | 'left' | 'top' | 'bottom'
7
- title?: string
8
- className?: string
9
- }
@@ -1,82 +0,0 @@
1
- <script server>
2
- export const className = $props.className || ''
3
- export const as = $props.as || 'div'
4
-
5
- const baseClasses = 'relative inline-block text-left'
6
- export const dropdownClasses = `${baseClasses} ${className}`.trim()
7
- export const dropdownInstanceId = `stx-dd-${Math.random().toString(36).slice(2, 11)}`
8
- </script>
9
-
10
- <script client>
11
- const emit = defineEmits()
12
- const dropdownInstanceId = {{ dropdownInstanceId }}
13
- const isOpen = state(false)
14
- let rootEl = null
15
- let outsideHandler = null
16
-
17
- function toggle() {
18
- isOpen.set(!isOpen())
19
- emit('change', isOpen())
20
- }
21
-
22
- function open() {
23
- if (isOpen()) return
24
- isOpen.set(true)
25
- emit('change', true)
26
- }
27
-
28
- function close() {
29
- if (!isOpen()) return
30
- isOpen.set(false)
31
- emit('change', false)
32
- }
33
-
34
- function onItemSelect(event) {
35
- event.stopPropagation()
36
- emit('select', event.detail)
37
- close()
38
- }
39
-
40
- function onToggle(event) { event.stopPropagation(); toggle() }
41
- function onOpen(event) { event.stopPropagation(); open() }
42
- function onClose(event) { event.stopPropagation(); close() }
43
-
44
- onMount(() => {
45
- rootEl = document.querySelector(`[data-dropdown-id="${dropdownInstanceId}"]`)
46
- outsideHandler = (event) => {
47
- if (!isOpen()) return
48
- if (rootEl && !rootEl.contains(event.target)) close()
49
- }
50
- document.addEventListener('click', outsideHandler, true)
51
- })
52
-
53
- onDestroy(() => {
54
- if (outsideHandler) document.removeEventListener('click', outsideHandler, true)
55
- })
56
-
57
- const dataState = derived(() => isOpen() ? 'open' : 'closed')
58
- const dataExpanded = derived(() => isOpen() ? 'true' : 'false')
59
-
60
- defineExpose({ isOpen, toggle, open, close })
61
- </script>
62
-
63
- <component
64
- :is="{{ as }}"
65
- class="{{ dropdownClasses }}"
66
- data-stx-dropdown
67
- data-dropdown-id="{{ dropdownInstanceId }}"
68
- :data-state="dataState()"
69
- :data-expanded="dataExpanded()"
70
- @stx:dropdown-toggle="onToggle($event)"
71
- @stx:dropdown-open="onOpen($event)"
72
- @stx:dropdown-close="onClose($event)"
73
- @stx:dropdown-select="onItemSelect($event)"
74
- >
75
- <slot />
76
- </component>
77
-
78
- <style>
79
- [data-stx-dropdown][data-state="closed"] [data-stx-dropdown-items] {
80
- display: none;
81
- }
82
- </style>
@@ -1,29 +0,0 @@
1
- <script server>
2
- export const className = $props.className || ''
3
- export const as = $props.as || 'button'
4
- export const disabled = $props.disabled || false
5
-
6
- const baseClasses = 'inline-flex justify-center items-center rounded-md focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75'
7
- export const buttonClasses = `${baseClasses} ${className}`.trim()
8
- </script>
9
-
10
- <script client>
11
- const emit = defineEmits()
12
- const isDisabled = {{ disabled }}
13
-
14
- function onClick(event) {
15
- if (isDisabled) return
16
- emit('click', event)
17
- event.currentTarget.dispatchEvent(new CustomEvent('stx:dropdown-toggle', { bubbles: true }))
18
- }
19
- </script>
20
-
21
- <component
22
- :is="{{ as }}"
23
- class="{{ buttonClasses }}"
24
- data-stx-dropdown-button
25
- @if(disabled)disabled aria-disabled="true"@endif
26
- @click="onClick($event)"
27
- >
28
- <slot />
29
- </component>
@@ -1,35 +0,0 @@
1
- <script server>
2
- export const className = $props.className || ''
3
- export const as = $props.as || 'div'
4
- export const disabled = $props.disabled || false
5
- export const value = $props.value
6
-
7
- const baseClasses = 'group flex w-full items-center px-2 py-2 text-sm transition-colors text-neutral-900 dark:text-neutral-100 hover:bg-blue-500 hover:text-white dark:hover:bg-blue-600'
8
- const disabledClasses = disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'
9
- export const itemClasses = `${baseClasses} ${disabledClasses} ${className}`.trim()
10
- </script>
11
-
12
- <script client>
13
- const emit = defineEmits()
14
- const isDisabled = {{ disabled }}
15
- const itemValue = {{ value === undefined ? 'null' : value }}
16
-
17
- function onClick(event) {
18
- if (isDisabled) return
19
- emit('click', event)
20
- event.currentTarget.dispatchEvent(
21
- new CustomEvent('stx:dropdown-select', { bubbles: true, detail: itemValue }),
22
- )
23
- }
24
- </script>
25
-
26
- <component
27
- :is="{{ as }}"
28
- class="{{ itemClasses }}"
29
- data-stx-dropdown-item
30
- role="menuitem"
31
- @if(disabled)aria-disabled="true"@endif
32
- @click="onClick($event)"
33
- >
34
- <slot :disabled="disabled" />
35
- </component>
@@ -1,18 +0,0 @@
1
- <script server>
2
- export const className = $props.className || ''
3
- export const as = $props.as || 'div'
4
-
5
- const baseClasses = 'absolute z-10 mt-2 origin-top-right divide-y divide-neutral-100 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none dark:bg-neutral-800 dark:divide-neutral-700 dark:ring-neutral-600'
6
- export const itemsClasses = `${baseClasses} ${className}`.trim()
7
- </script>
8
-
9
- <component
10
- :is="{{ as }}"
11
- class="{{ itemsClasses }}"
12
- data-stx-dropdown-items
13
- role="menu"
14
- aria-orientation="vertical"
15
- tabindex="-1"
16
- >
17
- <slot />
18
- </component>