@proyecto-viviana/ui 0.1.7 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/README.md +192 -0
  2. package/dist/autocomplete/index.d.ts +89 -0
  3. package/dist/autocomplete/index.d.ts.map +1 -0
  4. package/dist/breadcrumbs/index.d.ts +38 -0
  5. package/dist/breadcrumbs/index.d.ts.map +1 -0
  6. package/dist/button/Button.d.ts.map +1 -1
  7. package/dist/calendar/DateField.d.ts +47 -0
  8. package/dist/calendar/DateField.d.ts.map +1 -0
  9. package/dist/calendar/DatePicker.d.ts +48 -0
  10. package/dist/calendar/DatePicker.d.ts.map +1 -0
  11. package/dist/calendar/RangeCalendar.d.ts +42 -0
  12. package/dist/calendar/RangeCalendar.d.ts.map +1 -0
  13. package/dist/calendar/TimeField.d.ts +44 -0
  14. package/dist/calendar/TimeField.d.ts.map +1 -0
  15. package/dist/calendar/index.d.ts +50 -0
  16. package/dist/calendar/index.d.ts.map +1 -0
  17. package/dist/checkbox/index.d.ts.map +1 -1
  18. package/dist/color/index.d.ts +228 -0
  19. package/dist/color/index.d.ts.map +1 -0
  20. package/dist/combobox/index.d.ts +81 -0
  21. package/dist/combobox/index.d.ts.map +1 -0
  22. package/dist/components.css +116 -14
  23. package/dist/custom/chip/index.d.ts +7 -2
  24. package/dist/custom/chip/index.d.ts.map +1 -1
  25. package/dist/custom/event-card/index.d.ts +5 -1
  26. package/dist/custom/event-card/index.d.ts.map +1 -1
  27. package/dist/custom/header/index.d.ts +16 -0
  28. package/dist/custom/header/index.d.ts.map +1 -0
  29. package/dist/custom/logo/index.d.ts +2 -0
  30. package/dist/custom/logo/index.d.ts.map +1 -1
  31. package/dist/custom/page-layout/index.d.ts +2 -0
  32. package/dist/custom/page-layout/index.d.ts.map +1 -1
  33. package/dist/custom/profile-card/index.d.ts +5 -1
  34. package/dist/custom/profile-card/index.d.ts.map +1 -1
  35. package/dist/custom/timeline-item/index.d.ts +12 -2
  36. package/dist/custom/timeline-item/index.d.ts.map +1 -1
  37. package/dist/dialog/Dialog.d.ts +67 -0
  38. package/dist/dialog/Dialog.d.ts.map +1 -0
  39. package/dist/dialog/index.d.ts +2 -17
  40. package/dist/dialog/index.d.ts.map +1 -1
  41. package/dist/disclosure/index.d.ts +84 -0
  42. package/dist/disclosure/index.d.ts.map +1 -0
  43. package/dist/gridlist/index.d.ts +92 -0
  44. package/dist/gridlist/index.d.ts.map +1 -0
  45. package/dist/index.d.ts +58 -4
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +6984 -783
  48. package/dist/index.js.map +1 -1
  49. package/dist/index.ssr.js +5905 -571
  50. package/dist/index.ssr.js.map +1 -1
  51. package/dist/landmark/index.d.ts +83 -0
  52. package/dist/landmark/index.d.ts.map +1 -0
  53. package/dist/link/index.d.ts.map +1 -1
  54. package/dist/listbox/index.d.ts +47 -0
  55. package/dist/listbox/index.d.ts.map +1 -0
  56. package/dist/menu/index.d.ts +74 -0
  57. package/dist/menu/index.d.ts.map +1 -0
  58. package/dist/meter/index.d.ts +49 -0
  59. package/dist/meter/index.d.ts.map +1 -0
  60. package/dist/numberfield/index.d.ts +50 -0
  61. package/dist/numberfield/index.d.ts.map +1 -0
  62. package/dist/popover/index.d.ts +85 -0
  63. package/dist/popover/index.d.ts.map +1 -0
  64. package/dist/radio/index.d.ts +7 -4
  65. package/dist/radio/index.d.ts.map +1 -1
  66. package/dist/searchfield/index.d.ts +44 -0
  67. package/dist/searchfield/index.d.ts.map +1 -0
  68. package/dist/select/index.d.ts +72 -0
  69. package/dist/select/index.d.ts.map +1 -0
  70. package/dist/slider/index.d.ts +53 -0
  71. package/dist/slider/index.d.ts.map +1 -0
  72. package/dist/switch/ToggleSwitch.d.ts.map +1 -1
  73. package/dist/table/index.d.ts +140 -0
  74. package/dist/table/index.d.ts.map +1 -0
  75. package/dist/tabs/index.d.ts +56 -0
  76. package/dist/tabs/index.d.ts.map +1 -0
  77. package/dist/tag-group/index.d.ts +80 -0
  78. package/dist/tag-group/index.d.ts.map +1 -0
  79. package/dist/toast/index.d.ts +101 -0
  80. package/dist/toast/index.d.ts.map +1 -0
  81. package/dist/toolbar/index.d.ts +42 -0
  82. package/dist/toolbar/index.d.ts.map +1 -0
  83. package/dist/tooltip/index.d.ts +66 -5
  84. package/dist/tooltip/index.d.ts.map +1 -1
  85. package/dist/tree/index.d.ts +99 -0
  86. package/dist/tree/index.d.ts.map +1 -0
  87. package/package.json +66 -58
  88. package/src/autocomplete/index.tsx +313 -0
  89. package/src/breadcrumbs/index.tsx +207 -0
  90. package/src/button/Button.tsx +74 -75
  91. package/src/calendar/DateField.tsx +200 -0
  92. package/src/calendar/DatePicker.tsx +298 -0
  93. package/src/calendar/RangeCalendar.tsx +236 -0
  94. package/src/calendar/TimeField.tsx +196 -0
  95. package/src/calendar/index.tsx +223 -0
  96. package/src/checkbox/index.tsx +3 -4
  97. package/src/color/index.tsx +687 -0
  98. package/src/combobox/index.tsx +383 -0
  99. package/src/components.css +116 -14
  100. package/src/custom/chip/index.tsx +17 -3
  101. package/src/custom/event-card/index.tsx +8 -2
  102. package/src/custom/header/index.tsx +33 -0
  103. package/src/custom/logo/index.tsx +7 -3
  104. package/src/custom/page-layout/index.tsx +12 -3
  105. package/src/custom/profile-card/index.tsx +8 -2
  106. package/src/custom/timeline-item/index.tsx +28 -4
  107. package/src/dialog/Dialog.tsx +260 -0
  108. package/src/dialog/index.tsx +3 -69
  109. package/src/disclosure/index.tsx +307 -0
  110. package/src/gridlist/index.tsx +403 -0
  111. package/src/index.ts +219 -4
  112. package/src/landmark/index.tsx +231 -0
  113. package/src/link/index.tsx +1 -2
  114. package/src/listbox/index.tsx +231 -0
  115. package/src/menu/index.tsx +297 -0
  116. package/src/meter/index.tsx +163 -0
  117. package/src/numberfield/index.tsx +482 -0
  118. package/src/popover/index.tsx +260 -0
  119. package/src/radio/index.tsx +36 -82
  120. package/src/searchfield/index.tsx +453 -0
  121. package/src/select/index.tsx +349 -0
  122. package/src/slider/index.tsx +382 -0
  123. package/src/switch/ToggleSwitch.tsx +1 -2
  124. package/src/table/index.tsx +531 -0
  125. package/src/tabs/index.tsx +273 -0
  126. package/src/tag-group/index.tsx +240 -0
  127. package/src/toast/index.tsx +324 -0
  128. package/src/toolbar/index.tsx +108 -0
  129. package/src/tooltip/index.tsx +171 -5
  130. package/src/tree/index.tsx +494 -0
