Basic Usage
use-styled
allows you to create styled components declaratively, separating the style logic from the component logic. The main configuration is done through an object passed as the second argument to the useStyled
hook. Let’s explore the key properties:
The base
property defines the styles and props that will be applied unconditionally to the component. It’s useful for styles and attributes that don’t change, regardless of the variants.
You can pass any valid prop for the base element or component you are styling. This includes:
- Standard HTML attributes (e.g.,
type="button"
for a<button>
element) data-*
attributes (e.g.,data-testid="my-button"
)- Event handlers (e.g.,
onClick
for React,onPress
for React Native) - Any other prop that the base component accepts.
The best part is that you’ll have TypeScript IntelliSense to help autocomplete and validate these props!
import { useStyled } from 'use-styled';
const Button = useStyled('button', { base: { className: 'px-4 py-2 rounded font-semibold transition-colors', type: 'button', // Standard HTML attribute 'data-testid': 'basic-button', // data-* attribute // onClick: () => console.log('Clicked!'), // Event handler }, // ... other configurations});
In this example, besides the classes, the button will always have type="button"
and data-testid="basic-button"
.
variants
Section titled “variants”variants
allow you to define different styles or props based on specific properties passed to the component. Each key in the variants
object represents a variant property (e.g., intent
, size
), and its values define the styles for each possible variant value (e.g., primary
, secondary
for intent
).
Variant values can be strings, but they can also be booleans, which is great for variants representing binary states (on/off), such as disabled
, active
, or outlined
.
import { useStyled } from 'use-styled';
const Button = useStyled('button', { base: { /* ... */ }, variants: { intent: { primary: { className: 'bg-blue-500 text-white hover:bg-blue-600' }, secondary: { className: 'bg-gray-200 text-black hover:bg-gray-300' }, }, size: { small: { className: 'text-sm px-3 py-1' }, large: { className: 'text-lg px-6 py-3' }, }, disabled: { true: { className: 'opacity-50 cursor-not-allowed' }, // false (optional): can have specific styles when not disabled }, }, // ... other configurations});
// Usage:<Button intent="primary" size="large">Click Me</Button><Button intent="secondary" disabled>Cannot Click</Button>
Here, a Button
with intent="primary"
will have a blue background and white text, while intent="secondary"
will have a gray background and black text. The size
variant controls padding and font size. The boolean disabled
variant applies opacity and cursor styles when true
.
defaultVariants
Section titled “defaultVariants”If you want a variant to have a default value in case no corresponding prop is passed, use defaultVariants
.
import { useStyled } from 'use-styled';
const Button = useStyled('button', { base: { /* ... */ }, variants: { intent: { /* ... */ }, size: { /* ... */ }, }, defaultVariants: { intent: 'primary', size: 'small', }, // ... other configurations});
// Usage:<Button>Click Me</Button> // Will be `intent="primary"` and `size="small"` by default<Button intent="secondary">Another Button</Button> // Will be `intent="secondary"` and `size="small"`
compoundVariants
Section titled “compoundVariants”Sometimes, you need to apply specific styles only when a combination of variants is active. That’s what compoundVariants
are for. They receive an array of objects, where each object defines the variants
of the combination and the props
(usually className
or style
) to be applied.
import { useStyled } from 'use-styled';
const Button = useStyled('button', { base: { /* ... */ }, variants: { intent: { /* ... */ }, outlined: { true: { className: 'border bg-transparent' }, }, }, defaultVariants: { /* ... */ }, compoundVariants: [ { intent: 'primary', outlined: true, props: { className: 'border-blue-500 text-blue-500 hover:bg-blue-50', // Specific style for primary + outlined } }, { intent: 'secondary', outlined: true, props: { className: 'border-gray-500 text-gray-500 hover:bg-gray-100', // Specific style for secondary + outlined } }, ],});
// Usage:<Button intent="primary" outlined={true}>Primary Outlined</Button>
In this case, the combination intent="primary"
and outlined={true}
receives specific styles that override or complement the base styles and individual variant styles.
Next Steps: Structuring Components
Section titled “Next Steps: Structuring Components”Besides styling individual components with useStyled
, you might want to structure more complex components with distinct parts (like a Card with Header and Body). For this, explore the useSlot
hook, which facilitates the creation of Compound Components with a clean API.