Prose & kbd

A scope for text this system did not write - a changelog, a docs page, anything rendered from Markdown - and the element for a key the reader presses.

Reference

sk-prose

Everything else here styles markup an application composes deliberately. This styles markup that arrives as a blob, where nothing can put a class on the individual elements - so the scope does it from above. It is also the one place in the system with vertical rhythm: the reset zeroes every margin on purpose, because a system that ships default margins is one that every layout then has to fight, but long-form text is exactly the context where the spacing has to come from the content.

<div class="sk-prose" data-measure="true">{{ markdown }}</div>
AttributeTypeDefaultNotes
data-measure"true"-Caps the line at 68ch - characters, not pixels, so it tracks the font size. Opt-in, because a docs page in an already-narrow column has a measure and a second cap strands the text in the middle of its own container.
> * + *--The rhythm is one rule: the gap belongs BETWEEN two blocks, so it goes on the second and never on the first. That is what keeps a prose block flush with whatever sits above it, with no :first-child exception per element.
ul, ol--Markers come back. The reset removes them because every other list in this system is a menu, a nav or a set of cards - here they are actual lists.
table--display: block with overflow-x. A Markdown table has no wrapper to hang sk-table-wrap on, so the scroll container has to be the table's own box.

sk-kbd

A real <kbd>, which is the element for what the reader types. Reader modes and several screen readers announce it distinctly, and "press ctrl k" read as running prose is a sentence nobody can follow. Sized in em, like Badge, so a key inside a menu item is the size of that item's text rather than a fixed lump that wrecks the leading.

Press <kbd class="sk-kbd">Ctrl</kbd><kbd class="sk-kbd">K</kbd>
AttributeTypeDefaultNotes
Shortcut[]string-Binding only: one <kbd> per key. Taken already split rather than parsed from "Ctrl+K", because the separator differs by platform and a component that splits on "+" cannot render a shortcut containing one.
MenuItemProps.Shortcut[]string-Renders into the menu item's trailing slot, where the keys take that slot's muted colour so the hint does not compete with the label. A hint, not a binding - handling the key still needs the application's own script.

Examples

Prose

One blob of rendered Markdown, styled entirely by the scope around it.

Release 0.3.0

This release adds the components applications were building by hand on top of the system: a popover, a segmented control, a split button and a scope for long-form text.

Added

  • Popover - a panel of content attached to a control, filling the gap between Tooltip and Menu.
  • Segmented - radios that look like a button group, so a view toggle can live in a form.
  • Prose - this.
    • Markers come back inside the scope.
    • Code blocks scroll rather than stretching the article.

A design system that ships default margins is a design system every layout then has to fight - except here, where nothing else is around to do the arranging.

Notes

Bump the version with the stylesheet, since the mount path carries it.

const Version = "0.3.0"
ComponentReplaces
PopoverA tooltip with buttons in it
SegmentedA button group plus a hidden input
Show markup
<div class="sk-prose" data-measure="true">
  <h2>
    Release 0.3.0
  </h2>
  <p>
    This release adds the components applications were building by hand on top of the system: a popover, a segmented control, a split button and a scope for long-form text.
  </p>
  <h3>
    Added
  </h3>
  <ul>
    <li>
      <strong>
        Popover
      </strong>
      - a panel of content attached to a control, filling the gap between
      <code>
        Tooltip
      </code>
      and
      <code>
        Menu
      </code>
      .
    </li>
    <li>
      <strong>
        Segmented
      </strong>
      - radios that look like a button group, so a view toggle can live in a form.
    </li>
    <li>
      <strong>
        Prose
      </strong>
      - this.
      <ul>
        <li>
          Markers come back inside the scope.
        </li>
        <li>
          Code blocks scroll rather than stretching the article.
        </li>
      </ul>
    </li>
  </ul>
  <blockquote>
    <p>
      A design system that ships default margins is a design system every layout then has to fight - except here, where nothing else is around to do the arranging.
    </p>
  </blockquote>
  <h3>
    Notes
  </h3>
  <p>
    Bump the version with the stylesheet, since
    <a href="#prose">
      the mount path carries it
    </a>
    .
  </p>
  <pre>
    <code>
      const Version = &#34;0.3.0&#34;
    </code>
  </pre>
  <table>
    <thead>
      <tr>
        <th>
          Component
        </th>
        <th>
          Replaces
        </th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>
          Popover
        </td>
        <td>
          A tooltip with buttons in it
        </td>
      </tr>
      <tr>
        <td>
          Segmented
        </td>
        <td>
          A button group plus a hidden input
        </td>
      </tr>
    </tbody>
  </table>
</div>

Keys

PressCtrlK to search, orEsc to close anything that is open.


Show markup
<div class="sk-flex sk-flex-col sk-gap-5">
  <p>
    Press
    <kbd class="sk-kbd">
      Ctrl
    </kbd>
    <kbd class="sk-kbd">
      K
    </kbd>
    to search, or
    <kbd class="sk-kbd">
      Esc
    </kbd>
    to close anything that is open.
  </p>
  <div class="sk-flex sk-flex-wrap sk-gap-3">
    <button class="sk-button" type="button" data-variant="neutral" data-size="md" popovertarget="kbd-menu">
      File
      <svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
        <path d="m6 9 6 6 6-6">
        </path>
      </svg>
    </button>
    <div class="sk-menu" id="kbd-menu" popover aria-label="File">
      <button type="button" class="sk-menu-item">
        New build
        <span class="sk-menu-item-detail">
          <kbd class="sk-kbd">
            Ctrl
          </kbd>
          <kbd class="sk-kbd">
            N
          </kbd>
        </span>
      </button>
      <button type="button" class="sk-menu-item">
        Save
        <span class="sk-menu-item-detail">
          <kbd class="sk-kbd">
            Ctrl
          </kbd>
          <kbd class="sk-kbd">
            S
          </kbd>
        </span>
      </button>
      <button type="button" class="sk-menu-item">
        Recent builds
        <span class="sk-menu-item-detail">
          412
        </span>
      </button>
      <hr class="sk-menu-separator">
      <button type="button" class="sk-menu-item" data-status="danger">
        Delete project
        <span class="sk-menu-item-detail">
          <kbd class="sk-kbd">
            Ctrl
          </kbd>
          <kbd class="sk-kbd">
            Del
          </kbd>
        </span>
      </button>
    </div>
  </div>
</div>