From e4ec9f88233c2b556379dcaef371c72f79d37b57 Mon Sep 17 00:00:00 2001 From: Maxim Dolgolyov Date: Thu, 21 May 2026 09:58:23 +0300 Subject: [PATCH] feat(design-system): comprehensive showcase page at /design-system Standalone discoverable hub of all LearnSpace design tokens, components, patterns, motion, accessibility primitives, and icons. Sections: - Foundations: colors (WCAG ratios), typography, spacing, radii, shadows, blur - Components: buttons, inputs, badges, chips, cards, modal, toast, skeleton, empty-states, avatars (all with state variants) - Patterns: stat-card, data-table, search-bar, sidebar nav, tabs, hero, bento, hover-row-actions - Motion: transitions, shimmer, prefers-reduced-motion toggle - Accessibility: focus rings, touch targets, live contrast checker - Icons: top 50 Lucide names with click-to-copy - Anti-patterns: 4x don't vs do examples Interactive: click-to-copy on swatches/icons/classes, search filter across sections, code snippets via
blocks per component, LS.modal/toast live triggers with standalone fallback. Co-Authored-By: Claude Sonnet 4.6 --- frontend/design-system.html | 1573 +++++++++++++++++++++++++++++++++++ 1 file changed, 1573 insertions(+) create mode 100644 frontend/design-system.html diff --git a/frontend/design-system.html b/frontend/design-system.html new file mode 100644 index 0000000..e622086 --- /dev/null +++ b/frontend/design-system.html @@ -0,0 +1,1573 @@ + + + + + +LearnSpace Design System + + + + + + + + + + +
Copied!
+ + +
+ + Design System v1.0 · light theme + +
+ +
+ + + + + +
+ + +
+

Colors

+

Brand palette, semantic aliases, and text hierarchy. Click any swatch to copy the CSS variable.

+ +
+
Brand
+
+
+
Semantic Aliases
+
+
+
Text & Surface
+
+
+
WCAG Contrast Preview
+
+
+ +
Code snippet
/* Brand */
+--violet: #9B5DE5;
+--cyan:   #06D6E0;
+--green:  #06D664;
+--pink:   #F15BB5;
+--amber:  #FFB347;
+
+/* Semantic */
+--success: var(--green);
+--warning: var(--amber);
+--danger:  var(--pink);
+--info:    var(--cyan);
+
+ + +
+

Typography

+

Type scale, font families, and weight ladder. Unbounded: display/headings/KPI numbers. Manrope: everything else.

+ +
+
Type Scale
+
+
+
Font Families
+
+
+
Manrope — body
+
The quick brown fox
+
Body text, labels, inputs
+
+
+
Unbounded — display
+
The quick brown fox
+
Headings, KPI numbers, logo
+
+
+
+
Weight Ladder
+
+
+ +
Code snippet
--text-xs:   0.72rem;   /* 11.5px */
+--text-sm:   0.82rem;   /* 13px   */
+--text-base: 0.92rem;   /* 14.7px */
+--text-md:   1.02rem;   /* 16.3px */
+--text-lg:   1.18rem;   /* 18.9px */
+--text-xl:   1.5rem;    /* 24px   */
+--text-2xl:  2rem;      /* 32px   */
+--text-3xl:  2.6rem;    /* 41.6px */
+
+--fw-regular:   400;
+--fw-medium:    500;
+--fw-semibold:  600;
+--fw-bold:      700;
+--fw-extrabold: 800;
+
+ + +
+

Spacing

+

4px base scale. Use tokens instead of hardcoded values for consistent rhythm.

+
+
+
+
Code snippet
--space-1:  4px;
+--space-2:  8px;
+--space-3:  12px;
+--space-4:  16px;
+--space-5:  20px;
+--space-6:  24px;
+--space-8:  32px;
+--space-10: 40px;
+--space-12: 48px;
+--space-16: 64px;
+
+ + +
+

Radii

+

Border-radius ladder from sharp to pill. Click to copy.

