Skip to content

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 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.

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"`

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.


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.