`,
+ );
+
+ // Full width — --block stretches unconditionally; --block-cq only inside a
+ // query container narrower than 20rem, so it's shown inside a 16rem container
+ // (dashed) where it actually fills its width.
+ // align-items:flex-start so buttons size to content — only --block (explicit
+ // 100%) and the block-cq inside the 16rem query container actually stretch.
+ const widths = well(`
+
+
+
+
+
+
+
`);
+
+ // States — default, disabled, loading.
const states = well(cluster(
btn("sf-btn--primary", "Default"),
``,
``,
));
+ // A rich card that exercises the full slot API: media, avatar header,
+ // title, body and a footer action row. Media/avatar use a token-driven
+ // gradient (no external asset) so they re-tint live with the colour panel.
+ const swatch = "var(--sf-gradient-primary, var(--sf-color-primary))";
+ const mediaCard = `
+
+
+
+
+
+
Media card
+ __media · __avatar · __title
+
+
+
+
Composed from the full card slot API. Every dimension — padding, radius, gap, media ratio, avatar size — is token-driven and reacts live.
+
+ `;
+
+ // The three shipped card modifiers, side by side.
const card = (mods: string, title: string, body: string, btnMods: string, action: string) =>
`
${esc(title)}
${esc(body)}
`;
- const cards = grid(
- 16,
- card("", "Base card", "Default surface, radius, border and text tokens.", "sf-btn--primary sf-btn--s", "Open"),
- card("sf-card--bordered", "Bordered card", "The shipped bordered modifier for clearer structure.", "sf-btn--outline sf-btn--s", "Details"),
- card("sf-card--elevated sf-card--interactive", "Interactive card", "Elevation and interaction states react to tokens.", "sf-btn--soft sf-btn--s", "Select"),
+ const cardModifiers = grid(
+ 15,
+ card("", "Base", "Default surface, radius, border and shadow.", "sf-btn--primary sf-btn--s", "Open"),
+ card("sf-card--bordered", "Bordered", "Keeps the border, drops the shadow.", "sf-btn--outline sf-btn--s", "Details"),
+ card("sf-card--elevated sf-card--interactive", "Interactive", "Elevated, with a hover/focus lift.", "sf-btn--soft sf-btn--s", "Select"),
);
return page(
"Components",
- "Buttons and cards — every family, style, the full XS–XL size scale and states. This is where the size-scale knobs in the Components panel show their effect immediately.",
- section("Button families", families),
- section("Styles", stylesRow),
- section("Size scale (xs · s · default · l · xl)", sizes, "Global Padding / Min-height / Label-size knobs override this whole scale."),
+ "Buttons and cards built from the real .sf-btn / .sf-card classes — every family and style, the full XS–XL size ladder, states, full-width and the card slot API. Edit the Components panel and each specimen reacts live.",
+ section("Button families", families, `${BTN_FAMILIES.length} shipped colour families`),
+ section("Styles", styles, "fill · soft · outline · gradient"),
+ section("Size scale (xs · s · default · l · xl)", sizes, "Each rung has its own font-size, padding and min-height knob (Components panel ▸ Per-size); the Label-size multiplier scales the whole ladder proportionally."),
+ section("Full width", widths, "sf-btn--block stretches to the container; sf-btn--block-cq does so only in a narrow query container."),
section("States", states),
- section("Cards", cards),
+ section("Card — full slot API", mediaCard),
+ section("Card modifiers", cardModifiers, "base · bordered · elevated + interactive"),
);
}