# Frameworks

Source: https://plumeria.dev/docs/integration/frameworks



Plumeria compiles the `css` calls, not the component. Any framework Vite can build reaches it through the same [`@plumeria/unplugin`](/docs/integration/vite) entry — put `plumeria.vite()` in `plugins` beside the framework plugin.

```ts title="vite.config.ts"
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import plumeria from '@plumeria/unplugin';

export default defineConfig({
  plugins: [vue(), plumeria.vite()],
});
```

That file is the whole integration. [`examples/vite-vue-ts`](https://github.com/zss-in-js/plumeria/tree/main/examples/example-vite-vue-ts), [`examples/vite-svelte-ts`](https://github.com/zss-in-js/plumeria/tree/main/examples/example-vite-svelte-ts), [`examples/vite-solid`](https://github.com/zss-in-js/plumeria/tree/main/examples/example-vite-solid), [`examples/vite-preact`](https://github.com/zss-in-js/plumeria/tree/main/examples/example-vite-preact), [`examples/vite-qwik`](https://github.com/zss-in-js/plumeria/tree/main/examples/example-vite-qwik), [`examples/react-router`](https://github.com/zss-in-js/plumeria/tree/main/examples/example-react-router) and [`examples/storybook`](https://github.com/zss-in-js/plumeria/tree/main/examples/example-storybook) are that file with the framework plugin swapped.

## The styling prop [#the-styling-prop]

`@plumeria/core/class-style` declares `classStyle` on React's `HTMLAttributes` and `SVGAttributes`, so anything rendering through the React namespace needs one line:

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

A framework that keeps its JSX types in its own module cannot be reached that way. Module augmentation resolves the package from the file that writes it, and `@plumeria/core` does not depend on your framework, so the declaration has to live in your project:

```ts title="types.d.ts"
import 'preact';
import type { Style } from '@plumeria/core';

declare module 'preact' {
  namespace JSX {
    interface HTMLAttributes {
      classStyle?: Style;
    }
    interface SVGAttributes {
      classStyle?: Style;
    }
  }
}
```

```ts title="types.d.ts"
import '@builder.io/qwik';
import type { Style } from '@plumeria/core';

declare module '@builder.io/qwik' {
  interface HTMLAttributes extends JSX.HTMLAttributes {
    classStyle?: Style;
  }
  interface SVGAttributes extends JSX.SVGAttributes {
    classStyle?: Style;
  }
}
```

Declare `SVGAttributes` even where the framework has it extend `HTMLAttributes` and one interface would do — Qwik's extends `AriaAttributes` instead, and an `<svg classStyle={...}>` under a declaration that covers only HTML is rejected outright.

The type is `Style`. A name the package does not export is not reported here, so a stale one leaves `classStyle` accepting anything at all rather than failing.

## Single-file components [#single-file-components]

The transform parses TypeScript and TSX. A `.vue`, `.svelte` or `.astro` file is neither, so `css.create` goes in a `.ts` module the component imports from:

```ts title="src/components/style.ts"
import * as css from '@plumeria/core';

export const styles = css.create({
  main: { color: 'teal' },
});
```

```html title="src/components/Card.vue"
<script setup lang="ts">
import { styles } from './style';
</script>

<template>
  <div :class="styles.main">card</div>
</template>
```

The lint rules read the same TypeScript, so the style module is covered by them.

The plugin receives the component file whole, before the framework splits its script block out, so a `css.create` written inside one fails the build on the surrounding markup:

```
[plugin @plumeria/unplugin:vite] src/components/HelloWorld.vue
Error:   x Expected '</', got ':'
```

A framework whose components are TSX — Qwik, Preact, Solid, React Router — has nowhere to put the call but the component, and needs no separate module.

## Qwik [#qwik]

`plumeria.vite()` goes before `qwikVite()`. The Qwik optimizer rewrites the component and re-exports what it finds there, so it has to run on styles that are already compiled away:

```ts title="vite.config.ts"
import { defineConfig } from 'vite';
import { qwikVite } from '@builder.io/qwik/optimizer';
import plumeria from '@plumeria/unplugin';

export default defineConfig({
  plugins: [plumeria.vite(), qwikVite({ csr: true })],
});
```

The other order fails the build with `Export 'styles' is not defined`.

## Astro [#astro]

Astro takes Vite plugins under `vite`:

```js title="astro.config.mjs"
import { defineConfig } from 'astro/config';
import react from '@astrojs/react';
import plumeria from '@plumeria/unplugin';

export default defineConfig({
  vite: {
    plugins: [plumeria.vite()],
  },
  integrations: [react()],
});
```

See [`examples/vite-astro-ts`](https://github.com/zss-in-js/plumeria/tree/main/examples/example-vite-astro-ts).

<Cards>
  <Card title="See more about Vite" href="/docs/integration/vite" />

  <Card title="See more about unplugin options" href="/docs/api-reference/plugins/unplugin" />
</Cards>
