From 03a6fded162ab85272c53f581f9d11d2a170de35 Mon Sep 17 00:00:00 2001 From: Rajat Chaudhary Date: Thu, 29 Feb 2024 10:55:35 +0530 Subject: [PATCH] feat: added nativewind checkbox component examples --- .../nativewind/Checkbox/index.tsx | 157 +++-- .../components/Checkbox/Checkbox.stories.tsx | 10 + .../src/components/Checkbox/Checkbox.tsx | 63 +- .../components/Checkbox/index.nw.stories.mdx | 545 +++++++++++++++++- 4 files changed, 672 insertions(+), 103 deletions(-) diff --git a/example/storybook-nativewind/src/components-example/nativewind/Checkbox/index.tsx b/example/storybook-nativewind/src/components-example/nativewind/Checkbox/index.tsx index 695c99dcde..ac86639bf5 100644 --- a/example/storybook-nativewind/src/components-example/nativewind/Checkbox/index.tsx +++ b/example/storybook-nativewind/src/components-example/nativewind/Checkbox/index.tsx @@ -2,16 +2,15 @@ import React from 'react'; import { createCheckbox } from '@gluestack-ui/checkbox'; import { View, Pressable, Text } from 'react-native'; import { - cn, withStates, withStyleContextAndStates, useStyleContext, tva, withStyleContext, cssInterop, + VariantProps, } from '@gluestack-ui/nativewind-utils'; import { Platform } from 'react-native'; - import { Check } from 'lucide-react-native'; const UICheckbox = createCheckbox({ @@ -20,10 +19,10 @@ const UICheckbox = createCheckbox({ Platform.OS === 'web' ? withStyleContext(View) : withStyleContextAndStates(Pressable), - Group: Platform.OS === 'web' ? View : withStates(View), - Icon: Platform.OS === 'web' ? Check : withStates(Check), - Label: Platform.OS === 'web' ? Text : withStates(Text), - Indicator: Platform.OS === 'web' ? View : withStates(View), + Group: withStates(View), + Icon: withStates(Check), + Label: withStates(Text), + Indicator: withStates(View), }); cssInterop(UICheckbox, { className: 'style' }); @@ -32,35 +31,62 @@ cssInterop(UICheckbox.Icon, { className: 'style' }); cssInterop(UICheckbox.Label, { className: 'style' }); cssInterop(UICheckbox.Indicator, { className: 'style' }); -const checkboxIndicator = tva({ - 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', +const checkboxStyle = tva({ + base: 'group/checkbox flex-row items-center justify-start gap-2 web:cursor-pointer data-[disabled=true]:cursor-not-allowed', +}); + +const checkboxIndicatorStyle = tva({ + 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', parentVariants: { size: { - lg: 'w-6 h-6 border-4', + lg: 'w-6 h-6 border-[3px]', md: 'w-5 h-5 border-2', sm: 'w-4 h-4 border-2', }, }, }); -const checkboxLabel = tva({ - base: 'text-typography-600', +const checkboxLabelStyle = tva({ + 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', parentVariants: { size: { lg: 'text-lg', - md: 'text-md', + md: 'text-base', sm: 'text-sm', }, }, }); +const checkboxIconStyle = tva({ + base: 'group-data-[checked=true]/checkboxInd:text-typography-0 data-[disabled=true]:opacity-40', + + parentVariants: { + size: { + sm: 'h-3 w-3', + md: 'h-4 w-4', + lg: 'h-5 w-5', + }, + }, +}); + const CheckboxGroup = UICheckbox.Group; +type ICheckboxProps = React.ComponentProps & + VariantProps; const Checkbox = React.forwardRef( - ({ className, size = 'sm', ...props }: any, ref) => { + ( + { + className, + size = 'md', + ...props + }: { className?: string } & ICheckboxProps, + ref + ) => { return ( & + VariantProps; const CheckboxIndicator = React.forwardRef( - ({ className, ...props }: any, ref) => { + ( + { className, ...props }: { className?: string } & ICheckboxIndicatorProps, + ref + ) => { const { size: parentSize } = useStyleContext(); return ( { - const { size: parentSize } = useStyleContext(); - return ( - - ); -}); +type ICheckboxLabelProps = React.ComponentProps & + VariantProps; +const CheckboxLabel = React.forwardRef( + ( + { className, ...props }: { className?: string } & ICheckboxLabelProps, + ref + ) => { + const { size: parentSize } = useStyleContext(); + return ( + + ); + } +); -const CheckboxIcon = React.forwardRef(({ className, ...props }: any, ref) => { - return ( - - ); -}); +type ICheckboxIconProps = React.ComponentProps & { + as?: any; +}; +const CheckboxIcon = React.forwardRef( + ( + { + className, + as: AsComp, + ...props + }: ICheckboxIconProps & { className?: any }, + ref + ) => { + const { size: parentSize } = useStyleContext(); + if (AsComp) { + return ( + + + + ); + } + + return ( + + ); + } +); // Assign display names Checkbox.displayName = 'Checkbox'; diff --git a/example/storybook-nativewind/src/components/Checkbox/Checkbox.stories.tsx b/example/storybook-nativewind/src/components/Checkbox/Checkbox.stories.tsx index f2ae4d5b58..199ae0f168 100644 --- a/example/storybook-nativewind/src/components/Checkbox/Checkbox.stories.tsx +++ b/example/storybook-nativewind/src/components/Checkbox/Checkbox.stories.tsx @@ -14,9 +14,19 @@ const CheckboxMeta: ComponentMeta = { control: 'select', options: ['sm', 'md', 'lg'], }, + isDisabled: { + control: 'boolean', + options: [true, false], + }, + isInvalid: { + control: 'boolean', + options: [true, false], + }, }, args: { size: 'md', + isDisabled: false, + isInvalid: false, }, }; diff --git a/example/storybook-nativewind/src/components/Checkbox/Checkbox.tsx b/example/storybook-nativewind/src/components/Checkbox/Checkbox.tsx index 240f91ce64..bad00ef33c 100644 --- a/example/storybook-nativewind/src/components/Checkbox/Checkbox.tsx +++ b/example/storybook-nativewind/src/components/Checkbox/Checkbox.tsx @@ -6,48 +6,23 @@ import { CheckboxLabel, CheckboxGroup, } from '@/components/ui/Checkbox'; +import { Text } from '@/components/ui/Text'; +import { RemoveIcon, Icon, CheckIcon } from '@/components/ui/Icon'; +import { FormControl } from '@/components/ui/FormControl'; +import { Center } from '@/components/ui/Center'; +import { VStack } from '@/components/ui/VStack'; +import { HStack } from '@/components/ui/HStack'; +import { Heading } from '@/components/ui/Heading'; +import { Box } from '@/components/ui/Box'; const CheckboxGroupBasic = ({ ...props }: any) => { - const [values, setValues] = React.useState(['Label 1']); - return ( - - - // eslint-disable-next-line no-console - console.log(isSelected, '###') - } - nativeID="checkbox-1" - > - - - - Label 1 - - - // eslint-disable-next-line no-console - console.log(isSelected, '###') - } - nativeID="checkbox-2" - > - - - - Label 2 - - + + + + + Label + ); }; @@ -61,4 +36,14 @@ export { CheckboxIndicator, CheckboxIcon, CheckboxLabel, + Text, + RemoveIcon, + Icon, + CheckIcon, + FormControl, + Center, + VStack, + HStack, + Heading, + Box, }; diff --git a/example/storybook-nativewind/src/components/Checkbox/index.nw.stories.mdx b/example/storybook-nativewind/src/components/Checkbox/index.nw.stories.mdx index 681784ee14..cf9b7252d0 100644 --- a/example/storybook-nativewind/src/components/Checkbox/index.nw.stories.mdx +++ b/example/storybook-nativewind/src/components/Checkbox/index.nw.stories.mdx @@ -20,17 +20,18 @@ import { CheckboxIndicator, CheckboxIcon, CheckboxLabel, -} from './Checkbox'; -import { Text, RemoveIcon, - FormControl, Icon, CheckIcon, -} from '@gluestack-ui/themed'; + FormControl, + Center, + VStack, + HStack, + Heading, + Box, +} from './Checkbox'; import { useState, useRef } from 'react'; -import { Center, VStack } from '@gluestack-ui/themed'; -import { HStack, Heading, Box } from '@gluestack-ui/themed'; import { transformedCode } from '../../utils'; import { AppProvider, @@ -104,9 +105,7 @@ npm i @gluestack-ui/checkbox ### Step 2: Copy and paste the following code into your project. - ```jsx - %%-- File: components-example/nativewind/Checkbox/index.tsx --%% - ``` + ```jsx %%-- File: components-example/nativewind/Checkbox/index.tsx --%% ``` ### Step 3: Update the import paths to match your project setup. @@ -483,17 +482,521 @@ We have outlined the various features that ensure the Checkbox component is acce Checkbox component is created using Pressable component from react-native. It extends all the props supported by [React Native Pressable](https://reactnative.dev/docs/pressable#props). - +The Examples section provides visual representations of the different variants of the component, allowing you to quickly and easily determine which one best fits your needs. Simply copy the code and integrate it into your project. + +#### Multiple Checkbox + +Checkbox provide a mutually exclusive selection mechanism, allowing users to choose a multiple option from a set of related choices. + + + { + setValues(keys) + }}> + + + + + + Framer + + + + + + Invision Studio + + + + + + Adobe XD + + + + ) + } + `, + transformCode: (code) => { + return transformedCode(code, 'function', 'App'); + }, + scope: { + Checkbox, + CheckboxGroup, + CheckboxIndicator, + CheckboxIcon, + CheckboxLabel, + Wrapper, + Center, + CheckIcon, + Icon, + VStack, + useState, + }, + argsType: {}, + }} + /> + + +#### Horizontal + +A horizontal component incorporating a checkbox allows for intuitive and space-efficient selection of multiple options within a linear layout. + + + { + setValues(keys) + }}> + + + + + + Illustration + + + + + + Animation + + + + + + Typography + + + + ) + } +`, + transformCode: (code) => { + return transformedCode(code, 'function', 'App'); + }, + scope: { + Wrapper, + CheckIcon, + Icon, + Checkbox, + CheckboxGroup, + CheckboxIndicator, + CheckboxIcon, + CheckboxLabel, + HStack, + useState, + }, + argsType: {}, + }} + /> + + +#### With help text + +A checkbox component with help text provides informative guidance alongside selectable options, ensuring clarity and ease of use. + + + { + setValues(keys) + }}> + + + + + + + Design + + Subscribe to updates from the Design Feed + + + + + + + Marketing + + Subscribe to updates from the Marketing Feed + + + + ) + } +`, + transformCode: (code) => { + return transformedCode(code, 'function', 'App'); + }, + scope: { + Wrapper, + CheckIcon, + Icon, + Checkbox, + CheckboxGroup, + CheckboxIndicator, + CheckboxIcon, + CheckboxLabel, + HStack, + VStack, + Text, + Box, + useState, + }, + argsType: {}, + }} + /> + + +#### Form Control + +A checkbox component integrated with form control enhances the user experience by enabling easy selection and submission of options within a structured input context. + + + + + Sign up for newsletters + + + + + Daily Bits + + + + + + Event Updates + + + + + + Sponsorship + + Subscribe to newsletters for updates + + + `, + transformCode: (code) => { + return transformedCode(code); + }, + scope: { + Checkbox, + CheckboxGroup, + CheckboxIndicator, + CheckboxIcon, + CheckboxLabel, + Wrapper, + Center, + CheckIcon, + Icon, + Text, + VStack, + Heading, + FormControl, + }, + argsType: {}, + }} + /> + + +#### Label left + +A checkbox component with Label left configuration aligns the label to the left, facilitating clear association between the option and its corresponding checkbox. + + + { + setValues(keys) + }}> + + + Jane Cooper + + + + + + Wade Warren + + + + + + Robert Fox + + + + + + + ) + }`, + transformCode: (code) => { + return transformedCode(code, 'function', 'App'); + }, + scope: { + Checkbox, + CheckboxGroup, + CheckboxIndicator, + CheckboxIcon, + CheckboxLabel, + Wrapper, + Center, + CheckIcon, + Icon, + VStack, + HStack, + useState, + }, + argsType: {}, + }} + /> + + +#### Controlled + +A controlled component architecture incorporates a checkbox component, allowing for precise management of its state and behavior through explicit control mechanisms. + + + { + setValues(keys); + }}> + + + + + + UX Research + + + + + + Software Development + + + + ) + } + `, + transformCode: (code) => { + return transformedCode(code, 'function', 'App'); + }, + scope: { + Wrapper, + CheckIcon, + Icon, + Checkbox, + CheckboxGroup, + CheckboxIndicator, + CheckboxIcon, + CheckboxLabel, + useState, + Center, + VStack, + }, + argsType: {}, + }} + /> + + +#### Uncontrolled + +An uncontrolled component utilizes a checkbox component, providing a simpler implementation where the checkbox state is managed internally, without explicit control from external sources. + + + { + e.preventDefault(); + const checkboxValue = radioRef.current.checked; + }; + return ( + + + + + + + Apartments + + + + + + Residents + + + + ) + } + `, + transformCode: (code) => { + return transformedCode(code, 'function', 'App'); + }, + scope: { + Wrapper, + CheckIcon, + Icon, + Checkbox, + CheckboxGroup, + CheckboxIndicator, + CheckboxIcon, + CheckboxLabel, + useRef, + Center, + VStack, + }, + argsType: {}, + }} + /> + + +#### Checkbox group + +The checkbox group component allows users to group checkbox and display them in a horizontal or vertical row for better visual representation and functionality. + + + + + + + + + + Label 1 + + + + + + Label 2 + + + + + ); +}; +`, + transformCode: (code) => { + return transformedCode(code, 'function', 'CheckboxExample'); + }, + scope: { + Checkbox, + CheckboxGroup, + CheckboxIndicator, + CheckboxIcon, + CheckboxLabel, + Wrapper, + Center, + CheckIcon, + VStack, + }, + argsType: {}, + }} + /> +