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 20 Passed
Dmitri P.Physics74%May 19 Review
Maria S.Chemistry88%May 18 Graded
Ivan B.History61%May 17 Failed
Elena V.Biology95%May 16 Top 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)

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)