Styling
CSS has hundreds of properties, and a browser silently ignores a typo in any of them. In chimera a style is a Luwu table whose values Luwu's type function validators check during analysis: padding = "1rx" is a type error, and dispaly = "flex" gets a "did you mean". Styles can also read theme tokens, and then they follow the reader's theme with no extra CSS.
One element
style sets an element's inline style:
Back up your saves before updating.
const note = Paragraph("Back up your saves before updating.")
:style({
padding = "0.75rem 1rem",
background = token("surface"),
border_left = `4px solid {token("accent")}`,
border_radius = token("radius"),
})
Keys are CSS property names with underscores instead of dashes. Keyword properties like display only accept their real values, while lengths also take plain numbers like margin = 0. Vendor prefixes start with webkit_ or moz_, and custom properties go in brackets: ["--gap"] = "1rem".
Theme tokens
token("accent") stands for var(--chimera-accent), the current theme's accent color. When the reader switches themes, every style that uses it changes with them. These are the tokens every theme sets:
background surface text muted border
primary primary_text accent
radius spacing font mono_font shadow
syntax_keyword syntax_string syntax_comment ... syntax_error
token("radius"):times(1.5) scales a length token, and token("primary"):mix(token("background"), 20) blends 20% of one color token into another.
Colors
Tinted
const swatch = Paragraph("Tinted")
:style({
padding = "0.5rem 1rem",
color = Color.named("white"),
background = Color.hex("#3b5bdb"):mix(Color.named("black"), 0.25),
border_radius = token("radius"):times(2),
})
Color.hex checks its literal while you type, and Color.named takes any CSS color name. Colors also convert to and from vectors, packed numbers, buffers and ANSI codes.
Inside one element
style_inside styles the matching elements inside one element and leaves the rest of the page alone:
const credits = Footer({ Small("Art by Nyla."), Link("More art", "#") })
:row()
:style_inside(Link, { color = token("muted") })
Every element of a kind
style_every on a Document or a Site styles everything that matches an element class or a CSS selector. These rules come after the theme's and win over them:
site
:style_every(Button, { border_radius = "999px" })
:style_every(Card, { padding = "2rem" })
:style_every(".hero h1", { font_size = "3rem" })
Rules and stylesheets
A Rule pairs a selector with a style. For media queries, nest rules inside one:
document:css({
Rule("nav a", { color = token("text") }),
Rule("@media (max-width: 600px)", {}, {
Rule("nav", { flex_direction = "column" }),
}),
})
document:css(text) also takes plain CSS, and link_stylesheet(href) links a stylesheet file. Going the other way, Rule.parse and Style.parse read CSS back into objects.
Styles that a component always needs belong in the component itself, as Custom components shows.