diff --git a/packages/components/src/tailwind/Button/Button.stories.tsx b/packages/components/src/tailwind/Button/Button.stories.tsx index c5249a513a5..923fe5c6627 100644 --- a/packages/components/src/tailwind/Button/Button.stories.tsx +++ b/packages/components/src/tailwind/Button/Button.stories.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import { Button } from './Button'; import { BinIcon } from '../../components/icons/BinIcon'; import type { Meta, StoryObj } from '@storybook/react'; +import { SevenContext } from '../SevenContext/SevenContext'; const meta = { title: 'Tailwind/Button', @@ -145,3 +146,44 @@ export const WithTWClassName: Story = { accent: true, }, }; + +import { tv } from 'tailwind-variants'; + +export const buttonStyles = tv({ + base: '', + variants: { + variant: { + primary: 'bg-red-600 text-white', + }, + }, +}); + +export const Custom: Story = { + render: (args) => ( +
+ + + + + +
+ ), + args: { + customize: buttonStyles, + variant: 'primary', + accent: true, + }, +}; diff --git a/packages/components/src/tailwind/Button/Button.tsx b/packages/components/src/tailwind/Button/Button.tsx index ff98c541113..df236014ead 100644 --- a/packages/components/src/tailwind/Button/Button.tsx +++ b/packages/components/src/tailwind/Button/Button.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useContext } from 'react'; import { composeRenderProps, Button as RACButton, @@ -6,7 +6,8 @@ import { } from 'react-aria-components'; import { tv } from 'tailwind-variants'; import { focusRing } from '../utils'; - +import { SevenContext } from '../SevenContext/SevenContext'; +import { twMerge } from 'tailwind-merge'; export interface ButtonProps extends RACButtonProps { variant?: 'neutral' | 'primary' | 'destructive'; size?: 'S' | 'L'; @@ -67,17 +68,33 @@ const button = tv({ }); export function Button(props: ButtonProps) { + const tvvalues = useContext(SevenContext); return ( - button({ - ...renderProps, - variant: props.variant, - size: props.size, - accent: props.accent, - className, - }), + className={composeRenderProps( + props.className, + (className, renderProps) => { + const result = twMerge( + className, + button({ + ...renderProps, + variant: props.variant, + size: props.size, + accent: props.accent, + }), + tvvalues.button + ? tv(tvvalues.button as any)({ + ...renderProps, + // @ts-ignore + variant: props.variant, + size: props.size, + accent: props.accent, + }) + : '', + ); + return result; + }, )} /> ); diff --git a/packages/components/src/tailwind/Checkbox/Checkbox.tsx b/packages/components/src/tailwind/Checkbox/Checkbox.tsx index 5d08c1ff1bc..0e04a330770 100644 --- a/packages/components/src/tailwind/Checkbox/Checkbox.tsx +++ b/packages/components/src/tailwind/Checkbox/Checkbox.tsx @@ -1,4 +1,4 @@ -import React, { type ReactNode } from 'react'; +import React, { useContext, type ReactNode } from 'react'; import { CheckboxIcon, DashIcon } from '../../components/icons'; import { Checkbox as AriaCheckbox, @@ -11,6 +11,9 @@ import { import { tv } from 'tailwind-variants'; import { Description, FieldError, Label } from '../Field/Field'; import { composeTailwindRenderProps, focusRing } from '../utils'; +import { SevenContext } from '../SevenContext/SevenContext'; +import clsx from 'clsx'; +import { twMerge } from 'tailwind-merge'; export interface CheckboxGroupProps extends Omit { @@ -69,11 +72,28 @@ const iconStyles = 'w-4 h-4 text-white group-disabled:text-gray-400 dark:text-slate-900 dark:group-disabled:text-slate-600 forced-colors:text-[HighlightText]'; export function Checkbox(props: CheckboxProps) { + const tvvalues = useContext(SevenContext); + return ( - checkboxStyles({ ...renderProps, className }), + className={composeRenderProps( + props.className, + (className, renderProps) => { + const result = twMerge( + className, + checkboxStyles({ + ...renderProps, + }), + tvvalues.checkbox + ? tv(tvvalues.checkbox as any)({ + ...renderProps, + }) + : '', + ); + + return result; + }, )} > {({ isSelected, isIndeterminate, ...renderProps }) => ( diff --git a/packages/components/src/tailwind/SevenContext/SevenContext.stories.tsx b/packages/components/src/tailwind/SevenContext/SevenContext.stories.tsx new file mode 100644 index 00000000000..15c840065bb --- /dev/null +++ b/packages/components/src/tailwind/SevenContext/SevenContext.stories.tsx @@ -0,0 +1,52 @@ +import React from 'react'; +import { SevenContext } from './SevenContext'; +import { Button } from '../Button/Button'; +import type { Meta, StoryObj } from '@storybook/react'; +import { Checkbox } from '../Checkbox/Checkbox'; + +const meta = { + title: 'Tailwind/SevenContext', + component: SevenContext, + parameters: { + layout: 'centered', + backgrounds: { disable: true }, + }, + tags: ['autodocs'], + argTypes: {}, + args: {}, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Custom: Story = { + render: (args) => ( +
+ + + Customized + + + Basic +
+ ), + args: { + value: { + button: { + base: 'text-4xl', + variants: { + variant: { + primary: 'bg-red-600 text-white', + }, + }, + }, + checkbox: { + base: 'bg-red-600 text-4xl text-white px-2', + }, + }, + }, +}; diff --git a/packages/components/src/tailwind/SevenContext/SevenContext.tsx b/packages/components/src/tailwind/SevenContext/SevenContext.tsx new file mode 100644 index 00000000000..8b7dc06a0fa --- /dev/null +++ b/packages/components/src/tailwind/SevenContext/SevenContext.tsx @@ -0,0 +1,15 @@ +import { createContext } from 'react'; +import { tv } from 'tailwind-variants'; // Import tv to infer its type + +// Infer the type of the first argument to the 'tv' function +// This correctly captures the structure of the configuration object +type TvConfigType = Parameters[0]; + +interface context { + button?: TvConfigType; + checkbox?: TvConfigType; +} +export const SevenContext = createContext({ + button: {}, + checkbox: {}, +});