+
+
+
+
Code snippet
--r-xs:   4px;
+--r-sm:   8px;
+--r-md:   12px;
+--r-lg:   20px;
+--r-xl:   24px;
+--r-pill: 999px;
+
+ + +
+

Shadows

+

Two-layer shadows: crisp ambient + lifted. Use --shadow-h on hover.

+
+
No shadow
+
--shadow
+
--shadow-h
+
+
Code snippet
--shadow:   0 2px 8px rgba(15,23,42,0.08), 0 8px 40px rgba(15,23,42,0.10);
+--shadow-h: 0 4px 16px rgba(15,23,42,0.12), 0 16px 56px rgba(15,23,42,0.13);
+
+ + +
+

Blur

+

--blur: blur(20px) — used with a semi-transparent background for glass surfaces.

+
+
+
No blur
+
+
+
Frosted glass
+
+
+
Code snippet
--blur: blur(20px);
+
+/* Usage */
+.glass-panel {
+  background: rgba(238,242,255,0.55);
+  backdrop-filter: var(--blur);
+  border: 1.5px solid rgba(255,255,255,0.4);
+}
+
+ + +
+

Buttons

+

All buttons meet WCAG 2.5.5 44px touch target. Primary has shimmer on hover.

+ +
+
Variants
+
+
+ +
+
+
+ +
+
+
+ +
+
+ +
+
+
Disabled state
+
+ + +
+
+
Loading state
+
+ +
+
+ +
Code snippet
<button class="btn-primary">Primary</button>
+<button class="btn-ghost">Ghost</button>
+<button class="btn-danger">Danger</button>
+<button class="icon-btn" aria-label="Settings">
+  <i data-lucide="settings"></i>
+</button>
+
+ + +
+

Form Inputs

+

All inputs use .form-input. Focus ring uses violet at 15% opacity.

+ +
+
+
+ + +
+
+ + + This field is required +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ +
Code snippet
<input class="form-input" type="text" placeholder="Enter value...">
+<input class="form-input error" type="text">
+<select class="form-input">...</select>
+<textarea class="form-input" rows="3"></textarea>
+
+ + +
+

Badges

+

5 brand-color variants, pill-shaped, suitable for status labels.

+
+
Variants
+
+ Учитель + Активен + Завершено + Новый + Ученик +
+
+
Sizes
+
+ Micro + Regular + Large +
+
+
Code snippet
<span class="badge badge-violet">Учитель</span>
+<span class="badge badge-cyan">Активен</span>
+<span class="badge badge-green">Завершено</span>
+<span class="badge badge-pink">Новый</span>
+<span class="badge badge-amber">Ученик</span>
+
+ + +
+

Chips

+

Interactive filter chips, KPI chips, and status chips.

+
+
KPI chip
+
+
+
+
Students
128
+
+
+
+
Top score
96%
+
+
+
+
Filter chips
+
+ + + + +
+
+
Code snippet
<button class="chip active">All subjects</button>
+<button class="chip">Mathematics
+  <span class="chip-x" aria-label="Remove">...</span>
+</button>
+
+ + +
+

Cards

+

Surface, glass, top-bar, and hero card variants.

+
+
+
Surface card
+
Uses var(--surface) background with shadow.
+
+
+
+
Glass card
+
Frosted backdrop-filter on gradient bg.
+
+
+
+
Top-bar card
+
::before colored bar at top.
+
+
+
+
+
Sessions this week
+
1,248
+
+12% vs last week
+
+
+
Code snippet
<div class="ds-surface-card">...</div>
+
+<!-- glass: wrap in gradient div, then -->
+<div style="backdrop-filter:var(--blur);background:rgba(255,255,255,0.35)">...</div>
+
+<!-- top-bar: ::before height:3px; background: gradient -->
+
+ + + + + +
+

Toast

+

4 variants via LS.toast(message, type). Auto-dismiss in 3.5s.

