@digiko-npm/designsystem 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +89 -0
  2. package/dist/designsystem.css +4642 -0
  3. package/dist/designsystem.js +67 -0
  4. package/package.json +32 -0
  5. package/src/base/index.css +2 -0
  6. package/src/base/reset.css +120 -0
  7. package/src/base/typography.css +163 -0
  8. package/src/components/accordion.css +150 -0
  9. package/src/components/alert.css +150 -0
  10. package/src/components/avatar.css +109 -0
  11. package/src/components/badge.css +80 -0
  12. package/src/components/breadcrumb.css +95 -0
  13. package/src/components/button.css +168 -0
  14. package/src/components/card.css +121 -0
  15. package/src/components/command.css +185 -0
  16. package/src/components/divider.css +66 -0
  17. package/src/components/drawer.css +209 -0
  18. package/src/components/dropdown.css +139 -0
  19. package/src/components/empty-state.css +69 -0
  20. package/src/components/index.css +35 -0
  21. package/src/components/input.css +116 -0
  22. package/src/components/kbd.css +55 -0
  23. package/src/components/modal.css +103 -0
  24. package/src/components/nav.css +153 -0
  25. package/src/components/pagination.css +166 -0
  26. package/src/components/popover.css +112 -0
  27. package/src/components/progress.css +214 -0
  28. package/src/components/skeleton.css +96 -0
  29. package/src/components/slider.css +125 -0
  30. package/src/components/table.css +48 -0
  31. package/src/components/tabs.css +163 -0
  32. package/src/components/tag.css +159 -0
  33. package/src/components/timeline.css +131 -0
  34. package/src/components/toast.css +70 -0
  35. package/src/components/toggle.css +135 -0
  36. package/src/components/tooltip.css +161 -0
  37. package/src/index.css +19 -0
  38. package/src/js/theme.js +67 -0
  39. package/src/tokens/colors.css +180 -0
  40. package/src/tokens/index.css +11 -0
  41. package/src/tokens/shadows.css +26 -0
  42. package/src/tokens/spacing.css +53 -0
  43. package/src/tokens/typography.css +51 -0
  44. package/src/utilities/index.css +3 -0
  45. package/src/utilities/layout.css +134 -0
  46. package/src/utilities/spacing.css +75 -0
  47. package/src/utilities/text.css +221 -0