@@ -0,0 +1,260 @@
1
+ /**
2
+ * Popover component for proyecto-viviana-ui
3
+ *
4
+ * A popover displays content in an overlay positioned relative to a trigger.
5
+ * Built on top of solidaria-components for accessibility.
6
+ * Follows Spectrum 2 design patterns.
7
+ */
8
+
9
+ import { type JSX, Show, splitProps } from 'solid-js'
10
+ import {
11
+ Popover as HeadlessPopover,
12
+ PopoverTrigger as HeadlessPopoverTrigger,
13
+ OverlayArrow as HeadlessOverlayArrow,
14
+ type PopoverProps as HeadlessPopoverProps,
15
+ type PopoverTriggerProps as HeadlessPopoverTriggerProps,
16
+ type PopoverRenderProps,
17
+ } from '@proyecto-viviana/solidaria-components'
18
+ import type { Placement, PlacementAxis } from '@proyecto-viviana/solidaria'
19
+
20
+ // ============================================
21
+ // TYPES
22
+ // ============================================
23
+
24
+ export type PopoverPlacement = Placement
25
+ export type PopoverSize = 'sm' | 'md' | 'lg'
26
+
27
+ export interface PopoverTriggerProps extends HeadlessPopoverTriggerProps {
28
+ /** The children of the popover trigger (trigger element and popover). */
29
+ children: JSX.Element
30
+ }
31
+
32
+ export interface PopoverProps extends Omit<HeadlessPopoverProps, 'class' | 'style' | 'children'> {
33
+ /** The content of the popover. */
34
+ children: JSX.Element
35
+ /** The position of the popover relative to the trigger. */
36
+ placement?: PopoverPlacement
37
+ /** Size variant of the popover. */
38
+ size?: PopoverSize
39
+ /** Additional CSS class name. */
40
+ class?: string
41
+ /** Whether to show an arrow pointing to the trigger. */
42
+ showArrow?: boolean
43
+ /** Custom padding inside the popover. */
44
+ padding?: 'none' | 'sm' | 'md' | 'lg'
45
+ }
46
+
47
+ // ============================================
48
+ // STYLES
49
+ // ============================================
50
+
51
+ const baseStyles = [
52
+ 'bg-bg-300',
53
+ 'rounded-lg',
54
+ 'shadow-xl',
55
+ 'border border-primary-700',
56
+ 'text-primary-200',
57
+ 'outline-none',
58
+ // Animation
59
+ 'animate-in fade-in-0 zoom-in-95',
60
+ 'data-[placement=top]:slide-in-from-bottom-2',
61
+ 'data-[placement=bottom]:slide-in-from-top-2',
62
+ 'data-[placement=left]:slide-in-from-right-2',
63
+ 'data-[placement=right]:slide-in-from-left-2',
64
+ 'data-[exiting]:animate-out data-[exiting]:fade-out-0 data-[exiting]:zoom-out-95',
65
+ ].join(' ')
66
+
67
+ const sizeStyles: Record<PopoverSize, string> = {
68
+ sm: 'max-w-xs',
69
+ md: 'max-w-sm',
70
+ lg: 'max-w-lg',
71
+ }
72
+
73
+ const paddingStyles: Record<string, string> = {
74
+ none: '',
75
+ sm: 'p-2',
76
+ md: 'p-4',
77
+ lg: 'p-6',
78
+ }
79
+
80
+ // Arrow styles based on placement
81
+ const arrowBaseStyles = [
82
+ 'fill-bg-300',
83
+ 'stroke-primary-700',
84
+ 'stroke-1',
85
+ ].join(' ')
86
+
87
+ // Arrow positioning for each placement axis
88
+ const getArrowRotation = (placement: PlacementAxis | null): string => {
89
+ switch (placement) {
90
+ case 'top':
91
+ return 'rotate-180'
92
+ case 'bottom':
93
+ return ''
94
+ case 'left':
95
+ return 'rotate-90'
96
+ case 'right':
97
+ return '-rotate-90'
98
+ default:
99
+ return ''
100
+ }
101
+ }
102
+
103
+ // ============================================
104
+ // COMPONENTS
105
+ // ============================================
106
+
107
+ /**
108
+ * PopoverTrigger wraps around a trigger element and a Popover.
109
+ * It handles opening and closing the Popover when the user interacts
110
+ * with the trigger.
111
+ *
112
+ * @example
113
+ * ```tsx
114
+ * <PopoverTrigger>
115
+ * <Button>Open Popover</Button>
116
+ * <Popover>
117
+ * <p>Popover content here!</p>
118
+ * </Popover>
119
+ * </PopoverTrigger>
120
+ * ```
121
+ */
122
+ export function PopoverTrigger(props: PopoverTriggerProps): JSX.Element {
123
+ return <HeadlessPopoverTrigger {...props} />
124
+ }
125
+
126
+ /**
127
+ * Styled popover component that displays content in an overlay.
128
+ *
129
+ * @example
130
+ * ```tsx
131
+ * <PopoverTrigger>
132
+ * <Button>Settings</Button>
133
+ * <Popover placement="bottom" size="md">
134
+ * <h3>Settings</h3>
135
+ * <p>Configure your preferences here.</p>
136
+ * </Popover>
137
+ * </PopoverTrigger>
138
+ * ```
139
+ */
140
+ export function Popover(props: PopoverProps): JSX.Element {
141
+ const [local, rest] = splitProps(props, [
142
+ 'placement',
143
+ 'size',
144
+ 'class',
145
+ 'showArrow',
146
+ 'padding',
147
+ ])
148
+
149
+ const placement = () => local.placement ?? 'bottom'
150
+ const size = () => local.size ?? 'md'
151
+ const padding = () => local.padding ?? 'md'
152
+
153
+ return (
154
+ <HeadlessPopover
155
+ {...rest}
156
+ placement={placement()}
157
+ class={(_renderProps: PopoverRenderProps) => {
158
+ const classes = [
159
+ baseStyles,
160
+ sizeStyles[size()],
161
+ paddingStyles[padding()],
162
+ local.class ?? '',
163
+ ].filter(Boolean).join(' ')
164
+ return classes
165
+ }}
166
+ >
167
+ {(renderProps: PopoverRenderProps) => (
168
+ <>
169
+ <Show when={local.showArrow}>
170
+ <PopoverArrow placement={renderProps.placement} />
171
+ </Show>
172
+ {props.children}
173
+ </>
174
+ )}
175
+ </HeadlessPopover>
176
+ )
177
+ }
178
+
179
+ /**
180
+ * Arrow component for the popover.
181
+ * Automatically positions itself based on the popover placement.
182
+ */
183
+ interface PopoverArrowProps {
184
+ /** The current placement axis. */
185
+ placement: PlacementAxis | null
186
+ /** Additional CSS class. */
187
+ class?: string
188
+ }
189
+
190
+ function PopoverArrow(props: PopoverArrowProps): JSX.Element {
191
+ return (
192
+ <HeadlessOverlayArrow
193
+ class="absolute block"
194
+ style={{
195
+ // Position based on placement
196
+ ...(props.placement === 'top' && { bottom: '100%', left: '50%', transform: 'translateX(-50%)' }),
197
+ ...(props.placement === 'bottom' && { top: '-8px', left: '50%', transform: 'translateX(-50%)' }),
198
+ ...(props.placement === 'left' && { right: '100%', top: '50%', transform: 'translateY(-50%)' }),
199
+ ...(props.placement === 'right' && { left: '-8px', top: '50%', transform: 'translateY(-50%)' }),
200
+ }}
201
+ >
202
+ <svg
203
+ width="12"
204
+ height="12"
205
+ viewBox="0 0 12 12"
206
+ class={`${arrowBaseStyles} ${getArrowRotation(props.placement)} ${props.class ?? ''}`}
207
+ >
208
+ <path d="M0 0 L6 6 L12 0" />
209
+ </svg>
210
+ </HeadlessOverlayArrow>
211
+ )
212
+ }
213
+
214
+ // ============================================
215
+ // POPOVER CONTENT SECTIONS
216
+ // ============================================
217
+
218
+ export interface PopoverHeaderProps {
219
+ /** The title of the popover. */
220
+ title: string
221
+ /** Optional description text. */
222
+ description?: string
223
+ /** Additional CSS class. */
224
+ class?: string
225
+ }
226
+
227
+ /**
228
+ * Header section for popover with title and optional description.
229
+ */
230
+ export function PopoverHeader(props: PopoverHeaderProps): JSX.Element {
231
+ return (
232
+ <div class={`mb-3 ${props.class ?? ''}`}>
233
+ <h3 class="text-lg font-semibold text-primary-100">{props.title}</h3>
234
+ <Show when={props.description}>
235
+ <p class="text-sm text-primary-400 mt-1">{props.description}</p>
236
+ </Show>
237
+ </div>
238
+ )
239
+ }
240
+
241
+ export interface PopoverFooterProps {
242
+ /** Footer content, typically buttons. */
243
+ children: JSX.Element
244
+ /** Additional CSS class. */
245
+ class?: string
246
+ }
247
+
248
+ /**
249
+ * Footer section for popover actions.
250
+ */
251
+ export function PopoverFooter(props: PopoverFooterProps): JSX.Element {
252
+ return (
253
+ <div class={`flex gap-2 justify-end mt-4 pt-3 border-t border-primary-700 ${props.class ?? ''}`}>
254
+ {props.children}
255
+ </div>
256
+ )
257
+ }
258
+
259
+ // Re-export types
260
+ export type { PopoverRenderProps, Placement, PlacementAxis }
@@ -2,10 +2,7 @@
2
2
  * RadioGroup and Radio components for proyecto-viviana-ui
