Skip to content

Styling

Four styling tools — all functions, no build step required.

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.

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")
import { cx, div } from "@whisq/core";
div({ class: cx("btn", isPrimary && "btn-primary", isLarge && "btn-lg") })
div({ class: cx("card", { active: true, disabled: false }) })
import { signal, rcx, div } from "@whisq/core";
const variant = signal("primary");
div({
class: rcx(
"btn",
() => variant.value === "primary" && "btn-primary",
() => loading.value && "btn-loading",
),
})
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)",
},
});

Whisq renders real DOM elements — div() produces an actual <div>, button() produces a <button>. Any CSS framework that works with HTML works with Whisq.

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}`);

Import a CSS file in your entry point and use class names directly:

main.ts
import "./styles.css";
import { div, p } from "@whisq/core";
div({ class: "card" },
p({ class: "card-title" }, "Hello"),
);
ApproachBest for
sheet()Component-scoped styles, no external deps
styles()Reactive inline styles
Tailwind / UnoCSSUtility-first, rapid prototyping
Plain CSSExisting stylesheets, CSS variables

You can mix approaches — use sheet() for component logic and Tailwind for layout utilities in the same project.