Styling
Four styling tools — all functions, no build step required.
sheet() — Scoped CSS Classes
Section titled “sheet() — Scoped CSS Classes”import { sheet, div, h2, p } from "@whisq/core";
const s = sheet({ card: { padding: "1.5rem", borderRadius: "12px", background: "#fff", boxShadow: "0 2px 8px rgba(0,0,0,0.1)", "&:hover": { background: "#f5f5f5" }, }, title: { fontSize: "1.25rem", fontWeight: 600 },});
div({ class: s.card }, h2({ class: s.title }, "Hello"), p("World"),)Classes are auto-scoped (e.g., wq0_card). A <style> tag is injected automatically.
styles() — Reactive Inline Styles
Section titled “styles() — Reactive Inline Styles”import { signal, styles, div } from "@whisq/core";
const dark = signal(false);
div({ style: styles({ padding: "1rem", background: () => dark.value ? "#111" : "#fff", color: () => dark.value ? "#fff" : "#111", }),}, "Content")cx() — Static Class Composition
Section titled “cx() — Static Class Composition”import { cx, div } from "@whisq/core";
div({ class: cx("btn", isPrimary && "btn-primary", isLarge && "btn-lg") })div({ class: cx("card", { active: true, disabled: false }) })rcx() — Reactive Class Composition
Section titled “rcx() — Reactive Class Composition”import { signal, rcx, div } from "@whisq/core";
const variant = signal("primary");
div({ class: rcx( "btn", () => variant.value === "primary" && "btn-primary", () => loading.value && "btn-loading", ),})theme() — Design Tokens
Section titled “theme() — Design Tokens”import { theme, sheet } from "@whisq/core";
theme({ color: { primary: "#4386FB", text: "#111827", bg: "#ffffff" }, space: { sm: "0.5rem", md: "1rem", lg: "1.5rem" }, radius: { md: "8px", lg: "12px" },});
// Use in sheet():const s = sheet({ card: { background: "var(--color-bg)", padding: "var(--space-lg)", borderRadius: "var(--radius-lg)", },});Using External CSS Frameworks
Section titled “Using External CSS Frameworks”Whisq renders real DOM elements — div() produces an actual <div>, button() produces a <button>. Any CSS framework that works with HTML works with Whisq.
Tailwind CSS
Section titled “Tailwind CSS”import { signal, div, button, span } from "@whisq/core";
const count = signal(0);
div({ class: "flex items-center gap-4 p-8 bg-gray-900 rounded-xl" }, button({ class: "w-10 h-10 rounded-lg bg-indigo-600 hover:bg-indigo-500 text-white font-bold", onclick: () => count.value--, }, "-"), span({ class: "text-3xl font-mono text-cyan-400" }, () => `${count.value}`), button({ class: "w-10 h-10 rounded-lg bg-indigo-600 hover:bg-indigo-500 text-white font-bold", onclick: () => count.value++, }, "+"),);Reactive classes work naturally:
div({ class: () => count.value > 0 ? "text-green-400 font-bold" : "text-red-400 font-bold",}, () => `${count.value}`);Plain CSS / CSS Modules
Section titled “Plain CSS / CSS Modules”Import a CSS file in your entry point and use class names directly:
import "./styles.css";import { div, p } from "@whisq/core";
div({ class: "card" }, p({ class: "card-title" }, "Hello"),);When to Use What
Section titled “When to Use What”| Approach | Best for |
|---|---|
sheet() | Component-scoped styles, no external deps |
styles() | Reactive inline styles |
| Tailwind / UnoCSS | Utility-first, rapid prototyping |
| Plain CSS | Existing stylesheets, CSS variables |
You can mix approaches — use sheet() for component logic and Tailwind for layout utilities in the same project.
Next Steps
Section titled “Next Steps”- Conditional Rendering — Show/hide UI reactively