3
3
  *
4
4
  * Styled radio components built on top of solidaria-components.
5
- *
6
- * IMPORTANT: Due to SolidJS's JSX evaluation order, we cannot wrap the headless
7
- * components in a traditional way. Instead, we re-export them and provide
8
- * styling through the class prop functions.
5
+ * SSR-compatible - renders children and UI elements directly without render props.
9
6
  */
10
7
 
11
8
  import { type JSX, Show, createContext, useContext, splitProps } from 'solid-js'
@@ -88,7 +85,6 @@ export function RadioGroup(props: RadioGroupProps): JSX.Element {
88
85
  'label',
89
86
  'description',
90
87
  'errorMessage',
91
- 'children',
92
88
  ])
93
89
 
94
90
  const size = local.size ?? 'md'
@@ -102,22 +98,6 @@ export function RadioGroup(props: RadioGroupProps): JSX.Element {
102
98
  return [base, orientationClass, disabledClass, customClass].filter(Boolean).join(' ')
103
99
  }
104
100
 
105
- // Create render children function
106
- const renderChildren = (renderProps: RadioGroupRenderProps) => (
107
- <>
108
- <Show when={local.label}>
109
- <span class="text-primary-200 font-medium mb-1">{local.label}</span>
110
- </Show>
111
- {typeof local.children === 'function' ? local.children(renderProps) : local.children}
112
- <Show when={local.description && !renderProps.isInvalid}>
113
- <span class="text-primary-400 text-sm">{local.description}</span>
114
- </Show>
115
- <Show when={local.errorMessage && renderProps.isInvalid}>
116
- <span class="text-danger-400 text-sm">{local.errorMessage}</span>
117
- </Show>
118
- </>
119
- )
120
-
121
101
  // Pass remaining props through to headless component
