CSS
Class names
BEM with a PascalCase block, every class prefixed, and state read from ARIA and data attributes.
Every class is BEM with a PascalCase block, and every block starts with Unmagic, so none
collides with your app's classes or Tailwind's utilities.
Blocks, elements and modifiers
- Block
UnmagicTooltip - The component: the outermost element a helper renders.
- Element
UnmagicTooltip__popup - A part of it, after two underscores. Elements don't nest in the name: a part inside a part is still Block__part.
- Modifier
UnmagicButton--primary - A variant, after two dashes, worn alongside the block: class="UnmagicButton UnmagicButton--primary".
A modifier comes from a helper's options, such as variant:, size: or
tone:, so you rarely write one by hand.
State comes from attributes
There are no state classes such as is-open or active. A component's state is styled
from the attributes its markup already carries for accessibility or for its script:
.UnmagicTabs__tab[aria-selected="true"],
.UnmagicTabs__tab[aria-current="page"] {
@apply bg-white text-neutral-900 dark:bg-neutral-700 dark:text-neutral-100;
}
.UnmagicClipboard[data-copied] .UnmagicClipboard__done {
@apply block;
}
So the markup, what a screen reader hears and what's on screen can't disagree. For state of your own, set
the attribute (aria-current="page", aria-invalid="true", disabled,
hidden) and the style follows.
Custom elements
Behaviour lives in custom elements named unmagic-* (<unmagic-tooltip>,
<unmagic-modal>). Most carry a block class as well. Those that only add behaviour, such as
UnmagicOptimistic and UnmagicAutoscroll, are display: contents, so
they don't take part in their parent's layout.
What's safe to target
Block and modifier names, and the ARIA and data- attributes a helper documents, are what the
components' own Ruby and JavaScript rely on, so they stay stable. Element names and the markup inside a
component can change between versions. To restyle part of a component, prefer the helper's options or a
class: on it over a selector for its insides.