+
+
+ + + + +
+
+
Code snippet
LS.toast('Action completed!', 'success');
+LS.toast('Review your input.',  'warn');
+LS.toast('An error occurred.',  'error');
+LS.toast('Session saved.',      'info');
+
+ + +
+

Skeleton

+

Shimmer placeholders for loading states. Use .ls-skeleton as base.

+
+
Line skeleton
+
+
+
+
+
+
+
Card skeleton
+
+
+
+
+
+
+
Row skeleton (violet shimmer variant)
+
+
+
+
+
+
Code snippet
<!-- Neutral shimmer -->
+<div class="ls-skeleton ls-skeleton-line"></div>
+
+<!-- Violet shimmer (existing) -->
+<div class="ls-sk" style="height:36px"></div>
+
+ + +
+

Empty State

+

Zero-data, error, and no-results variants using .rich-empty.

+
+
+
+
No data yet
+
Create your first item to get started.
+ +
+
+
+
Something went wrong
+
We couldn't load the data. Check your connection.
+ +
+
+
+
No results
+
Try adjusting your search or filters.
+ +
+
+
Code snippet
<div class="rich-empty">
+  <div class="rich-empty-svg"><!-- Lucide icon --></div>
+  <div class="rich-empty-title">No data yet</div>
+  <div class="rich-empty-sub">Description text</div>
+  <button class="rich-empty-btn">Action</button>
+</div>
+
+ + +
+

Avatar

+

Initials-based pills with HSL color derived from name hash. Role-colored variants.

+
+
Name-hashed colors
+
+
+
Role variants
+
+
+
AD
+
Admin
Gradient
+
+
+
TR
+
Teacher
Cyan-green
+
+
+
ST
+
Student
Subtle violet
+
+
+
+
Code snippet
function avatarColor(name) {
+  let h = 0;
+  for (const c of name) h = (h * 31 + c.charCodeAt(0)) % 360;
+  return `hsl(${h}, 60%, 48%)`;
+}
+// initials
+const initials = name.split(' ').slice(0,2).map(w=>w[0]).join('').toUpperCase();
+
+ + +
+

Stat Card

+

KPI cards with colored top bar and optional delta indicator.

+
+
+
Total sessions
+
1,248
+
+12% this week
+
+
+
Avg. score
+
78%
+
Stable
+
+
+
Active classes
+
24
+
+3 new
+
+
+
Code snippet
<div class="stat-card vc">
+  <div class="stat-label">Total sessions</div>
+  <div class="stat-val">1,248</div>
+  <div class="stat-delta">+12% this week</div>
+</div>
+/* .vc = violet-cyan bar, .gc = green-cyan, .ac = amber-pink */
+
+ + +
+

Data Table

+

Sticky header, hover highlight, row actions revealed on hover.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StudentSubjectScoreDateStatus
Anna K.Mathematics92%May 20Passed
Dmitri P.Physics74%May 19Review
Maria S.Chemistry88%May 18Graded
Ivan B.History61%May 17Failed
Elena V.Biology95%May 16Top score
+
+
Code snippet
<div class="ds-table-wrap">
+  <table class="ds-table">
+    <thead><tr><th>Name</th>...</tr></thead>
+    <tbody>
+      <tr>
+        <td>Anna K.</td>...
+        <td><div class="row-actions">...</div></td>
+      </tr>
+    </tbody>
+  </table>
+</div>
+
+ + + + + + + + +
+

Tabs

+

Pill-tabs with white active indicator. Wraps in a muted violet track.

+
+
+ + + + +
+
+
Code snippet
<div class="ds-tabs">
+  <button class="ds-tab active">Overview</button>
+  <button class="ds-tab">Sessions</button>
+  <button class="ds-tab">Students</button>
+</div>
+
+ + +
+

Hero Header

+

Greeting + KPI chip row used at the top of dashboard pages.

+
+
Good morning, Maxim
+
+
+
+
Subjects
8
+
+
+
+
Students
128
+
+
+
+
Avg. score
78%
+
+
+
+
+ + +
+

