Skip to content

Variants ​

Every component's class list is produced by a tv() recipe, and the recipes are exported. They do nothing but map props to class names — no Vue, no DOM, no state.

ts
import { buttonVariants, type ButtonVariants } from "@ropav/styles";

buttonVariants({ variant: "primary", size: "sm" });
// "rp-button rp-button--primary rp-button--sm"

That is useful in three places.

Styling an element the library does not render ​

A link that should look like a button, a native <button> inside a third-party widget, a cell rendered by a table you do not own:

vue
<script setup lang="ts">
import { buttonVariants } from "@ropav/styles";
</script>

<template>
  <RouterLink :class="buttonVariants({ variant: 'secondary' })" to="/docs">Docs</RouterLink>
</template>

You get the appearance and none of the behaviour — no press handling, no focus ring wiring, no pending state. For anything interactive, prefer the component.

Deriving the prop types ​

The recipe's own types are where a component's prop unions come from, so you can name them directly:

ts
import type { ButtonVariants } from "@ropav/styles";

type Size = ButtonVariants["size"]; // "xs" | "sm" | "md" | "lg"

Shipping less ​

Each recipe has its own subpath, so a bundler drops the rest:

ts
import { buttonVariants } from "@ropav/styles/components/button";

The CSS is per component too — see Installation.