@duro-app/ui 0.21.0 → 0.23.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.
- package/dist/components/ActionBar/ActionBar.stories.d.ts.map +1 -1
- package/dist/components/Alert/Alert.meta.d.ts.map +1 -1
- package/dist/components/Callout/Callout.meta.d.ts.map +1 -1
- package/dist/components/Card/Card.meta.d.ts.map +1 -1
- package/dist/components/CheckboxGroup/CheckboxGroup.d.ts +22 -0
- package/dist/components/CheckboxGroup/CheckboxGroup.d.ts.map +1 -0
- package/dist/components/CheckboxGroup/CheckboxGroup.meta.d.ts +3 -0
- package/dist/components/CheckboxGroup/CheckboxGroup.meta.d.ts.map +1 -0
- package/dist/components/CheckboxGroup/CheckboxGroup.stories.d.ts +9 -0
- package/dist/components/CheckboxGroup/CheckboxGroup.stories.d.ts.map +1 -0
- package/dist/components/CheckboxGroup/styles.css.d.ts +12 -0
- package/dist/components/CheckboxGroup/styles.css.d.ts.map +1 -0
- package/dist/components/DetailPanel/DetailPanel.d.ts.map +1 -1
- package/dist/components/DetailPanel/DetailPanel.meta.d.ts.map +1 -1
- package/dist/components/DetailPanel/DetailPanel.stories.d.ts.map +1 -1
- package/dist/components/DetailPanel/styles.css.d.ts +4 -0
- package/dist/components/DetailPanel/styles.css.d.ts.map +1 -1
- package/dist/components/Dialog/Dialog.meta.d.ts.map +1 -1
- package/dist/components/Drawer/Drawer.meta.d.ts.map +1 -1
- package/dist/components/EmptyState/EmptyState.meta.d.ts.map +1 -1
- package/dist/components/Field/Field.stories.d.ts.map +1 -1
- package/dist/components/InputGroup/InputGroup.meta.d.ts.map +1 -1
- package/dist/components/List/List.d.ts +46 -0
- package/dist/components/List/List.d.ts.map +1 -0
- package/dist/components/List/List.meta.d.ts +3 -0
- package/dist/components/List/List.meta.d.ts.map +1 -0
- package/dist/components/List/List.stories.d.ts +9 -0
- package/dist/components/List/List.stories.d.ts.map +1 -0
- package/dist/components/List/styles.css.d.ts +77 -0
- package/dist/components/List/styles.css.d.ts.map +1 -0
- package/dist/components/Panel/Panel.d.ts.map +1 -1
- package/dist/components/Panel/Panel.meta.d.ts.map +1 -1
- package/dist/components/Panel/Panel.stories.d.ts.map +1 -1
- package/dist/components/Panel/styles.css.d.ts +4 -0
- package/dist/components/Panel/styles.css.d.ts.map +1 -1
- package/dist/components/RadioGroup/RadioGroup.d.ts +22 -0
- package/dist/components/RadioGroup/RadioGroup.d.ts.map +1 -0
- package/dist/components/RadioGroup/RadioGroup.meta.d.ts +3 -0
- package/dist/components/RadioGroup/RadioGroup.meta.d.ts.map +1 -0
- package/dist/components/RadioGroup/RadioGroup.stories.d.ts +9 -0
- package/dist/components/RadioGroup/RadioGroup.stories.d.ts.map +1 -0
- package/dist/components/RadioGroup/styles.css.d.ts +60 -0
- package/dist/components/RadioGroup/styles.css.d.ts.map +1 -0
- package/dist/components/StatusIcon/StatusIcon.meta.d.ts.map +1 -1
- package/dist/components/Table/Table.d.ts +4 -3
- package/dist/components/Table/Table.d.ts.map +1 -1
- package/dist/components/Table/Table.stories.d.ts.map +1 -1
- package/dist/components/Table/styles.css.d.ts +1 -1
- package/dist/components/Tabs/Tabs.stories.d.ts.map +1 -1
- package/dist/components/ThemeProvider/ThemeProvider.meta.d.ts.map +1 -1
- package/dist/components/Tooltip/Tooltip.stories.d.ts.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1771 -1386
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/components/ActionBar/ActionBar.stories.tsx +10 -0
- package/src/components/Alert/Alert.meta.ts +4 -1
- package/src/components/Callout/Callout.meta.ts +4 -1
- package/src/components/Card/Card.meta.ts +4 -1
- package/src/components/Checkbox/styles.css.ts +1 -1
- package/src/components/CheckboxGroup/CheckboxGroup.meta.ts +25 -0
- package/src/components/CheckboxGroup/CheckboxGroup.stories.tsx +88 -0
- package/src/components/CheckboxGroup/CheckboxGroup.tsx +105 -0
- package/src/components/CheckboxGroup/styles.css.ts +13 -0
- package/src/components/DetailPanel/DetailPanel.meta.ts +4 -1
- package/src/components/DetailPanel/DetailPanel.stories.tsx +54 -27
- package/src/components/DetailPanel/DetailPanel.tsx +3 -16
- package/src/components/DetailPanel/styles.css.ts +5 -0
- package/src/components/Dialog/Dialog.meta.ts +8 -2
- package/src/components/Drawer/Drawer.meta.ts +4 -1
- package/src/components/EmptyState/EmptyState.meta.ts +1 -4
- package/src/components/Field/Field.stories.tsx +6 -0
- package/src/components/Icon/Icon.meta.ts +5 -5
- package/src/components/InputGroup/InputGroup.meta.ts +4 -1
- package/src/components/List/List.meta.ts +39 -0
- package/src/components/List/List.stories.tsx +200 -0
- package/src/components/List/List.tsx +118 -0
- package/src/components/List/styles.css.ts +99 -0
- package/src/components/Panel/Panel.meta.ts +12 -3
- package/src/components/Panel/Panel.stories.tsx +17 -10
- package/src/components/Panel/Panel.tsx +2 -10
- package/src/components/Panel/styles.css.ts +5 -0
- package/src/components/RadioGroup/RadioGroup.meta.ts +25 -0
- package/src/components/RadioGroup/RadioGroup.stories.tsx +83 -0
- package/src/components/RadioGroup/RadioGroup.tsx +113 -0
- package/src/components/RadioGroup/styles.css.ts +66 -0
- package/src/components/StatusIcon/StatusIcon.meta.ts +1 -4
- package/src/components/Table/Table.stories.tsx +25 -9
- package/src/components/Table/Table.tsx +31 -15
- package/src/components/Table/styles.css.ts +2 -2
- package/src/components/Tabs/Tabs.stories.tsx +7 -0
- package/src/components/ThemeProvider/ThemeProvider.meta.ts +1 -3
- package/src/components/Tooltip/Tooltip.stories.tsx +15 -0
- package/src/index.ts +3 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import {type ReactNode, createContext, useContext, useCallback} from 'react'
|
|
2
|
+
import {html} from 'react-strict-dom'
|
|
3
|
+
import {useControllableValue} from '../../hooks/useControllableValue'
|
|
4
|
+
import {styles} from './styles.css'
|
|
5
|
+
|
|
6
|
+
// --- Context ---
|
|
7
|
+
|
|
8
|
+
interface RadioGroupContextValue {
|
|
9
|
+
value: string
|
|
10
|
+
onSelect: (value: string) => void
|
|
11
|
+
disabled: boolean
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const RadioGroupContext = createContext<RadioGroupContextValue | null>(null)
|
|
15
|
+
|
|
16
|
+
function useRadioGroup() {
|
|
17
|
+
const ctx = useContext(RadioGroupContext)
|
|
18
|
+
if (!ctx) {
|
|
19
|
+
throw new Error('RadioGroup.Item must be used within RadioGroup.Root')
|
|
20
|
+
}
|
|
21
|
+
return ctx
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// --- Root ---
|
|
25
|
+
|
|
26
|
+
interface RootProps {
|
|
27
|
+
value?: string
|
|
28
|
+
defaultValue?: string
|
|
29
|
+
onValueChange?: (value: string) => void
|
|
30
|
+
orientation?: 'horizontal' | 'vertical'
|
|
31
|
+
disabled?: boolean
|
|
32
|
+
children: ReactNode
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function Root({
|
|
36
|
+
value: controlledValue,
|
|
37
|
+
defaultValue = '',
|
|
38
|
+
onValueChange,
|
|
39
|
+
orientation = 'vertical',
|
|
40
|
+
disabled = false,
|
|
41
|
+
children,
|
|
42
|
+
}: RootProps) {
|
|
43
|
+
const [value, setValue] = useControllableValue(controlledValue, defaultValue, onValueChange)
|
|
44
|
+
|
|
45
|
+
const onSelect = useCallback(
|
|
46
|
+
(itemValue: string) => {
|
|
47
|
+
if (!disabled) {
|
|
48
|
+
setValue(itemValue)
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
[disabled, setValue],
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<RadioGroupContext.Provider value={{value, onSelect, disabled}}>
|
|
56
|
+
<html.div
|
|
57
|
+
role="radiogroup"
|
|
58
|
+
aria-orientation={orientation}
|
|
59
|
+
style={[styles.root, orientation === 'horizontal' && styles.rootHorizontal]}
|
|
60
|
+
>
|
|
61
|
+
{children}
|
|
62
|
+
</html.div>
|
|
63
|
+
</RadioGroupContext.Provider>
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// --- Item ---
|
|
68
|
+
|
|
69
|
+
interface ItemProps {
|
|
70
|
+
value: string
|
|
71
|
+
disabled?: boolean
|
|
72
|
+
children: ReactNode
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function Item({value, disabled: itemDisabled = false, children}: ItemProps) {
|
|
76
|
+
const {value: groupValue, onSelect, disabled: groupDisabled} = useRadioGroup()
|
|
77
|
+
const isChecked = groupValue === value
|
|
78
|
+
const isDisabled = groupDisabled || itemDisabled
|
|
79
|
+
|
|
80
|
+
const handleClick = () => {
|
|
81
|
+
if (!isDisabled) {
|
|
82
|
+
onSelect(value)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<html.label
|
|
88
|
+
style={[styles.item, isDisabled && styles.itemDisabled]}
|
|
89
|
+
onClick={handleClick}
|
|
90
|
+
>
|
|
91
|
+
<html.input
|
|
92
|
+
type="radio"
|
|
93
|
+
value={value}
|
|
94
|
+
checked={isChecked}
|
|
95
|
+
disabled={isDisabled}
|
|
96
|
+
onChange={() => onSelect(value)}
|
|
97
|
+
style={styles.input}
|
|
98
|
+
/>
|
|
99
|
+
<html.span
|
|
100
|
+
style={[styles.circle, isChecked ? styles.circleChecked : styles.circleUnchecked]}
|
|
101
|
+
aria-hidden
|
|
102
|
+
>
|
|
103
|
+
{isChecked && <html.span style={styles.dot} />}
|
|
104
|
+
</html.span>
|
|
105
|
+
{children && <html.span>{children}</html.span>}
|
|
106
|
+
</html.label>
|
|
107
|
+
)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export const RadioGroup = {
|
|
111
|
+
Root,
|
|
112
|
+
Item,
|
|
113
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import {css} from 'react-strict-dom'
|
|
2
|
+
import {colors} from '@duro-app/tokens/tokens/colors.css'
|
|
3
|
+
import {spacing, radii} from '@duro-app/tokens/tokens/spacing.css'
|
|
4
|
+
import {typography} from '@duro-app/tokens/tokens/typography.css'
|
|
5
|
+
|
|
6
|
+
export const styles = css.create({
|
|
7
|
+
root: {
|
|
8
|
+
display: 'flex',
|
|
9
|
+
flexDirection: 'column',
|
|
10
|
+
gap: spacing.sm,
|
|
11
|
+
},
|
|
12
|
+
rootHorizontal: {
|
|
13
|
+
flexDirection: 'row',
|
|
14
|
+
},
|
|
15
|
+
item: {
|
|
16
|
+
display: 'inline-flex',
|
|
17
|
+
alignItems: 'center',
|
|
18
|
+
gap: spacing.sm,
|
|
19
|
+
cursor: 'pointer',
|
|
20
|
+
fontSize: typography.fontSizeSm,
|
|
21
|
+
color: colors.text,
|
|
22
|
+
lineHeight: typography.lineHeight,
|
|
23
|
+
},
|
|
24
|
+
itemDisabled: {
|
|
25
|
+
opacity: 0.5,
|
|
26
|
+
cursor: 'not-allowed',
|
|
27
|
+
},
|
|
28
|
+
circle: {
|
|
29
|
+
width: 18,
|
|
30
|
+
height: 18,
|
|
31
|
+
borderWidth: 1,
|
|
32
|
+
borderStyle: 'solid',
|
|
33
|
+
borderRadius: radii.full,
|
|
34
|
+
display: 'inline-flex',
|
|
35
|
+
alignItems: 'center',
|
|
36
|
+
justifyContent: 'center',
|
|
37
|
+
flexShrink: 0,
|
|
38
|
+
transitionProperty: 'background-color, border-color',
|
|
39
|
+
transitionDuration: '150ms',
|
|
40
|
+
transitionTimingFunction: 'ease',
|
|
41
|
+
},
|
|
42
|
+
circleUnchecked: {
|
|
43
|
+
backgroundColor: colors.bg,
|
|
44
|
+
borderColor: {
|
|
45
|
+
default: colors.border,
|
|
46
|
+
':hover': colors.textMuted,
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
circleChecked: {
|
|
50
|
+
backgroundColor: colors.bg,
|
|
51
|
+
borderColor: colors.accent,
|
|
52
|
+
},
|
|
53
|
+
dot: {
|
|
54
|
+
width: 8,
|
|
55
|
+
height: 8,
|
|
56
|
+
borderRadius: radii.full,
|
|
57
|
+
backgroundColor: colors.accent,
|
|
58
|
+
},
|
|
59
|
+
input: {
|
|
60
|
+
position: 'absolute',
|
|
61
|
+
width: 1,
|
|
62
|
+
height: 1,
|
|
63
|
+
opacity: 0,
|
|
64
|
+
overflow: 'hidden',
|
|
65
|
+
},
|
|
66
|
+
})
|
|
@@ -8,10 +8,7 @@ export const meta: ComponentMeta = {
|
|
|
8
8
|
'List item status icons with colored backgrounds',
|
|
9
9
|
'Feature or capability indicators',
|
|
10
10
|
],
|
|
11
|
-
whenNotToUse: [
|
|
12
|
-
'Inline icons without background — use Icon',
|
|
13
|
-
'Status text labels — use Badge',
|
|
14
|
-
],
|
|
11
|
+
whenNotToUse: ['Inline icons without background — use Icon', 'Status text labels — use Badge'],
|
|
15
12
|
relatedTo: [
|
|
16
13
|
{component: 'Icon', relationship: 'StatusIcon wraps Icon with background; Icon is bare SVG'},
|
|
17
14
|
{component: 'Badge', relationship: 'Badge for text status; StatusIcon for icon status'},
|
|
@@ -11,6 +11,22 @@ import {colors} from '@duro-app/tokens/tokens/colors.css'
|
|
|
11
11
|
|
|
12
12
|
const meta: Meta = {
|
|
13
13
|
title: 'Components/Table',
|
|
14
|
+
argTypes: {
|
|
15
|
+
columns: {
|
|
16
|
+
control: 'number',
|
|
17
|
+
description: 'Number of columns in the table grid',
|
|
18
|
+
},
|
|
19
|
+
variant: {
|
|
20
|
+
control: 'select',
|
|
21
|
+
options: ['default', 'striped', 'bordered'],
|
|
22
|
+
description: 'Visual style variant of the table',
|
|
23
|
+
},
|
|
24
|
+
size: {
|
|
25
|
+
control: 'select',
|
|
26
|
+
options: ['sm', 'md', 'lg'],
|
|
27
|
+
description: 'Density/size of table rows',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
14
30
|
}
|
|
15
31
|
|
|
16
32
|
export default meta
|
|
@@ -39,7 +55,7 @@ function statusVariant(status: string) {
|
|
|
39
55
|
|
|
40
56
|
export const Default: Story = {
|
|
41
57
|
render: () => (
|
|
42
|
-
<Table.Root
|
|
58
|
+
<Table.Root>
|
|
43
59
|
<Table.Header>
|
|
44
60
|
<Table.Row>
|
|
45
61
|
<Table.HeaderCell>Service</Table.HeaderCell>
|
|
@@ -92,7 +108,7 @@ export const Default: Story = {
|
|
|
92
108
|
|
|
93
109
|
export const Striped: Story = {
|
|
94
110
|
render: () => (
|
|
95
|
-
<Table.Root variant="striped"
|
|
111
|
+
<Table.Root variant="striped">
|
|
96
112
|
<Table.Header>
|
|
97
113
|
<Table.Row>
|
|
98
114
|
<Table.HeaderCell>Service</Table.HeaderCell>
|
|
@@ -125,7 +141,7 @@ export const Striped: Story = {
|
|
|
125
141
|
|
|
126
142
|
export const Bordered: Story = {
|
|
127
143
|
render: () => (
|
|
128
|
-
<Table.Root variant="bordered"
|
|
144
|
+
<Table.Root variant="bordered">
|
|
129
145
|
<Table.Header>
|
|
130
146
|
<Table.Row>
|
|
131
147
|
<Table.HeaderCell>Service</Table.HeaderCell>
|
|
@@ -159,7 +175,7 @@ export const Bordered: Story = {
|
|
|
159
175
|
|
|
160
176
|
export const Compact: Story = {
|
|
161
177
|
render: () => (
|
|
162
|
-
<Table.Root size="sm"
|
|
178
|
+
<Table.Root size="sm">
|
|
163
179
|
<Table.Header>
|
|
164
180
|
<Table.Row>
|
|
165
181
|
<Table.HeaderCell>Service</Table.HeaderCell>
|
|
@@ -232,7 +248,7 @@ function CheckboxTableDemo() {
|
|
|
232
248
|
|
|
233
249
|
return (
|
|
234
250
|
<>
|
|
235
|
-
<Table.Root
|
|
251
|
+
<Table.Root>
|
|
236
252
|
<Table.Header>
|
|
237
253
|
<Table.Row>
|
|
238
254
|
<Table.HeaderCell aria-label="Select all">
|
|
@@ -300,7 +316,7 @@ export const AllVariants: Story = {
|
|
|
300
316
|
<html.div style={storyStyles.stack}>
|
|
301
317
|
<html.div>
|
|
302
318
|
<html.span style={storyStyles.label}>Default</html.span>
|
|
303
|
-
<Table.Root
|
|
319
|
+
<Table.Root>
|
|
304
320
|
<Table.Header>
|
|
305
321
|
<Table.Row>
|
|
306
322
|
<Table.HeaderCell>Name</Table.HeaderCell>
|
|
@@ -325,7 +341,7 @@ export const AllVariants: Story = {
|
|
|
325
341
|
|
|
326
342
|
<html.div>
|
|
327
343
|
<html.span style={storyStyles.label}>Striped</html.span>
|
|
328
|
-
<Table.Root variant="striped"
|
|
344
|
+
<Table.Root variant="striped">
|
|
329
345
|
<Table.Header>
|
|
330
346
|
<Table.Row>
|
|
331
347
|
<Table.HeaderCell>Name</Table.HeaderCell>
|
|
@@ -355,7 +371,7 @@ export const AllVariants: Story = {
|
|
|
355
371
|
|
|
356
372
|
<html.div>
|
|
357
373
|
<html.span style={storyStyles.label}>Bordered</html.span>
|
|
358
|
-
<Table.Root variant="bordered"
|
|
374
|
+
<Table.Root variant="bordered">
|
|
359
375
|
<Table.Header>
|
|
360
376
|
<Table.Row>
|
|
361
377
|
<Table.HeaderCell>Name</Table.HeaderCell>
|
|
@@ -380,7 +396,7 @@ export const AllVariants: Story = {
|
|
|
380
396
|
|
|
381
397
|
<html.div>
|
|
382
398
|
<html.span style={storyStyles.label}>Compact (sm)</html.span>
|
|
383
|
-
<Table.Root size="sm"
|
|
399
|
+
<Table.Root size="sm">
|
|
384
400
|
<Table.Header>
|
|
385
401
|
<Table.Row>
|
|
386
402
|
<Table.HeaderCell>Name</Table.HeaderCell>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {type ReactNode, createContext, useContext, Children} from 'react'
|
|
1
|
+
import {type ReactNode, type MutableRefObject, createContext, useContext, useRef, Children, isValidElement} from 'react'
|
|
2
2
|
import {html} from 'react-strict-dom'
|
|
3
3
|
import {styles} from './styles.css'
|
|
4
4
|
|
|
@@ -12,8 +12,8 @@ export type TableSize = 'sm' | 'md'
|
|
|
12
12
|
interface TableContextValue {
|
|
13
13
|
variant: TableVariant
|
|
14
14
|
size: TableSize
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
/** Mutable ref: header Row writes inferred template, body Rows read it */
|
|
16
|
+
inferredTemplateRef: MutableRefObject<string | null>
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
const TableContext = createContext<TableContextValue | null>(null)
|
|
@@ -24,7 +24,7 @@ function useTable() {
|
|
|
24
24
|
return ctx
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
// --- HeaderContext
|
|
27
|
+
// --- HeaderContext ---
|
|
28
28
|
|
|
29
29
|
const HeaderContext = createContext(false)
|
|
30
30
|
|
|
@@ -34,12 +34,13 @@ interface RootProps {
|
|
|
34
34
|
children: ReactNode
|
|
35
35
|
variant?: TableVariant
|
|
36
36
|
size?: TableSize
|
|
37
|
-
columns: number
|
|
38
37
|
}
|
|
39
38
|
|
|
40
|
-
function Root({children, variant = 'default', size = 'md'
|
|
39
|
+
function Root({children, variant = 'default', size = 'md'}: RootProps) {
|
|
40
|
+
const inferredTemplateRef = useRef<string | null>(null)
|
|
41
|
+
|
|
41
42
|
return (
|
|
42
|
-
<TableContext.Provider value={{variant, size,
|
|
43
|
+
<TableContext.Provider value={{variant, size, inferredTemplateRef}}>
|
|
43
44
|
<html.div role="table" style={styles.root}>
|
|
44
45
|
{children}
|
|
45
46
|
</html.div>
|
|
@@ -83,24 +84,40 @@ function Body({children}: {children: ReactNode}) {
|
|
|
83
84
|
)
|
|
84
85
|
}
|
|
85
86
|
|
|
86
|
-
// Row index context for striped variant
|
|
87
87
|
const RowIndexContext = createContext<number>(-1)
|
|
88
88
|
|
|
89
89
|
// --- Row ---
|
|
90
90
|
|
|
91
91
|
function Row({children}: {children: ReactNode}) {
|
|
92
|
-
const {variant,
|
|
92
|
+
const {variant, inferredTemplateRef} = useTable()
|
|
93
93
|
const isHeader = useContext(HeaderContext)
|
|
94
94
|
const rowIndex = useContext(RowIndexContext)
|
|
95
95
|
const isEvenRow = rowIndex >= 0 && rowIndex % 2 === 1
|
|
96
96
|
const childArray = Children.toArray(children)
|
|
97
97
|
|
|
98
|
+
let template: string
|
|
99
|
+
|
|
100
|
+
if (isHeader) {
|
|
101
|
+
// Build template from HeaderCell width props
|
|
102
|
+
const widths: string[] = []
|
|
103
|
+
Children.forEach(children, (child) => {
|
|
104
|
+
if (isValidElement(child)) {
|
|
105
|
+
const props = child.props as {width?: string}
|
|
106
|
+
widths.push(props.width || '1fr')
|
|
107
|
+
}
|
|
108
|
+
})
|
|
109
|
+
template = widths.join(' ')
|
|
110
|
+
inferredTemplateRef.current = template
|
|
111
|
+
} else {
|
|
112
|
+
template = inferredTemplateRef.current ?? `repeat(${childArray.length}, 1fr)`
|
|
113
|
+
}
|
|
114
|
+
|
|
98
115
|
return (
|
|
99
116
|
<html.div
|
|
100
117
|
role="row"
|
|
101
118
|
style={[
|
|
102
119
|
styles.row,
|
|
103
|
-
styles.gridColumns(
|
|
120
|
+
styles.gridColumns(template),
|
|
104
121
|
!isHeader && styles.bodyRow,
|
|
105
122
|
!isHeader && variant === 'striped' && isEvenRow && styles.stripedEven,
|
|
106
123
|
]}
|
|
@@ -116,19 +133,18 @@ function Row({children}: {children: ReactNode}) {
|
|
|
116
133
|
)
|
|
117
134
|
}
|
|
118
135
|
|
|
119
|
-
|
|
120
|
-
const CellIndexContext = createContext<{index: number; total: number}>({
|
|
121
|
-
index: 0,
|
|
122
|
-
total: 0,
|
|
123
|
-
})
|
|
136
|
+
const CellIndexContext = createContext<{index: number; total: number}>({index: 0, total: 0})
|
|
124
137
|
|
|
125
138
|
// --- HeaderCell ---
|
|
126
139
|
|
|
127
140
|
function HeaderCell({
|
|
128
141
|
children,
|
|
142
|
+
width: _width,
|
|
129
143
|
'aria-label': ariaLabel,
|
|
130
144
|
}: {
|
|
131
145
|
children?: ReactNode
|
|
146
|
+
/** Column width: CSS value like '40px', '2fr', 'auto'. Defaults to '1fr'. */
|
|
147
|
+
width?: string
|
|
132
148
|
'aria-label'?: string
|
|
133
149
|
}) {
|
|
134
150
|
const {size, variant} = useTable()
|
|
@@ -91,7 +91,7 @@ export const styles = css.create({
|
|
|
91
91
|
},
|
|
92
92
|
|
|
93
93
|
// Dynamic styles — simple identifier params only (StyleX constraint)
|
|
94
|
-
gridColumns: (
|
|
95
|
-
gridTemplateColumns:
|
|
94
|
+
gridColumns: (template: string) => ({
|
|
95
|
+
gridTemplateColumns: template,
|
|
96
96
|
}),
|
|
97
97
|
})
|
|
@@ -4,6 +4,13 @@ import {Tabs} from './Tabs'
|
|
|
4
4
|
|
|
5
5
|
const meta: Meta = {
|
|
6
6
|
title: 'Components/Tabs',
|
|
7
|
+
argTypes: {
|
|
8
|
+
orientation: {
|
|
9
|
+
control: 'select',
|
|
10
|
+
options: ['horizontal', 'vertical'],
|
|
11
|
+
description: 'Layout orientation of the tab list',
|
|
12
|
+
},
|
|
13
|
+
},
|
|
7
14
|
}
|
|
8
15
|
|
|
9
16
|
export default meta
|
|
@@ -7,9 +7,7 @@ export const meta: ComponentMeta = {
|
|
|
7
7
|
'App root — required for all Duro components to render correctly',
|
|
8
8
|
'Theme switching (dark/light mode toggle)',
|
|
9
9
|
],
|
|
10
|
-
whenNotToUse: [
|
|
11
|
-
'Never omit — all Duro components require ThemeProvider',
|
|
12
|
-
],
|
|
10
|
+
whenNotToUse: ['Never omit — all Duro components require ThemeProvider'],
|
|
13
11
|
example: `<ThemeProvider theme="dark">
|
|
14
12
|
<App />
|
|
15
13
|
</ThemeProvider>`,
|
|
@@ -6,6 +6,21 @@ import {Badge} from '../Badge/Badge'
|
|
|
6
6
|
|
|
7
7
|
const meta: Meta = {
|
|
8
8
|
title: 'Components/Tooltip',
|
|
9
|
+
argTypes: {
|
|
10
|
+
content: {
|
|
11
|
+
control: 'text',
|
|
12
|
+
description: 'Text content displayed inside the tooltip',
|
|
13
|
+
},
|
|
14
|
+
placement: {
|
|
15
|
+
control: 'select',
|
|
16
|
+
options: ['top', 'bottom', 'left', 'right'],
|
|
17
|
+
description: 'Preferred placement of the tooltip relative to the trigger',
|
|
18
|
+
},
|
|
19
|
+
delay: {
|
|
20
|
+
control: 'number',
|
|
21
|
+
description: 'Delay in milliseconds before the tooltip appears on hover',
|
|
22
|
+
},
|
|
23
|
+
},
|
|
9
24
|
}
|
|
10
25
|
|
|
11
26
|
export default meta
|
package/src/index.ts
CHANGED
|
@@ -11,11 +11,13 @@ export {Button, type ButtonVariant, type ButtonSize} from './components/Button/B
|
|
|
11
11
|
export {Callout, type CalloutVariant} from './components/Callout/Callout'
|
|
12
12
|
export {Card, type CardVariant, type CardSize} from './components/Card/Card'
|
|
13
13
|
export {Checkbox} from './components/Checkbox/Checkbox'
|
|
14
|
+
export {CheckboxGroup} from './components/CheckboxGroup/CheckboxGroup'
|
|
14
15
|
export {Dialog, type DialogSize} from './components/Dialog/Dialog'
|
|
15
16
|
export {DetailPanel, type DetailPanelSize} from './components/DetailPanel/DetailPanel'
|
|
16
17
|
export {Drawer, type DrawerAnchor, type DrawerSize} from './components/Drawer/Drawer'
|
|
17
18
|
export {EmptyState} from './components/EmptyState/EmptyState'
|
|
18
19
|
export {Heading, type HeadingVariant} from './components/Heading/Heading'
|
|
20
|
+
export {List, type ListSelectionMode} from './components/List/List'
|
|
19
21
|
export {Field} from './components/Field/Field'
|
|
20
22
|
export {Form, type FormProps} from './components/Form/Form'
|
|
21
23
|
export {Fieldset, type FieldsetGap} from './components/Fieldset/Fieldset'
|
|
@@ -28,6 +30,7 @@ export {
|
|
|
28
30
|
} from './components/LinkButton/LinkButton'
|
|
29
31
|
export {Menu} from './components/Menu/Menu'
|
|
30
32
|
export {Panel} from './components/Panel/Panel'
|
|
33
|
+
export {RadioGroup} from './components/RadioGroup/RadioGroup'
|
|
31
34
|
export {ScrollArea} from './components/ScrollArea/ScrollArea'
|
|
32
35
|
export {Select} from './components/Select/Select'
|
|
33
36
|
export {SideNav} from './components/SideNav/SideNav'
|