diff --git a/packages/ui/src/components/checkbox/checkbox.css.ts b/packages/ui/src/components/checkbox/checkbox.css.ts new file mode 100644 index 0000000..163b55e --- /dev/null +++ b/packages/ui/src/components/checkbox/checkbox.css.ts @@ -0,0 +1,100 @@ +import { + createGlobalThemeContract, + createTheme, + style, + styleVariants, +} from '@vanilla-extract/css'; +import { calc } from '@vanilla-extract/css-utils'; +import { type RecipeVariants, recipe } from '@vanilla-extract/recipes'; +import { alignItems, display, justifyContent } from '../../styles'; +import { globalVars, paletteTokens } from '../../theme.css'; + +const color = styleVariants(paletteTokens, (_, paletteTokenKey) => ({ + backgroundColor: globalVars.palette[paletteTokenKey], +})); + +const borderColor = styleVariants(paletteTokens, (_, paletteTokenKey) => ({ + borderColor: globalVars.palette[paletteTokenKey], +})); + +const sizeTokens = { + '1': '1', + '2': '2', + '3': '3', +}; + +const sizeVars = createGlobalThemeContract( + sizeTokens, + (value) => `favolink-checkbox-size-${value}`, +); + +const sizeClass = createTheme(sizeVars, { + '1': '16px', + '2': '24px', + '3': '32px', +}); + +const borderSizeVars = createGlobalThemeContract( + sizeTokens, + (value) => `favolink-checkbox-border-size-${value}`, +); + +const borderSizeClass = createTheme(borderSizeVars, { + '1': '1px', + '2': '1.5px', + '3': '2px', +}); + +const size = styleVariants(sizeVars, (_, sizeKey) => ({ + width: sizeVars[sizeKey], + height: sizeVars[sizeKey], + borderWidth: calc.multiply(borderSizeVars[sizeKey], 1.75), + borderRadius: calc.multiply(borderSizeVars[sizeKey], 3), +})); + +const base = style([ + sizeClass, + borderSizeClass, + display['inline-flex'], + alignItems.center, + justifyContent.center, + { + boxSizing: 'border-box', + padding: 0, + borderColor: globalVars.palette.gray800, + borderStyle: 'solid', + + selectors: { + '&[data-state="false"]': { + backgroundColor: 'transparent', + }, + }, + }, +]); + +export const checkboxVariants = recipe({ + base, + + variants: { + color, + borderColor, + size, + }, + + defaultVariants: { + color: 'black', + borderColor: 'gray700', + size: '1', + }, +}); + +export type CheckboxVariants = Exclude< + RecipeVariants, + undefined +>; + +export const icon = style({ + width: '100%', + height: '100%', + color: globalVars.palette.white, +}); diff --git a/packages/ui/src/components/checkbox/checkbox.tsx b/packages/ui/src/components/checkbox/checkbox.tsx new file mode 100644 index 0000000..d9bf8bd --- /dev/null +++ b/packages/ui/src/components/checkbox/checkbox.tsx @@ -0,0 +1,42 @@ +import * as Styles from './checkbox.css'; +import * as CheckboxPrimitive from './checkbox.primitive'; +import { CheckIcon } from '../../icons'; +import { type ComponentPropsWithout, forwardRef } from '../../system'; +import { cx } from '../../utils'; +import { type MarginVariants, extractMarginProps } from '../margin'; + +export type CheckboxProps = ComponentPropsWithout< + typeof CheckboxPrimitive.Root, + 'asChild' | 'children' | 'color' | 'defaultValue' +> & + MarginVariants & + Styles.CheckboxVariants; + +export const Checkbox = forwardRef< + CheckboxProps, + typeof CheckboxPrimitive.Root +>(function Checkbox(props, forwardedRef) { + const { className, color, borderColor, size, ...restProps } = + extractMarginProps(props); + + return ( + + + + + + ); +}); + +Checkbox.displayName = 'Checkbox'; diff --git a/packages/ui/src/components/checkbox/index.ts b/packages/ui/src/components/checkbox/index.ts index 24486f6..01f4784 100644 --- a/packages/ui/src/components/checkbox/index.ts +++ b/packages/ui/src/components/checkbox/index.ts @@ -1,2 +1,4 @@ -/* eslint-disable @stylistic/padding-line-between-statements, react-refresh/only-export-components */ +/* eslint-disable @stylistic/padding-line-between-statements */ export * as CheckboxPrimitive from './checkbox.primitive'; + +export { Checkbox, type CheckboxProps } from './checkbox';