Skip to main content

State Styling

Tosui's Box component supports state props for styling hover, focus, active, and disabled states.

State Props

Box accepts four state props that override base styles:

PropTriggered By
_hoverMouse hover
_focusKeyboard focus
_activeMouse press / active
_disabledDisabled state
import { Box } from "@tosui/react";

<Box
bg="surface"
p={4}
cursor="pointer"
_hover={{ bg: "primary-subtle" }}
>
Hover to highlight
</Box>

Combining States

Apply multiple state styles to a single element:

<Box
bg="surface"
p={4}
cursor="pointer"
_hover={{ bg: "primary-subtle" }}
_active={{ bg: "primary-default" }}
>
Click me
</Box>

When multiple states apply simultaneously (e.g., hover + active), they combine with later states taking precedence for conflicting properties.

Supported Properties by State

All style properties support all four states:

Category_hover_focus_active_disabled
Colors (color, bg, borderColor)YesYesYesYes
Spacing (p, m, etc.)YesYesYesYes
Sizing (w, h, etc.)YesYesYesYes
Layout (display, position, etc.)YesYesYesYes
Typography (fontSize, fontWeight, etc.)YesYesYesYes
OpacityYesYesYesYes
ShadowYesYesYesYes
Interactions (cursor, pointerEvents, userSelect)YesYesYesYes
Borders (border, borderX, borderY, etc.)YesYesYesYes
Roundness (rounded, roundedTop, etc.)YesYesYesYes
Flexbox/GridYesYesYesYes
Text (textAlign, whiteSpace)YesYesYesYes

Disabled State

Use _disabled to style elements when disabled:

<Box
as="button"
p={4}
bg="primary-default"
color="foreground-inverted"
cursor="pointer"
disabled
_hover={{ bg: "primary-emphasis" }}
_disabled={{
opacity: "faint",
cursor: "not-allowed",
bg: "surface"
}}
>
Submit
</Box>

The _disabled styles apply when the element has the disabled attribute or aria-disabled="true".

Responsive State Styling

State props support responsive values:

<Box
bg="surface"
p={4}
_hover={{
bg: { base: "primary-subtle", md: "primary-default" },
p: { base: 4, md: 6 }
}}
>
Different hover effect by screen size
</Box>

See the Responsive guide for more on breakpoints.

Built-in Component States

Interactive components like Button and Input have built-in state styling. You don't need to add state props—they're already styled:

// Button handles hover, active, focus, and disabled automatically
<Button>Click me</Button>
<Button disabled>Can't click</Button>

// Input handles focus and disabled automatically
<Input placeholder="Type here" />
<Input disabled placeholder="Disabled" />

Button States

Button applies these states automatically based on variant and colorScheme:

  • Hover: Slightly darker/lighter background
  • Active: Further emphasis
  • Focus: Focus ring for accessibility
  • Disabled: Reduced opacity, not-allowed cursor

Input States

Input applies these states automatically:

  • Focus: Border color change, focus ring
  • Disabled: Reduced opacity, different background

When to Use State Props

Use state props for:

  • Custom interactive elements built with Box
  • Hover effects on cards or list items
  • Custom buttons not using the Button component

Don't use state props for:

  • Standard Button, Input, Link (already styled)
  • Non-interactive content
  • Complex hover effects (use CSS modules instead)

Examples

Hoverable Card

<Box
as="article"
p={6}
bg="surface"
rounded="md"
shadow="sm"
cursor="pointer"
_hover={{ shadow: "md", bg: "primary-subtle" }}
>
<Heading fontSize="lg">Card Title</Heading>
<Text color="foreground-muted">Card description</Text>
</Box>

Interactive List Item

<Box
p={3}
cursor="pointer"
_hover={{ bg: "surface" }}
_active={{ bg: "primary-subtle" }}
>
List item content
</Box>

Custom Button

<Box
as="button"
px={4}
py={2}
bg="primary-default"
color="foreground-inverted"
rounded="md"
cursor="pointer"
_hover={{ bg: "primary-emphasis" }}
_active={{ bg: "primary-emphasis", opacity: "high" }}
_disabled={{ opacity: "faint", cursor: "not-allowed" }}
>
Custom Button
</Box>

Focus Ring

<Box
as="button"
p={4}
bg="surface"
rounded="md"
cursor="pointer"
_focus={{ shadow: "md", borderColor: "primary-default" }}
border="thin"
borderColor="border"
>
Focusable element
</Box>

CSS Pseudo-Classes

For more complex state styling, use CSS modules with standard pseudo-classes:

/* custom.module.css */
.customButton {
transition: all 0.15s ease;
}

.customButton:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

.customButton:active {
transform: translateY(0);
}

.customButton:focus-visible {
outline: 2px solid var(--t-color-primary-default);
outline-offset: 2px;
}
import styles from "./custom.module.css";

<Box className={styles.customButton} p={4} bg="surface" rounded="md">
Fancy button
</Box>

This approach is better for:

  • Transitions and animations
  • Transform effects
  • Focus rings with outline
  • Complex multi-property changes