@walkeros/explorer 0.3.0 → 0.5.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.
- package/AGENT.md +381 -0
- package/STYLE.md +993 -0
- package/dist/chunk-WKBCYMTQ.mjs +2650 -0
- package/dist/chunk-WKBCYMTQ.mjs.map +1 -0
- package/dist/index.d.cts +32 -4
- package/dist/index.d.ts +32 -4
- package/dist/index.js +2412 -17436
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1438 -627
- package/dist/index.mjs.map +1 -1
- package/dist/{monaco-types-T3WXA7KH.mjs → monaco-types-GHUJ2SZE.mjs} +2 -2
- package/dist/styles.css +70 -0
- package/package.json +41 -28
- package/dist/chunk-P5UDSGZL.mjs +0 -18485
- package/dist/chunk-P5UDSGZL.mjs.map +0 -1
- /package/dist/{monaco-types-T3WXA7KH.mjs.map → monaco-types-GHUJ2SZE.mjs.map} +0 -0
package/STYLE.md
ADDED
|
@@ -0,0 +1,993 @@
|
|
|
1
|
+
# Explorer Styling Guide
|
|
2
|
+
|
|
3
|
+
Complete guide to styling, theming, and customization in walkerOS Explorer.
|
|
4
|
+
|
|
5
|
+
**Quick Links:** [Quick Start](#quick-start) · [Theme Variables](#theme-variables) · [Grid System](#grid-system) · [Monaco Editor](#monaco-editor) · [SCSS Architecture](#scss-architecture)
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Quick Start
|
|
10
|
+
|
|
11
|
+
### Theme Switching
|
|
12
|
+
|
|
13
|
+
Explorer supports two built-in themes via the `data-theme` attribute:
|
|
14
|
+
|
|
15
|
+
```html
|
|
16
|
+
<!-- Dark theme (default) -->
|
|
17
|
+
<div data-theme="dark">
|
|
18
|
+
<YourExplorerComponents />
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
<!-- Light theme -->
|
|
22
|
+
<div data-theme="light">
|
|
23
|
+
<YourExplorerComponents />
|
|
24
|
+
</div>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Theme detection priority:
|
|
28
|
+
1. Closest ancestor `data-theme` attribute
|
|
29
|
+
2. Document root `data-theme` attribute
|
|
30
|
+
3. System preference via `prefers-color-scheme`
|
|
31
|
+
|
|
32
|
+
### Customizing Colors
|
|
33
|
+
|
|
34
|
+
Override CSS variables in your stylesheet:
|
|
35
|
+
|
|
36
|
+
```css
|
|
37
|
+
[data-theme="dark"] {
|
|
38
|
+
--color-primary: #your-brand-color;
|
|
39
|
+
--bg-box: #your-background;
|
|
40
|
+
--text-primary: #your-text-color;
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Required Import
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
import '@walkeros/explorer/styles.css';
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Theme Variables
|
|
53
|
+
|
|
54
|
+
### Complete Variable Reference
|
|
55
|
+
|
|
56
|
+
#### Text Colors
|
|
57
|
+
|
|
58
|
+
| Variable | Light | Dark | Usage |
|
|
59
|
+
|----------|-------|------|-------|
|
|
60
|
+
| `--color-text` | `#000` | `#e0e0e0` | Primary text |
|
|
61
|
+
| `--color-text-label` | `#424242` | `#cccccc` | Labels, headers |
|
|
62
|
+
| `--color-text-button` | `#616161` | `#cccccc` | Button text (inactive) |
|
|
63
|
+
| `--color-text-button-hover` | `#424242` | `#ffffff` | Button text on hover |
|
|
64
|
+
| `--color-text-button-active` | `#1f2937` | `#ffffff` | Button text when active |
|
|
65
|
+
| `--color-text-muted` | `#666` | `#999` | Secondary/muted text |
|
|
66
|
+
| `--color-text-toggle` | `#666` | `#999` | Toggle/switch labels |
|
|
67
|
+
| `--color-text-input` | `#000` | `#e0e0e0` | Input field text |
|
|
68
|
+
| `--color-text-placeholder` | `#9ca3af` | `#666` | Input placeholder text |
|
|
69
|
+
|
|
70
|
+
#### Background Colors
|
|
71
|
+
|
|
72
|
+
| Variable | Light | Dark | Usage |
|
|
73
|
+
|----------|-------|------|-------|
|
|
74
|
+
| `--bg-box` | `#ffffff` | `#1e1e1e` | Main container background |
|
|
75
|
+
| `--bg-header` | `#f5f5f5` | `#252526` | Header background |
|
|
76
|
+
| `--bg-footer` | `#f5f5f5` | `#252526` | Footer background |
|
|
77
|
+
| `--bg-button-hover` | `#e8e8e8` | `#2a2d2e` | Button background on hover |
|
|
78
|
+
| `--bg-button-active` | `#ffffff` | `#1e1e1e` | Button background when active |
|
|
79
|
+
| `--bg-button-group` | `#f3f4f6` | `#2a2d2e` | Button group container |
|
|
80
|
+
| `--bg-input` | `#ffffff` | `#252526` | Input field background |
|
|
81
|
+
| `--bg-input-hover` | `#f9f9f9` | `#2a2d2e` | Input field on hover |
|
|
82
|
+
| `--bg-code-inline` | `#f9f9f9` | `rgba(255,255,255,0.05)` | Inline code background |
|
|
83
|
+
| `--bg-dropdown` | `#ffffff` | `#252526` | Dropdown menu background |
|
|
84
|
+
| `--bg-dropdown-option-hover` | `#f0f0f0` | `#2a2d2e` | Dropdown option on hover |
|
|
85
|
+
| `--bg-dropdown-option-highlighted` | `#e3f2fd` | `#1e3a5f` | Highlighted dropdown option |
|
|
86
|
+
|
|
87
|
+
#### Border Colors
|
|
88
|
+
|
|
89
|
+
| Variable | Light | Dark | Usage |
|
|
90
|
+
|----------|-------|------|-------|
|
|
91
|
+
| `--border-box` | `#e0e0e0` | `#3c3c3c` | Main container border |
|
|
92
|
+
| `--border-header` | `#e0e0e0` | `#3c3c3c` | Header border |
|
|
93
|
+
| `--border-footer` | `#e0e0e0` | `#3c3c3c` | Footer border |
|
|
94
|
+
| `--border-button-group` | `#d1d5db` | `#3c3c3c` | Button group borders |
|
|
95
|
+
| `--border-input` | `#d1d5db` | `#3c3c3c` | Input field border |
|
|
96
|
+
| `--border-input-focus` | `#3b82f6` | `#4a90e2` | Input border when focused |
|
|
97
|
+
|
|
98
|
+
#### Button Colors
|
|
99
|
+
|
|
100
|
+
| Variable | Light | Dark | Usage |
|
|
101
|
+
|----------|-------|------|-------|
|
|
102
|
+
| `--color-button-primary` | `#3b82f6` | `#4a90e2` | Primary button background |
|
|
103
|
+
| `--color-button-primary-hover` | `#2563eb` | `#357abd` | Primary button on hover |
|
|
104
|
+
| `--color-button-primary-text` | `#ffffff` | `#ffffff` | Primary button text |
|
|
105
|
+
| `--color-button-danger` | `#ef4444` | `#ef4444` | Danger button background |
|
|
106
|
+
| `--color-button-danger-hover` | `#dc2626` | `#dc2626` | Danger button on hover |
|
|
107
|
+
| `--color-button-danger-text` | `#ffffff` | `#ffffff` | Danger button text |
|
|
108
|
+
|
|
109
|
+
#### Status Colors
|
|
110
|
+
|
|
111
|
+
| Variable | Light | Dark | Usage |
|
|
112
|
+
|----------|-------|------|-------|
|
|
113
|
+
| `--color-status-enabled` | `#22c55e` | `#22c55e` | Enabled/success state |
|
|
114
|
+
| `--color-status-disabled` | `#9ca3af` | `#9ca3af` | Disabled state |
|
|
115
|
+
| `--color-status-warning` | `#f59e0b` | `#f59e0b` | Warning state |
|
|
116
|
+
|
|
117
|
+
#### Highlight Colors
|
|
118
|
+
|
|
119
|
+
Used for code highlighting and data attribute visualization.
|
|
120
|
+
|
|
121
|
+
| Variable | Light | Dark | Usage |
|
|
122
|
+
|----------|-------|------|-------|
|
|
123
|
+
| `--color-highlight-primary` | `#01b5e2` | `#01b5e2` | Primary highlight color |
|
|
124
|
+
| `--highlight-globals` | `#4fc3f7cc` | `#4fc3f7cc` | Global properties highlight |
|
|
125
|
+
| `--highlight-context` | `#ffbd44cc` | `#ffbd44cc` | Context properties highlight |
|
|
126
|
+
| `--highlight-entity` | `#00ca4ecc` | `#00ca4ecc` | Entity name highlight |
|
|
127
|
+
| `--highlight-property` | `#ff605ccc` | `#ff605ccc` | Property name highlight |
|
|
128
|
+
| `--highlight-action` | `#9900ffcc` | `#9900ffcc` | Action name highlight |
|
|
129
|
+
| `--highlight-background` | `#1f2937` | `#1f2937` | Highlight tooltip background |
|
|
130
|
+
| `--highlight-text` | `#9ca3af` | `#9ca3af` | Highlight tooltip text |
|
|
131
|
+
| `--highlight-hover` | `rgba(255,255,255,0.05)` | `rgba(255,255,255,0.05)` | Highlight hover effect |
|
|
132
|
+
| `--highlight-separator` | `rgba(255,255,255,0.05)` | `rgba(255,255,255,0.05)` | Separator in highlights |
|
|
133
|
+
|
|
134
|
+
#### Typography
|
|
135
|
+
|
|
136
|
+
| Variable | Light | Dark | Usage |
|
|
137
|
+
|----------|-------|------|-------|
|
|
138
|
+
| `--font-family-base` | `system-ui, -apple-system, ...` | Same | Base font family |
|
|
139
|
+
| `--font-mono` | `'SF Mono', 'Monaco', ...` | Same | Monospace font for code |
|
|
140
|
+
| `--font-size-base` | `14px` | Same | Base font size |
|
|
141
|
+
| `--font-size-label` | `13px` | Same | Label font size |
|
|
142
|
+
| `--font-size-toggle` | `12px` | Same | Toggle/switch font size |
|
|
143
|
+
| `--font-size-highlight-button` | `0.75rem` | Same | Highlight button font size |
|
|
144
|
+
| `--line-height-base` | `1.5` | Same | Base line height |
|
|
145
|
+
| `--font-weight-normal` | `400` | Same | Normal font weight |
|
|
146
|
+
| `--font-weight-semibold` | `600` | Same | Semibold font weight |
|
|
147
|
+
|
|
148
|
+
#### Spacing & Layout
|
|
149
|
+
|
|
150
|
+
| Variable | Light | Dark | Usage |
|
|
151
|
+
|----------|-------|------|-------|
|
|
152
|
+
| `--spacing-header` | `6px 10px` | Same | Header padding |
|
|
153
|
+
| `--spacing-footer` | `6px 10px` | Same | Footer padding |
|
|
154
|
+
| `--spacing-button` | `4px 8px` | Same | Button padding |
|
|
155
|
+
| `--spacing-button-group` | `1px` | Same | Gap between button group items |
|
|
156
|
+
| `--spacing-grid-gap` | `12px` | Same | Grid gap spacing |
|
|
157
|
+
| `--grid-min-box-width` | `350px` | Same | Minimum box width in grid |
|
|
158
|
+
| `--grid-row-min-height` | `250px` | Same | Minimum grid row height |
|
|
159
|
+
| `--grid-row-max-height` | `450px` | Same | Maximum grid row height |
|
|
160
|
+
| `--grid-box-max-height-mobile` | `500px` | Same | Max box height on mobile |
|
|
161
|
+
|
|
162
|
+
#### Border Radius
|
|
163
|
+
|
|
164
|
+
| Variable | Light | Dark | Usage |
|
|
165
|
+
|----------|-------|------|-------|
|
|
166
|
+
| `--radius-box` | `4px` | Same | Main container border radius |
|
|
167
|
+
| `--radius-button` | `3px` | Same | Button border radius |
|
|
168
|
+
| `--radius-button-group` | `4px` | Same | Button group border radius |
|
|
169
|
+
| `--radius-highlight-button` | `6px` | Same | Highlight button border radius |
|
|
170
|
+
|
|
171
|
+
#### Shadows
|
|
172
|
+
|
|
173
|
+
| Variable | Light | Dark | Usage |
|
|
174
|
+
|----------|-------|------|-------|
|
|
175
|
+
| `--shadow-button-active` | `0 1px 2px rgba(0,0,0,0.1)` | `0 1px 2px rgba(0,0,0,0.3)` | Active button shadow |
|
|
176
|
+
| `--shadow-dropdown` | `0 4px 6px rgba(0,0,0,0.1)` | `0 4px 6px rgba(0,0,0,0.5)` | Dropdown shadow |
|
|
177
|
+
|
|
178
|
+
#### Monaco Editor
|
|
179
|
+
|
|
180
|
+
| Variable | Light | Dark | Usage |
|
|
181
|
+
|----------|-------|------|-------|
|
|
182
|
+
| `--monaco-font-size` | `13px` | Same | Monaco editor font size |
|
|
183
|
+
| `--monaco-line-height` | `1.5` | Same | Monaco editor line height |
|
|
184
|
+
|
|
185
|
+
### Customization Examples
|
|
186
|
+
|
|
187
|
+
**Custom Brand Colors:**
|
|
188
|
+
|
|
189
|
+
```css
|
|
190
|
+
.elb-explorer {
|
|
191
|
+
--color-button-primary: #ff6b35;
|
|
192
|
+
--color-button-primary-hover: #ff5722;
|
|
193
|
+
--border-input-focus: #ff6b35;
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
**Larger Fonts for Accessibility:**
|
|
198
|
+
|
|
199
|
+
```css
|
|
200
|
+
.elb-explorer {
|
|
201
|
+
--font-size-base: 16px;
|
|
202
|
+
--font-size-label: 15px;
|
|
203
|
+
--monaco-font-size: 15px;
|
|
204
|
+
--line-height-base: 1.6;
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
**High Contrast Theme:**
|
|
209
|
+
|
|
210
|
+
```css
|
|
211
|
+
[data-theme='light'] .elb-explorer {
|
|
212
|
+
--color-text: #000000;
|
|
213
|
+
--bg-box: #ffffff;
|
|
214
|
+
--border-box: #000000;
|
|
215
|
+
--color-button-primary: #0000ff;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
[data-theme='dark'] .elb-explorer {
|
|
219
|
+
--color-text: #ffffff;
|
|
220
|
+
--bg-box: #000000;
|
|
221
|
+
--border-box: #ffffff;
|
|
222
|
+
--color-button-primary: #00ffff;
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## Grid System
|
|
229
|
+
|
|
230
|
+
Explorer uses a sophisticated Grid component with three height modes for responsive layouts.
|
|
231
|
+
|
|
232
|
+
### Height Modes
|
|
233
|
+
|
|
234
|
+
**1. Equal Heights** - All boxes in same row share the tallest content height
|
|
235
|
+
```tsx
|
|
236
|
+
<Grid columns={3} heightMode="equal">
|
|
237
|
+
<CodeBox code={event} />
|
|
238
|
+
<CodeBox code={mapping} />
|
|
239
|
+
<CodeBox code={output} />
|
|
240
|
+
</Grid>
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
**2. Auto Heights** - Each box sized independently to content
|
|
244
|
+
```tsx
|
|
245
|
+
<Grid columns={3} heightMode="auto">
|
|
246
|
+
<CodeBox code={shortEvent} />
|
|
247
|
+
<CodeBox code={longMapping} />
|
|
248
|
+
<CodeBox code={mediumOutput} />
|
|
249
|
+
</Grid>
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
**3. Synced Heights** - Boxes in same row share height, different rows can differ
|
|
253
|
+
```tsx
|
|
254
|
+
<Grid columns={3} heightMode="synced">
|
|
255
|
+
<CodeBox code={event} />
|
|
256
|
+
<CodeBox code={mapping} />
|
|
257
|
+
<CodeBox code={output} />
|
|
258
|
+
{/* Next row can have different height */}
|
|
259
|
+
<CodeBox code={shortSnippet} />
|
|
260
|
+
</Grid>
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Implementation Details
|
|
264
|
+
|
|
265
|
+
**Why Grid Heights Are Complex:**
|
|
266
|
+
|
|
267
|
+
The Grid height synchronization required sophisticated coordination because:
|
|
268
|
+
|
|
269
|
+
1. **Monaco reports content-only height** - Excludes header (40px) and border (2px)
|
|
270
|
+
2. **Box needs total height** - Must add header + border for consistent row sizing
|
|
271
|
+
3. **Height changes cascade** - Content → Monaco → Box → Grid → Row
|
|
272
|
+
4. **Race conditions during mount** - Components mount asynchronously
|
|
273
|
+
5. **Automatic layout detection** - Must detect container resize events
|
|
274
|
+
|
|
275
|
+
**Key Files:**
|
|
276
|
+
- [useMonacoHeight.ts](./src/hooks/useMonacoHeight.ts) - Monaco content measurement
|
|
277
|
+
- [GridHeightContext.tsx](./src/contexts/GridHeightContext.tsx) - Cross-component coordination
|
|
278
|
+
- [box.tsx](./src/components/molecules/box.tsx) - Total height calculation
|
|
279
|
+
- [grid.tsx](./src/components/organisms/grid.tsx) - Row height orchestration
|
|
280
|
+
|
|
281
|
+
**Common Pitfalls:**
|
|
282
|
+
|
|
283
|
+
1. **Forgetting Box overhead** - Always add header (40px) + border (2px) to Monaco height
|
|
284
|
+
2. **Not handling async layout** - Monaco's layout() is async, use callbacks
|
|
285
|
+
3. **ResizeObserver loops** - Debounce layout calls with requestAnimationFrame
|
|
286
|
+
4. **Theme-specific heights** - Test both light and dark themes for consistency
|
|
287
|
+
|
|
288
|
+
**Usage Guidelines:**
|
|
289
|
+
|
|
290
|
+
```tsx
|
|
291
|
+
// Grid context - Don't use autoHeight (maintains equal row heights)
|
|
292
|
+
<Grid columns={3} heightMode="synced">
|
|
293
|
+
<CodeBox code={event} label="Event" />
|
|
294
|
+
<CodeBox code={mapping} label="Mapping" />
|
|
295
|
+
</Grid>
|
|
296
|
+
|
|
297
|
+
// Standalone context - Use autoHeight to fit content
|
|
298
|
+
<CodeBox
|
|
299
|
+
code={setupExample}
|
|
300
|
+
label="Setup"
|
|
301
|
+
autoHeight={{ min: 100, max: 600 }}
|
|
302
|
+
disabled
|
|
303
|
+
/>
|
|
304
|
+
|
|
305
|
+
// Explicit height override
|
|
306
|
+
<CodeBox code={longCode} height="600px" />
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
**Height Calculation:**
|
|
310
|
+
|
|
311
|
+
```typescript
|
|
312
|
+
// Monaco provides content-only height
|
|
313
|
+
const contentHeight = editor.getContentHeight(); // e.g., 347px
|
|
314
|
+
|
|
315
|
+
// Box calculates total height
|
|
316
|
+
const totalHeight = contentHeight + 40 + 2; // 389px (includes header + border)
|
|
317
|
+
|
|
318
|
+
// Grid syncs heights across row
|
|
319
|
+
const rowHeight = Math.max(...boxHeightsInRow); // Use tallest box
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## Monaco Editor
|
|
325
|
+
|
|
326
|
+
### Theme Integration
|
|
327
|
+
|
|
328
|
+
Explorer includes two Monaco themes that automatically sync with `data-theme` attribute:
|
|
329
|
+
|
|
330
|
+
- **`elbTheme-dark`** - Dark theme based on Prism Palenight
|
|
331
|
+
- **`elbTheme-light`** - Light theme based on GitHub syntax highlighting
|
|
332
|
+
|
|
333
|
+
**Automatic Theme Switching:**
|
|
334
|
+
|
|
335
|
+
```typescript
|
|
336
|
+
// Theme detection in code.tsx
|
|
337
|
+
const checkTheme = () => {
|
|
338
|
+
const dataTheme = getDataTheme();
|
|
339
|
+
const isDark = dataTheme === 'dark' ||
|
|
340
|
+
(dataTheme === null && window.matchMedia('(prefers-color-scheme: dark)').matches);
|
|
341
|
+
const newTheme = isDark ? 'elbTheme-dark' : 'elbTheme-light';
|
|
342
|
+
setMonacoTheme(newTheme);
|
|
343
|
+
};
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### Token Color Palette (Dark Theme)
|
|
347
|
+
|
|
348
|
+
Current color scheme matches Prism Palenight:
|
|
349
|
+
|
|
350
|
+
| Token Type | Color | Usage |
|
|
351
|
+
|------------|-------|-------|
|
|
352
|
+
| Comments | `#697098` | Gray, italic |
|
|
353
|
+
| Strings | `#c3e88d` | Green |
|
|
354
|
+
| Numbers | `#f78c6c` | Orange |
|
|
355
|
+
| Functions | `#82aaff` | Blue |
|
|
356
|
+
| Delimiters | `#c792ea` | Purple (braces, brackets) |
|
|
357
|
+
| Operators | `#89ddff` | Cyan |
|
|
358
|
+
| Keywords | `#c084fc` | Bright purple, italic |
|
|
359
|
+
| Types/Classes | `#ffcb6b` | Yellow/gold |
|
|
360
|
+
| Variables | `#bfc7d5` | Light gray |
|
|
361
|
+
| Booleans | `#ff5874` | Red |
|
|
362
|
+
| Tags (HTML) | `#bfc7d5` | Light gray |
|
|
363
|
+
| Attributes (HTML) | `#bfc7d5` | Light gray |
|
|
364
|
+
|
|
365
|
+
### Language-Specific Token Rules
|
|
366
|
+
|
|
367
|
+
**Critical**: Monaco uses specific token names per language. Always add language-specific rules for proper highlighting:
|
|
368
|
+
|
|
369
|
+
```typescript
|
|
370
|
+
// Generic rule (may not work)
|
|
371
|
+
{ token: 'string', foreground: 'c3e88d' },
|
|
372
|
+
|
|
373
|
+
// Language-specific rules (work reliably)
|
|
374
|
+
{ token: 'string.html', foreground: 'c3e88d' },
|
|
375
|
+
{ token: 'string.json', foreground: 'c3e88d' },
|
|
376
|
+
{ token: 'string.js', foreground: 'c3e88d' },
|
|
377
|
+
{ token: 'string.ts', foreground: 'c3e88d' },
|
|
378
|
+
{ token: 'string.value.json', foreground: 'c3e88d' },
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
**Common Language-Specific Tokens:**
|
|
382
|
+
|
|
383
|
+
```typescript
|
|
384
|
+
// HTML
|
|
385
|
+
'entity.name.tag.html' // <div>
|
|
386
|
+
'attribute.name.html' // class=""
|
|
387
|
+
'attribute.value.html' // ="value"
|
|
388
|
+
'delimiter.html' // < > / =
|
|
389
|
+
'comment.html' // <!-- -->
|
|
390
|
+
|
|
391
|
+
// JSON
|
|
392
|
+
'string.key.json' // "key":
|
|
393
|
+
'string.value.json' // : "value"
|
|
394
|
+
'support.type.property-name.json' // Object keys
|
|
395
|
+
|
|
396
|
+
// JavaScript/TypeScript
|
|
397
|
+
'variable.parameter.ts' // Function parameters
|
|
398
|
+
'support.type.primitive.ts' // string, number, etc.
|
|
399
|
+
'entity.name.type.ts' // Type names
|
|
400
|
+
'keyword.operator.type.ts' // : => |
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
### Local Loading (Not CDN)
|
|
404
|
+
|
|
405
|
+
**Problem:** Monaco's default behavior loads from CDN, causing CORS issues.
|
|
406
|
+
|
|
407
|
+
**Solution:** Static synchronous imports in [code.tsx](./src/components/atoms/code.tsx):
|
|
408
|
+
|
|
409
|
+
```typescript
|
|
410
|
+
// Static imports for Monaco and workers
|
|
411
|
+
import * as monaco from 'monaco-editor';
|
|
412
|
+
import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker';
|
|
413
|
+
import JsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker';
|
|
414
|
+
// ... other workers
|
|
415
|
+
|
|
416
|
+
// Configure BEFORE any Editor component mounts
|
|
417
|
+
if (typeof window !== 'undefined') {
|
|
418
|
+
self.MonacoEnvironment = {
|
|
419
|
+
getWorker(_: unknown, label: string) {
|
|
420
|
+
if (label === 'json') return new JsonWorker();
|
|
421
|
+
// ... other worker mappings
|
|
422
|
+
return new EditorWorker();
|
|
423
|
+
},
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
loader.config({ monaco }); // Prevents CDN fallback
|
|
427
|
+
}
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
**Why It Works:**
|
|
431
|
+
- Static imports execute synchronously at module load time
|
|
432
|
+
- `loader.config()` runs BEFORE any `<Editor>` component mounts
|
|
433
|
+
- No network requests to CDN
|
|
434
|
+
|
|
435
|
+
### Monaco UI Colors
|
|
436
|
+
|
|
437
|
+
```typescript
|
|
438
|
+
colors: {
|
|
439
|
+
// Transparent backgrounds let CSS variables control color
|
|
440
|
+
'editor.background': '#00000000',
|
|
441
|
+
'editorGutter.background': '#00000000',
|
|
442
|
+
'editor.lineHighlightBackground': '#00000000',
|
|
443
|
+
|
|
444
|
+
// CRITICAL: Sticky scroll MUST have solid background
|
|
445
|
+
'editorStickyScroll.background': '#1e1e2e',
|
|
446
|
+
|
|
447
|
+
// Cursor/selection transparent for read-only snippets
|
|
448
|
+
'editorCursor.foreground': '#00000000',
|
|
449
|
+
'editor.selectionBackground': '#00000000',
|
|
450
|
+
}
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
### Custom Monaco Themes
|
|
454
|
+
|
|
455
|
+
To create a custom Monaco theme:
|
|
456
|
+
|
|
457
|
+
```typescript
|
|
458
|
+
import { lighthouseTheme } from '@walkeros/explorer';
|
|
459
|
+
import type { editor } from 'monaco-editor';
|
|
460
|
+
|
|
461
|
+
const customTheme: editor.IStandaloneThemeData = {
|
|
462
|
+
...lighthouseTheme,
|
|
463
|
+
rules: [
|
|
464
|
+
...lighthouseTheme.rules,
|
|
465
|
+
{ token: 'string', foreground: '00ff00' }, // Green strings
|
|
466
|
+
],
|
|
467
|
+
};
|
|
468
|
+
|
|
469
|
+
// Register in Code component's beforeMount
|
|
470
|
+
<Code
|
|
471
|
+
code={code}
|
|
472
|
+
beforeMount={(monaco) => {
|
|
473
|
+
monaco.editor.defineTheme('my-custom-theme', customTheme);
|
|
474
|
+
monaco.editor.setTheme('my-custom-theme');
|
|
475
|
+
}}
|
|
476
|
+
/>
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
### Debugging Token Colors
|
|
480
|
+
|
|
481
|
+
**Step 1: Find Token Scope**
|
|
482
|
+
|
|
483
|
+
Open Monaco Editor with F1 → "Developer: Inspect Tokens"
|
|
484
|
+
|
|
485
|
+
```
|
|
486
|
+
Token: "const"
|
|
487
|
+
Scopes:
|
|
488
|
+
- keyword.const.ts
|
|
489
|
+
- source.ts
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
**Step 2: Add Specific Rule**
|
|
493
|
+
|
|
494
|
+
```typescript
|
|
495
|
+
// Before (not working)
|
|
496
|
+
{ token: 'keyword', foreground: 'c084fc' }
|
|
497
|
+
|
|
498
|
+
// After (works)
|
|
499
|
+
{ token: 'keyword.const.ts', foreground: 'c084fc' }
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
**Step 3: Verify in Browser DevTools**
|
|
503
|
+
|
|
504
|
+
Inspect rendered Monaco token span:
|
|
505
|
+
```html
|
|
506
|
+
<span class="mtk5">const</span>
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
Check computed styles for `.mtk5` - should have your foreground color.
|
|
510
|
+
|
|
511
|
+
### TypeScript IntelliSense
|
|
512
|
+
|
|
513
|
+
Monaco Editor provides IntelliSense for walkerOS packages through a virtual file system.
|
|
514
|
+
|
|
515
|
+
**How It Works:**
|
|
516
|
+
|
|
517
|
+
```
|
|
518
|
+
User types code → Monaco TypeScript Service → Virtual File System
|
|
519
|
+
import type { WalkerOS } from '@walkeros/core';
|
|
520
|
+
↓
|
|
521
|
+
file:///node_modules/@walkeros/core/index.d.ts
|
|
522
|
+
↓
|
|
523
|
+
IntelliSense: Autocomplete, type checking, hover docs
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
**Bundled Types** (included at build time):
|
|
527
|
+
- `@walkeros/core`
|
|
528
|
+
- `@walkeros/collector`
|
|
529
|
+
- `@walkeros/web-source-browser`
|
|
530
|
+
|
|
531
|
+
**Setup** (automatic):
|
|
532
|
+
|
|
533
|
+
The [monaco-types.ts](./src/utils/monaco-types.ts) utility:
|
|
534
|
+
1. Registers walkerOS type definitions with Monaco
|
|
535
|
+
2. Creates virtual files in Monaco's file system
|
|
536
|
+
3. Provides autocomplete and type checking
|
|
537
|
+
|
|
538
|
+
**Usage:**
|
|
539
|
+
|
|
540
|
+
```typescript
|
|
541
|
+
import { registerWalkerOSTypes } from '../../utils/monaco-types';
|
|
542
|
+
|
|
543
|
+
const handleBeforeMount = (monaco: typeof import('monaco-editor')) => {
|
|
544
|
+
registerWalkerOSTypes(monaco); // Enables IntelliSense
|
|
545
|
+
registerAllThemes(monaco);
|
|
546
|
+
monaco.editor.setTheme('elbTheme-dark');
|
|
547
|
+
};
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
---
|
|
551
|
+
|
|
552
|
+
## SCSS Architecture
|
|
553
|
+
|
|
554
|
+
### Directory Structure
|
|
555
|
+
|
|
556
|
+
```
|
|
557
|
+
src/styles/
|
|
558
|
+
├── index.scss # Main entry (import all components here)
|
|
559
|
+
├── theme/
|
|
560
|
+
│ ├── _tokens.scss # SCSS tokens ($spacing-md: 12px)
|
|
561
|
+
│ ├── _variables.scss # CSS variables (--bg-input, --color-text)
|
|
562
|
+
│ └── _dark.scss # Dark theme overrides
|
|
563
|
+
├── foundation/
|
|
564
|
+
│ ├── _reset.scss
|
|
565
|
+
│ ├── _typography.scss
|
|
566
|
+
│ ├── _layout.scss # Grid/flex mixins
|
|
567
|
+
│ ├── _spacing.scss
|
|
568
|
+
│ └── _responsive.scss # Breakpoint mixins
|
|
569
|
+
└── components/
|
|
570
|
+
├── atoms/ # _button.scss, _toggle.scss, etc.
|
|
571
|
+
├── molecules/ # _code-panel.scss, _tree-sidebar.scss
|
|
572
|
+
└── organisms/ # _box.scss, _grid.scss, _live-code.scss
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
### SCSS Compliance Rules (MANDATORY)
|
|
576
|
+
|
|
577
|
+
**✅ DO:**
|
|
578
|
+
|
|
579
|
+
1. Use ONLY defined CSS variables from `theme/_variables.scss`
|
|
580
|
+
2. Follow BEM naming: `.elb-{component}-{element}--{modifier}`
|
|
581
|
+
3. Use `calc(var(--font-size-base) - 1px)` for font size variations
|
|
582
|
+
4. Create one SCSS file per component in correct directory
|
|
583
|
+
5. Import new files alphabetically in `index.scss`
|
|
584
|
+
6. Use standard gap: `12px` for vertical spacing in flex/grid layouts
|
|
585
|
+
7. Test in both light and dark themes
|
|
586
|
+
|
|
587
|
+
**❌ DON'T:**
|
|
588
|
+
|
|
589
|
+
1. Use undefined CSS variables (e.g., `--bg-secondary`, `--font-size-sm`)
|
|
590
|
+
2. Use `--font-family-mono` (correct: `--font-mono`)
|
|
591
|
+
3. Hardcode colors, spacing, or font sizes
|
|
592
|
+
4. Use inline `style` attributes
|
|
593
|
+
5. Skip wrapper pattern for widgets: `elb-rjsf-widget` → `elb-{name}-widget-wrapper`
|
|
594
|
+
|
|
595
|
+
### Example Component SCSS
|
|
596
|
+
|
|
597
|
+
```scss
|
|
598
|
+
// _my-component.scss
|
|
599
|
+
.elb-my-component {
|
|
600
|
+
// Layout
|
|
601
|
+
display: flex;
|
|
602
|
+
flex-direction: column;
|
|
603
|
+
gap: 12px; // Standard gap
|
|
604
|
+
|
|
605
|
+
// Box model (outside to inside)
|
|
606
|
+
margin: var(--spacing-md);
|
|
607
|
+
border: 1px solid var(--border-box);
|
|
608
|
+
padding: var(--spacing-md);
|
|
609
|
+
|
|
610
|
+
// Typography
|
|
611
|
+
font-family: var(--font-family-base);
|
|
612
|
+
font-size: var(--font-size-base);
|
|
613
|
+
|
|
614
|
+
// Visual
|
|
615
|
+
background-color: var(--bg-box);
|
|
616
|
+
color: var(--color-text);
|
|
617
|
+
border-radius: var(--radius-box);
|
|
618
|
+
|
|
619
|
+
// Modifier
|
|
620
|
+
&--primary {
|
|
621
|
+
background-color: var(--color-button-primary);
|
|
622
|
+
color: white;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
// Element
|
|
626
|
+
&__header {
|
|
627
|
+
font-size: calc(var(--font-size-base) + 2px);
|
|
628
|
+
font-weight: 600;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
// State
|
|
632
|
+
&.-active {
|
|
633
|
+
background-color: var(--color-button-primary);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
### Component Checklist
|
|
639
|
+
|
|
640
|
+
Before submitting any component:
|
|
641
|
+
|
|
642
|
+
- [ ] Placed in correct atomic layer (atoms/molecules/organisms)
|
|
643
|
+
- [ ] TypeScript types exported from component file
|
|
644
|
+
- [ ] SCSS file created with BEM naming (`elb-{component}-*`)
|
|
645
|
+
- [ ] SCSS imported in `index.scss` (alphabetical order)
|
|
646
|
+
- [ ] All CSS variables exist in `theme/_variables.scss`
|
|
647
|
+
- [ ] No hardcoded values (colors, spacing, fonts)
|
|
648
|
+
- [ ] Uses `calc(var(--font-size-base) - Npx)` for size variations
|
|
649
|
+
- [ ] No inline `style` attributes
|
|
650
|
+
- [ ] Light and dark theme tested
|
|
651
|
+
- [ ] Build succeeds: `npm run build`
|
|
652
|
+
|
|
653
|
+
---
|
|
654
|
+
|
|
655
|
+
## Design Rules
|
|
656
|
+
|
|
657
|
+
### When to Add CSS Variables
|
|
658
|
+
|
|
659
|
+
Add a CSS variable when:
|
|
660
|
+
|
|
661
|
+
1. **Color appears in 2+ places** - Ensures consistency
|
|
662
|
+
2. **Value should be theme-aware** - Different light/dark values
|
|
663
|
+
3. **Users might customize** - Exposed as customization API
|
|
664
|
+
4. **Component-specific but reused** - Like `--pane-header-height`
|
|
665
|
+
|
|
666
|
+
Don't add CSS variables for:
|
|
667
|
+
|
|
668
|
+
1. **One-off values** - Use literal values in component SCSS
|
|
669
|
+
2. **Calculated values** - Use SCSS math instead
|
|
670
|
+
3. **Values that never change** - Like specific font names
|
|
671
|
+
|
|
672
|
+
### Color Selection Guidelines
|
|
673
|
+
|
|
674
|
+
**Primary Colors:**
|
|
675
|
+
- Use for interactive elements (buttons, links, focus states)
|
|
676
|
+
- Should have 4.5:1 contrast ratio with background
|
|
677
|
+
- Provide variants (hover, active, disabled)
|
|
678
|
+
|
|
679
|
+
**Text Colors:**
|
|
680
|
+
- Primary text: 7:1 contrast minimum
|
|
681
|
+
- Secondary text: 4.5:1 contrast minimum
|
|
682
|
+
- Always test with [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/)
|
|
683
|
+
|
|
684
|
+
**Syntax Highlighting:**
|
|
685
|
+
- Follow established palette (Prism Palenight for dark, GitHub for light)
|
|
686
|
+
- Ensure readability (4.5:1 minimum for code)
|
|
687
|
+
- Use semantic colors (green for strings, red for errors)
|
|
688
|
+
|
|
689
|
+
**Accessibility:**
|
|
690
|
+
- All interactive elements: 3:1 contrast with background minimum
|
|
691
|
+
- Focus indicators: 3:1 contrast with adjacent colors
|
|
692
|
+
- Test with multiple color vision deficiencies
|
|
693
|
+
|
|
694
|
+
---
|
|
695
|
+
|
|
696
|
+
## Common Tasks
|
|
697
|
+
|
|
698
|
+
### Add a New Component
|
|
699
|
+
|
|
700
|
+
**1. Create Component SCSS** (`src/styles/components/_your-component.scss`):
|
|
701
|
+
|
|
702
|
+
```scss
|
|
703
|
+
@use '../theme/variables';
|
|
704
|
+
|
|
705
|
+
.elb-your-component {
|
|
706
|
+
background-color: var(--bg-box);
|
|
707
|
+
color: var(--color-text);
|
|
708
|
+
border: 1px solid var(--border-box);
|
|
709
|
+
border-radius: var(--radius-box);
|
|
710
|
+
padding: var(--spacing-md);
|
|
711
|
+
|
|
712
|
+
&__header {
|
|
713
|
+
font-size: calc(var(--font-size-base) + 2px);
|
|
714
|
+
font-weight: 600;
|
|
715
|
+
color: var(--color-text);
|
|
716
|
+
border-bottom: 1px solid var(--border-box);
|
|
717
|
+
padding-bottom: var(--spacing-sm);
|
|
718
|
+
margin-bottom: var(--spacing-md);
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
&--primary {
|
|
722
|
+
background-color: var(--color-button-primary);
|
|
723
|
+
color: white;
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
**2. Import in Main SCSS** (`src/styles/index.scss`):
|
|
729
|
+
|
|
730
|
+
```scss
|
|
731
|
+
@use 'components/your-component';
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
**3. Create Component** (`src/components/molecules/your-component.tsx`):
|
|
735
|
+
|
|
736
|
+
```typescript
|
|
737
|
+
import React from 'react';
|
|
738
|
+
|
|
739
|
+
interface YourComponentProps {
|
|
740
|
+
title: string;
|
|
741
|
+
variant?: 'default' | 'primary';
|
|
742
|
+
children: React.ReactNode;
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
export function YourComponent({
|
|
746
|
+
title,
|
|
747
|
+
variant = 'default',
|
|
748
|
+
children
|
|
749
|
+
}: YourComponentProps) {
|
|
750
|
+
const className = `elb-your-component ${variant === 'primary' ? 'elb-your-component--primary' : ''}`.trim();
|
|
751
|
+
|
|
752
|
+
return (
|
|
753
|
+
<div className={className}>
|
|
754
|
+
<div className="elb-your-component__header">
|
|
755
|
+
{title}
|
|
756
|
+
</div>
|
|
757
|
+
{children}
|
|
758
|
+
</div>
|
|
759
|
+
);
|
|
760
|
+
}
|
|
761
|
+
```
|
|
762
|
+
|
|
763
|
+
### Customize Theme Colors
|
|
764
|
+
|
|
765
|
+
**Option 1: Override CSS Variables** (Recommended)
|
|
766
|
+
|
|
767
|
+
```css
|
|
768
|
+
/* custom-theme.css */
|
|
769
|
+
[data-theme="dark"] {
|
|
770
|
+
--color-button-primary: #your-brand-color;
|
|
771
|
+
--bg-app: #your-dark-bg;
|
|
772
|
+
--bg-box: #your-dark-box-bg;
|
|
773
|
+
--color-text: #your-dark-text;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
[data-theme="light"] {
|
|
777
|
+
--color-button-primary: #your-brand-color;
|
|
778
|
+
--bg-app: #your-light-bg;
|
|
779
|
+
--bg-box: #your-light-box-bg;
|
|
780
|
+
--color-text: #your-light-text;
|
|
781
|
+
}
|
|
782
|
+
```
|
|
783
|
+
|
|
784
|
+
Import after Explorer styles:
|
|
785
|
+
|
|
786
|
+
```typescript
|
|
787
|
+
import '@walkeros/explorer/dist/index.css';
|
|
788
|
+
import './custom-theme.css'; // Overrides Explorer defaults
|
|
789
|
+
```
|
|
790
|
+
|
|
791
|
+
**Option 2: Fork and Modify** (Advanced)
|
|
792
|
+
|
|
793
|
+
1. Clone Explorer package
|
|
794
|
+
2. Modify `src/styles/_variables.scss`
|
|
795
|
+
3. Rebuild with `npm run build`
|
|
796
|
+
4. Use local build instead of npm package
|
|
797
|
+
|
|
798
|
+
---
|
|
799
|
+
|
|
800
|
+
## Troubleshooting
|
|
801
|
+
|
|
802
|
+
### Monaco Editor Issues
|
|
803
|
+
|
|
804
|
+
**Problem:** Monaco shows black/white background instead of theme colors
|
|
805
|
+
|
|
806
|
+
**Cause:** Monaco theme not registered before Editor mounts
|
|
807
|
+
|
|
808
|
+
**Solution:** Ensure `handleBeforeMount` registers themes:
|
|
809
|
+
```typescript
|
|
810
|
+
const handleBeforeMount = (monaco: typeof import('monaco-editor')) => {
|
|
811
|
+
registerAllThemes(monaco);
|
|
812
|
+
monaco.editor.setTheme('elbTheme-dark');
|
|
813
|
+
};
|
|
814
|
+
```
|
|
815
|
+
|
|
816
|
+
---
|
|
817
|
+
|
|
818
|
+
**Problem:** Syntax highlighting wrong colors for specific language
|
|
819
|
+
|
|
820
|
+
**Cause:** Missing language-specific token rules
|
|
821
|
+
|
|
822
|
+
**Solution:** Add language variant rules:
|
|
823
|
+
```typescript
|
|
824
|
+
{ token: 'string', foreground: 'c3e88d' }, // Generic
|
|
825
|
+
{ token: 'string.html', foreground: 'c3e88d' }, // HTML-specific
|
|
826
|
+
{ token: 'string.json', foreground: 'c3e88d' }, // JSON-specific
|
|
827
|
+
```
|
|
828
|
+
|
|
829
|
+
---
|
|
830
|
+
|
|
831
|
+
**Problem:** Monaco loads from CDN despite local imports
|
|
832
|
+
|
|
833
|
+
**Cause:** `loader.config()` called after Editor mounts
|
|
834
|
+
|
|
835
|
+
**Solution:** Use static imports at module level:
|
|
836
|
+
```typescript
|
|
837
|
+
// Top of file - runs synchronously
|
|
838
|
+
import * as monaco from 'monaco-editor';
|
|
839
|
+
if (typeof window !== 'undefined') {
|
|
840
|
+
loader.config({ monaco });
|
|
841
|
+
}
|
|
842
|
+
```
|
|
843
|
+
|
|
844
|
+
---
|
|
845
|
+
|
|
846
|
+
**Problem:** Height not updating when content changes
|
|
847
|
+
|
|
848
|
+
**Cause:** Monaco's `automaticLayout: true` missed resize event
|
|
849
|
+
|
|
850
|
+
**Solution:** Add ResizeObserver to force layout:
|
|
851
|
+
```typescript
|
|
852
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
853
|
+
requestAnimationFrame(() => editor.layout());
|
|
854
|
+
});
|
|
855
|
+
resizeObserver.observe(container);
|
|
856
|
+
```
|
|
857
|
+
|
|
858
|
+
---
|
|
859
|
+
|
|
860
|
+
### Grid Layout Issues
|
|
861
|
+
|
|
862
|
+
**Problem:** Boxes different heights in same row (synced mode)
|
|
863
|
+
|
|
864
|
+
**Cause:** Box height calculation missing header/border
|
|
865
|
+
|
|
866
|
+
**Solution:** Verify Box adds header (40px) + border (2px):
|
|
867
|
+
```typescript
|
|
868
|
+
const boxHeight = monacoHeight + 40 + 2;
|
|
869
|
+
```
|
|
870
|
+
|
|
871
|
+
---
|
|
872
|
+
|
|
873
|
+
**Problem:** Grid rows collapsing or overflowing
|
|
874
|
+
|
|
875
|
+
**Cause:** Flex container constraints not set
|
|
876
|
+
|
|
877
|
+
**Solution:** Apply flex constraints to Grid:
|
|
878
|
+
```scss
|
|
879
|
+
.elb-grid {
|
|
880
|
+
display: flex;
|
|
881
|
+
flex-direction: column;
|
|
882
|
+
min-height: 0; // Critical for flex overflow containment
|
|
883
|
+
|
|
884
|
+
&__row {
|
|
885
|
+
display: flex;
|
|
886
|
+
flex: 1;
|
|
887
|
+
min-height: 0; // Also critical
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
```
|
|
891
|
+
|
|
892
|
+
---
|
|
893
|
+
|
|
894
|
+
**Problem:** Heights "bouncing" during resize
|
|
895
|
+
|
|
896
|
+
**Cause:** Race condition between Monaco layout and Grid calculation
|
|
897
|
+
|
|
898
|
+
**Solution:** Use `requestAnimationFrame` to batch updates:
|
|
899
|
+
```typescript
|
|
900
|
+
requestAnimationFrame(() => {
|
|
901
|
+
editor.layout();
|
|
902
|
+
updateHeight(editor.getContentHeight());
|
|
903
|
+
});
|
|
904
|
+
```
|
|
905
|
+
|
|
906
|
+
---
|
|
907
|
+
|
|
908
|
+
### Theme Switching Issues
|
|
909
|
+
|
|
910
|
+
**Problem:** Theme changes but Monaco stays same color
|
|
911
|
+
|
|
912
|
+
**Cause:** Monaco theme name doesn't match data-theme value
|
|
913
|
+
|
|
914
|
+
**Solution:** Map data-theme to Monaco theme name:
|
|
915
|
+
```typescript
|
|
916
|
+
const themeName = dataTheme === 'dark' ? 'elbTheme-dark' : 'elbTheme-light';
|
|
917
|
+
setMonacoTheme(themeName);
|
|
918
|
+
```
|
|
919
|
+
|
|
920
|
+
---
|
|
921
|
+
|
|
922
|
+
**Problem:** CSS variables update but colors don't change
|
|
923
|
+
|
|
924
|
+
**Cause:** Components caching old CSS variable values
|
|
925
|
+
|
|
926
|
+
**Solution:** CSS variables update immediately - check for hard-coded colors:
|
|
927
|
+
```scss
|
|
928
|
+
// Wrong
|
|
929
|
+
.component {
|
|
930
|
+
color: #bfc7d5;
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
// Correct
|
|
934
|
+
.component {
|
|
935
|
+
color: var(--color-text);
|
|
936
|
+
}
|
|
937
|
+
```
|
|
938
|
+
|
|
939
|
+
---
|
|
940
|
+
|
|
941
|
+
## Change Log
|
|
942
|
+
|
|
943
|
+
### November 2025
|
|
944
|
+
|
|
945
|
+
**HTML Token Standardization**
|
|
946
|
+
- Changed HTML tag colors from red (#ff5572) to light gray (#bfc7d5)
|
|
947
|
+
- Changed HTML attribute colors from green (#c3e88d) to light gray (#bfc7d5)
|
|
948
|
+
- Kept attribute string values green for consistency
|
|
949
|
+
- Added comprehensive HTML-specific token rules
|
|
950
|
+
|
|
951
|
+
**Debug Logging Cleanup**
|
|
952
|
+
- Removed all console.log statements from production code
|
|
953
|
+
- Cleaned up code.tsx, monaco-setup.ts, theme files
|
|
954
|
+
|
|
955
|
+
**Documentation Consolidation**
|
|
956
|
+
- Created unified STYLE.md as single source of truth
|
|
957
|
+
- Archived historical docs (STYLE.md, THEME.md, etc.)
|
|
958
|
+
- Eliminated ~30% duplicate content
|
|
959
|
+
|
|
960
|
+
### October 2025
|
|
961
|
+
|
|
962
|
+
**Monaco Theme Rename**
|
|
963
|
+
- Renamed `palenight` theme to `elbTheme-dark`
|
|
964
|
+
- Renamed `lighthouse` theme to `elbTheme-light`
|
|
965
|
+
- Updated all references
|
|
966
|
+
|
|
967
|
+
**Local Monaco Loading**
|
|
968
|
+
- Migrated from CDN to local npm package loading
|
|
969
|
+
- Added static imports for Monaco and language workers
|
|
970
|
+
- Configured MonacoEnvironment for Vite workers
|
|
971
|
+
|
|
972
|
+
**Language-Specific Token Rules**
|
|
973
|
+
- Added HTML-specific tokens
|
|
974
|
+
- Added JSON-specific tokens
|
|
975
|
+
- Added JavaScript/TypeScript-specific tokens
|
|
976
|
+
- Improved token matching reliability
|
|
977
|
+
|
|
978
|
+
### September 2025
|
|
979
|
+
|
|
980
|
+
**Website Color Alignment**
|
|
981
|
+
- Aligned Explorer colors with walkerOS website
|
|
982
|
+
- Updated Prism Palenight colors for dark theme
|
|
983
|
+
- Updated GitHub colors for light theme
|
|
984
|
+
|
|
985
|
+
**Contrast Improvements**
|
|
986
|
+
- Fixed low-contrast text issues (7:1 for primary text)
|
|
987
|
+
- Fixed button contrast issues (4.5:1 minimum)
|
|
988
|
+
- Fixed border contrast issues (3:1 minimum)
|
|
989
|
+
- WCAG AA compliance achieved
|
|
990
|
+
|
|
991
|
+
---
|
|
992
|
+
|
|
993
|
+
**Last Updated:** 2025-11-06
|