Skip to main content

priv/static/design-system.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Design System Reference</title>
  <link rel="stylesheet" href="./css/rulestead_admin.css">
  <style>
    .swatch {
      display: inline-block;
      width: 80px;
      height: 48px;
      border: 1px solid rgba(128,128,128,0.3);
      border-radius: 4px;
      margin: 2px;
      vertical-align: top;
    }
    .swatch-label {
      font-size: 0.68rem;
      color: var(--rs-text-muted);
      margin-top: 0.2rem;
      text-align: center;
      max-width: 80px;
      word-break: break-all;
    }
    .swatch-group {
      display: inline-flex;
      flex-direction: column;
      align-items: center;
      margin: 0.25rem;
      vertical-align: top;
    }
    .ds-section {
      margin-bottom: 2rem;
    }
    .ds-section-heading {
      font-size: var(--rs-text-sm);
      font-weight: var(--rs-weight-semibold);
      color: var(--rs-text-muted);
      text-transform: uppercase;
      letter-spacing: var(--rs-tracking-wide);
      margin: 0 0 0.75rem;
      padding-bottom: 0.4rem;
      border-bottom: 1px solid var(--rs-border-subtle);
    }
    .ds-row {
      display: flex;
      gap: 0.5rem;
      flex-wrap: wrap;
      align-items: flex-start;
    }
    body { margin: 0; padding: 0; }
    #outside-shell-probe {
      padding: 1rem;
      font-family: sans-serif;
      font-size: 0.875rem;
      color: #333;
    }
  </style>
</head>
<body>

