Skip to content

Commit be1d84e

Browse files
authored
Merge pull request #1856 from gluestack/feat/eg-checkbox
Feat/eg checkbox
2 parents f782b1a + 03a6fde commit be1d84e

File tree

4 files changed

+672
-103
lines changed

4 files changed

+672
-103
lines changed

example/storybook-nativewind/src/components-example/nativewind/Checkbox/index.tsx

Lines changed: 114 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,15 @@ import React from 'react';
22
import { createCheckbox } from '@gluestack-ui/checkbox';
33
import { View, Pressable, Text } from 'react-native';
44
import {
5-
cn,
65
withStates,
76
withStyleContextAndStates,
87
useStyleContext,
98
tva,
109
withStyleContext,
1110
cssInterop,
11+
VariantProps,
1212
} from '@gluestack-ui/nativewind-utils';
1313
import { Platform } from 'react-native';
14-
1514
import { Check } from 'lucide-react-native';
1615

1716
const UICheckbox = createCheckbox({
@@ -20,10 +19,10 @@ const UICheckbox = createCheckbox({
2019
Platform.OS === 'web'
2120
? withStyleContext(View)
2221
: withStyleContextAndStates(Pressable),
23-
Group: Platform.OS === 'web' ? View : withStates(View),
24-
Icon: Platform.OS === 'web' ? Check : withStates(Check),
25-
Label: Platform.OS === 'web' ? Text : withStates(Text),
26-
Indicator: Platform.OS === 'web' ? View : withStates(View),
22+
Group: withStates(View),
23+
Icon: withStates(Check),
24+
Label: withStates(Text),
25+
Indicator: withStates(View),
2726
});
2827

2928
cssInterop(UICheckbox, { className: 'style' });
@@ -32,35 +31,62 @@ cssInterop(UICheckbox.Icon, { className: 'style' });
3231
cssInterop(UICheckbox.Label, { className: 'style' });
3332
cssInterop(UICheckbox.Indicator, { className: 'style' });
3433

35-
const checkboxIndicator = tva({
36-
base: 'justify-center items-center border-outline-400 rounded-sm data-[focus=true]:outline-none data-[focus-visible=true]:ring-2 data-[focus-visible=true]:ring-primary-700 data-[focus-visible=true]:ring-offset-1 overflow-hidden data-[checked=true]:border-primary-600',
34+
const checkboxStyle = tva({
35+
base: 'group/checkbox flex-row items-center justify-start gap-2 web:cursor-pointer data-[disabled=true]:cursor-not-allowed',
36+
});
37+
38+
const checkboxIndicatorStyle = tva({
39+
base: 'group/checkboxInd justify-center items-center border-outline-400 bg-transparent rounded web:data-[focus-visible=true]:outline-none web:data-[focus-visible=true]:ring-2 web:data-[focus-visible=true]:ring-primary-700 data-[checked=true]:bg-primary-600 group-hover/checkbox:border-outline-500 group-hover/checkbox:bg-transparent group-hover/checkbox:data-[invalid=true]:border-error-700 group-hover/checkbox:data-[checked=true]:bg-primary-700 group-hover/checkbox:data-[checked=true]:data-[disabled=true]:border-primary-600 group-hover/checkbox:data-[checked=true]:data-[disabled=true]:bg-primary-600 group-hover/checkbox:data-[checked=true]:data-[disabled=true]:opacity-40 group-hover/checkbox:data-[checked=true]:data-[disabled=true]:data-[invalid=true]:border-error-700 group-hover/checkbox:data-[disabled=true]:border-outline-400 group-hover/checkbox:data-[disabled=true]:data-[invalid=true]:border-error-700 active:data-[checked=true]:bg-primary-800 active:data-[checked=true]:border-primary-800 data-[invalid=true]:border-error-700 data-[disabled=true]:opacity-40',
3740
parentVariants: {
3841
size: {
39-
lg: 'w-6 h-6 border-4',
42+
lg: 'w-6 h-6 border-[3px]',
4043
md: 'w-5 h-5 border-2',
4144
sm: 'w-4 h-4 border-2',
4245
},
4346
},
4447
});
4548

46-
const checkboxLabel = tva({
47-
base: 'text-typography-600',
49+
const checkboxLabelStyle = tva({
50+
base: 'text-typography-600 data-[checked=true]:text-typography-900 group-hover/checkbox:text-typography-900 group-hover/checkbox:data-[checked=true]:text-typography-900 group-hover/checkbox:data-[checked=true]:data-[disabled=true]:text-typography-900 group-hover/checkbox:data-[disabled=true]:text-typography-600 active:text-typography-900 active:data-[checked=true]:text-typography-900 data-[disabled=true]:opacity-40 web:select-none',
4851
parentVariants: {
4952
size: {
5053
lg: 'text-lg',
51-
md: 'text-md',
54+
md: 'text-base',
5255
sm: 'text-sm',
5356
},
5457
},
5558
});
5659

60+
const checkboxIconStyle = tva({
61+
base: 'group-data-[checked=true]/checkboxInd:text-typography-0 data-[disabled=true]:opacity-40',
62+
63+
parentVariants: {
64+
size: {
65+
sm: 'h-3 w-3',
66+
md: 'h-4 w-4',
67+
lg: 'h-5 w-5',
68+
},
69+
},
70+
});
71+
5772
const CheckboxGroup = UICheckbox.Group;
5873

74+
type ICheckboxProps = React.ComponentProps<typeof UICheckbox> &
75+
VariantProps<typeof checkboxStyle>;
5976
const Checkbox = React.forwardRef(
60-
({ className, size = 'sm', ...props }: any, ref) => {
77+
(
78+
{
79+
className,
80+
size = 'md',
81+
...props
82+
}: { className?: string } & ICheckboxProps,
83+
ref
84+
) => {
6185
return (
6286
<UICheckbox
63-
className={cn('flex-row items-center justify-start gap-2', className)}
87+
className={checkboxStyle({
88+
class: className,
89+
})}
6490
{...props}
6591
context={{
6692
size,
@@ -71,13 +97,20 @@ const Checkbox = React.forwardRef(
7197
}
7298
);
7399

100+
type ICheckboxIndicatorProps = React.ComponentProps<
101+
typeof UICheckbox.Indicator
102+
> &
103+
VariantProps<typeof checkboxIndicatorStyle>;
74104
const CheckboxIndicator = React.forwardRef(
75-
({ className, ...props }: any, ref) => {
105+
(
106+
{ className, ...props }: { className?: string } & ICheckboxIndicatorProps,
107+
ref
108+
) => {
76109
const { size: parentSize } = useStyleContext();
77110

78111
return (
79112
<UICheckbox.Indicator
80-
className={checkboxIndicator({
113+
className={checkboxIndicatorStyle({
81114
parentVariants: {
82115
size: parentSize,
83116
},
@@ -90,34 +123,72 @@ const CheckboxIndicator = React.forwardRef(
90123
}
91124
);
92125

93-
const CheckboxLabel = React.forwardRef(({ className, ...props }: any, ref) => {
94-
const { size: parentSize } = useStyleContext();
95-
return (
96-
<UICheckbox.Label
97-
className={checkboxLabel({
98-
parentVariants: {
99-
size: parentSize,
100-
},
101-
class: className,
102-
})}
103-
{...props}
104-
ref={ref}
105-
/>
106-
);
107-
});
126+
type ICheckboxLabelProps = React.ComponentProps<typeof UICheckbox.Label> &
127+
VariantProps<typeof checkboxLabelStyle>;
128+
const CheckboxLabel = React.forwardRef(
129+
(
130+
{ className, ...props }: { className?: string } & ICheckboxLabelProps,
131+
ref
132+
) => {
133+
const { size: parentSize } = useStyleContext();
134+
return (
135+
<UICheckbox.Label
136+
className={checkboxLabelStyle({
137+
parentVariants: {
138+
size: parentSize,
139+
},
140+
class: className,
141+
})}
142+
{...props}
143+
ref={ref}
144+
/>
145+
);
146+
}
147+
);
108148

109-
const CheckboxIcon = React.forwardRef(({ className, ...props }: any, ref) => {
110-
return (
111-
<UICheckbox.Icon
112-
className={cn(
113-
'w-full h-full bg-primary-600 stroke-typography-0 color-typography-0',
114-
className
115-
)}
116-
{...props}
117-
ref={ref}
118-
/>
119-
);
120-
});
149+
type ICheckboxIconProps = React.ComponentProps<typeof UICheckbox.Icon> & {
150+
as?: any;
151+
};
152+
const CheckboxIcon = React.forwardRef(
153+
(
154+
{
155+
className,
156+
as: AsComp,
157+
...props
158+
}: ICheckboxIconProps & { className?: any },
159+
ref
160+
) => {
161+
const { size: parentSize } = useStyleContext();
162+
if (AsComp) {
163+
return (
164+
<UICheckbox.Icon>
165+
<AsComp
166+
{...props}
167+
className={checkboxIconStyle({
168+
parentVariants: {
169+
size: parentSize,
170+
},
171+
class: className,
172+
})}
173+
/>
174+
</UICheckbox.Icon>
175+
);
176+
}
177+
178+
return (
179+
<UICheckbox.Icon
180+
className={checkboxIconStyle({
181+
parentVariants: {
182+
size: parentSize,
183+
},
184+
class: className,
185+
})}
186+
{...props}
187+
ref={ref}
188+
/>
189+
);
190+
}
191+
);
121192

122193
// Assign display names
123194
Checkbox.displayName = 'Checkbox';

example/storybook-nativewind/src/components/Checkbox/Checkbox.stories.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,19 @@ const CheckboxMeta: ComponentMeta<typeof Checkbox> = {
1414
control: 'select',
1515
options: ['sm', 'md', 'lg'],
1616
},
17+
isDisabled: {
18+
control: 'boolean',
19+
options: [true, false],
20+
},
21+
isInvalid: {
22+
control: 'boolean',
23+
options: [true, false],
24+
},
1725
},
1826
args: {
1927
size: 'md',
28+
isDisabled: false,
29+
isInvalid: false,
2030
},
2131
};
2232

example/storybook-nativewind/src/components/Checkbox/Checkbox.tsx

Lines changed: 24 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -6,48 +6,23 @@ import {
66
CheckboxLabel,
77
CheckboxGroup,
88
} from '@/components/ui/Checkbox';
9+
import { Text } from '@/components/ui/Text';
10+
import { RemoveIcon, Icon, CheckIcon } from '@/components/ui/Icon';
11+
import { FormControl } from '@/components/ui/FormControl';
12+
import { Center } from '@/components/ui/Center';
13+
import { VStack } from '@/components/ui/VStack';
14+
import { HStack } from '@/components/ui/HStack';
15+
import { Heading } from '@/components/ui/Heading';
16+
import { Box } from '@/components/ui/Box';
917

1018
const CheckboxGroupBasic = ({ ...props }: any) => {
11-
const [values, setValues] = React.useState(['Label 1']);
12-
1319
return (
14-
<CheckboxGroup
15-
aria-label="Checkbox Group"
16-
value={values}
17-
onChange={setValues}
18-
nativeID="checkbox-group"
19-
>
20-
<Checkbox
21-
size={props.size}
22-
value="Label 1"
23-
aria-label="Label 1"
24-
onChange={(isSelected: boolean) =>
25-
// eslint-disable-next-line no-console
26-
console.log(isSelected, '###')
27-
}
28-
nativeID="checkbox-1"
29-
>
30-
<CheckboxIndicator>
31-
<CheckboxIcon />
32-
</CheckboxIndicator>
33-
<CheckboxLabel>Label 1</CheckboxLabel>
34-
</Checkbox>
35-
<Checkbox
36-
size={props.size}
37-
value="Label 2"
38-
aria-label="Label 2"
39-
onChange={(isSelected: boolean) =>
40-
// eslint-disable-next-line no-console
41-
console.log(isSelected, '###')
42-
}
43-
nativeID="checkbox-2"
44-
>
45-
<CheckboxIndicator>
46-
<CheckboxIcon />
47-
</CheckboxIndicator>
48-
<CheckboxLabel>Label 2</CheckboxLabel>
49-
</Checkbox>
50-
</CheckboxGroup>
20+
<Checkbox {...props}>
21+
<CheckboxIndicator>
22+
<CheckboxIcon as={CheckIcon} />
23+
</CheckboxIndicator>
24+
<CheckboxLabel>Label</CheckboxLabel>
25+
</Checkbox>
5126
);
5227
};
5328

@@ -61,4 +36,14 @@ export {
6136
CheckboxIndicator,
6237
CheckboxIcon,
6338
CheckboxLabel,
39+
Text,
40+
RemoveIcon,
41+
Icon,
42+
CheckIcon,
43+
FormControl,
44+
Center,
45+
VStack,
46+
HStack,
47+
Heading,
48+
Box,
6449
};

0 commit comments

Comments
 (0)