Plumeria
Types

API

Style

API reference for the Style type

type Style = StyleList<StyleNamespace>;
export type { Style };

Style is the type of the classStyle prop and of every argument to css.use(). It accepts a style created by css.create, the falsy values false, null and undefined, and arrays nesting any of those.

Example

TypeScript
import * as css from '@plumeria/core';

const styles = css.create({
  base: {
    color: 'red',
  },
  active: {
    fontWeight: 'bold',
  },
});

export function Component({ active }: { active: boolean }) {
  return <div classStyle={[styles.base, active && styles.active]} />;
}

Only created styles are accepted

A style has to come out of css.create for the compiler to resolve it. An inline object is a type error:

<div classStyle={styles.base} />       // ok
<div classStyle={{ color: 'red' }} />  // Type error

The object css.create returns holds the styles rather than being one of them, so passing it whole is a type error as well:

<div classStyle={styles} />  // Type error

Declaring the styling prop

@plumeria/core ships no prop declaration of its own. classStyle comes from the declaration bundled with the package, which you reference from plumeria.d.ts:

plumeria.d.ts
/// <reference types="@plumeria/core/class-style" />

Exporting Style is what lets you name that prop yourself instead. Set styleProp in the build configuration, then declare the same name against React:

plumeria.d.ts
import type { Style } from '@plumeria/core';

declare global {
  namespace React {
    interface HTMLAttributes<T> {
      sx?: Style;
    }
    interface SVGAttributes<T> {
      sx?: Style;
    }
  }
}

The prop then behaves exactly like classStyle, arrays and falsy values included:

<div sx={[styles.text, cond && styles.cond]} />

The styleProp in the build configuration and the property name in plumeria.d.ts must match. If they disagree, the prop type-checks but is never compiled away. See Next.js or Vite for the configuration.

Any prop can carry a style

Style is not tied to a host element prop at all. Type any prop of your own component with it, and the compiler resolves the style through the call site, because prop styles are registered by component rather than by prop name:

TypeScript
import * as css from '@plumeria/core';

type CardProps = {
  boxStyle?: css.Style;
};

function Card({ boxStyle }: CardProps) {
  return <div classStyle={[styles.base, boxStyle]} />;
}

export function Example() {
  return <Card boxStyle={styles.active} />;
}

One style rather than a list

Style describes a list, so a prop typed with it can be handed an array, a conditional or nothing at all. A prop that instead takes exactly one created style, because the component reads a property off it, is AtomicStyle:

function Glyph({ glyphStyle }: { glyphStyle: css.AtomicStyle<{ color: string }> }) {
  return <svg fill="currentColor" className={glyphStyle.color} />;
}

That is the whole difference: Style is what a styling prop accepts, AtomicStyle is what a component can look inside.

It is also the name TypeScript writes when it emits a declaration for an exported style, so a package that ships styles compiles with declaration: true.

Good to know

Style accepts every property. To constrain what a component accepts through a style prop, use StyleProps, WithoutProperties or StaticStyles.

Edit on GitHub

On this page