Skip to main content

styled

Tool to create styled components.

github
View source code
import { styled } from '@uhg-abyss/web/tools/styled';

Object syntax only​

Write CSS using the object style syntax. The reasons for this are: performance, bundle size and developer experience (type checks and autocomplete suggestions for both properties and values).

const Button = styled('button', {
color: 'red',
fontSize: '14px',
'&:hover': {
color: 'black',
fontSize: '14px',
},
});

Element shorthands​

Every HTML and SVG tag is also available directly on styled, so a one-off element doesn't need a named component declared just to style it.

<styled.div css={{ display: 'flex', gap: '$web.semantic.spacing.scale.md' }}>
<styled.span css={{ color: '$web.semantic.color.text.brand' }}>
Hello
</styled.span>
</styled.div>

The css prop resolves design tokens exactly as it does on a component built with the call form, and each tag's component is created once and reused, so shorthands are safe to render inside a component body.

Tip

Prefer the call form instead when the component is reused or when it needs variants or dynamic styles.

Chaining selectors​

All chained selectors require the & sign.

const Button = styled('button', {
// all chained
'&:hover': {},
'&::before': {},
'&.class': {},
});

Prop interpolation vs. variants​

You can conditionally apply variants at the consumption level, including at different breakpoints.

const Button = styled('button', {
variants: {
color: {
violet: { backgroundColor: 'blueviolet' },
gray: { backgroundColor: 'gainsboro' },
},
},
});
() => <Button color="violet">Button</Button>;

Tokens and themes​

You can define tokens in the createTheme config file and seamlessly consume and access them directly in the Style Object.

See the Tokens documentation page for more information.

const Example = styled('div', {
backgroundColor: '$core.color.brand.100',
height: 100,
width: 100,
});

Focus rings​

You can use the focusRing property to add focus rings to your styled components.

const Example = styled('div', {
'&:focus-visible': {
focusRing: 'default',
},
});

Available focus ring styles:

OptionDescription
defaultStandard focus for most interactive elements. Includes outline with border radius.
boundingBorderUse when focus outline should align exactly with element borders.
activeImmediatelyUse for buttons and clickable elements to show focus on mouse click.
insetUse when focus should appear inside element boundaries (e.g., in tight layouts).
insetHighlightUse for form inputs and controls requiring prominent inset focus indication.
noneRemove all focus styles

Modifiers:

  • Add !alt to any style (e.g., focusRing: 'default !alt') to use the alternate focus color.
  • You can override the focus color by passing a token (e.g., focusRing: 'default $core.color.brand.100').

Global styles​

You can add global styles with the globalCss API.

import { globalCss } from '@uhg-abyss/web/tools/styled';
const globalStyles = globalCss({
body: {
margin: '0',
},
});
export function App() => {
globalStyles();
return <div>Your app</div>
}

Animations​

You can use the keyframes function to add animations

import { keyframes } from '@uhg-abyss/web/tools/styled';
const fadeIn = keyframes({
'0%': { opacity: '0' },
'100%': { opacity: '1' },
});
const Box = styled('div', {
animationName: fadeIn,
});

Dynamic/static​

When Emotion variants won't work and the CSS styling you need is variable, you can use the static and dynamic config in the styled tool. Place all of your static CSS along with variants, compoundVariants, and defaultVariants in the static config. The dynamic config accepts a function that returns any properties that are passed to the component. You can then use those props to handle dynamic styles like sizing and colors.

Tip

For the best results and performance, prefer using static variants over the dynamic function whenever possible.

Media queries​

The styled tool also supports media queries with Abyss's predefined breakpoints. You can use the ScreenQueries enum from the styled tool for convenience or provide your own custom strings.

import { ScreenQueries } from '@uhg-abyss/web/tools/styled';

This example uses the ScreenQueries enum:

This example uses the Abyss @screen string syntax:

This example uses custom media query strings:

Table of Contents