@@ -0,0 +1,67 @@
1
+ /**
2
+ * @ds/designsystem — Theme Manager
3
+ *
4
+ * Handles light/dark theme toggling with localStorage persistence.
5
+ *
6
+ * Usage:
7
+ * import { theme } from '@ds/designsystem/js';
8
+ * theme.toggle();
9
+ * theme.set('dark');
10
+ * theme.get(); // 'light' | 'dark' | 'system'
11
+ */
12
+
13
+ const STORAGE_KEY = 'ds-theme';
14
+
15
+ function getSystemTheme() {
16
+ return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
17
+ }
18
+
19
+ function applyTheme(mode) {
20
+ const resolved = mode === 'system' ? getSystemTheme() : mode;
21
+ document.documentElement.setAttribute('data-theme', resolved);
22
+ }
23
+
24
+ export const theme = {
25
+ /** Initialize theme from stored preference or system default */
26
+ init() {
27
+ const stored = localStorage.getItem(STORAGE_KEY);
28
+ if (stored) {
29
+ applyTheme(stored);
30
+ }
31
+ // Listen for system theme changes
32
+ window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
33
+ const current = localStorage.getItem(STORAGE_KEY);
34
+ if (!current || current === 'system') {
35
+ applyTheme('system');
36
+ }
37
+ });
38
+ },
39
+
40
+ /** Set theme: 'light', 'dark', or 'system' */
41
+ set(mode) {
42
+ localStorage.setItem(STORAGE_KEY, mode);
43
+ applyTheme(mode);
44
+ },
45
+
46
+ /** Get current stored preference */
47
+ get() {
48
+ return localStorage.getItem(STORAGE_KEY) || 'system';
49
+ },
50
+
51
+ /** Toggle between light and dark */
52
+ toggle() {
53
+ const current = document.documentElement.getAttribute('data-theme');
54
+ const next = current === 'dark' ? 'light' : 'dark';
55
+ this.set(next);
56
+ return next;
57
+ }
58
+ };
59
+
60
+ // Auto-init if script is loaded directly
61
+ if (typeof document !== 'undefined') {
62
+ if (document.readyState === 'loading') {
63
+ document.addEventListener('DOMContentLoaded', () => theme.init());
64
+ } else {
65
+ theme.init();
66
+ }
67
+ }
@@ -0,0 +1,180 @@
1
+ /* ==========================================================================
2
+ Design Tokens: Colors
3
+ Refined zinc palette, editorial warmth.
4
+ Light-first with elegant dark mode. Override any --ds-* variable to re-theme.
5
+ ========================================================================== */
6
+
7
+ /* Light theme (default) */
8
+ :root,
9
+ [data-theme="light"] {
10
+ /* --- Backgrounds — clean whites, warm grays --- */
11
+ --ds-color-bg: #fafafa;
12
+ --ds-color-bg-subtle: #ffffff;
13
+ --ds-color-bg-muted: #e4e4e7;
14
+ --ds-color-bg-elevated: #f4f4f5;
15
+
16
+ --ds-color-surface: #ffffff;
17
+ --ds-color-surface-hover: #fafafa;
18
+ --ds-color-surface-active: #f4f4f5;
19
+
20
+ /* --- Text — zinc hierarchy --- */
21
+ --ds-color-text: #09090b;
22
+ --ds-color-text-secondary: #52525b;
23
+ --ds-color-text-tertiary: #a1a1aa;
24
+ --ds-color-text-disabled: #d4d4d8;
25
+
26
+ /* --- Inverted (primary buttons: dark bg + light text) --- */
27
+ --ds-color-inverted: #18181b;
28
+ --ds-color-on-inverted: #fafafa;
29
+
30
+ /* --- Borders — solid zinc --- */
31
+ --ds-color-border: #e4e4e7;
32
+ --ds-color-border-hover: #d4d4d8;
33
+ --ds-color-border-active: #a1a1aa;
34
+ --ds-color-border-subtle: #f4f4f5;
35
+
36
+ /* --- Interactive --- */
37
+ --ds-color-interactive: #3f3f46;
38
+ --ds-color-interactive-hover: #27272a;
39
+
40
+ /* --- Overlays --- */
41
+ --ds-color-overlay: rgba(0, 0, 0, 0.5);
42
+ --ds-color-overlay-subtle: rgba(0, 0, 0, 0.02);
43
+ --ds-color-overlay-hover: rgba(0, 0, 0, 0.04);
44
+ --ds-color-overlay-active: rgba(0, 0, 0, 0.08);
45
+
46
+ /* --- Navigation (glass effect) --- */
47
+ --ds-color-nav-bg: rgba(250, 250, 250, 0.8);
48
+ --ds-color-nav-border: rgba(228, 228, 231, 0.6);
49
+
50
+ /* --- Selection --- */
51
+ --ds-color-selection-bg: #09090b;
52
+ --ds-color-selection-text: #fafafa;
53
+
54
+ /* --- Shadows --- */
55
+ --ds-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
56
+ --ds-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08);
57
+ --ds-shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.12);
58
+
59
+ /* --- Scrollbar --- */
60
+ --ds-scrollbar-thumb: #d4d4d4;
61
+ --ds-scrollbar-thumb-hover: #a3a3a3;
62
+
63
+ color-scheme: light;
64
+ }
65
+
66
+ /* Dark theme */
67
+ [data-theme="dark"] {
68
+ /* --- Backgrounds — deep, refined zinc-900 palette --- */
69
+ --ds-color-bg: #09090b;
70
+ --ds-color-bg-subtle: #0f0f11;
71
+ --ds-color-bg-muted: #27272a;
72
+ --ds-color-bg-elevated: #18181b;
73
+
74
+ --ds-color-surface: #0f0f11;
75
+ --ds-color-surface-hover: #18181b;
76
+ --ds-color-surface-active: #27272a;
77
+
78
+ /* --- Text --- */
79
+ --ds-color-text: #fafafa;
80
+ --ds-color-text-secondary: #a1a1aa;
81
+ --ds-color-text-tertiary: #52525b;
82
+ --ds-color-text-disabled: #3f3f46;
83
+
84
+ /* --- Inverted (primary buttons: light bg + dark text) --- */
85
+ --ds-color-inverted: #fafafa;
86
+ --ds-color-on-inverted: #09090b;
87
+
88
+ /* --- Borders --- */
89
+ --ds-color-border: #27272a;
90
+ --ds-color-border-hover: #3f3f46;
91
+ --ds-color-border-active: #52525b;
92
+ --ds-color-border-subtle: #18181b;
93
+
94
+ /* --- Interactive --- */
95
+ --ds-color-interactive: #d4d4d8;
96
+ --ds-color-interactive-hover: #fafafa;
97
+
98
+ /* --- Overlays --- */
99
+ --ds-color-overlay: rgba(0, 0, 0, 0.7);
100
+ --ds-color-overlay-subtle: rgba(255, 255, 255, 0.03);
101
+ --ds-color-overlay-hover: rgba(255, 255, 255, 0.06);
102
+ --ds-color-overlay-active: rgba(255, 255, 255, 0.1);
103
+
104
+ /* --- Navigation --- */
105
+ --ds-color-nav-bg: rgba(9, 9, 11, 0.8);
106
+ --ds-color-nav-border: rgba(39, 39, 42, 0.6);
107
+
108
+ /* --- Selection --- */
109
+ --ds-color-selection-bg: #fafafa;
110
+ --ds-color-selection-text: #09090b;
111
+
112
+ /* --- Shadows (stronger in dark) --- */
113
+ --ds-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.2);
114
+ --ds-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.3);
115
+ --ds-shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.4);
116
+
117
+ /* --- Scrollbar --- */
118
+ --ds-scrollbar-thumb: #27272a;
119
+ --ds-scrollbar-thumb-hover: #3f3f46;
120
+
121
+ color-scheme: dark;
122
+ }
123
+
124
+ /* Shared tokens (same in both themes) */
125
+ :root {
126
+ /* --- Semantic Status --- */
127
+ --ds-color-success: #16a34a;
128
+ --ds-color-success-subtle: rgba(22, 163, 74, 0.1);
129
+ --ds-color-success-border: rgba(22, 163, 74, 0.2);
130
+
131
+ --ds-color-warning: #d97706;
132
+ --ds-color-warning-subtle: rgba(217, 119, 6, 0.1);
133
+ --ds-color-warning-border: rgba(217, 119, 6, 0.2);
134
+
135
+ --ds-color-error: #dc2626;
136
+ --ds-color-error-subtle: rgba(220, 38, 38, 0.1);
137
+ --ds-color-error-border: rgba(220, 38, 38, 0.2);
138
+
139
+ --ds-color-info: #2563eb;
140
+ --ds-color-info-subtle: rgba(37, 99, 235, 0.1);
141
+ --ds-color-info-border: rgba(37, 99, 235, 0.2);
142
+
143
+ /* --- Accent Colors (for badges, categories) --- */
144
+ --ds-color-accent-blue: #2563eb;
145
+ --ds-color-accent-purple: #7c3aed;
146
+ --ds-color-accent-green: #16a34a;
147
+ --ds-color-accent-orange: #d97706;
148
+ --ds-color-accent-blue-subtle: rgba(37, 99, 235, 0.1);
149
+ --ds-color-accent-purple-subtle: rgba(124, 58, 237, 0.1);
150
+ --ds-color-accent-green-subtle: rgba(22, 163, 74, 0.1);
151
+ --ds-color-accent-orange-subtle: rgba(217, 119, 6, 0.1);
152
+ }
153
+
154
+ /* Dark overrides for status/accent (brighter for contrast) */
155
+ [data-theme="dark"] {
156
+ --ds-color-success: #4ade80;
157
+ --ds-color-success-subtle: rgba(74, 222, 128, 0.1);
158
+ --ds-color-success-border: rgba(74, 222, 128, 0.2);
159
+
160
+ --ds-color-warning: #fbbf24;
161
+ --ds-color-warning-subtle: rgba(251, 191, 36, 0.1);
162
+ --ds-color-warning-border: rgba(251, 191, 36, 0.2);
163
+
164
+ --ds-color-error: #f87171;
165
+ --ds-color-error-subtle: rgba(248, 113, 113, 0.1);
166
+ --ds-color-error-border: rgba(248, 113, 113, 0.2);
167
+
168
+ --ds-color-info: #60a5fa;
169
+ --ds-color-info-subtle: rgba(96, 165, 250, 0.1);
170
+ --ds-color-info-border: rgba(96, 165, 250, 0.2);
171
+
172
+ --ds-color-accent-blue: #60a5fa;
173
+ --ds-color-accent-purple: #a78bfa;
174
+ --ds-color-accent-green: #4ade80;
175
+ --ds-color-accent-orange: #fbbf24;
176
+ --ds-color-accent-blue-subtle: rgba(96, 165, 250, 0.1);
177
+ --ds-color-accent-purple-subtle: rgba(167, 139, 250, 0.1);
178
+ --ds-color-accent-green-subtle: rgba(74, 222, 128, 0.1);
179
+ --ds-color-accent-orange-subtle: rgba(251, 191, 36, 0.1);
180
+ }
@@ -0,0 +1,11 @@
1
+ /* ==========================================================================
2
+ Design Tokens — All tokens in one import
3
+
4
+ To override: just redeclare any --ds-* variable in your project's CSS.
5
+ Your values win. Nothing breaks.
6
+ ========================================================================== */
7
+
8
+ @import './colors.css';
9
+ @import './typography.css';
10
+ @import './spacing.css';
11
+ @import './shadows.css';
@@ -0,0 +1,26 @@
1
+ /* ==========================================================================
2
+ Design Tokens: Effects & Transitions
3
+ Expo easing, smooth editorial motion.
4
+ Shadows are defined per-theme in colors.css.
5
+ ========================================================================== */
6
+
7
+ :root {
8
+ /* --- Focus Ring --- */
9
+ --ds-ring-width: 2px;
10
+ --ds-ring-offset: 2px;
11
+ --ds-ring-color: var(--ds-color-border-active);
12
+
13
+ /* --- Transitions --- */
14
+ --ds-duration-fast: 100ms;
15
+ --ds-duration-normal: 200ms;
16
+ --ds-duration-slow: 400ms;
17
+ --ds-duration-slower: 800ms;
18
+
19
+ --ds-ease-default: ease;
20
+ --ds-ease-out: cubic-bezier(0, 0, 0.2, 1);
21
+ --ds-ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
22
+ --ds-ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1);
23
+
24
+ /* --- Opacity --- */
25
+ --ds-opacity-disabled: 0.5;
26
+ }
@@ -0,0 +1,53 @@
1
+ /* ==========================================================================
2
+ Design Tokens: Spacing & Layout
3
+ Generous whitespace, responsive sections.
4
+ ========================================================================== */
5
+
6
+ :root {
7
+ /* --- Spacing Scale --- */
8
+ --ds-space-0: 0;
9
+ --ds-space-0-5: 0.125rem; /* 2px */
10
+ --ds-space-1: 0.25rem; /* 4px */
11
+ --ds-space-1-5: 0.375rem; /* 6px */
12
+ --ds-space-2: 0.5rem; /* 8px */
13
+ --ds-space-2-5: 0.625rem; /* 10px */
14
+ --ds-space-3: 0.75rem; /* 12px */
15
+ --ds-space-4: 1rem; /* 16px */
16
+ --ds-space-5: 1.25rem; /* 20px */
17
+ --ds-space-6: 1.5rem; /* 24px */
18
+ --ds-space-8: 2rem; /* 32px */
19
+ --ds-space-10: 2.5rem; /* 40px */
20
+ --ds-space-12: 3rem; /* 48px */
21
+ --ds-space-16: 4rem; /* 64px */
22
+ --ds-space-20: 5rem; /* 80px */
23
+ --ds-space-24: 6rem; /* 96px */
24
+ --ds-space-32: 8rem; /* 128px */
25
+
26
+ /* --- Section Padding (responsive, generous) --- */
27
+ --ds-section-padding: clamp(80px, 12vw, 160px);
28
+
29
+ /* --- Container --- */
30
+ --ds-container-max: 1200px;
31
+ --ds-container-padding: clamp(20px, 5vw, 80px);
32
+ --ds-container-sm: 640px;
33
+ --ds-container-md: 768px;
34
+ --ds-container-lg: 1024px;
35
+
36
+ /* --- Border Radius (refined, slightly larger) --- */
37
+ --ds-radius-none: 0;
38
+ --ds-radius-sm: 6px;
39
+ --ds-radius-md: 8px;
40
+ --ds-radius-lg: 12px;
41
+ --ds-radius-xl: 16px;
42
+ --ds-radius-2xl: 20px;
43
+ --ds-radius-full: 9999px;
44
+
45
+ /* --- Z-Index Scale --- */
46
+ --ds-z-base: 0;
47
+ --ds-z-dropdown: 50;
48
+ --ds-z-sticky: 60;
49
+ --ds-z-overlay: 80;
50
+ --ds-z-modal: 100;
51
+ --ds-z-toast: 150;
52
+ --ds-z-tooltip: 200;
53
+ }
@@ -0,0 +1,51 @@
1
+ /* ==========================================================================
2
+ Design Tokens: Typography
3
+ Clash Display headings, Switzer body.
4
+ Editorial feel, generous sizing, tight tracking on display.
5
+ ========================================================================== */
6
+
7
+ :root {
8
+ /* --- Font Families ---
9
+ Override these in your project to use your own fonts.
10
+ The DS provides the architecture; you bring the typeface. */
11
+ --ds-font-display: "Clash Display", system-ui, sans-serif;
12
+ --ds-font-sans: "Switzer", system-ui, -apple-system, sans-serif;
13
+ --ds-font-mono: "Geist Mono", ui-monospace, "SF Mono", monospace;
14
+
15
+ /* --- Display Font Weight (Clash Display looks best at 400) --- */
16
+ --ds-font-display-weight: 400;
17
+
18
+ /* --- Font Sizes --- */
19
+ --ds-text-xs: 0.75rem; /* 12px */
20
+ --ds-text-sm: 0.875rem; /* 14px */
21
+ --ds-text-base: 1rem; /* 16px */
22
+ --ds-text-lg: 1.125rem; /* 18px */
23
+ --ds-text-xl: 1.25rem; /* 20px */
24
+ --ds-text-2xl: 1.5rem; /* 24px */
25
+ --ds-text-3xl: 1.875rem; /* 30px */
26
+ --ds-text-4xl: 2.25rem; /* 36px */
27
+ --ds-text-5xl: 3rem; /* 48px */
28
+ --ds-text-6xl: 3.75rem; /* 60px */
29
+ --ds-text-7xl: 4.5rem; /* 72px */
30
+
31
+ /* --- Font Weights --- */
32
+ --ds-weight-light: 300;
33
+ --ds-weight-normal: 400;
34
+ --ds-weight-medium: 500;
35
+ --ds-weight-semibold: 600;
36
+ --ds-weight-bold: 700;
37
+
38
+ /* --- Line Heights --- */
39
+ --ds-leading-none: 1;
40
+ --ds-leading-tight: 1.1;
41
+ --ds-leading-snug: 1.25;
42
+ --ds-leading-normal: 1.5;
43
+ --ds-leading-relaxed: 1.625;
44
+ --ds-leading-loose: 2;
45
+
46
+ /* --- Letter Spacing --- */
47
+ --ds-tracking-tighter: -0.02em;
48
+ --ds-tracking-tight: -0.01em;
49
+ --ds-tracking-normal: 0;
50
+ --ds-tracking-wide: 0.05em;
51
+ }
@@ -0,0 +1,3 @@
1
+ @import './layout.css';
2
+ @import './spacing.css';
3
+ @import './text.css';
@@ -0,0 +1,134 @@
1
+ /* ==========================================================================
2
+ Utilities: Layout
3
+ Container with clamp padding, generous responsive grid.
4
+ ========================================================================== */
5
+
6
+ /* --- Container --- */
7
+ .ds-container {
8
+ width: 100%;
9
+ max-width: var(--ds-container-max);
10
+ margin-inline: auto;
11
+ padding-inline: var(--ds-container-padding);
12
+ }
13
+
14
+ /* --- Section (generous vertical rhythm) --- */
15
+ .ds-section {
16
+ padding-block: var(--ds-section-padding);
17
+ }
18
+
19
+ /* --- Flex --- */
20
+ .ds-flex { display: flex; }
21
+ .ds-inline-flex { display: inline-flex; }
22
+ .ds-flex-col { flex-direction: column; }
23
+ .ds-flex-row { flex-direction: row; }
24
+ .ds-flex-wrap { flex-wrap: wrap; }
25
+ .ds-flex-1 { flex: 1 1 0%; }
26
+ .ds-flex-auto { flex: 1 1 auto; }
27
+ .ds-flex-none { flex: none; }
28
+ .ds-shrink-0 { flex-shrink: 0; }
29
+
30
+ /* --- Alignment --- */
31
+ .ds-items-start { align-items: flex-start; }
32
+ .ds-items-center { align-items: center; }
33
+ .ds-items-end { align-items: flex-end; }
34
+ .ds-items-stretch { align-items: stretch; }
35
+ .ds-items-baseline { align-items: baseline; }
36
+
37
+ .ds-justify-start { justify-content: flex-start; }
38
+ .ds-justify-center { justify-content: center; }
39
+ .ds-justify-end { justify-content: flex-end; }
40
+ .ds-justify-between { justify-content: space-between; }
41
+ .ds-justify-around { justify-content: space-around; }
42
+ .ds-justify-evenly { justify-content: space-evenly; }
43
+
44
+ .ds-self-start { align-self: flex-start; }
45
+ .ds-self-center { align-self: center; }
46
+ .ds-self-end { align-self: flex-end; }
47
+
48
+ /* --- Grid --- */
49
+ .ds-grid {
50
+ display: grid;
51
+ gap: var(--ds-space-6);
52
+ }
53
+
54
+ .ds-grid-cols-1 { grid-template-columns: repeat(1, 1fr); }
55
+ .ds-grid-cols-2 { grid-template-columns: repeat(2, 1fr); }
56
+ .ds-grid-cols-3 { grid-template-columns: repeat(3, 1fr); }
57
+ .ds-grid-cols-4 { grid-template-columns: repeat(4, 1fr); }
58
+
59
+ @media (min-width: 640px) {
60
+ .ds-sm\:grid-cols-2 { grid-template-columns: repeat(2, 1fr); }
61
+ .ds-sm\:grid-cols-3 { grid-template-columns: repeat(3, 1fr); }
62
+ }
63
+
64
+ @media (min-width: 768px) {
65
+ .ds-md\:grid-cols-2 { grid-template-columns: repeat(2, 1fr); }
66
+ .ds-md\:grid-cols-3 { grid-template-columns: repeat(3, 1fr); }
67
+ .ds-md\:grid-cols-4 { grid-template-columns: repeat(4, 1fr); }
68
+ .ds-md\:flex-row { flex-direction: row; }
69
+ }
70
+
71
+ @media (min-width: 1024px) {
72
+ .ds-lg\:grid-cols-3 { grid-template-columns: repeat(3, 1fr); }
73
+ .ds-lg\:grid-cols-4 { grid-template-columns: repeat(4, 1fr); }
74
+ }
75
+
76
+ /* --- Gap --- */
77
+ .ds-gap-0 { gap: var(--ds-space-0); }
78
+ .ds-gap-1 { gap: var(--ds-space-1); }
79
+ .ds-gap-2 { gap: var(--ds-space-2); }
80
+ .ds-gap-3 { gap: var(--ds-space-3); }
81
+ .ds-gap-4 { gap: var(--ds-space-4); }
82
+ .ds-gap-5 { gap: var(--ds-space-5); }
83
+ .ds-gap-6 { gap: var(--ds-space-6); }
84
+ .ds-gap-8 { gap: var(--ds-space-8); }
85
+ .ds-gap-12 { gap: var(--ds-space-12); }
86
+
87
+ /* --- Display --- */
88
+ .ds-block { display: block; }
89
+ .ds-inline-block { display: inline-block; }
90
+ .ds-inline { display: inline; }
91
+ .ds-hidden { display: none; }
92
+
93
+ @media (min-width: 768px) {
94
+ .ds-md\:hidden { display: none; }
95
+ .ds-md\:block { display: block; }
96
+ .ds-md\:flex { display: flex; }
97
+ }
98
+
99
+ /* --- Position --- */
100
+ .ds-relative { position: relative; }
101
+ .ds-absolute { position: absolute; }
102
+ .ds-fixed { position: fixed; }
103
+ .ds-sticky { position: sticky; top: 0; }
104
+
105
+ /* --- Overflow --- */
106
+ .ds-overflow-hidden { overflow: hidden; }
107
+ .ds-overflow-auto { overflow: auto; }
108
+ .ds-overflow-x-auto { overflow-x: auto; }
109
+
110
+ /* --- Width/Height --- */
111
+ .ds-w-full { width: 100%; }
112
+ .ds-h-full { height: 100%; }
113
+ .ds-h-screen { height: 100dvh; }
114
+ .ds-min-h-screen { min-height: 100dvh; }
115
+
116
+ /* --- Stack (vertical spacing) --- */
117
+ .ds-stack > * + * {
118
+ margin-top: var(--ds-space-4);
119
+ }
120
+
121
+ .ds-stack--sm > * + * { margin-top: var(--ds-space-2); }
122
+ .ds-stack--lg > * + * { margin-top: var(--ds-space-8); }
123
+
124
+ /* --- Center content --- */
125
+ .ds-center {
126
+ display: flex;
127
+ align-items: center;
128
+ justify-content: center;
129
+ }
130
+
131
+ /* --- Aspect Ratio --- */
132
+ .ds-aspect-square { aspect-ratio: 1; }
133
+ .ds-aspect-video { aspect-ratio: 16/9; }
134
+ .ds-aspect-card { aspect-ratio: 16/10; }
@@ -0,0 +1,75 @@
1
+ /* ==========================================================================
2
+ Utilities: Spacing (margin & padding)
3
+ Pattern: ds-{m|p}{side}-{size}
4
+ ========================================================================== */
5
+
6
+ /* --- Padding --- */
7
+ .ds-p-0 { padding: var(--ds-space-0); }
8
+ .ds-p-1 { padding: var(--ds-space-1); }
9
+ .ds-p-2 { padding: var(--ds-space-2); }
10
+ .ds-p-3 { padding: var(--ds-space-3); }
11
+ .ds-p-4 { padding: var(--ds-space-4); }
12
+ .ds-p-5 { padding: var(--ds-space-5); }
13
+ .ds-p-6 { padding: var(--ds-space-6); }
14
+ .ds-p-8 { padding: var(--ds-space-8); }
15
+ .ds-p-10 { padding: var(--ds-space-10); }
16
+ .ds-p-12 { padding: var(--ds-space-12); }
17
+
18
+ .ds-px-0 { padding-inline: var(--ds-space-0); }
19
+ .ds-px-2 { padding-inline: var(--ds-space-2); }
20
+ .ds-px-3 { padding-inline: var(--ds-space-3); }
21
+ .ds-px-4 { padding-inline: var(--ds-space-4); }
22
+ .ds-px-5 { padding-inline: var(--ds-space-5); }
23
+ .ds-px-6 { padding-inline: var(--ds-space-6); }
24
+ .ds-px-8 { padding-inline: var(--ds-space-8); }
25
+
26
+ .ds-py-0 { padding-block: var(--ds-space-0); }
27
+ .ds-py-2 { padding-block: var(--ds-space-2); }
28
+ .ds-py-3 { padding-block: var(--ds-space-3); }
29
+ .ds-py-4 { padding-block: var(--ds-space-4); }
30
+ .ds-py-5 { padding-block: var(--ds-space-5); }
31
+ .ds-py-6 { padding-block: var(--ds-space-6); }
32
+ .ds-py-8 { padding-block: var(--ds-space-8); }
33
+ .ds-py-10 { padding-block: var(--ds-space-10); }
34
+ .ds-py-12 { padding-block: var(--ds-space-12); }
35
+ .ds-py-16 { padding-block: var(--ds-space-16); }
36
+ .ds-py-20 { padding-block: var(--ds-space-20); }
37
+
38
+ .ds-pt-4 { padding-top: var(--ds-space-4); }
39
+ .ds-pt-8 { padding-top: var(--ds-space-8); }
40
+ .ds-pt-12 { padding-top: var(--ds-space-12); }
41
+ .ds-pt-16 { padding-top: var(--ds-space-16); }
42
+
43
+ .ds-pb-4 { padding-bottom: var(--ds-space-4); }
44
+ .ds-pb-8 { padding-bottom: var(--ds-space-8); }
45
+
46
+ /* --- Margin --- */
47
+ .ds-m-0 { margin: var(--ds-space-0); }
48
+ .ds-m-auto { margin: auto; }
49
+
50
+ .ds-mx-auto { margin-inline: auto; }
51
+ .ds-mx-2 { margin-inline: var(--ds-space-2); }
52
+ .ds-mx-4 { margin-inline: var(--ds-space-4); }
53
+
54
+ .ds-my-0 { margin-block: var(--ds-space-0); }
55
+ .ds-my-2 { margin-block: var(--ds-space-2); }
56
+ .ds-my-4 { margin-block: var(--ds-space-4); }
57
+ .ds-my-6 { margin-block: var(--ds-space-6); }
58
+ .ds-my-8 { margin-block: var(--ds-space-8); }
59
+
60
+ .ds-mt-0 { margin-top: var(--ds-space-0); }
61
+ .ds-mt-1 { margin-top: var(--ds-space-1); }
62
+ .ds-mt-2 { margin-top: var(--ds-space-2); }
63
+ .ds-mt-4 { margin-top: var(--ds-space-4); }
64
+ .ds-mt-6 { margin-top: var(--ds-space-6); }
65
+ .ds-mt-8 { margin-top: var(--ds-space-8); }
66
+
67
+ .ds-mb-0 { margin-bottom: var(--ds-space-0); }
68
+ .ds-mb-1 { margin-bottom: var(--ds-space-1); }
69
+ .ds-mb-2 { margin-bottom: var(--ds-space-2); }
70
+ .ds-mb-4 { margin-bottom: var(--ds-space-4); }
71
+ .ds-mb-6 { margin-bottom: var(--ds-space-6); }
72
+ .ds-mb-8 { margin-bottom: var(--ds-space-8); }
73
+
74
+ .ds-ml-auto { margin-left: auto; }
75
+ .ds-mr-auto { margin-right: auto; }