:state()

Write :state(attr-…) or :state(state-…) in a component's <style> and REALM adds or removes that custom state on the host, through internals.states. Match it with :host(:state(…)) inside the component, or tag-name:state(…) from the page.

:host(:state(attr-variant-is-outline)) {
  border: 1px solid var(--border);
}
:host(:state(state-todo-remaining-gt-0)) .clear {
  display: none;
}

States

State Present while
attr-name The prop or attribute name is truthy
attr-name-is-value It equals value (compared as text)
attr-name-gt-n It is greater than n (as numbers)
attr-name-gte-n Greater than or equal to n
attr-name-lt-n Less than n
attr-name-lte-n Less than or equal to n
state-a-b The reference #a.b is truthy
state-a-b-is-value, -gt-n, -gte-n, -lt-n, -lte-n The same comparisons on #a.b
loading A fetch attribute request in the component is running

attr-… reads the prop's value when a prop uses that attribute, otherwise the attribute text (an absent attribute is null, so it is falsy). As with --state-*, dashes separate path segments in state-…, so use camelCase names.

REALM finds these states by scanning the text of the component's <style> and <link rel="stylesheet"> elements. Only names written there are maintained.

loading

:state(loading) is present while at least one request started by fetch attributes in the component's markup is running. The fetch element itself also gets aria-busy="true".

:host(:state(loading)) .results {
  opacity: 0.5;
}

Your own states

Add any other state from the script and match it the same way:

internals.states.add("expanded");
internals.states.delete("expanded");
:host(:state(expanded)) .details {
  display: block;
}

Example

Previewindex.htmllevel-badge.html
Level
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>:state() demo</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
  <script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
</head>
<body>
  <import-element from="./level-badge.html"></import-element>

  <level-badge level="2"></level-badge>
  <level-badge level="6"></level-badge>
  <level-badge level="9"></level-badge>
</body>
</html>
<custom-element name="level-badge">
  <script>
    const props = defineProps({ level: prop.number().int().min(0).max(10).default(0) });
  </script>

  <style>
    :host {
      display: inline-block;
      padding: calc(var(--spacing) * 1) calc(var(--spacing) * 3);
      border-radius: var(--radius-full);
      background: var(--muted);
      font-size: var(--text-sm);
    }
    :host(:state(attr-level-gte-5)) {
      background: var(--chart-4);
      color: var(--primary);
    }
    :host(:state(attr-level-gte-8)) {
      background: var(--destructive);
      color: var(--primary-foreground);
    }
  </style>

  Level <slot name="@level"></slot>
</custom-element>

Edit this page on GitHub · View as Markdown