122
102
  // headlessProps maintains reactivity for controlled values like value/onChange
123
103
  return (
@@ -126,8 +106,18 @@ export function RadioGroup(props: RadioGroupProps): JSX.Element {
126
106
  {...headlessProps}
127
107
  class={getClassName}
128
108
  data-size={size}
129
- children={renderChildren as any}
130
- />
109
+ >
110
+ <Show when={local.label}>
111
+ <span class="text-primary-200 font-medium mb-1">{local.label}</span>
112
+ </Show>
113
+ {props.children as JSX.Element}
114
+ <Show when={local.description}>
115
+ <span class="text-primary-400 text-sm [&:has(~[data-invalid])]:hidden">{local.description}</span>
116
+ </Show>
117
+ <Show when={local.errorMessage}>
118
+ <span class="text-danger-400 text-sm hidden [[data-invalid]_&]:block">{local.errorMessage}</span>
119
+ </Show>
120
+ </HeadlessRadioGroup>
131
121
  </RadioSizeContext.Provider>
132
122
  )
133
123
  }
@@ -139,81 +129,45 @@ export function RadioGroup(props: RadioGroupProps): JSX.Element {
139
129
  /**
140
130
  * A radio button allows users to select a single option from a list.
141
131
  * Must be used within a RadioGroup.
132
+ * SSR-compatible - renders static JSX without render prop children.
133
+ *
134
+ * Note: Unlike other styled components, Radio does not use render props for children.
135
+ * Instead, it relies on data attributes set by the headless Radio component for styling.
136
+ * However, since we need dynamic styling based on state, we accept that this component
137
+ * has some limitations compared to the render-props-based original implementation.
142
138
  *
143
139
  * Built on solidaria-components Radio for full accessibility support.
144
140
  */
145
141
  export function Radio(props: RadioProps): JSX.Element {
142
+ const [local, headlessProps] = splitProps(props, ['class'])
146
143
  const sizeFromContext = useContext(RadioSizeContext)
147
- const size = () => sizeStyles[sizeFromContext]
148
- const customClass = props.class ?? ''
144
+ const sizeStyle = sizeStyles[sizeFromContext]
145
+ const customClass = local.class ?? ''
149
146
 
150
147
  // Generate class based on render props
151
148
  const getClassName = (renderProps: RadioRenderProps): string => {
152
- const base = 'inline-flex items-center gap-2 cursor-pointer'
153
- const disabledClass = renderProps.isDisabled ? 'cursor-not-allowed opacity-50' : ''
154
- return [base, disabledClass, customClass].filter(Boolean).join(' ')
149
+ const base = 'inline-flex items-center gap-2'
150
+ const cursorClass = renderProps.isDisabled ? 'cursor-not-allowed' : 'cursor-pointer'
151
+ const disabledClass = renderProps.isDisabled ? 'opacity-50' : ''
152
+ return [base, cursorClass, disabledClass, customClass].filter(Boolean).join(' ')
155
153
  }
156
154
 
157
- // Extract props to pass to headless
158
- const { class: _, children, ...headlessProps } = props
155
+ // Static classes - will use a simplified visual style since we can't dynamically style based on state without render props
156
+ const circleClass = `relative flex items-center justify-center rounded-full border-2 transition-all duration-200 ${sizeStyle.circle} border-primary-600 bg-transparent hover:border-accent-300`
157
+ const dotClass = `rounded-full bg-accent transition-all duration-200 ${sizeStyle.dot}`
158
+ const labelClass = `text-primary-200 ${sizeStyle.label}`
159
159
 
160
160
  return (
161
161
  <HeadlessRadio
162
162
  {...headlessProps}
163
163
  class={getClassName}
164
164
  >
165
- {(renderProps: RadioRenderProps) => {
166
- const circleClasses = () => {
167
- const base = 'relative flex items-center justify-center rounded-full border-2 transition-all duration-200'
168
- const sizeClass = size().circle
169
-
170
- let colorClass: string
171
- if (renderProps.isDisabled) {
172
- colorClass = 'border-bg-300 bg-bg-200'
173
- } else if (renderProps.isSelected) {
174
- colorClass = 'border-accent bg-transparent'
175
- } else {
176
- colorClass = 'border-primary-600 bg-transparent hover:border-accent-300'
177
- }
178
-
179
- const focusClass = renderProps.isFocusVisible
180
- ? 'ring-2 ring-accent-300 ring-offset-2 ring-offset-bg-400'
181
- : ''
182
- const cursorClass = renderProps.isDisabled ? 'cursor-not-allowed' : 'cursor-pointer'
183
-
184
- return [base, sizeClass, colorClass, focusClass, cursorClass].filter(Boolean).join(' ')
185
- }
186
-
187
- const dotClasses = () => {
188
- const base = 'rounded-full bg-accent transition-all duration-200'
189
- const sizeClass = size().dot
190
- const visibilityClass = renderProps.isSelected ? 'scale-100 opacity-100' : 'scale-0 opacity-0'
191
-
192
- return [base, sizeClass, visibilityClass].filter(Boolean).join(' ')
193
- }
194
-
195
- const labelClasses = () => {
196
- const base = 'text-primary-200'
197
- const sizeClass = size().label
198
- const disabledClass = renderProps.isDisabled ? 'opacity-50' : ''
199
-
200
- return [base, sizeClass, disabledClass].filter(Boolean).join(' ')
201
- }
202
-
203
- // Resolve children - could be a function or JSX element
204
- const resolvedChildren = typeof children === 'function' ? children(renderProps) : children
205
-
206
- return (
207
- <>
208
- <span class={circleClasses()}>
209
- <span class={dotClasses()} />
210
- </span>
211
- <Show when={resolvedChildren}>
212
- <span class={labelClasses()}>{resolvedChildren}</span>
213
- </Show>
214
- </>
215
- )
216
- }}
165
+ <span class={circleClass}>
166
+ <span class={dotClass} />
167
+ </span>
168
+ <Show when={props.children}>
169
+ <span class={labelClass}>{props.children as JSX.Element}</span>
170
+ </Show>
217
171
  </HeadlessRadio>
218
172
  )
219
173
  }