CoordiationCSS
Menu
Docs/Core concepts/Attribute selectors

VARIANTS · COMPLETE IN 0.2

Attribute and selector variants

Conditionally apply any Coordiation utility using accessible ARIA state, application data, descendant state, negation, or a literal custom selector.

This capability is registry-backed and exhaustively tested. Unknown boolean ARIA shortcuts and unsafe selector fragments are rejected instead of generating invalid CSS.

QUICK REFERENCE

Variant syntax

Variants are literal prefixes placed before a supported utility. They can be stacked with responsive, dark, group, peer, and state variants.

PatternSelector behavior
aria-expanded:co-*&[aria-expanded="true"]
aria-[sort=ascending]:co-*&[aria-sort="ascending"]
data-active:co-*&[data-active]
data-[state=open]:co-*&[data-state="open"]
has-checked:co-*&:has(:checked)
not-focus:co-*&:not(:focus)
[&.is-ready]:co-*&.is-ready

ARIA STATES

Style accessible state directly

Boolean ARIA shortcuts target the explicit value true. Supported names are busy, checked, disabled, expanded, hidden, pressed, readonly, required, selected.

HTML
<button
  aria-expanded="true"
  class="co-bg-white aria-expanded:co-bg-black aria-expanded:co-text-white"
>
  Menu
</button>
Generated CSS
.aria-expanded\:co-bg-black[aria-expanded="true"] {
  background-color: var(--co-color-black);
}

ARBITRARY VALUES

Match a specific attribute value

Use brackets when an ARIA or data attribute is not boolean. Underscores become spaces, and generated attribute values are quoted safely.

HTML
<th aria-sort="ascending" class="aria-[sort=ascending]:co-bg-black">
  Invoice
</th>

<div data-state="open" class="data-[state=open]:co-block">
  Panel content
</div>

GROUP AND PEER

Respond to parent or sibling attributes

Attribute conditions compose with named markers, keeping nested menus, tables, and form controls unambiguous.

HTML
<div class="co-group/menu" data-state="open">
  <button>Toggle menu</button>
  <div class="co-hidden group-data-[state=open]/menu:co-block">
    Menu content
  </div>
</div>

<input class="co-peer/email" aria-invalid="true" />
<p class="co-hidden peer-aria-[invalid=true]/email:co-block">
  Enter a valid email address.
</p>

DESCENDANTS AND NEGATION

Use has and not without template logic

has-* reacts to matching descendants. not-* applies a utility only when its condition does not match.

HTML
<label class="co-border has-checked:co-ring-2">
  <input type="checkbox" /> Enable notifications
</label>

<button class="not-focus:co-opacity-50">Save</button>
<article class="has-[img]:co-p-0">...</article>

ARBITRARY SELECTORS

Place the target with an ampersand

Wrap a one-off selector in brackets and use & where the generated utility selector belongs. Spaces are written as underscores so source scanning stays deterministic.

HTML
<li class="[&.is-dragging]:co-cursor-pointer">Draggable item</li>
<div class="[&_p]:co-mt-4">
  <p>Every nested paragraph receives margin.</p>
</div>

AI GENERATION CONTRACT

Keep selectors discoverable

Agents can inspect attributeVariantRegistry and validate concrete classes with compileCandidates().

  • Generate complete literal class strings; never concatenate a variant at runtime.
  • Prefer named boolean ARIA and data-existence variants over brackets.
  • Use brackets only for explicit values or one-off selectors.
  • Rejected candidates must be reported instead of silently replaced.