# Styling
> Style Wave components and build your own styled components.

Wave components accept `className` and `style` props, so you can style them with plain CSS, CSS Modules or any other approach you already use.

Wave also provides its own styling APIs: `styled()`, the `css` prop and `css()`. They give you design tokens, breakpoints and variants, with autocompletion in TypeScript. Prefer them when you customise Wave components or build your own.

## styled()

`styled()` creates a component with styles attached. Wave builds its own components with it. Pass it an HTML element or any component and a style object.
The style object is a superset of CSS: it takes all CSS properties and selectors, plus design tokens, breakpoints and utilities:

```jsx
import { styled } from '@volue/wave-react';

const Panel = styled('div', {
  // write standard CSS
  display: 'grid',

  // access design tokens
  backgroundColor: '$backgroundNeutralSubtle',
  padding: '$spacingM',

  // write responsive styles
  '@mqLargeAndUp': {
    padding: '$spacingL'
  },

  // use shorthand utilities
  mb: '$spacingXl'
});
```

> **Tip**
>
> When working in a TypeScript codebase our design token options will show up with autocompletion depending on the CSS property used.

Pass a Wave component to build on it. The new component keeps the props of the component it wraps:

```jsx
import { Flex, styled } from '@volue/wave-react';

const Toolbar = styled(Flex, {
  borderBottom: '1px solid $borderNeutralSubtle',
  padding: '$spacingS'
});

() => (
  <Toolbar main="space-between" cross="center">
    {children}
  </Toolbar>
);
```

In addition to the base component styles, `styled()` lets you define variants: styles that apply based on the props you pass.
Variants can be applied conditionally or responsively:

```jsx
import { styled } from '@volue/wave-react';

const Panel = styled('div', {
  display: 'grid',

  variants: {
    size: {
      small: { gap: '$spacingS' },
      large: { gap: '$spacingL' }
    },
    bordered: {
      true: { border: '1px solid $borderNeutralSubtle' }
    }
  }
});

() => (
  <Panel size={{ '@initial': 'small', '@mqLargeAndUp': 'large' }} bordered />
);
```

Use `styled()` by default: define the styles once, give them a name and reuse the component wherever you need it.

## css prop

Every Wave component, and every component you create with `styled()`, accepts a `css` prop. It takes the same style object and applies it as a class on that one instance. Unlike inline styles, it can use design tokens, breakpoints and utilities:

```jsx
import { Box } from '@volue/wave-react';

<Box
  css={{
    padding: '$spacingM',
    '@mqLargeAndUp': {
      padding: '$spacingL'
    }
  }}
/>;
```

> **Tip**
>
> [Box](https://next.wave-design-system.pages.dev/components/layout/box.md) is a plain `div` made with `styled()`. Use it when you need an element to style without creating a component.

Use the `css` prop for one-off adjustments to a single instance:

- When you repeat the same styles, move them into a `styled()` component.
- When styles depend on a condition, define variants instead of building the `css` object conditionally.
- When values change often, such as a position that follows the pointer, pass them in `style`. Each distinct `css` object adds a new CSS rule to the page, and the rule stays there.

> **Tip**
>
> Wave's styling APIs are built on [a fork of Stitches](https://github.com/Volue/stitches).

## css()

`css()` creates a reusable style function with the same object syntax and variants as `styled()`. Use it to share styles between components, or to style an element you don't create with `styled()`, such as a third-party component.

To share styles, compose the function into `styled()`, which renders its styles for you:

```jsx
import { css, styled } from '@volue/wave-react';

const cardCss = css({
  padding: '$spacingM',
  variants: { size: { small: { padding: '$spacingS' } } }
});

const CardRoot = styled('div', cardCss);
const CardLink = styled('a', cardCss, { textDecoration: 'none' });
```

To style another element, call the function and pass its `className` to the element. Render the `styles` of the call next to it: they carry the CSS for that class name when the page renders on the server:

```jsx
function CardChart({ size, ...props }) {
  const card = cardCss({ size });

  return (
    <>
      {card.styles}
      <ThirdPartyChart {...props} className={card.className} />
    </>
  );
}
```

## Server components

With [`WaveStyles`](https://next.wave-design-system.pages.dev/get-started/developing.md#server-rendering) set up, the `css` prop, `styled()` and `css()` work in [React Server Components](https://react.dev/reference/rsc/server-components) as they do in the browser: the CSS travels with the elements they style. Wave's own components are client components.

One exception: a styled server component cannot be the child of a component that passes its props to that child, such as the triggers of `Tooltip`, `Popover` and `Menu`, or `as={Slot}`. On the server, React renders a styled component as two nodes, its element and its `<style>` elements. Add `'use client'` to the file that defines the styled component, so that it reaches them as one element.
