Utilities and Recipes
Authoring APIs that compile to the same FIR and de-duplicate to shared atoms.
Facet has three authoring surfaces.
1) Utility strings in markup
bg-action
fg-on-action
p-inset-md
hover:bg-action-hover
focus-visible:ring
@md:px-inset-lg
ps-inset-lg
Prefix order is flexible: one or more variants (hover, focus-visible, @md, etc.), then
family-value, or a raw keyword.
Known utility families include:
bg,fg(color)p,px,py,ps,pe,gap(spacing)w,h,minw,maxw,minh,maxhradius,text,weight,leading,shadow,bw,fontring(flag)
Known states: hover, focus, focus-visible, focus-within, active, disabled.
Container keywords: @sm, @md, @lg (container-query breakpoints).
Arbitrary utility syntax uses brackets and uses _ as a space:
bg-[#ff0000]
p-[10px]
2) Typed fx() objects
Typed objects are lowered through the same FIR as utilities.
import { createAtomizer } from "facet";
const az = createAtomizer();
az.addFx({
bg: "action",
fg: "on-action",
p: "inset.md",
_hover: { bg: "action-hover" },
_focusVisible: { ring: true },
"@md": { px: "inset.lg" }
});
Arbitrary values are explicit and escaped:
{ fg: { raw: "#222222" }, p: { raw: "10px" } }
3) Recipes
Recipes let you define named variant combinations around typed objects.
import { defineRecipe, registerRecipe } from "facet";
const button = registerRecipe(az, defineRecipe({
base: { _focusVisible: { ring: true } },
variants: {
tone: {
primary: { bg: "action", fg: "on-action", _hover: { bg: "action-hover" } },
subtle: { bg: "bg", fg: "ink-muted" },
},
size: {
sm: { px: "inset.sm", py: "inset.md" },
lg: { px: "inset.lg", py: "inset.md" },
},
},
defaultVariants: { tone: "primary", size: "lg" },
}));
button.classesFor({ tone: "primary", size: "lg" });
Built output behavior
Utilities and fx() share vocabulary and token-to-FIR mapping, so identical declarations across
surfaces compile to identical classes.
scanSource reads class strings and literal fx({...}) from raw source (.jsx/.vue/.svelte/.html),
and reports non-static fx calls instead of silently dropping them.
Planned note
The source mentions parser breadth (comments and static extraction completeness) as a future production improvement area.