はじめに
Constelaは、JSONで宣言的にUIを記述するコンパイラファーストのUIフレームワークです。
@constela/server v4.1.0で、サーバーサイドレンダリング(SSR)時にスタイル式を評価できるようになりました。
新機能
renderToStringにstylesオプションが追加され、スタイルプリセットを渡せるようになりました。これにより、スタイル式がSSR時に評価され、CSSクラス文字列として出力されます。
使い方
1. スタイルプリセットを定義
{
"styles": {
"button": {
"base": "px-4 py-2 rounded font-medium",
"variants": {
"variant": {
"primary": "bg-blue-500 text-white",
"secondary": "bg-gray-200 text-gray-800"
},
"size": {
"sm": "text-sm",
"lg": "text-lg px-6 py-3"
}
},
"defaultVariants": {
"variant": "primary",
"size": "sm"
}
}
}
}
2. ビューでスタイル式を使用
{
"view": {
"kind": "element",
"tag": "button",
"props": {
"className": {
"expr": "style",
"name": "button",
"variants": {
"variant": { "expr": "lit", "value": "primary" },
"size": { "expr": "lit", "value": "lg" }
}
}
},
"children": [
{ "kind": "text", "value": { "expr": "lit", "value": "Click me" } }
]
}
}
3. SSRでスタイルプリセットを渡す
import { renderToString } from '@constela/server';
import { compile } from '@constela/compiler';
const result = compile(ast);
if (!result.ok) throw new Error('Compilation failed');
const html = await renderToString(result.program, {
styles: ast.styles,
});
出力
<button class="px-4 py-2 rounded font-medium bg-blue-500 text-white text-lg px-6 py-3">
Click me
</button>
スタイルシステムの特徴
ConstelaのスタイルシステムはTailwind Variantsやclass-variance-authority(CVA)に似た設計です。
- base: 常に適用されるベースクラス
- variants: 条件に応じて適用されるクラスのマップ
- defaultVariants: バリアントが指定されない場合のデフォルト値
状態に応じた動的なスタイル切り替えも可能です:
{
"variants": {
"variant": { "expr": "state", "name": "buttonVariant" }
}
}
API
interface RenderOptions {
route?: {
params?: Record<string, string>;
query?: Record<string, string>;
path?: string;
};
imports?: Record<string, unknown>;
styles?: Record<string, StylePreset>; // v4.1.0で追加
}
interface StylePreset {
base: string;
variants?: Record<string, Record<string, string>>;
defaultVariants?: Record<string, string>;
}
まとめ
@constela/server v4.1.0で、SSR時にスタイル式が評価されるようになりました。renderToStringのstylesオプションにスタイルプリセットを渡すだけで、サーバーサイドでもクライアントと同じスタイルが適用されます。
Constelaに興味を持っていただけたら、ぜひ試してみてください。フィードバックやIssueもお待ちしています。