@keenmate/svelte-treeview 5.0.0-rc07 → 5.0.0-rc09

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.
@@ -1,354 +1,355 @@
1
- STYLING AND THEMING
2
- ===================
3
-
4
- CRITICAL: Styles must be imported separately
5
- - Component has no embedded styles
6
- - Import CSS or SCSS
7
- - Extensive CSS variables for theming
8
-
9
- IMPORT STYLES
10
- -------------
11
- // CSS (compiled)
12
- import '@keenmate/svelte-treeview/styles.css';
13
-
14
- // SCSS (with variable overrides)
15
- import '@keenmate/svelte-treeview/styles.scss';
16
-
17
- CSS VARIABLES
18
- -------------
19
- Override in your CSS:
20
-
21
- :root {
22
- /* Indentation */
23
- --tree-node-indent-per-level: 0.5rem;
24
-
25
- /* Colors */
26
- --ltree-primary: #0d6efd;
27
- --ltree-primary-rgb: 13, 110, 253;
28
- --ltree-success: #198754;
29
- --ltree-success-rgb: 25, 135, 84;
30
- --ltree-danger: #dc3545;
31
- --ltree-danger-rgb: 220, 53, 69;
32
- --ltree-light: #f8f9fa;
33
- --ltree-border: #dee2e6;
34
- --ltree-body-color: #212529;
35
-
36
- /* Touch ghost */
37
- --tree-ghost-bg: rgba(59, 130, 246, 0.9);
38
- --tree-ghost-color: white;
39
- }
40
-
41
- SCSS VARIABLES
42
- --------------
43
- Override BEFORE importing:
44
-
45
- <style lang="scss">
46
- // Override variables
47
- $tree-node-indent-per-level: 1rem;
48
- $ltree-primary: #6366f1;
49
- $tree-node-font-family: 'Inter', sans-serif;
50
-
51
- // Then import
52
- @import '@keenmate/svelte-treeview/styles.scss';
53
- </style>
54
-
55
- Available SCSS variables:
56
- - $tree-node-indent-per-level
57
- - $tree-node-font-family
58
- - $tree-node-content-border-radius
59
- - $ltree-primary, $ltree-success, $ltree-danger
60
- - $drop-zone-* variables (see below)
61
-
62
- SELECTED NODE CLASSES
63
- ---------------------
64
- <Tree highlightedNodeClass="ltree-selected-bold" />
65
-
66
- Built-in classes:
67
- - ltree-selected-bold - Bold text with primary color
68
- - ltree-selected-border - Border and background highlight
69
- - ltree-selected-brackets - Decorative brackets Node ❮
70
-
71
- Custom selected style:
72
- .my-selected {
73
- background: #e0f2fe;
74
- border-left: 3px solid #0284c7;
75
- font-weight: 600;
76
- }
77
-
78
- <Tree highlightedNodeClass="my-selected" />
79
-
80
- DRAG-OVER CLASSES
81
- -----------------
82
- <Tree dragOverNodeClass="ltree-dragover-glow" />
83
-
84
- Built-in classes:
85
- - ltree-dragover-highlight - Dashed border with background
86
- - ltree-dragover-glow - Shadow glow effect
87
-
88
- Custom drag-over style:
89
- .my-drag-over {
90
- outline: 2px dashed #3b82f6;
91
- outline-offset: 2px;
92
- background: rgba(59, 130, 246, 0.1);
93
- }
94
-
95
- <Tree dragOverNodeClass="my-drag-over" />
96
-
97
- ICON CLASSES
98
- ------------
99
- <Tree
100
- expandIconClass="ltree-icon-expand"
101
- collapseIconClass="ltree-icon-collapse"
102
- leafIconClass="ltree-icon-leaf"
103
- />
104
-
105
- Custom icons with CSS:
106
- .my-expand::before { content: '▶'; }
107
- .my-collapse::before { content: ''; }
108
- .my-leaf::before { content: ''; }
109
-
110
- <Tree
111
- expandIconClass="my-expand"
112
- collapseIconClass="my-collapse"
113
- leafIconClass="my-leaf"
114
- />
115
-
116
- SCROLL HIGHLIGHT CLASSES
117
- ------------------------
118
- <Tree
119
- scrollHighlightClass="ltree-scroll-highlight"
120
- scrollHighlightTimeout={4000}
121
- />
122
-
123
- Built-in classes:
124
- - ltree-scroll-highlight - Blue background glow
125
- - ltree-scroll-highlight-arrow - Red arrow indicator
126
-
127
- Custom highlight:
128
- .my-highlight {
129
- animation: pulse 0.5s ease-in-out 3;
130
- }
131
-
132
- @keyframes pulse {
133
- 0%, 100% { background: transparent; }
134
- 50% { background: #fef08a; }
135
- }
136
-
137
- <Tree scrollHighlightClass="my-highlight" />
138
-
139
- DROP ZONE STYLING
140
- -----------------
141
- SCSS variables for drop zones:
142
-
143
- // Border radius
144
- $drop-zone-border-radius: 4px;
145
-
146
- // Before zone
147
- $drop-zone-before-bg: rgba(134, 239, 172, 0.25);
148
- $drop-zone-before-color: #166534;
149
- $drop-zone-before-active-bg: rgba(134, 239, 172, 0.85);
150
- $drop-zone-before-active-color: #14532d;
151
- $drop-zone-before-active-shadow: 0 2px 8px rgba(34, 197, 94, 0.4);
152
-
153
- // After zone
154
- $drop-zone-after-bg: rgba(253, 186, 116, 0.25);
155
- $drop-zone-after-color: #9a3412;
156
- $drop-zone-after-active-bg: rgba(253, 186, 116, 0.85);
157
- $drop-zone-after-active-color: #7c2d12;
158
- $drop-zone-after-active-shadow: 0 2px 8px rgba(249, 115, 22, 0.4);
159
-
160
- // Child zone
161
- $drop-zone-child-bg: rgba(196, 181, 253, 0.25);
162
- $drop-zone-child-color: #5b21b6;
163
- $drop-zone-child-active-bg: rgba(196, 181, 253, 0.85);
164
- $drop-zone-child-active-color: #4c1d95;
165
- $drop-zone-child-active-shadow: 0 2px 8px rgba(139, 92, 246, 0.4);
166
-
167
- // Arrow indicators
168
- $drop-arrow-size: 24px;
169
- $drop-arrow-position: 66%;
170
-
171
- GLOW MODE STYLING
172
- -----------------
173
- CSS classes for glow indicators:
174
-
175
- .ltree-glow-before {
176
- border-top: 3px solid #22c55e;
177
- box-shadow: 0 -4px 8px rgba(34, 197, 94, 0.3);
178
- }
179
-
180
- .ltree-glow-after {
181
- border-bottom: 3px solid #f97316;
182
- box-shadow: 0 4px 8px rgba(249, 115, 22, 0.3);
183
- }
184
-
185
- .ltree-glow-child {
186
- border: 3px solid #8b5cf6;
187
- box-shadow: 0 0 12px rgba(139, 92, 246, 0.4);
188
- }
189
-
190
- CONTEXT MENU STYLING
191
- --------------------
192
- .ltree-context-menu {
193
- background: white;
194
- border: 1px solid #e5e7eb;
195
- border-radius: 8px;
196
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
197
- padding: 4px;
198
- min-width: 160px;
199
- }
200
-
201
- .ltree-context-menu-item {
202
- display: flex;
203
- align-items: center;
204
- padding: 8px 12px;
205
- border-radius: 4px;
206
- cursor: pointer;
207
- gap: 8px;
208
- }
209
-
210
- .ltree-context-menu-item:hover {
211
- background: #f3f4f6;
212
- }
213
-
214
- .ltree-context-menu-item-disabled {
215
- opacity: 0.5;
216
- cursor: not-allowed;
217
- }
218
-
219
- .ltree-context-menu-divider {
220
- height: 1px;
221
- background: #e5e7eb;
222
- margin: 4px 0;
223
- }
224
-
225
- TOUCH GHOST STYLING
226
- -------------------
227
- .ltree-touch-ghost {
228
- background: var(--tree-ghost-bg, rgba(59, 130, 246, 0.9));
229
- color: var(--tree-ghost-color, white);
230
- padding: 8px 16px;
231
- border-radius: 6px;
232
- font-size: 14px;
233
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
234
- }
235
-
236
- CSS CLASS REFERENCE
237
- -------------------
238
- Tree structure:
239
- - .ltree-tree - Main container
240
- - .ltree-tree-body - Tree body
241
- - .ltree-node - Node container
242
- - .ltree-node-row - Node row wrapper
243
- - .ltree-node-content - Node content area
244
- - .ltree-toggle-icon - Expand/collapse icon
245
- - .ltree-children - Children container
246
-
247
- States:
248
- - .ltree-expanded - Expanded node
249
- - .ltree-collapsed - Collapsed node
250
- - .ltree-selected - Selected node
251
- - .ltree-draggable - Draggable node
252
- - .ltree-drag-over - Drop target during drag
253
-
254
- Drop zones:
255
- - .ltree-drop-zones - Drop zone container
256
- - .ltree-drop-zone - Individual drop zone
257
- - .ltree-drop-before - Before position
258
- - .ltree-drop-after - After position
259
- - .ltree-drop-child - Child position
260
- - .ltree-drop-copy - Copy operation active
261
-
262
- Context menu:
263
- - .ltree-context-menu - Menu container
264
- - .ltree-context-menu-item - Menu item
265
- - .ltree-context-menu-icon - Item icon
266
- - .ltree-context-menu-divider - Divider
267
-
268
- Empty/loading:
269
- - .ltree-empty-state - Empty tree state
270
- - .ltree-drop-placeholder - Drop placeholder
271
-
272
- BODY CLASS
273
- ----------
274
- <Tree bodyClass="my-tree-body" />
275
-
276
- Adds class to tree body element for scoped styling:
277
-
278
- .my-tree-body .ltree-node-content {
279
- padding: 4px 8px;
280
- }
281
-
282
- DARK THEME EXAMPLE
283
- ------------------
284
- .dark-theme {
285
- --ltree-body-color: #e5e7eb;
286
- --ltree-border: #374151;
287
- --ltree-light: #1f2937;
288
- --ltree-primary: #60a5fa;
289
- }
290
-
291
- .dark-theme .ltree-tree {
292
- background: #111827;
293
- }
294
-
295
- .dark-theme .ltree-node-content:hover {
296
- background: #1f2937;
297
- }
298
-
299
- .dark-theme .ltree-context-menu {
300
- background: #1f2937;
301
- border-color: #374151;
302
- }
303
-
304
- INDENTATION
305
- -----------
306
- Control node indentation:
307
-
308
- :root {
309
- --tree-node-indent-per-level: 1rem;
310
- }
311
-
312
- Each level gets this fixed indent.
313
- Level 1 = 1rem, Level 2 = 2rem, etc.
314
-
315
- NODE TEMPLATE STYLING
316
- ---------------------
317
- <Tree {data}>
318
- {#snippet nodeTemplate(node)}
319
- <div class="custom-node">
320
- <span class="icon">{node.data.icon}</span>
321
- <span class="name">{node.data.name}</span>
322
- <span class="badge">{node.data.count}</span>
323
- </div>
324
- {/snippet}
325
- </Tree>
326
-
327
- <style>
328
- .custom-node {
329
- display: flex;
330
- align-items: center;
331
- gap: 8px;
332
- }
333
- .icon { font-size: 1.2em; }
334
- .name { flex: 1; }
335
- .badge {
336
- background: #e5e7eb;
337
- padding: 2px 6px;
338
- border-radius: 9999px;
339
- font-size: 0.75em;
340
- }
341
- </style>
342
-
343
- BEST PRACTICES
344
- --------------
345
- ✅ Import styles at app level (once)
346
- Use CSS variables for theming
347
- Override SCSS variables before import
348
- Use built-in classes when possible
349
- Scope custom styles properly
350
-
351
- ❌ Don't import styles multiple times
352
- ❌ Don't override built-in classes globally
353
- ❌ Don't use !important unless necessary
354
- ❌ Don't forget to test dark mode
1
+ STYLING AND THEMING
2
+ ===================
3
+
4
+ CRITICAL: Styles must be imported separately
5
+ - Component has no embedded styles
6
+ - Import CSS or SCSS
7
+ - Extensive CSS variables for theming
8
+
9
+ IMPORT STYLES
10
+ -------------
11
+ // Bundled CSS (all partials merged)
12
+ import '@keenmate/svelte-treeview/styles.css';
13
+
14
+ // Or individual partials (override per-section)
15
+ import '@keenmate/svelte-treeview/styles/main.css';
16
+
17
+ CSS VARIABLES
18
+ -------------
19
+ Override in your CSS:
20
+
21
+ :root {
22
+ /* Base sizing unit — scale all dimensions with one knob */
23
+ --ltree-rem: 10px;
24
+
25
+ /* Indentation */
26
+ --ltree-node-indent-per-level: calc(0.8 * var(--ltree-rem));
27
+
28
+ /* Colors — tints derived automatically via color-mix() */
29
+ --ltree-primary: #0d6efd;
30
+ --ltree-success: #198754;
31
+ --ltree-danger: #dc3545;
32
+ --ltree-light: #f8f9fa;
33
+ --ltree-border: #dee2e6;
34
+ --ltree-body-color: #212529;
35
+
36
+ /* Touch ghost */
37
+ --tree-ghost-bg: rgba(59, 130, 246, 0.9);
38
+ --tree-ghost-color: white;
39
+ }
40
+
41
+ --base-* TOKEN INTEGRATION
42
+ --------------------------
43
+ Every --ltree-* variable chains through a --base-* token shared with other
44
+ @keenmate/* web components, then falls back to a hardcoded default:
45
+
46
+ --ltree-primary: var(--base-accent-color, #0d6efd);
47
+
48
+ Set --base-* once at :root and every KM component picks it up automatically:
49
+
50
+ :root {
51
+ --base-accent-color: #6366f1;
52
+ --base-font-family: 'Inter', system-ui, sans-serif;
53
+ --base-border-color: #e5e7eb;
54
+ --base-border-radius-sm: 6px;
55
+ --base-text-color-1: #111827;
56
+ --base-text-color-3: #6b7280;
57
+ --base-hover-bg: #f3f4f6;
58
+ }
59
+
60
+ Tree-specific --ltree-* overrides take precedence over --base-* tokens, so
61
+ you can theme a single tree without affecting other components.
62
+
63
+ SELECTED NODE CLASSES
64
+ ---------------------
65
+ <Tree highlightedNodeClass="ltree-selected-bold" />
66
+
67
+ Built-in classes:
68
+ - ltree-selected-bold - Bold text with primary color
69
+ - ltree-selected-border - Border and background highlight
70
+ - ltree-selected-brackets - Decorative brackets ❯ Node ❮
71
+
72
+ Custom selected style:
73
+ .my-selected {
74
+ background: #e0f2fe;
75
+ border-left: 3px solid #0284c7;
76
+ font-weight: 600;
77
+ }
78
+
79
+ <Tree highlightedNodeClass="my-selected" />
80
+
81
+ DRAG-OVER CLASSES
82
+ -----------------
83
+ <Tree dragOverNodeClass="ltree-dragover-glow" />
84
+
85
+ Built-in classes:
86
+ - ltree-dragover-highlight - Dashed border with background
87
+ - ltree-dragover-glow - Shadow glow effect
88
+
89
+ Custom drag-over style:
90
+ .my-drag-over {
91
+ outline: 2px dashed #3b82f6;
92
+ outline-offset: 2px;
93
+ background: rgba(59, 130, 246, 0.1);
94
+ }
95
+
96
+ <Tree dragOverNodeClass="my-drag-over" />
97
+
98
+ ICON CLASSES
99
+ ------------
100
+ <Tree
101
+ expandIconClass="ltree-icon-expand"
102
+ collapseIconClass="ltree-icon-collapse"
103
+ leafIconClass="ltree-icon-leaf"
104
+ />
105
+
106
+ Custom icons with CSS:
107
+ .my-expand::before { content: ''; }
108
+ .my-collapse::before { content: ''; }
109
+ .my-leaf::before { content: '•'; }
110
+
111
+ <Tree
112
+ expandIconClass="my-expand"
113
+ collapseIconClass="my-collapse"
114
+ leafIconClass="my-leaf"
115
+ />
116
+
117
+ SCROLL HIGHLIGHT CLASSES
118
+ ------------------------
119
+ <Tree
120
+ scrollHighlightClass="ltree-scroll-highlight"
121
+ scrollHighlightTimeout={4000}
122
+ />
123
+
124
+ Built-in classes:
125
+ - ltree-scroll-highlight - Blue background glow
126
+ - ltree-scroll-highlight-arrow - Red arrow indicator
127
+
128
+ Custom highlight:
129
+ .my-highlight {
130
+ animation: pulse 0.5s ease-in-out 3;
131
+ }
132
+
133
+ @keyframes pulse {
134
+ 0%, 100% { background: transparent; }
135
+ 50% { background: #fef08a; }
136
+ }
137
+
138
+ <Tree scrollHighlightClass="my-highlight" />
139
+
140
+ DROP ZONE STYLING
141
+ -----------------
142
+ SCSS variables for drop zones:
143
+
144
+ // Border radius
145
+ $drop-zone-border-radius: 4px;
146
+
147
+ // Before zone
148
+ $drop-zone-before-bg: rgba(134, 239, 172, 0.25);
149
+ $drop-zone-before-color: #166534;
150
+ $drop-zone-before-active-bg: rgba(134, 239, 172, 0.85);
151
+ $drop-zone-before-active-color: #14532d;
152
+ $drop-zone-before-active-shadow: 0 2px 8px rgba(34, 197, 94, 0.4);
153
+
154
+ // After zone
155
+ $drop-zone-after-bg: rgba(253, 186, 116, 0.25);
156
+ $drop-zone-after-color: #9a3412;
157
+ $drop-zone-after-active-bg: rgba(253, 186, 116, 0.85);
158
+ $drop-zone-after-active-color: #7c2d12;
159
+ $drop-zone-after-active-shadow: 0 2px 8px rgba(249, 115, 22, 0.4);
160
+
161
+ // Child zone
162
+ $drop-zone-child-bg: rgba(196, 181, 253, 0.25);
163
+ $drop-zone-child-color: #5b21b6;
164
+ $drop-zone-child-active-bg: rgba(196, 181, 253, 0.85);
165
+ $drop-zone-child-active-color: #4c1d95;
166
+ $drop-zone-child-active-shadow: 0 2px 8px rgba(139, 92, 246, 0.4);
167
+
168
+ // Arrow indicators
169
+ $drop-arrow-size: 24px;
170
+ $drop-arrow-position: 66%;
171
+
172
+ GLOW MODE STYLING
173
+ -----------------
174
+ CSS classes for glow indicators:
175
+
176
+ .ltree-glow-before {
177
+ border-top: 3px solid #22c55e;
178
+ box-shadow: 0 -4px 8px rgba(34, 197, 94, 0.3);
179
+ }
180
+
181
+ .ltree-glow-after {
182
+ border-bottom: 3px solid #f97316;
183
+ box-shadow: 0 4px 8px rgba(249, 115, 22, 0.3);
184
+ }
185
+
186
+ .ltree-glow-child {
187
+ border: 3px solid #8b5cf6;
188
+ box-shadow: 0 0 12px rgba(139, 92, 246, 0.4);
189
+ }
190
+
191
+ CONTEXT MENU STYLING
192
+ --------------------
193
+ .ltree-context-menu {
194
+ background: white;
195
+ border: 1px solid #e5e7eb;
196
+ border-radius: 8px;
197
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
198
+ padding: 4px;
199
+ min-width: 160px;
200
+ }
201
+
202
+ .ltree-context-menu-item {
203
+ display: flex;
204
+ align-items: center;
205
+ padding: 8px 12px;
206
+ border-radius: 4px;
207
+ cursor: pointer;
208
+ gap: 8px;
209
+ }
210
+
211
+ .ltree-context-menu-item:hover {
212
+ background: #f3f4f6;
213
+ }
214
+
215
+ .ltree-context-menu-item-disabled {
216
+ opacity: 0.5;
217
+ cursor: not-allowed;
218
+ }
219
+
220
+ .ltree-context-menu-divider {
221
+ height: 1px;
222
+ background: #e5e7eb;
223
+ margin: 4px 0;
224
+ }
225
+
226
+ TOUCH GHOST STYLING
227
+ -------------------
228
+ .ltree-touch-ghost {
229
+ background: var(--tree-ghost-bg, rgba(59, 130, 246, 0.9));
230
+ color: var(--tree-ghost-color, white);
231
+ padding: 8px 16px;
232
+ border-radius: 6px;
233
+ font-size: 14px;
234
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
235
+ }
236
+
237
+ CSS CLASS REFERENCE
238
+ -------------------
239
+ Tree structure:
240
+ - .ltree-tree - Main container
241
+ - .ltree-tree-body - Tree body
242
+ - .ltree-node - Node container
243
+ - .ltree-node-row - Node row wrapper
244
+ - .ltree-node-content - Node content area
245
+ - .ltree-toggle-icon - Expand/collapse icon
246
+ - .ltree-children - Children container
247
+
248
+ States:
249
+ - .ltree-expanded - Expanded node
250
+ - .ltree-collapsed - Collapsed node
251
+ - .ltree-selected - Selected node
252
+ - .ltree-draggable - Draggable node
253
+ - .ltree-drag-over - Drop target during drag
254
+
255
+ Drop zones:
256
+ - .ltree-drop-zones - Drop zone container
257
+ - .ltree-drop-zone - Individual drop zone
258
+ - .ltree-drop-before - Before position
259
+ - .ltree-drop-after - After position
260
+ - .ltree-drop-child - Child position
261
+ - .ltree-drop-copy - Copy operation active
262
+
263
+ Context menu:
264
+ - .ltree-context-menu - Menu container
265
+ - .ltree-context-menu-item - Menu item
266
+ - .ltree-context-menu-icon - Item icon
267
+ - .ltree-context-menu-divider - Divider
268
+
269
+ Empty/loading:
270
+ - .ltree-empty-state - Empty tree state
271
+ - .ltree-drop-placeholder - Drop placeholder
272
+
273
+ BODY CLASS
274
+ ----------
275
+ <Tree bodyClass="my-tree-body" />
276
+
277
+ Adds class to tree body element for scoped styling:
278
+
279
+ .my-tree-body .ltree-node-content {
280
+ padding: 4px 8px;
281
+ }
282
+
283
+ DARK THEME EXAMPLE
284
+ ------------------
285
+ .dark-theme {
286
+ --ltree-body-color: #e5e7eb;
287
+ --ltree-border: #374151;
288
+ --ltree-light: #1f2937;
289
+ --ltree-primary: #60a5fa;
290
+ }
291
+
292
+ .dark-theme .ltree-tree {
293
+ background: #111827;
294
+ }
295
+
296
+ .dark-theme .ltree-node-content:hover {
297
+ background: #1f2937;
298
+ }
299
+
300
+ .dark-theme .ltree-context-menu {
301
+ background: #1f2937;
302
+ border-color: #374151;
303
+ }
304
+
305
+ INDENTATION
306
+ -----------
307
+ Control node indentation:
308
+
309
+ :root {
310
+ --tree-node-indent-per-level: 1rem;
311
+ }
312
+
313
+ Each level gets this fixed indent.
314
+ Level 1 = 1rem, Level 2 = 2rem, etc.
315
+
316
+ NODE TEMPLATE STYLING
317
+ ---------------------
318
+ <Tree {data}>
319
+ {#snippet nodeTemplate(node)}
320
+ <div class="custom-node">
321
+ <span class="icon">{node.data.icon}</span>
322
+ <span class="name">{node.data.name}</span>
323
+ <span class="badge">{node.data.count}</span>
324
+ </div>
325
+ {/snippet}
326
+ </Tree>
327
+
328
+ <style>
329
+ .custom-node {
330
+ display: flex;
331
+ align-items: center;
332
+ gap: 8px;
333
+ }
334
+ .icon { font-size: 1.2em; }
335
+ .name { flex: 1; }
336
+ .badge {
337
+ background: #e5e7eb;
338
+ padding: 2px 6px;
339
+ border-radius: 9999px;
340
+ font-size: 0.75em;
341
+ }
342
+ </style>
343
+
344
+ BEST PRACTICES
345
+ --------------
346
+ Import styles at app level (once)
347
+ Use CSS variables for theming
348
+ Override SCSS variables before import
349
+ Use built-in classes when possible
350
+ ✅ Scope custom styles properly
351
+
352
+ ❌ Don't import styles multiple times
353
+ ❌ Don't override built-in classes globally
354
+ ❌ Don't use !important unless necessary
355
+ ❌ Don't forget to test dark mode