@cdx-ui/components 0.1.0 → 0.1.2
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 +8 -12
- package/lib/commonjs/components/Input/styles.js +12 -4
- package/lib/commonjs/components/Input/styles.js.map +1 -1
- package/lib/commonjs/components/InsuranceDisclosure/FdicLockup.js +31 -0
- package/lib/commonjs/components/InsuranceDisclosure/FdicLockup.js.map +1 -0
- package/lib/commonjs/components/InsuranceDisclosure/index.js +22 -4
- package/lib/commonjs/components/InsuranceDisclosure/index.js.map +1 -1
- package/lib/commonjs/components/InsuranceDisclosure/styles.js +13 -3
- package/lib/commonjs/components/InsuranceDisclosure/styles.js.map +1 -1
- package/lib/commonjs/components/Radio/index.js +14 -3
- package/lib/commonjs/components/Radio/index.js.map +1 -1
- package/lib/commonjs/components/Radio/styles.js +24 -8
- package/lib/commonjs/components/Radio/styles.js.map +1 -1
- package/lib/commonjs/components/Select/styles.js +11 -3
- package/lib/commonjs/components/Select/styles.js.map +1 -1
- package/lib/commonjs/components/Switch/styles.js +14 -14
- package/lib/commonjs/components/Switch/styles.js.map +1 -1
- package/lib/commonjs/components/Textarea/styles.js +4 -2
- package/lib/commonjs/components/Textarea/styles.js.map +1 -1
- package/lib/commonjs/figma/Field.Radio.figma.js +58 -0
- package/lib/commonjs/figma/Field.Radio.figma.js.map +1 -0
- package/lib/commonjs/figma/InsuranceDisclosure.figma.js +26 -0
- package/lib/commonjs/figma/InsuranceDisclosure.figma.js.map +1 -0
- package/lib/commonjs/figma/Radio.Group.figma.js +24 -0
- package/lib/commonjs/figma/Radio.Group.figma.js.map +1 -0
- package/lib/commonjs/figma/Radio.figma.js +12 -6
- package/lib/commonjs/figma/Radio.figma.js.map +1 -1
- package/lib/commonjs/styles/constants.js +5 -1
- package/lib/commonjs/styles/constants.js.map +1 -1
- package/lib/module/components/Input/styles.js +13 -5
- package/lib/module/components/Input/styles.js.map +1 -1
- package/lib/module/components/InsuranceDisclosure/FdicLockup.js +27 -0
- package/lib/module/components/InsuranceDisclosure/FdicLockup.js.map +1 -0
- package/lib/module/components/InsuranceDisclosure/index.js +22 -4
- package/lib/module/components/InsuranceDisclosure/index.js.map +1 -1
- package/lib/module/components/InsuranceDisclosure/styles.js +13 -3
- package/lib/module/components/InsuranceDisclosure/styles.js.map +1 -1
- package/lib/module/components/Radio/index.js +14 -3
- package/lib/module/components/Radio/index.js.map +1 -1
- package/lib/module/components/Radio/styles.js +25 -9
- package/lib/module/components/Radio/styles.js.map +1 -1
- package/lib/module/components/Select/styles.js +12 -4
- package/lib/module/components/Select/styles.js.map +1 -1
- package/lib/module/components/Switch/styles.js +14 -14
- package/lib/module/components/Switch/styles.js.map +1 -1
- package/lib/module/components/Textarea/styles.js +5 -3
- package/lib/module/components/Textarea/styles.js.map +1 -1
- package/lib/module/figma/Field.Radio.figma.js +52 -0
- package/lib/module/figma/Field.Radio.figma.js.map +1 -0
- package/lib/module/figma/InsuranceDisclosure.figma.js +20 -0
- package/lib/module/figma/InsuranceDisclosure.figma.js.map +1 -0
- package/lib/module/figma/Radio.Group.figma.js +18 -0
- package/lib/module/figma/Radio.Group.figma.js.map +1 -0
- package/lib/module/figma/Radio.figma.js +12 -6
- package/lib/module/figma/Radio.figma.js.map +1 -1
- package/lib/module/styles/constants.js +4 -0
- package/lib/module/styles/constants.js.map +1 -1
- package/lib/typescript/components/Input/styles.d.ts.map +1 -1
- package/lib/typescript/components/InsuranceDisclosure/FdicLockup.d.ts +2 -0
- package/lib/typescript/components/InsuranceDisclosure/FdicLockup.d.ts.map +1 -0
- package/lib/typescript/components/InsuranceDisclosure/index.d.ts +24 -3
- package/lib/typescript/components/InsuranceDisclosure/index.d.ts.map +1 -1
- package/lib/typescript/components/InsuranceDisclosure/styles.d.ts +5 -1
- package/lib/typescript/components/InsuranceDisclosure/styles.d.ts.map +1 -1
- package/lib/typescript/components/Radio/index.d.ts.map +1 -1
- package/lib/typescript/components/Radio/styles.d.ts.map +1 -1
- package/lib/typescript/components/Select/styles.d.ts.map +1 -1
- package/lib/typescript/components/Switch/styles.d.ts.map +1 -1
- package/lib/typescript/components/Textarea/styles.d.ts.map +1 -1
- package/lib/typescript/figma/Field.Radio.figma.d.ts +8 -0
- package/lib/typescript/figma/Field.Radio.figma.d.ts.map +1 -0
- package/lib/typescript/figma/InsuranceDisclosure.figma.d.ts +8 -0
- package/lib/typescript/figma/InsuranceDisclosure.figma.d.ts.map +1 -0
- package/lib/typescript/figma/Radio.Group.figma.d.ts +8 -0
- package/lib/typescript/figma/Radio.Group.figma.d.ts.map +1 -0
- package/lib/typescript/figma/Radio.figma.d.ts.map +1 -1
- package/lib/typescript/styles/constants.d.ts +1 -0
- package/lib/typescript/styles/constants.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/components/Input/styles.ts +11 -3
- package/src/components/InsuranceDisclosure/FdicLockup.tsx +23 -0
- package/src/components/InsuranceDisclosure/index.tsx +54 -14
- package/src/components/InsuranceDisclosure/styles.ts +28 -9
- package/src/components/Radio/index.tsx +22 -6
- package/src/components/Radio/styles.ts +46 -6
- package/src/components/Select/styles.ts +11 -3
- package/src/components/Switch/styles.ts +23 -15
- package/src/components/Textarea/styles.ts +5 -3
- package/src/styles/constants.ts +4 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Path, Svg } from 'react-native-svg';
|
|
2
|
+
|
|
3
|
+
const FDIC_NAVY = '#003366';
|
|
4
|
+
|
|
5
|
+
export function FdicLockup() {
|
|
6
|
+
return (
|
|
7
|
+
<Svg width="100%" height="100%" viewBox="0 0 44 20" fill="none">
|
|
8
|
+
<Path
|
|
9
|
+
d="M5.39953 18.3086H0.896923V1.73399H10.1587V6.06628H5.39953V8.7493H9.88382V13.0821H5.39953V18.3086Z"
|
|
10
|
+
fill={FDIC_NAVY}
|
|
11
|
+
/>
|
|
12
|
+
<Path d="M30.228 1.69895H25.7254V18.308H30.228V1.69895Z" fill={FDIC_NAVY} />
|
|
13
|
+
<Path
|
|
14
|
+
d="M39.4208 13.924C37.2579 13.924 35.4679 12.1616 35.4679 10.0003C35.4679 7.83897 37.2579 6.07598 39.4208 6.07598C41.3929 6.07598 42.424 7.12483 43.1031 8.50623V2.55916C43.1031 2.55916 41.1094 1.665 39.2516 1.665C35.1252 1.665 30.6543 5.46047 30.6543 10.0003C30.6543 15.5582 34.9187 18.335 39.2516 18.335C41.1089 18.335 43.1031 17.4419 43.1031 17.4419V11.5466C42.2903 12.9479 41.3821 13.924 39.4208 13.924Z"
|
|
15
|
+
fill={FDIC_NAVY}
|
|
16
|
+
/>
|
|
17
|
+
<Path
|
|
18
|
+
d="M15.3172 1.73399C18.1366 1.73399 24.946 2.42118 24.946 10.0132C24.946 17.6209 18.8254 18.2935 15.3172 18.293H10.7785V1.73399H15.3172ZM20.4752 9.98679C20.4752 7.02943 18.1027 5.99783 15.3102 5.99783V13.9758C18.1027 13.9758 20.4752 12.9436 20.4752 9.98679Z"
|
|
19
|
+
fill={FDIC_NAVY}
|
|
20
|
+
/>
|
|
21
|
+
</Svg>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
@@ -5,49 +5,89 @@ import { cn } from '@cdx-ui/utils';
|
|
|
5
5
|
import { Image as ForgeImage } from '../Image/Image';
|
|
6
6
|
import { HStack, type HStackProps } from '../Stack/HStack';
|
|
7
7
|
import { Text } from '../Text';
|
|
8
|
+
import { FdicLockup } from './FdicLockup';
|
|
8
9
|
import {
|
|
9
10
|
insuranceDisclosureLogoVariants,
|
|
10
11
|
insuranceDisclosureRootVariants,
|
|
11
12
|
insuranceDisclosureTextVariants,
|
|
12
13
|
} from './styles';
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
type InsuranceDisclosureSharedProps = Omit<HStackProps, 'children'> & {
|
|
16
|
+
/**
|
|
17
|
+
* When `true`, renders surface chrome (background, border, radius, padding).
|
|
18
|
+
* Defaults to `false` — unframed disclosures have no border or padding.
|
|
19
|
+
*
|
|
20
|
+
* @breakingChange Prior versions always rendered a bordered container with `p-4`.
|
|
21
|
+
* Pass `framed` to restore chrome; padding is now `px-3 py-2`.
|
|
22
|
+
*/
|
|
23
|
+
framed?: boolean;
|
|
17
24
|
label?: string;
|
|
18
25
|
className?: string;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/** Bundled official FDIC lockup — omit `logoSource` to use the default mark. */
|
|
29
|
+
export interface InsuranceDisclosureBundledLogoProps extends InsuranceDisclosureSharedProps {
|
|
30
|
+
logoSource?: undefined;
|
|
31
|
+
/** Ignored when the bundled FDIC lockup is used. */
|
|
32
|
+
logoAccessibilityLabel?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Custom logo override — `logoAccessibilityLabel` is required. */
|
|
36
|
+
export interface InsuranceDisclosureCustomLogoProps extends InsuranceDisclosureSharedProps {
|
|
37
|
+
/** Logo image — a remote URI string or a React Native image source. */
|
|
38
|
+
logoSource: string | ImageSourcePropType;
|
|
39
|
+
/** Accessible label for the custom logo, announced by assistive technology. */
|
|
40
|
+
logoAccessibilityLabel: string;
|
|
19
41
|
}
|
|
20
42
|
|
|
43
|
+
export type InsuranceDisclosureProps =
|
|
44
|
+
| InsuranceDisclosureBundledLogoProps
|
|
45
|
+
| InsuranceDisclosureCustomLogoProps;
|
|
46
|
+
|
|
21
47
|
export const InsuranceDisclosure = forwardRef<
|
|
22
48
|
ComponentRef<typeof HStack>,
|
|
23
49
|
InsuranceDisclosureProps
|
|
24
50
|
>(function InsuranceDisclosure(
|
|
25
|
-
{ logoSource, logoAccessibilityLabel, label, className, style, ...props },
|
|
51
|
+
{ framed = false, logoSource, logoAccessibilityLabel, label, className, style, ...props },
|
|
26
52
|
ref,
|
|
27
53
|
) {
|
|
54
|
+
const useCustomLogo = logoSource != null;
|
|
55
|
+
|
|
28
56
|
return (
|
|
29
57
|
<HStack
|
|
30
58
|
ref={ref}
|
|
31
59
|
space="md"
|
|
32
|
-
className={cn(insuranceDisclosureRootVariants(), className)}
|
|
60
|
+
className={cn(insuranceDisclosureRootVariants({ framed }), className)}
|
|
33
61
|
style={style}
|
|
34
62
|
{...props}
|
|
35
63
|
{...mergeDataAttributes(props, dataAttributes({ slot: 'insurance-disclosure' }))}
|
|
36
64
|
>
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
65
|
+
{useCustomLogo ? (
|
|
66
|
+
<ForgeImage
|
|
67
|
+
source={logoSource}
|
|
68
|
+
accessibilityLabel={logoAccessibilityLabel}
|
|
69
|
+
accessible={logoAccessibilityLabel != null}
|
|
70
|
+
resizeMode="contain"
|
|
71
|
+
className={insuranceDisclosureLogoVariants()}
|
|
72
|
+
{...mergeDataAttributes({}, dataAttributes({ slot: 'insurance-disclosure-logo' }))}
|
|
73
|
+
/>
|
|
74
|
+
) : (
|
|
75
|
+
<View
|
|
76
|
+
accessible
|
|
77
|
+
accessibilityRole="image"
|
|
78
|
+
accessibilityLabel="FDIC"
|
|
79
|
+
className={insuranceDisclosureLogoVariants()}
|
|
80
|
+
{...mergeDataAttributes({}, dataAttributes({ slot: 'insurance-disclosure-logo' }))}
|
|
81
|
+
>
|
|
82
|
+
<FdicLockup />
|
|
83
|
+
</View>
|
|
84
|
+
)}
|
|
45
85
|
{label ? (
|
|
46
86
|
<View
|
|
47
87
|
className="min-w-0 shrink"
|
|
48
88
|
{...mergeDataAttributes({}, dataAttributes({ slot: 'insurance-disclosure-content' }))}
|
|
49
89
|
>
|
|
50
|
-
<Text size="
|
|
90
|
+
<Text size="sm" className={insuranceDisclosureTextVariants()}>
|
|
51
91
|
{label}
|
|
52
92
|
</Text>
|
|
53
93
|
</View>
|
|
@@ -1,12 +1,31 @@
|
|
|
1
|
-
import { cva } from '@cdx-ui/utils';
|
|
1
|
+
import { cva, type VariantProps } from '@cdx-ui/utils';
|
|
2
2
|
|
|
3
|
-
export const insuranceDisclosureRootVariants = cva(
|
|
4
|
-
'w-full max-w-full items-center justify-start',
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
export const insuranceDisclosureRootVariants = cva(
|
|
4
|
+
['w-full max-w-full items-center justify-start'],
|
|
5
|
+
{
|
|
6
|
+
variants: {
|
|
7
|
+
framed: {
|
|
8
|
+
true: [
|
|
9
|
+
'bg-surface-primary',
|
|
10
|
+
'border border-stroke-secondary',
|
|
11
|
+
'rounded-[var(--border-radius-default)]',
|
|
12
|
+
'px-3 py-2',
|
|
13
|
+
],
|
|
14
|
+
false: '',
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
defaultVariants: {
|
|
18
|
+
framed: false,
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
export type InsuranceDisclosureRootVariantProps = VariantProps<
|
|
24
|
+
typeof insuranceDisclosureRootVariants
|
|
25
|
+
>;
|
|
9
26
|
|
|
10
|
-
export const insuranceDisclosureLogoVariants = cva(['h-
|
|
27
|
+
export const insuranceDisclosureLogoVariants = cva(['h-5 w-11 shrink-0']);
|
|
11
28
|
|
|
12
|
-
export const insuranceDisclosureTextVariants = cva([
|
|
29
|
+
export const insuranceDisclosureTextVariants = cva([
|
|
30
|
+
'shrink text-content-primary italic [font-family:var(--font-body-italic)]',
|
|
31
|
+
]);
|
|
@@ -74,10 +74,11 @@ const RadioIndicator = forwardRef<View, RadioIndicatorProps>(
|
|
|
74
74
|
useRadioContext();
|
|
75
75
|
|
|
76
76
|
const checkState = isChecked ? 'checked' : 'unchecked';
|
|
77
|
-
const fieldState =
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
77
|
+
const fieldState = isReadOnly
|
|
78
|
+
? (`readonly-${checkState}${isInvalid ? '-invalid' : ''}` as const)
|
|
79
|
+
: INDICATOR_STATES[
|
|
80
|
+
`${checkState}:${isInvalid ? 'true' : 'false'}:${isPressed ? 'true' : 'false'}`
|
|
81
|
+
];
|
|
81
82
|
|
|
82
83
|
const computedClassName = cn(radioIndicatorVariants(), className);
|
|
83
84
|
const Comp = asChild ? Slot : View;
|
|
@@ -104,11 +105,18 @@ const RadioIndicator = forwardRef<View, RadioIndicatorProps>(
|
|
|
104
105
|
)}
|
|
105
106
|
>
|
|
106
107
|
<View
|
|
107
|
-
|
|
108
|
+
collapsable={false}
|
|
109
|
+
className={cn(
|
|
110
|
+
radioInnerDotVariants(),
|
|
111
|
+
// Native: unconditional bg so Uniwind does not have to win a data-attribute
|
|
112
|
+
// background over `bg-surface-action-strong` (web keeps compound selectors).
|
|
113
|
+
isReadOnly && isChecked && !isInvalid && 'bg-content-primary',
|
|
114
|
+
)}
|
|
108
115
|
{...dataAttributes({
|
|
109
116
|
checked: isChecked,
|
|
110
117
|
invalid: isInvalid,
|
|
111
118
|
hover: isHovered,
|
|
119
|
+
readonly: isReadOnly,
|
|
112
120
|
fieldState,
|
|
113
121
|
})}
|
|
114
122
|
/>
|
|
@@ -132,6 +140,7 @@ export interface RadioLabelProps extends TextProps {
|
|
|
132
140
|
|
|
133
141
|
const RadioLabel = forwardRef<Text, RadioLabelProps>(
|
|
134
142
|
({ asChild, className, children, style, ...props }, ref) => {
|
|
143
|
+
const { isDisabled, isReadOnly } = useRadioContext();
|
|
135
144
|
const computedClassName = cn(radioLabelVariants(), className);
|
|
136
145
|
const Comp = asChild ? Slot : Text;
|
|
137
146
|
|
|
@@ -141,7 +150,14 @@ const RadioLabel = forwardRef<Text, RadioLabelProps>(
|
|
|
141
150
|
className={computedClassName}
|
|
142
151
|
style={style}
|
|
143
152
|
{...props}
|
|
144
|
-
{...mergeDataAttributes(
|
|
153
|
+
{...mergeDataAttributes(
|
|
154
|
+
props,
|
|
155
|
+
dataAttributes({
|
|
156
|
+
slot: 'radio-label',
|
|
157
|
+
disabled: isDisabled,
|
|
158
|
+
readonly: isReadOnly,
|
|
159
|
+
}),
|
|
160
|
+
)}
|
|
145
161
|
>
|
|
146
162
|
{children}
|
|
147
163
|
</Comp>
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { Platform } from 'react-native';
|
|
2
2
|
import { cva } from '@cdx-ui/utils';
|
|
3
|
-
import { DISABLED_CURSOR, TRANSITION_COLORS } from '../../styles/constants';
|
|
3
|
+
import { DISABLED_CURSOR, DISABLED_OPACITY, TRANSITION_COLORS } from '../../styles/constants';
|
|
4
4
|
|
|
5
5
|
export const radioRootVariants = cva([
|
|
6
6
|
'flex-row items-center gap-2',
|
|
7
|
-
|
|
7
|
+
DISABLED_OPACITY,
|
|
8
8
|
DISABLED_CURSOR,
|
|
9
|
+
'data-[readonly=true]:cursor-default',
|
|
9
10
|
// Suppress default :focus-visible outline on the role="radio" Pressable;
|
|
10
11
|
// focus ring is drawn on the indicator instead of wrapping the whole control.
|
|
11
12
|
'web:outline-none web:focus:outline-none web:focus-visible:outline-none',
|
|
@@ -16,7 +17,8 @@ export const radioIndicatorVariants = cva([
|
|
|
16
17
|
'rounded-[var(--border-radius-round)]',
|
|
17
18
|
'border-[length:var(--border-width-selected)]',
|
|
18
19
|
'h-5 w-5',
|
|
19
|
-
|
|
20
|
+
// Figma: indicator fill is transparent; selection reads via border + inner dot only.
|
|
21
|
+
'bg-transparent',
|
|
20
22
|
'data-[checked=false]:border-content-secondary',
|
|
21
23
|
'data-[checked=true]:border-stroke-action',
|
|
22
24
|
'data-[invalid=true]:border-stroke-danger',
|
|
@@ -36,12 +38,32 @@ export const radioIndicatorVariants = cva([
|
|
|
36
38
|
'web:active:data-[hover=true]:data-[invalid=true]:data-[checked=false]:border-surface-danger-strong-active',
|
|
37
39
|
'web:active:data-[hover=true]:data-[checked=true]:border-surface-action-strong-active',
|
|
38
40
|
'web:active:data-[hover=true]:data-[checked=true]:data-[invalid=true]:border-surface-danger-strong-active',
|
|
41
|
+
// Focus ring — applies to read-only as well (focusable + aria-readonly).
|
|
39
42
|
'web:data-[focus-visible=true]:outline-none',
|
|
40
43
|
'web:data-[focus-visible=true]:ring-2 web:data-[focus-visible=true]:ring-stroke-focus web:data-[focus-visible=true]:ring-offset-2',
|
|
44
|
+
// Read-only — Figma: transparent fill + content-tertiary border (checked and unchecked).
|
|
45
|
+
// After hover/active so equal-or-higher specificity keeps the static treatment.
|
|
46
|
+
// Invalid is not a Figma readonly variant; retain danger so error remains visible.
|
|
47
|
+
'data-[readonly=true]:data-[checked=false]:border-content-tertiary',
|
|
48
|
+
'data-[readonly=true]:data-[checked=true]:border-content-tertiary',
|
|
49
|
+
'data-[readonly=true]:data-[invalid=true]:border-stroke-danger',
|
|
50
|
+
'data-[readonly=true]:data-[hover=true]:data-[checked=false]:bg-transparent',
|
|
51
|
+
'data-[readonly=true]:data-[hover=true]:data-[invalid=true]:data-[checked=false]:bg-transparent',
|
|
52
|
+
'data-[readonly=true]:data-[hover=true]:data-[checked=false]:border-content-tertiary',
|
|
53
|
+
'data-[readonly=true]:data-[hover=true]:data-[checked=true]:border-content-tertiary',
|
|
54
|
+
'data-[readonly=true]:data-[hover=true]:data-[invalid=true]:border-stroke-danger',
|
|
55
|
+
'web:active:data-[readonly=true]:data-[hover=true]:data-[checked=false]:border-content-tertiary',
|
|
56
|
+
'web:active:data-[readonly=true]:data-[hover=true]:data-[checked=true]:border-content-tertiary',
|
|
57
|
+
'web:active:data-[readonly=true]:data-[hover=true]:data-[invalid=true]:data-[checked=false]:border-stroke-danger',
|
|
58
|
+
'web:active:data-[readonly=true]:data-[hover=true]:data-[checked=true]:data-[invalid=true]:border-stroke-danger',
|
|
41
59
|
].join(' '),
|
|
42
60
|
default: [
|
|
43
61
|
// Native: Uniwind only evaluates the last data-[] condition in a compound chain.
|
|
44
62
|
// Use single-condition data-[field-state=...] selectors (emitted by RadioIndicator).
|
|
63
|
+
'data-[field-state=readonly-unchecked]:border-content-tertiary',
|
|
64
|
+
'data-[field-state=readonly-checked]:border-content-tertiary',
|
|
65
|
+
'data-[field-state=readonly-unchecked-invalid]:border-stroke-danger',
|
|
66
|
+
'data-[field-state=readonly-checked-invalid]:border-stroke-danger',
|
|
45
67
|
'data-[field-state=active]:border-stroke-hover',
|
|
46
68
|
'data-[field-state=invalid-active]:border-surface-danger-strong-active',
|
|
47
69
|
'data-[field-state=checked-active]:border-surface-action-strong-active',
|
|
@@ -52,9 +74,12 @@ export const radioIndicatorVariants = cva([
|
|
|
52
74
|
|
|
53
75
|
export const radioInnerDotVariants = cva([
|
|
54
76
|
'rounded-[var(--border-radius-round)]',
|
|
77
|
+
'overflow-hidden',
|
|
55
78
|
'h-2.5 w-2.5',
|
|
56
|
-
|
|
57
|
-
|
|
79
|
+
// Opacity (not scale): iOS compositing of scale-0 views samples the parent ring, so the
|
|
80
|
+
// checked fill never paints and the dot looks content-tertiary instead of content-primary.
|
|
81
|
+
'opacity-0',
|
|
82
|
+
'data-[checked=true]:opacity-100',
|
|
58
83
|
'bg-surface-action-strong',
|
|
59
84
|
'data-[invalid=true]:bg-surface-danger-strong',
|
|
60
85
|
Platform.select({
|
|
@@ -64,15 +89,30 @@ export const radioInnerDotVariants = cva([
|
|
|
64
89
|
// Active via group-active on indicator (inner dot is not the :active target).
|
|
65
90
|
'web:group-active:data-[hover=true]:data-[checked=true]:bg-surface-action-strong-active',
|
|
66
91
|
'web:group-active:data-[hover=true]:data-[checked=true]:data-[invalid=true]:bg-surface-danger-strong-active',
|
|
92
|
+
// Read-only checked — Figma: content-primary dot; invalid retains danger.
|
|
93
|
+
'data-[readonly=true]:data-[checked=true]:bg-content-primary',
|
|
94
|
+
'data-[readonly=true]:data-[checked=true]:data-[invalid=true]:bg-surface-danger-strong',
|
|
95
|
+
'web:group-active:data-[readonly=true]:data-[hover=true]:data-[checked=true]:bg-content-primary',
|
|
96
|
+
'web:group-active:data-[readonly=true]:data-[hover=true]:data-[checked=true]:data-[invalid=true]:bg-surface-danger-strong',
|
|
67
97
|
].join(' '),
|
|
68
98
|
default: [
|
|
69
99
|
'data-[field-state=checked-active]:bg-surface-action-strong-active',
|
|
70
100
|
'data-[field-state=checked-invalid-active]:bg-surface-danger-strong-active',
|
|
101
|
+
// `!` beats the base `bg-surface-action-strong` — Uniwind native does not cascade
|
|
102
|
+
// data-attribute backgrounds over an unconditional bg on the same View.
|
|
103
|
+
'data-[readonly=true]:bg-content-primary!',
|
|
104
|
+
'data-[field-state=readonly-checked]:bg-content-primary!',
|
|
105
|
+
'data-[field-state=readonly-checked-invalid]:bg-surface-danger-strong!',
|
|
71
106
|
].join(' '),
|
|
72
107
|
}),
|
|
73
108
|
]);
|
|
74
109
|
|
|
75
|
-
export const radioLabelVariants = cva([
|
|
110
|
+
export const radioLabelVariants = cva([
|
|
111
|
+
'body-md',
|
|
112
|
+
'text-content-primary',
|
|
113
|
+
'data-[disabled=true]:text-content-tertiary',
|
|
114
|
+
'data-[readonly=true]:cursor-default',
|
|
115
|
+
]);
|
|
76
116
|
|
|
77
117
|
export const radioGroupVariants = cva([], {
|
|
78
118
|
variants: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { cva, type VariantProps } from '@cdx-ui/utils';
|
|
2
|
-
import { DISABLED_CURSOR, TRANSITION_COLORS } from '../../styles/constants';
|
|
2
|
+
import { DISABLED_CURSOR, TRANSITION_COLORS, WEB_NARROW_FIELD_TEXT } from '../../styles/constants';
|
|
3
3
|
|
|
4
4
|
// ── Trigger ─────────────────────────────────────────────────
|
|
5
5
|
|
|
@@ -46,6 +46,9 @@ export const selectTriggerVariants = cva(
|
|
|
46
46
|
size: {
|
|
47
47
|
default: [
|
|
48
48
|
'h-11 min-h-11 px-4 py-3 gap-4',
|
|
49
|
+
// Web <600px: trim vertical padding so 16px / leading-normal (24px line box) fits
|
|
50
|
+
// in h-11. Native and web ≥600px keep py-3 at 14px text (Figma Viewport=Wide).
|
|
51
|
+
'web:max-[600px]:py-2',
|
|
49
52
|
// Native only: subtract one hairline so the wider focus border doesn't shift layout.
|
|
50
53
|
'native:data-[focus=true]:px-[calc(var(--spacing-4)-var(--spacing-px))]',
|
|
51
54
|
'native:data-[focus=true]:py-[calc(var(--spacing-3)-var(--spacing-px))]',
|
|
@@ -54,6 +57,9 @@ export const selectTriggerVariants = cva(
|
|
|
54
57
|
],
|
|
55
58
|
small: [
|
|
56
59
|
'h-8 min-h-8 px-3 py-2 gap-1.5',
|
|
60
|
+
// Web <600px: grow shell to h-9 so 16px text fits. Native and web ≥600px stay
|
|
61
|
+
// h-8 at 12px text.
|
|
62
|
+
'web:max-[600px]:h-9 web:max-[600px]:min-h-9 web:max-[600px]:py-1.5',
|
|
57
63
|
'native:data-[focus=true]:px-[calc(var(--spacing-3)-var(--spacing-px))]',
|
|
58
64
|
'native:data-[focus=true]:py-[calc(var(--spacing-2)-var(--spacing-px))]',
|
|
59
65
|
'native:data-[state=open]:px-[calc(var(--spacing-3)-var(--spacing-px))]',
|
|
@@ -80,8 +86,10 @@ export const selectValueVariants = cva(
|
|
|
80
86
|
{
|
|
81
87
|
variants: {
|
|
82
88
|
size: {
|
|
83
|
-
|
|
84
|
-
|
|
89
|
+
// Web <600px: 16px matches Input/Textarea and prevents iOS Safari focus-zoom.
|
|
90
|
+
// Native and web ≥600px keep 14px / 12px (Figma Viewport=Wide).
|
|
91
|
+
default: ['text-[0.875rem]', WEB_NARROW_FIELD_TEXT],
|
|
92
|
+
small: ['text-[0.75rem]', WEB_NARROW_FIELD_TEXT],
|
|
85
93
|
},
|
|
86
94
|
},
|
|
87
95
|
defaultVariants: {
|
|
@@ -4,40 +4,40 @@ import { cva, type VariantProps } from '@cdx-ui/utils';
|
|
|
4
4
|
// NATIVE — Uniwind className bindings for RN Switch
|
|
5
5
|
// =============================================================================
|
|
6
6
|
|
|
7
|
-
export const switchThumbColorVariants = cva(['accent-
|
|
7
|
+
export const switchThumbColorVariants = cva(['accent-surface-primary'], {
|
|
8
8
|
variants: {
|
|
9
9
|
isDisabled: {
|
|
10
|
-
true: 'accent-
|
|
10
|
+
true: 'accent-surface-neutral-subtle',
|
|
11
11
|
false: '',
|
|
12
12
|
},
|
|
13
13
|
},
|
|
14
14
|
defaultVariants: { isDisabled: false },
|
|
15
15
|
});
|
|
16
16
|
|
|
17
|
-
export const switchTrackOnVariants = cva(['accent-
|
|
17
|
+
export const switchTrackOnVariants = cva(['accent-surface-action-strong'], {
|
|
18
18
|
variants: {
|
|
19
19
|
isInvalid: {
|
|
20
|
-
true: 'accent-
|
|
20
|
+
true: 'accent-surface-danger-strong',
|
|
21
21
|
false: '',
|
|
22
22
|
},
|
|
23
23
|
},
|
|
24
24
|
defaultVariants: { isInvalid: false },
|
|
25
25
|
});
|
|
26
26
|
|
|
27
|
-
export const switchTrackOffVariants = cva(['accent-
|
|
27
|
+
export const switchTrackOffVariants = cva(['accent-surface-neutral-subtle'], {
|
|
28
28
|
variants: {
|
|
29
29
|
isInvalid: {
|
|
30
|
-
true: 'accent-
|
|
30
|
+
true: 'accent-surface-danger-subtle',
|
|
31
31
|
false: '',
|
|
32
32
|
},
|
|
33
33
|
},
|
|
34
34
|
defaultVariants: { isInvalid: false },
|
|
35
35
|
});
|
|
36
36
|
|
|
37
|
-
export const switchIosBgVariants = cva(['accent-
|
|
37
|
+
export const switchIosBgVariants = cva(['accent-surface-neutral-subtle'], {
|
|
38
38
|
variants: {
|
|
39
39
|
isInvalid: {
|
|
40
|
-
true: 'accent-
|
|
40
|
+
true: 'accent-surface-danger-subtle',
|
|
41
41
|
false: '',
|
|
42
42
|
},
|
|
43
43
|
},
|
|
@@ -53,8 +53,8 @@ export const switchTrackVariants = cva(
|
|
|
53
53
|
'flex-row items-center rounded-full cursor-pointer',
|
|
54
54
|
'transition-colors duration-200',
|
|
55
55
|
'data-[disabled=true]:opacity-50 data-[disabled=true]:cursor-not-allowed',
|
|
56
|
-
'web:data-[focus-visible=true]:ring-3 web:data-[focus-visible=true]:ring-
|
|
57
|
-
'web:data-[invalid=true]:data-[focus-visible=true]:ring-
|
|
56
|
+
'web:data-[focus-visible=true]:ring-3 web:data-[focus-visible=true]:ring-stroke-focus/50',
|
|
57
|
+
'web:data-[invalid=true]:data-[focus-visible=true]:ring-stroke-danger/50',
|
|
58
58
|
],
|
|
59
59
|
{
|
|
60
60
|
variants: {
|
|
@@ -73,8 +73,8 @@ export const switchTrackVariants = cva(
|
|
|
73
73
|
export const switchWebTrackColorVariants = cva([], {
|
|
74
74
|
variants: {
|
|
75
75
|
isChecked: {
|
|
76
|
-
true: 'bg-
|
|
77
|
-
false: 'bg-
|
|
76
|
+
true: 'bg-surface-action-strong data-[hover=true]:bg-surface-action-strong-hover',
|
|
77
|
+
false: 'bg-surface-neutral-subtle data-[hover=true]:bg-surface-neutral-subtle-hover',
|
|
78
78
|
},
|
|
79
79
|
isInvalid: {
|
|
80
80
|
true: '',
|
|
@@ -82,8 +82,16 @@ export const switchWebTrackColorVariants = cva([], {
|
|
|
82
82
|
},
|
|
83
83
|
},
|
|
84
84
|
compoundVariants: [
|
|
85
|
-
{
|
|
86
|
-
|
|
85
|
+
{
|
|
86
|
+
isChecked: true,
|
|
87
|
+
isInvalid: true,
|
|
88
|
+
className: 'bg-surface-danger-strong data-[hover=true]:bg-surface-danger-strong-hover',
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
isChecked: false,
|
|
92
|
+
isInvalid: true,
|
|
93
|
+
className: 'bg-surface-danger-subtle data-[hover=true]:bg-surface-danger-subtle-hover',
|
|
94
|
+
},
|
|
87
95
|
],
|
|
88
96
|
defaultVariants: {
|
|
89
97
|
isChecked: false,
|
|
@@ -92,7 +100,7 @@ export const switchWebTrackColorVariants = cva([], {
|
|
|
92
100
|
});
|
|
93
101
|
|
|
94
102
|
export const switchThumbVariants = cva(
|
|
95
|
-
['rounded-full bg-
|
|
103
|
+
['rounded-full bg-surface-primary shadow-sm', 'transition-transform duration-200'],
|
|
96
104
|
{
|
|
97
105
|
variants: {
|
|
98
106
|
size: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { cva, type VariantProps } from '@cdx-ui/utils';
|
|
2
|
-
import { DISABLED_CURSOR, TRANSITION_COLORS } from '../../styles/constants';
|
|
2
|
+
import { DISABLED_CURSOR, TRANSITION_COLORS, WEB_NARROW_FIELD_TEXT } from '../../styles/constants';
|
|
3
3
|
|
|
4
4
|
export const textareaRootVariants = cva(
|
|
5
5
|
[
|
|
@@ -71,8 +71,10 @@ export const textareaFieldVariants = cva(
|
|
|
71
71
|
{
|
|
72
72
|
variants: {
|
|
73
73
|
size: {
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
// Web <600px: 16px prevents iOS Safari focus-zoom. Native and web ≥600px keep
|
|
75
|
+
// 14px / 12px (Figma Viewport=Wide).
|
|
76
|
+
default: ['text-[0.875rem]', WEB_NARROW_FIELD_TEXT],
|
|
77
|
+
small: ['text-[0.75rem]', WEB_NARROW_FIELD_TEXT],
|
|
76
78
|
},
|
|
77
79
|
},
|
|
78
80
|
defaultVariants: {
|
package/src/styles/constants.ts
CHANGED
|
@@ -8,3 +8,7 @@ export const TRANSITION_COLORS = 'transition-colors duration-150';
|
|
|
8
8
|
export const DISABLED_OPACITY = 'data-[disabled=true]:opacity-50';
|
|
9
9
|
export const DISABLED_CURSOR =
|
|
10
10
|
'data-[disabled=true]:cursor-not-allowed data-[disabled=true]:pointer-events-none';
|
|
11
|
+
|
|
12
|
+
// Web-only iOS Safari focus-zoom guard. Figma Viewport=Narrow (<600px) uses body/lg
|
|
13
|
+
// (16px / 24px); Viewport=Wide (≥600px) keeps the size variant's original px size.
|
|
14
|
+
export const WEB_NARROW_FIELD_TEXT = 'web:max-[600px]:text-base web:max-[600px]:leading-normal';
|