<div class="rs-shell" id="shell">
  <header class="rs-shell__header">
    <div>
      <a href="#" class="rs-shell__brand" aria-label="Rulestead">
        <img class="rs-shell__fixture-wordmark rs-shell__fixture-wordmark--light" src="./images/rs-wordmark.svg" alt="" aria-hidden="true">
        <img class="rs-shell__fixture-wordmark rs-shell__fixture-wordmark--dark" src="./images/rs-wordmark-dark.svg" alt="" aria-hidden="true">
        <span class="rs-shell__brand-text">Rulestead</span>
      </a>
      <h1 class="rs-shell__title">Design System Reference</h1>
      <p class="rs-shell__summary">Complete token, logo, and contrast fixture for light, dark, and system mode regression gates.</p>
    </div>
    <section class="rs-shell__context">
      <p class="rs-shell__context-label">Access</p>
      <div class="rs-shell__context-item">admin</div>
    </section>
  </header>
  <div class="rs-shell__layout">
    <nav class="rs-shell__rail">
      <div class="rs-shell__rail-group">
        <a href="#section-surface" class="rs-shell__rail-link" aria-current="page">Surfaces</a>
        <a href="#section-text" class="rs-shell__rail-link">Text</a>
        <a href="#section-badges" class="rs-shell__rail-link">Badges</a>
        <a href="#section-brand" class="rs-shell__rail-link">Brand</a>
        <a href="#section-focus" class="rs-shell__rail-link">Focus</a>
      </div>
    </nav>
    <main class="rs-shell__main">
      <div class="rs-shell__body">

        <!-- ── Section 1: Surface Elevation Ladder ── -->
        <section id="section-surface" class="ds-section">
          <h2 class="ds-section-heading">Surface Elevation Ladder</h2>
          <p style="font-size: var(--rs-text-xs); color: var(--rs-text-muted); margin: 0 0 0.75rem;">(lighter = elevated in dark mode)</p>
          <div class="ds-row">
            <div class="swatch-group">
              <div class="swatch" style="background: var(--rs-surface-faint);"></div>
              <div class="swatch-label">--rs-surface-faint</div>
            </div>
            <div class="swatch-group">
              <div class="swatch" style="background: var(--rs-bg);"></div>
              <div class="swatch-label">--rs-bg</div>
            </div>
            <div class="swatch-group">
              <div class="swatch" style="background: var(--rs-surface-muted);"></div>
              <div class="swatch-label">--rs-surface-muted</div>
            </div>
            <div class="swatch-group">
              <div class="swatch" style="background: var(--rs-surface);"></div>
              <div class="swatch-label">--rs-surface</div>
            </div>
          </div>
        </section>

        <!-- ── Section 2: Neutral Ramp ── -->
        <section id="section-neutral" class="ds-section">
          <h2 class="ds-section-heading">Neutral Ramp</h2>
          <div class="ds-row">
            <div class="swatch-group">
              <div class="swatch" style="background: var(--rs-neutral-0);"></div>
              <div class="swatch-label">neutral-0</div>
            </div>
            <div class="swatch-group">
              <div class="swatch" style="background: var(--rs-neutral-25);"></div>
              <div class="swatch-label">neutral-25</div>
            </div>
            <div class="swatch-group">
              <div class="swatch" style="background: var(--rs-neutral-50);"></div>
              <div class="swatch-label">neutral-50</div>
            </div>
            <div class="swatch-group">
              <div class="swatch" style="background: var(--rs-neutral-100);"></div>
              <div class="swatch-label">neutral-100</div>
            </div>
            <div class="swatch-group">
              <div class="swatch" style="background: var(--rs-neutral-200);"></div>
              <div class="swatch-label">neutral-200</div>
            </div>
            <div class="swatch-group">
              <div class="swatch" style="background: var(--rs-neutral-300);"></div>
              <div class="swatch-label">neutral-300</div>
            </div>
            <div class="swatch-group">
              <div class="swatch" style="background: var(--rs-neutral-400);"></div>
              <div class="swatch-label">neutral-400</div>
            </div>
            <div class="swatch-group">
              <div class="swatch" style="background: var(--rs-neutral-500);"></div>
              <div class="swatch-label">neutral-500</div>
            </div>
            <div class="swatch-group">
              <div class="swatch" style="background: var(--rs-neutral-600);"></div>
              <div class="swatch-label">neutral-600</div>
            </div>
            <div class="swatch-group">
              <div class="swatch" style="background: var(--rs-neutral-900);"></div>
              <div class="swatch-label">neutral-900</div>
            </div>
          </div>
        </section>

        <!-- ── Section 3: Body Text on Surfaces ── -->
        <section id="section-text" class="ds-section">
          <h2 class="ds-section-heading">Body Text on Surfaces</h2>
          <div class="rs-card" style="margin-bottom: 0.75rem;">
            <p style="margin: 0 0 0.4rem; color: var(--rs-text);">Primary text on --rs-surface</p>
            <p style="margin: 0 0 0.4rem; color: var(--rs-text-muted);">Muted text on --rs-surface</p>
            <p style="margin: 0; color: var(--rs-text-placeholder);">Placeholder text on --rs-surface</p>
          </div>
          <div style="background: var(--rs-bg); padding: 1rem; border-radius: var(--rs-radius-md); border: 1px solid var(--rs-border-subtle);">
            <p style="margin: 0 0 0.4rem; color: var(--rs-text);">Primary text on --rs-bg</p>
            <p style="margin: 0; color: var(--rs-text-muted);">Muted text on --rs-bg</p>
          </div>
        </section>

        <!-- ── Section 4: Badges (all 6 tones) ── -->
        <section id="section-badges" class="ds-section">
          <h2 class="ds-section-heading">Badges</h2>
          <div class="ds-row">
            <span class="rs-badge" data-tone="positive">positive</span>
            <span class="rs-badge" data-tone="warning">warning</span>
            <span class="rs-badge" data-tone="critical">critical</span>
            <span class="rs-badge" data-tone="neutral">neutral</span>
            <span class="rs-badge" data-tone="accent">accent</span>
            <span class="rs-badge" data-tone="muted">muted</span>
          </div>
        </section>

        <!-- ── Section 5: Flash (all 3 kinds) ── -->
        <section id="section-flash" class="ds-section">
          <h2 class="ds-section-heading">Flash</h2>
          <div class="rs-flash" data-kind="success" style="margin-bottom: 0.5rem;">
            <strong>Success</strong>
            <p style="margin: 0;">Operation completed successfully.</p>
          </div>
          <div class="rs-flash" data-kind="warning" style="margin-bottom: 0.5rem;">
            <strong>Warning</strong>
            <p style="margin: 0;">Review before proceeding.</p>
          </div>
          <div class="rs-flash" data-kind="error" style="margin-bottom: 0.5rem;">
            <strong>Error</strong>
            <p style="margin: 0;">Something went wrong.</p>
          </div>
        </section>

        <!-- ── Section 6: Brand / Primary ── -->
        <section id="section-brand" class="ds-section">
          <h2 class="ds-section-heading">Brand / Primary</h2>
          <div class="ds-row" style="margin-bottom: 0.75rem;">
            <button type="button" class="rs-button rs-button--primary">Primary button</button>
            <button type="button" class="rs-button">Secondary button</button>
            <button type="button" class="rs-button rs-button--danger">Danger button</button>
          </div>
          <div class="ds-row">
            <div class="swatch-group">
              <div class="swatch" style="background: var(--rs-primary);"></div>
              <div class="swatch-label">--rs-primary</div>
            </div>
            <div class="swatch-group">
              <div class="swatch" style="background: var(--rs-primary-hover);"></div>
              <div class="swatch-label">--rs-primary-hover</div>
            </div>
            <div class="swatch-group">
              <div class="swatch" style="background: var(--rs-accent);"></div>
              <div class="swatch-label">--rs-accent</div>
            </div>
            <div class="swatch-group">
              <div class="swatch" style="background: var(--rs-primary); display: flex; align-items: center; justify-content: center;">
                <span style="color: var(--rs-on-primary); font-size: 0.65rem; font-weight: 600;">on-primary</span>
              </div>
              <div class="swatch-label">--rs-on-primary<br>on --rs-primary</div>
            </div>
          </div>
        </section>

        <!-- ── Section 7: Status Colors ── -->
        <section id="section-status" class="ds-section">
          <h2 class="ds-section-heading">Status Colors</h2>
          <div class="ds-row" style="margin-bottom: 0.5rem;">
            <div class="swatch-group">
              <div class="swatch" style="background: var(--rs-success);"></div>
              <div class="swatch-label">--rs-success</div>
            </div>
            <div class="swatch-group">
              <div class="swatch" style="background: var(--rs-success-soft);"></div>
              <div class="swatch-label">--rs-success-soft</div>
            </div>
            <div class="swatch-group">
              <div class="swatch" style="background: var(--rs-success-bg-subtle);"></div>
              <div class="swatch-label">--rs-success-bg-subtle</div>
            </div>
          </div>
          <div class="ds-row" style="margin-bottom: 0.5rem;">
            <div class="swatch-group">
              <div class="swatch" style="background: var(--rs-warning);"></div>
              <div class="swatch-label">--rs-warning</div>
            </div>
            <div class="swatch-group">
              <div class="swatch" style="background: var(--rs-warning-soft);"></div>
              <div class="swatch-label">--rs-warning-soft</div>
            </div>
          </div>
          <div class="ds-row">
            <div class="swatch-group">
              <div class="swatch" style="background: var(--rs-error);"></div>
              <div class="swatch-label">--rs-error</div>
            </div>
            <div class="swatch-group">
              <div class="swatch" style="background: var(--rs-error-soft);"></div>
              <div class="swatch-label">--rs-error-soft</div>
            </div>
            <div class="swatch-group">
              <div class="swatch" style="background: var(--rs-error-bg-subtle);"></div>
              <div class="swatch-label">--rs-error-bg-subtle</div>
            </div>
          </div>
        </section>

        <!-- ── Section 8: Focus Ring Targets ── -->
        <section id="section-focus" class="ds-section">
          <h2 class="ds-section-heading">Focus Ring Targets</h2>

          <!-- GROUP 1: Text input + select on page-bg surface -->
          <div style="margin-bottom: 1rem;">
            <p style="font-size: var(--rs-text-sm); color: var(--rs-text-muted); margin: 0 0 0.5rem;">Text input + select (page-bg surface)</p>
            <div style="display: flex; gap: 0.75rem; flex-wrap: wrap; align-items: flex-end;">
              <div style="display: flex; flex-direction: column; gap: 0.3rem;">
                <label for="ds-text" style="font-size: 0.86rem; font-weight: var(--rs-weight-semibold); color: var(--rs-text);">Text input</label>
                <input id="ds-text" type="text" placeholder="Type here…" style="width: 16rem;">
              </div>
              <div style="display: flex; flex-direction: column; gap: 0.3rem;">
                <label for="ds-select" style="font-size: 0.86rem; font-weight: var(--rs-weight-semibold); color: var(--rs-text);">Select</label>
                <select id="ds-select" style="width: 16rem;">
                  <option>Option A</option>
                  <option>Option B</option>
                  <option>Option C</option>
                </select>
              </div>
            </div>
          </div>

          <!-- GROUP 2: Buttons on page-bg surface -->
          <div style="margin-bottom: 1rem;">
            <p style="font-size: var(--rs-text-sm); color: var(--rs-text-muted); margin: 0 0 0.5rem;">Buttons on page-bg surface</p>
            <div style="display: flex; gap: 0.5rem; flex-wrap: wrap;">
              <button type="button" class="rs-button">Secondary</button>
              <button type="button" class="rs-button rs-button--primary">Primary</button>
              <button type="button" class="rs-button rs-button--danger">Danger</button>
            </div>
          </div>

          <!-- GROUP 3: Primary button inside a card surface -->
          <div>
            <p style="font-size: var(--rs-text-sm); color: var(--rs-text-muted); margin: 0 0 0.5rem;">Primary button on card surface</p>
            <div class="rs-card" style="display: flex; align-items: center; gap: 1rem;">
              <button type="button" class="rs-button rs-button--primary">Primary on card</button>
              <span style="font-size: var(--rs-text-sm); color: var(--rs-text-muted);">card surface (--rs-surface)</span>
            </div>
          </div>
        </section>

        <!-- ── Section 9: Hover States ── -->
        <section id="section-hover" class="ds-section">
          <h2 class="ds-section-heading">Hover States</h2>
          <p style="font-size: var(--rs-text-xs); color: var(--rs-text-muted); margin: 0 0 0.75rem;">Hover to verify border/bg change in both themes.</p>
          <div class="ds-row">
            <button type="button" class="rs-button">Secondary (hover me)</button>
            <button type="button" class="rs-button rs-button--primary">Primary (hover me)</button>
            <button type="button" class="rs-button rs-button--danger">Danger (hover me)</button>
          </div>
        </section>

        <!-- ── Section 10: Disabled States ── -->
        <section id="section-disabled" class="ds-section">
          <h2 class="ds-section-heading">Disabled States</h2>
          <div class="ds-row" style="align-items: center; gap: 1rem;">
            <button disabled style="background: var(--rs-disabled-bg); color: var(--rs-disabled-text); border: 1px solid var(--rs-border); padding: 0.5rem 1rem; border-radius: var(--rs-radius-md); cursor: not-allowed; font: inherit;">Disabled button</button>
            <input type="text" disabled value="disabled input" style="width: 14rem;">
            <select disabled style="width: 12rem;">
              <option>Disabled select</option>
            </select>
          </div>
        </section>

        <!-- ── Section 11: Scope Probe ── -->
        <!-- NOTE: This section heading is inside .rs-shell intentionally (navigation anchor).
             The actual outside-shell probe div is placed OUTSIDE .rs-shell below. -->
        <section id="section-scope" class="ds-section">
          <h2 class="ds-section-heading">Scope Probe</h2>
          <p style="font-size: var(--rs-text-xs); color: var(--rs-text-muted); margin: 0;">
            The <code>outside-shell probe</code> div below (outside .rs-shell) tests that
            <code>--rs-bg</code> does not leak outside the shell. It should show red.
          </p>
        </section>

      </div>
    </main>
  </div>
</div>

<!-- THM-05 / Scope Probe — outside .rs-shell
     If --rs-bg leaks outside .rs-shell, this div shows the bg color.
     If correctly scoped, the fallback `red` applies — outside-shell probe shows red. -->
<div id="outside-shell-probe" style="background: var(--rs-bg, red); padding: 1rem; border-top: 2px solid #888;">
  <strong>outside-shell scope probe</strong> —
  background is <code>var(--rs-bg, red)</code>.
  If this shows <strong>red</strong>, token scoping is correct
  (--rs-bg is not declared outside .rs-shell).
</div>

<script>
  // Toggle theme from browser console or Playwright:
  //   setTheme('dark')   — pin dark
  //   setTheme('light')  — pin light
  //   clearTheme()       — remove pin (system mode)
  window.setTheme = (t) => document.getElementById('shell').setAttribute('data-theme', t);
  window.clearTheme = () => document.getElementById('shell').removeAttribute('data-theme');
</script>
</body>
</html>