@cdx-ui/components 0.0.1-beta.174 → 0.0.1-beta.176
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/README.md +2 -2
- package/coverage.svg +1 -1
- package/lib/commonjs/components/Accordion/index.js +46 -55
- package/lib/commonjs/components/Accordion/index.js.map +1 -1
- package/lib/commonjs/components/Accordion/styles.js +23 -16
- package/lib/commonjs/components/Accordion/styles.js.map +1 -1
- package/lib/commonjs/figma/Accordion.figma.js +13 -10
- package/lib/commonjs/figma/Accordion.figma.js.map +1 -1
- package/lib/module/components/Accordion/index.js +50 -59
- package/lib/module/components/Accordion/index.js.map +1 -1
- package/lib/module/components/Accordion/styles.js +23 -16
- package/lib/module/components/Accordion/styles.js.map +1 -1
- package/lib/module/figma/Accordion.figma.js +13 -10
- package/lib/module/figma/Accordion.figma.js.map +1 -1
- package/lib/typescript/components/Accordion/index.d.ts +20 -15
- package/lib/typescript/components/Accordion/index.d.ts.map +1 -1
- package/lib/typescript/components/Accordion/styles.d.ts +6 -7
- package/lib/typescript/components/Accordion/styles.d.ts.map +1 -1
- package/lib/typescript/figma/Accordion.figma.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/components/Accordion/index.tsx +87 -90
- package/src/components/Accordion/styles.ts +31 -31
|
@@ -1,26 +1,25 @@
|
|
|
1
|
-
import { forwardRef, useMemo, type ReactNode } from 'react';
|
|
1
|
+
import { cloneElement, forwardRef, isValidElement, useMemo, type ReactNode } from 'react';
|
|
2
2
|
import { Pressable, Text, View, type TextProps, type ViewProps } from 'react-native';
|
|
3
3
|
import {
|
|
4
|
+
AccordionContentRoot as AccordionContentRootPrimitive,
|
|
4
5
|
AccordionItemRoot as AccordionItemRootPrimitive,
|
|
5
|
-
AccordionPanelRoot as AccordionPanelRootPrimitive,
|
|
6
6
|
AccordionRoot as AccordionRootPrimitive,
|
|
7
7
|
AccordionTriggerRoot as AccordionTriggerRootPrimitive,
|
|
8
8
|
Slot,
|
|
9
9
|
dataAttributes,
|
|
10
10
|
mergeDataAttributes,
|
|
11
11
|
useAccordionItemContext,
|
|
12
|
+
type IAccordionContentProps,
|
|
12
13
|
type IAccordionItemProps,
|
|
13
14
|
type IAccordionProps,
|
|
14
15
|
type IAccordionTriggerProps,
|
|
15
16
|
} from '@cdx-ui/primitives';
|
|
16
17
|
import { KeyboardArrowDown } from '@cdx-ui/icons';
|
|
17
18
|
import { cn, ParentContext, useParentContext, useStyleContext } from '@cdx-ui/utils';
|
|
18
|
-
import { Divider } from '../Divider';
|
|
19
19
|
import { Icon } from '../Icon';
|
|
20
20
|
import {
|
|
21
|
-
|
|
21
|
+
accordionContentVariants,
|
|
22
22
|
accordionDescriptionVariants,
|
|
23
|
-
accordionHeadingVariants,
|
|
24
23
|
accordionIndicatorVariants,
|
|
25
24
|
accordionItemVariants,
|
|
26
25
|
accordionLabelVariants,
|
|
@@ -29,20 +28,18 @@ import {
|
|
|
29
28
|
accordionRootVariants,
|
|
30
29
|
accordionTitleVariants,
|
|
31
30
|
accordionTriggerVariants,
|
|
32
|
-
type AccordionItemVariantProps,
|
|
33
31
|
} from './styles';
|
|
34
32
|
|
|
35
33
|
const ITEM_SCOPE = 'ACCORDION_ITEM';
|
|
36
34
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
35
|
+
interface AccordionItemStyleContext {
|
|
36
|
+
fullBleed?: boolean;
|
|
37
|
+
}
|
|
40
38
|
|
|
41
|
-
const useAccordionItemStyleContext = (): AccordionItemStyleContext => {
|
|
39
|
+
const useAccordionItemStyleContext = (): Required<AccordionItemStyleContext> => {
|
|
42
40
|
const ctx = useStyleContext(ITEM_SCOPE) as AccordionItemStyleContext | undefined;
|
|
43
41
|
return {
|
|
44
|
-
|
|
45
|
-
showSeparator: ctx?.showSeparator ?? true,
|
|
42
|
+
fullBleed: ctx?.fullBleed ?? false,
|
|
46
43
|
};
|
|
47
44
|
};
|
|
48
45
|
|
|
@@ -50,15 +47,17 @@ const useAccordionItemStyleContext = (): AccordionItemStyleContext => {
|
|
|
50
47
|
// ROOT
|
|
51
48
|
// =============================================================================
|
|
52
49
|
|
|
53
|
-
export
|
|
50
|
+
export type AccordionProps = IAccordionProps & {
|
|
51
|
+
asChild?: boolean;
|
|
54
52
|
className?: string;
|
|
55
53
|
children?: ReactNode;
|
|
56
|
-
}
|
|
54
|
+
};
|
|
57
55
|
|
|
58
56
|
const AccordionRoot = forwardRef<View, AccordionProps>(
|
|
59
|
-
({ className, style, children, ...props }, ref) => (
|
|
57
|
+
({ asChild, className, style, children, ...props }, ref) => (
|
|
60
58
|
<AccordionRootPrimitive
|
|
61
59
|
ref={ref}
|
|
60
|
+
asChild={asChild}
|
|
62
61
|
className={cn(accordionRootVariants(), className)}
|
|
63
62
|
style={style}
|
|
64
63
|
{...props}
|
|
@@ -75,32 +74,33 @@ AccordionRoot.displayName = 'Accordion';
|
|
|
75
74
|
// =============================================================================
|
|
76
75
|
|
|
77
76
|
export interface AccordionItemProps extends IAccordionItemProps {
|
|
77
|
+
asChild?: boolean;
|
|
78
78
|
className?: string;
|
|
79
79
|
children?: ReactNode;
|
|
80
|
-
/** Removes horizontal padding
|
|
81
|
-
|
|
82
|
-
/** Renders a
|
|
80
|
+
/** Removes horizontal padding so trigger and content can render edge to edge. @default false */
|
|
81
|
+
fullBleed?: boolean;
|
|
82
|
+
/** Renders a separator below the item when true. @default true */
|
|
83
83
|
showSeparator?: boolean;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
const AccordionItem = forwardRef<View, AccordionItemProps>(
|
|
87
|
-
(
|
|
87
|
+
(
|
|
88
|
+
{ asChild, className, style, children, fullBleed = false, showSeparator = true, ...props },
|
|
89
|
+
ref,
|
|
90
|
+
) => {
|
|
88
91
|
const parent = useParentContext();
|
|
89
|
-
const ctx = useMemo(
|
|
90
|
-
() => ({ ...parent, [ITEM_SCOPE]: { disableGutters, showSeparator } }),
|
|
91
|
-
[parent, disableGutters, showSeparator],
|
|
92
|
-
);
|
|
92
|
+
const ctx = useMemo(() => ({ ...parent, [ITEM_SCOPE]: { fullBleed } }), [parent, fullBleed]);
|
|
93
93
|
|
|
94
94
|
return (
|
|
95
95
|
<ParentContext.Provider value={ctx}>
|
|
96
96
|
<AccordionItemRootPrimitive
|
|
97
97
|
ref={ref}
|
|
98
|
-
|
|
98
|
+
asChild={asChild}
|
|
99
|
+
className={cn(accordionItemVariants({ showSeparator }), className)}
|
|
99
100
|
style={style}
|
|
100
101
|
{...props}
|
|
101
102
|
>
|
|
102
103
|
{children}
|
|
103
|
-
{showSeparator ? <Divider /> : null}
|
|
104
104
|
</AccordionItemRootPrimitive>
|
|
105
105
|
</ParentContext.Provider>
|
|
106
106
|
);
|
|
@@ -122,38 +122,50 @@ export interface AccordionTriggerProps extends IAccordionTriggerProps {
|
|
|
122
122
|
* applied so the substituted component's own appearance wins.
|
|
123
123
|
*/
|
|
124
124
|
asChild?: boolean;
|
|
125
|
+
/**
|
|
126
|
+
* Replaces the default open/closed chevron. Pass `null` to suppress the
|
|
127
|
+
* indicator. When `asChild` is set, only an explicitly provided indicator is
|
|
128
|
+
* appended to the substituted child.
|
|
129
|
+
*/
|
|
130
|
+
indicator?: ReactNode;
|
|
125
131
|
className?: string;
|
|
126
132
|
children?: ReactNode;
|
|
127
133
|
}
|
|
128
134
|
|
|
129
135
|
const AccordionTrigger = forwardRef<React.ComponentRef<typeof Pressable>, AccordionTriggerProps>(
|
|
130
|
-
({ className, style, children, asChild, accessibilityLabel, ...props }, ref) => {
|
|
131
|
-
const {
|
|
136
|
+
({ className, style, children, asChild, indicator, accessibilityLabel, ...props }, ref) => {
|
|
137
|
+
const { fullBleed } = useAccordionItemStyleContext();
|
|
132
138
|
|
|
133
139
|
const computedClassName = asChild
|
|
134
140
|
? className
|
|
135
|
-
: cn(accordionTriggerVariants({
|
|
141
|
+
: cn(accordionTriggerVariants({ fullBleed }), className);
|
|
142
|
+
const triggerIndicator =
|
|
143
|
+
indicator === undefined ? asChild ? undefined : <AccordionIndicator /> : indicator;
|
|
144
|
+
const triggerChildren =
|
|
145
|
+
asChild &&
|
|
146
|
+
triggerIndicator !== undefined &&
|
|
147
|
+
isValidElement<{ children?: ReactNode }>(children)
|
|
148
|
+
? cloneElement(children, undefined, children.props.children, triggerIndicator)
|
|
149
|
+
: children;
|
|
136
150
|
|
|
137
151
|
return (
|
|
138
|
-
<
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
</AccordionTriggerRootPrimitive>
|
|
156
|
-
</View>
|
|
152
|
+
<AccordionTriggerRootPrimitive
|
|
153
|
+
ref={ref}
|
|
154
|
+
asChild={asChild}
|
|
155
|
+
accessibilityLabel={accessibilityLabel}
|
|
156
|
+
className={computedClassName}
|
|
157
|
+
style={style}
|
|
158
|
+
{...props}
|
|
159
|
+
>
|
|
160
|
+
{asChild ? (
|
|
161
|
+
triggerChildren
|
|
162
|
+
) : (
|
|
163
|
+
<>
|
|
164
|
+
{children}
|
|
165
|
+
{triggerIndicator}
|
|
166
|
+
</>
|
|
167
|
+
)}
|
|
168
|
+
</AccordionTriggerRootPrimitive>
|
|
157
169
|
);
|
|
158
170
|
},
|
|
159
171
|
);
|
|
@@ -165,26 +177,32 @@ AccordionTrigger.displayName = 'Accordion.Trigger';
|
|
|
165
177
|
// =============================================================================
|
|
166
178
|
|
|
167
179
|
export interface AccordionIndicatorProps extends ViewProps {
|
|
180
|
+
asChild?: boolean;
|
|
168
181
|
className?: string;
|
|
182
|
+
children?: ReactNode;
|
|
169
183
|
}
|
|
170
184
|
|
|
171
185
|
const AccordionIndicator = forwardRef<View, AccordionIndicatorProps>(
|
|
172
|
-
({ className, style, ...props }, ref) => {
|
|
173
|
-
const {
|
|
186
|
+
({ asChild, className, style, children, ...props }, ref) => {
|
|
187
|
+
const { isOpen } = useAccordionItemContext();
|
|
188
|
+
const Comp = asChild ? Slot : View;
|
|
174
189
|
|
|
175
190
|
return (
|
|
176
|
-
<
|
|
191
|
+
<Comp
|
|
177
192
|
ref={ref}
|
|
178
193
|
className={cn(accordionIndicatorVariants(), className)}
|
|
179
194
|
style={style}
|
|
180
195
|
{...props}
|
|
181
|
-
{...
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
196
|
+
{...mergeDataAttributes(
|
|
197
|
+
props,
|
|
198
|
+
dataAttributes({
|
|
199
|
+
slot: 'accordion-indicator',
|
|
200
|
+
state: isOpen ? 'open' : 'closed',
|
|
201
|
+
}),
|
|
202
|
+
)}
|
|
185
203
|
>
|
|
186
|
-
<Icon as={KeyboardArrowDown} size={24} />
|
|
187
|
-
</
|
|
204
|
+
{children ?? <Icon as={KeyboardArrowDown} size={24} />}
|
|
205
|
+
</Comp>
|
|
188
206
|
);
|
|
189
207
|
},
|
|
190
208
|
);
|
|
@@ -309,53 +327,34 @@ const AccordionMeta = forwardRef<Text, AccordionMetaProps>(
|
|
|
309
327
|
AccordionMeta.displayName = 'Accordion.Meta';
|
|
310
328
|
|
|
311
329
|
// =============================================================================
|
|
312
|
-
//
|
|
330
|
+
// CONTENT
|
|
313
331
|
// =============================================================================
|
|
314
332
|
|
|
315
|
-
export interface
|
|
316
|
-
|
|
317
|
-
children?: ReactNode;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
const AccordionPanel = forwardRef<View, AccordionPanelProps>(
|
|
321
|
-
({ className, style, children, ...props }, ref) => (
|
|
322
|
-
<AccordionPanelRootPrimitive
|
|
323
|
-
ref={ref}
|
|
324
|
-
className={cn('w-full', className)}
|
|
325
|
-
style={style}
|
|
326
|
-
{...props}
|
|
327
|
-
>
|
|
328
|
-
{children}
|
|
329
|
-
</AccordionPanelRootPrimitive>
|
|
330
|
-
),
|
|
331
|
-
);
|
|
332
|
-
|
|
333
|
-
AccordionPanel.displayName = 'Accordion.Panel';
|
|
334
|
-
|
|
335
|
-
export interface AccordionBodyProps extends ViewProps {
|
|
333
|
+
export interface AccordionContentProps extends IAccordionContentProps {
|
|
334
|
+
asChild?: boolean;
|
|
336
335
|
className?: string;
|
|
337
336
|
children?: ReactNode;
|
|
338
337
|
}
|
|
339
338
|
|
|
340
|
-
const
|
|
341
|
-
({ className, style, children, ...props }, ref) => {
|
|
342
|
-
const {
|
|
339
|
+
const AccordionContent = forwardRef<View, AccordionContentProps>(
|
|
340
|
+
({ asChild, className, style, children, ...props }, ref) => {
|
|
341
|
+
const { fullBleed } = useAccordionItemStyleContext();
|
|
343
342
|
|
|
344
343
|
return (
|
|
345
|
-
<
|
|
344
|
+
<AccordionContentRootPrimitive
|
|
346
345
|
ref={ref}
|
|
347
|
-
|
|
346
|
+
asChild={asChild}
|
|
347
|
+
className={cn(accordionContentVariants({ fullBleed }), className)}
|
|
348
348
|
style={style}
|
|
349
349
|
{...props}
|
|
350
|
-
{...mergeDataAttributes(props, dataAttributes({ slot: 'accordion-body' }))}
|
|
351
350
|
>
|
|
352
351
|
{children}
|
|
353
|
-
</
|
|
352
|
+
</AccordionContentRootPrimitive>
|
|
354
353
|
);
|
|
355
354
|
},
|
|
356
355
|
);
|
|
357
356
|
|
|
358
|
-
|
|
357
|
+
AccordionContent.displayName = 'Accordion.Content';
|
|
359
358
|
|
|
360
359
|
// =============================================================================
|
|
361
360
|
// COMPOUND EXPORT
|
|
@@ -370,8 +369,7 @@ type AccordionCompoundComponent = typeof AccordionRoot & {
|
|
|
370
369
|
Description: typeof AccordionDescription;
|
|
371
370
|
Meta: typeof AccordionMeta;
|
|
372
371
|
Indicator: typeof AccordionIndicator;
|
|
373
|
-
|
|
374
|
-
Body: typeof AccordionBody;
|
|
372
|
+
Content: typeof AccordionContent;
|
|
375
373
|
};
|
|
376
374
|
|
|
377
375
|
export const Accordion = Object.assign(AccordionRoot, {
|
|
@@ -383,6 +381,5 @@ export const Accordion = Object.assign(AccordionRoot, {
|
|
|
383
381
|
Description: AccordionDescription,
|
|
384
382
|
Meta: AccordionMeta,
|
|
385
383
|
Indicator: AccordionIndicator,
|
|
386
|
-
|
|
387
|
-
Body: AccordionBody,
|
|
384
|
+
Content: AccordionContent,
|
|
388
385
|
}) as AccordionCompoundComponent;
|
|
@@ -1,48 +1,50 @@
|
|
|
1
1
|
import { Platform } from 'react-native';
|
|
2
|
-
import { cva
|
|
3
|
-
import { DISABLED_CURSOR
|
|
2
|
+
import { cva } from '@cdx-ui/utils';
|
|
3
|
+
import { DISABLED_CURSOR } from '../../styles/constants';
|
|
4
4
|
|
|
5
5
|
export const accordionRootVariants = cva(['flex w-full flex-col']);
|
|
6
6
|
|
|
7
|
-
export const accordionItemVariants = cva(
|
|
8
|
-
'flex w-full flex-col
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
'has-[[data-focus-visible=true]]:before:opacity-[var(--opacity-focus)]',
|
|
22
|
-
].join(' '),
|
|
23
|
-
default: '',
|
|
24
|
-
}),
|
|
25
|
-
]);
|
|
7
|
+
export const accordionItemVariants = cva(
|
|
8
|
+
['flex w-full flex-col', 'data-[disabled=true]:opacity-[var(--opacity-disabled)]'],
|
|
9
|
+
{
|
|
10
|
+
variants: {
|
|
11
|
+
showSeparator: {
|
|
12
|
+
true: 'border-b border-solid border-stroke-secondary',
|
|
13
|
+
false: 'border-b-0',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
defaultVariants: {
|
|
17
|
+
showSeparator: true,
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
);
|
|
26
21
|
|
|
27
22
|
export const accordionTriggerVariants = cva(
|
|
28
23
|
[
|
|
29
|
-
'relative
|
|
24
|
+
'relative flex w-full flex-row items-center gap-3 min-h-[52px] bg-[var(--color-transparent)] outline-none',
|
|
30
25
|
'web:outline-none web:focus:outline-none web:focus-visible:outline-none',
|
|
31
26
|
DISABLED_CURSOR,
|
|
32
27
|
Platform.select({
|
|
33
|
-
web:
|
|
28
|
+
web: [
|
|
29
|
+
'before:pointer-events-none before:absolute before:inset-0 before:z-0 before:bg-content-primary before:opacity-0 before:content-[""]',
|
|
30
|
+
'before:transition-opacity before:duration-150 before:ease-out',
|
|
31
|
+
'data-[hover=true]:data-[state="closed"]:before:opacity-[var(--opacity-hover)]',
|
|
32
|
+
'data-[active=true]:data-[hover=true]:data-[state="closed"]:before:opacity-[var(--opacity-hover-overlay)]',
|
|
33
|
+
'data-[focus-visible=true]:before:opacity-[var(--opacity-focus)]',
|
|
34
|
+
'data-[focus-visible=true]:ring-2 data-[focus-visible=true]:ring-stroke-focus data-[focus-visible=true]:ring-offset-2',
|
|
35
|
+
].join(' '),
|
|
34
36
|
default: 'data-[active=true]:bg-surface-primary-hover',
|
|
35
37
|
}),
|
|
36
38
|
],
|
|
37
39
|
{
|
|
38
40
|
variants: {
|
|
39
|
-
|
|
41
|
+
fullBleed: {
|
|
40
42
|
true: 'px-0 py-4',
|
|
41
43
|
false: 'p-4',
|
|
42
44
|
},
|
|
43
45
|
},
|
|
44
46
|
defaultVariants: {
|
|
45
|
-
|
|
47
|
+
fullBleed: false,
|
|
46
48
|
},
|
|
47
49
|
},
|
|
48
50
|
);
|
|
@@ -64,19 +66,17 @@ export const accordionMetaVariants = cva(['body-xs text-content-secondary']);
|
|
|
64
66
|
export const accordionIndicatorVariants = cva([
|
|
65
67
|
'relative z-10 flex shrink-0 items-center justify-center text-content-primary',
|
|
66
68
|
'data-[state=open]:rotate-180',
|
|
67
|
-
|
|
69
|
+
Platform.select({ web: 'transition-transform duration-150 ease-out', default: '' }),
|
|
68
70
|
]);
|
|
69
71
|
|
|
70
|
-
export const
|
|
72
|
+
export const accordionContentVariants = cva(['flex w-full flex-col gap-2 pb-4'], {
|
|
71
73
|
variants: {
|
|
72
|
-
|
|
74
|
+
fullBleed: {
|
|
73
75
|
true: 'px-0',
|
|
74
76
|
false: 'px-4',
|
|
75
77
|
},
|
|
76
78
|
},
|
|
77
79
|
defaultVariants: {
|
|
78
|
-
|
|
80
|
+
fullBleed: false,
|
|
79
81
|
},
|
|
80
82
|
});
|
|
81
|
-
|
|
82
|
-
export type AccordionItemVariantProps = VariantProps<typeof accordionTriggerVariants>;
|