Bento Grid

+

3-column masonry-like grid with spanning cells for dashboard layouts.

+
+
+
Wide cell (span 2)
+
grid-column: span 2
+
+
+
Tall cell (span 2 rows)
+
grid-row: span 2
+
+
Cell A
+
Cell B
+
+
Code snippet
<div class="bento">
+  <div class="bento-cell wide">Span 2 cols</div>
+  <div class="bento-cell tall">Span 2 rows</div>
+  <div class="bento-cell">Normal</div>
+  <div class="bento-cell">Normal</div>
+</div>
+
+ + +
+

Hover Row Actions

+

Action buttons hidden by default, revealed on row hover via display:flex toggle.

+
+ + + + + + + +
NameRoleLast active
Anna K.Teacher2 min ago
Dmitri P.Student1 hour ago
Maria S.AdminJust now
+
+

Hover a row to see action buttons.

+
+ + +
+

Motion

+

Spring and ease-out transitions. Hover cards to see. Toggle prefers-reduced-motion simulation.

+
+ +
+
+
+ +
Spring
+
--ease-spring
0.22s
+
+
+ +
Ease-out
+
--ease-out
0.22s
+
+
+ +
Slow
+
--duration-slow
0.40s
+
+
+
+ Shimmer +
+
.ls-sk continuous
+
+
+
Code snippet
--ease-out:    cubic-bezier(0.16, 1, 0.3, 1);
+--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
+--duration-fast: 0.12s;
+--duration-base: 0.22s;
+--duration-slow: 0.40s;
+
+/* Usage */
+.card { transition: transform var(--duration-base) var(--ease-spring); }
+.card:hover { transform: translateY(-6px) scale(1.02); }
+
+/* Respect user preference */
+@media (prefers-reduced-motion: reduce) {
+  .card { transition: none; }
+}
+
+ + +
+

Accessibility

+

Focus rings use :focus-visible. All interactive elements meet 44px touch target (WCAG 2.5.5).

+
+
Focus ring (Tab through these)
+
+ + + Link C +
+
+
Touch target 44x44px (dashed outline = target area)
+
+
+ +
+
+
+ +
+
+
+ Nav link +
+
+
+
+
+ + +
+

Contrast Checker

+

Compute WCAG 2.1 contrast ratio live. AA requires 4.5:1 (normal text), 3:1 (large text).

+
+
+
+ + +
+
+ + +
+
+
+ Sample text on background +
+
+
+
Design system contrast checks
+
+
+
+ + +
+

Icons (Lucide)

+

Top 50 Lucide icons used in LearnSpace. Click to copy <i data-lucide="..."> tag.

+
+
Code snippet
<!-- Include once in <head> -->
+<script src="https://cdn.jsdelivr.net/npm/lucide@0.469.0/dist/umd/lucide.min.js"></script>
+
+<!-- Use icon -->
+<i data-lucide="users" style="width:18px;height:18px"></i>
+
+<!-- Initialize (call once after DOM) -->
+<script>lucide.createIcons();</script>
+
+ + +
+

Anti-Patterns

+

Common mistakes and their correct counterparts in LearnSpace.

+
+
+
Don't
+ color: #9B5DE5; +
Hardcoded hex bypasses theming
+
+
+
Do
+ color: var(--violet); +
Use CSS token — survives palette changes
+
+
+
Don't
+ style="display:none" +
Inline style overrides specificity
+
+
+
Do
+ class="hidden" +
Utility class, toggled with JS
+
+
+
Don't
+ style="background:#9B5DE5;color:#fff;border-radius:999px;..." +
Re-inventing existing components
+
+
+
Do
+ <button class="btn-primary"> +
Reuse design system component
+
+
+
Don't
+ style="padding:12px" +
Hardcoded spacing breaks scale
+
+
+
Do
+ class="p-3" +
Token-backed utility (= 12px = --space-3)
+
+
+
+ + + + +
+
+ + + +