Skip to content

Commit 006385a

Browse files
refactor: defaults.
1 parent f71defe commit 006385a

4 files changed

Lines changed: 109 additions & 94 deletions

File tree

src/app.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {
44
importFromCdnWithFallback,
55
} from './modules/cdn.js'
66
import { createCodeMirrorEditor } from './modules/editor-codemirror.js'
7-
import { defaultCss, defaultJsx } from './modules/defaults.js'
7+
import { defaultCss, defaultJsx, defaultReactJsx } from './modules/defaults.js'
88
import { createDiagnosticsUiController } from './modules/diagnostics-ui.js'
99
import { createLayoutThemeController } from './modules/layout-theme.js'
1010
import { createPreviewBackgroundController } from './modules/preview-background.js'
@@ -52,6 +52,7 @@ let getCssSource = () => cssEditor.value
5252
let renderRuntime = null
5353
let pendingClearAction = null
5454
let suppressEditorChangeSideEffects = false
55+
let hasAppliedReactModeDefault = false
5556
const clipboardSupported = Boolean(navigator.clipboard?.writeText)
5657

5758
const previewBackground = createPreviewBackgroundController({
@@ -350,7 +351,15 @@ const updateRenderButtonVisibility = () => {
350351
renderButton.hidden = autoRenderToggle.checked
351352
}
352353

353-
renderMode.addEventListener('change', maybeRender)
354+
renderMode.addEventListener('change', () => {
355+
if (renderMode.value === 'react' && !hasAppliedReactModeDefault) {
356+
hasAppliedReactModeDefault = true
357+
setJsxSource(defaultReactJsx)
358+
markTypeDiagnosticsStale()
359+
}
360+
361+
maybeRender()
362+
})
354363
styleMode.addEventListener('change', () => {
355364
if (cssCodeEditor) {
356365
cssCodeEditor.setLanguage(getStyleEditorLanguage(styleMode.value))

src/modules/defaults.js

Lines changed: 71 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,114 +1,94 @@
11
export const defaultJsx = [
2-
'const Item = ({ value }) => <li>{value}</li>',
3-
'const List = ({ items, onClick }) => (',
4-
' <ul onClick={onClick}>',
5-
' {items.map(item => <Item key={item} value={item} />)}',
6-
' </ul>',
2+
'type CounterButtonProps = {',
3+
' label: string',
4+
' onClick: (event: MouseEvent) => void',
5+
'}',
6+
'',
7+
'const CounterButton = ({ label, onClick }: CounterButtonProps) => (',
8+
' <button id="counter-button" type="button" onClick={onClick}>',
9+
' {label}',
10+
' </button>',
711
')',
8-
'const Checkbox = ({ checked = false }) => <input type="checkbox" checked={checked} />',
12+
'',
913
'const App = () => {',
10-
" const items = ['apple', 'banana', 'orange']",
11-
' const checkbox = <Checkbox checked={true} />',
12-
' const onClickList = evt => {',
13-
' if (evt.target.contains(checkbox)) {',
14-
' checkbox.remove()',
15-
' } else {',
16-
' evt.target.appendChild(checkbox)',
17-
' }',
14+
' let count = 0',
15+
' const handleClick = (event: MouseEvent) => {',
16+
' count += 1',
17+
' const button = event.currentTarget as HTMLButtonElement',
18+
' button.textContent = `Clicks: ${count}`',
19+
" button.dataset.active = count % 2 === 0 ? 'false' : 'true'",
20+
" button.classList.toggle('is-even', count % 2 === 0)",
1821
' }',
1922
'',
20-
' return <List items={items} onClick={onClickList} />',
23+
" return <CounterButton label='Clicks: 0' onClick={handleClick} />",
2124
'}',
2225
'',
2326
].join('\n')
2427

25-
export const defaultCss = `ul {
26-
--list-bg: linear-gradient(160deg, #d4dcec 0%, #c4cfe6 100%);
27-
--list-border: #a5b4d8;
28-
--item-bg: #b9bcc4;
29-
--item-hover: #c5c8cf;
30-
--item-text: #1f2a44;
31-
--item-accent: #3658c8;
32-
--check-ring: #6d86d1;
28+
export const defaultReactJsx = [
29+
'type CounterButtonProps = {',
30+
' label: string',
31+
' active: boolean',
32+
' onClick: (event: MouseEvent) => void',
33+
'}',
34+
'',
35+
'const CounterButton = ({ label, active, onClick }: CounterButtonProps) => (',
36+
' <button',
37+
' id="counter-button"',
38+
' type="button"',
39+
' data-active={active ? "true" : "false"}',
40+
' className={active ? "is-even" : ""}',
41+
' onClick={onClick}',
42+
' >',
43+
' {label}',
44+
' </button>',
45+
')',
46+
'',
47+
'const App = () => {',
48+
' const { useState } = React',
49+
' const [count, setCount] = useState(0)',
50+
' const handleClick = (_event: MouseEvent) => {',
51+
' setCount(current => current + 1)',
52+
' }',
53+
'',
54+
' return (',
55+
' <CounterButton',
56+
' label={`React clicks: ${count}`}',
57+
' active={count % 2 === 0}',
58+
' onClick={handleClick}',
59+
' />',
60+
' )',
61+
'}',
62+
'',
63+
].join('\n')
3364

65+
export const defaultCss = `#counter-button {
3466
margin: 0;
35-
padding: 14px;
36-
list-style: none;
37-
display: grid;
38-
gap: 10px;
39-
max-width: 340px;
40-
border-radius: 16px;
41-
border: 1px solid var(--list-border);
42-
background: var(--list-bg);
43-
box-shadow:
44-
0 14px 30px rgba(17, 27, 56, 0.16),
45-
inset 0 1px 0 rgba(255, 255, 255, 0.55);
46-
}
47-
48-
li {
49-
display: flex;
50-
align-items: center;
51-
justify-content: space-between;
52-
gap: 10px;
53-
min-height: 40px;
54-
padding: 10px 12px;
55-
border-radius: 12px;
56-
border: 1px solid rgba(54, 88, 200, 0.24);
57-
background: var(--item-bg);
58-
color: var(--item-text);
59-
font-weight: 650;
60-
letter-spacing: 0.01em;
67+
padding: 0.75rem 1rem;
68+
border: 1px solid #3558b8;
69+
border-radius: 0.5rem;
70+
background: #e9efff;
71+
color: #1a2a52;
72+
font-weight: 600;
6173
cursor: pointer;
62-
user-select: none;
63-
transition:
64-
transform 130ms ease,
65-
background-color 130ms ease,
66-
border-color 130ms ease,
67-
box-shadow 130ms ease;
68-
}
69-
70-
li:hover {
71-
transform: translateY(-1px);
72-
background: var(--item-hover);
73-
border-color: rgba(54, 88, 200, 0.34);
74-
box-shadow: 0 8px 18px rgba(24, 40, 95, 0.16);
75-
}
76-
77-
input[type='checkbox'] {
78-
appearance: none;
79-
width: 18px;
80-
height: 18px;
81-
margin: 0;
82-
border-radius: 5px;
83-
border: 1.5px solid #4a63b6;
84-
background: #fff;
85-
display: inline-grid;
86-
place-items: center;
87-
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7);
74+
transition: background-color 120ms ease;
8875
}
8976
90-
input[type='checkbox']::after {
91-
content: '';
92-
width: 8px;
93-
height: 4px;
94-
border: 2px solid #fff;
95-
border-top: 0;
96-
border-right: 0;
97-
transform: rotate(-45deg) scale(0);
98-
transition: transform 120ms ease;
77+
#counter-button:hover {
78+
background: #dce6ff;
9979
}
10080
101-
input[type='checkbox']:checked {
102-
background: linear-gradient(145deg, var(--item-accent), #345ee0);
103-
border-color: var(--item-accent);
81+
#counter-button[data-active='true'] {
82+
background: #3558b8;
83+
color: #fff;
10484
}
10585
106-
input[type='checkbox']:checked::after {
107-
transform: rotate(-45deg) scale(1);
86+
#counter-button.is-even {
87+
border-style: dashed;
10888
}
10989
110-
input[type='checkbox']:focus-visible {
111-
outline: 2px solid var(--check-ring);
90+
#counter-button:focus-visible {
91+
outline: 2px solid #6a84d8;
11292
outline-offset: 2px;
11393
}
11494
`

src/modules/diagnostics-ui.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ export const createDiagnosticsUiController = ({
5555
return 'pending'
5656
}
5757

58+
if (diagnosticsByScope.component.level === 'ok') {
59+
return 'ok'
60+
}
61+
5862
return 'neutral'
5963
}
6064

@@ -67,6 +71,7 @@ export const createDiagnosticsUiController = ({
6771
if (diagnosticsToggle) {
6872
diagnosticsToggle.classList.remove(
6973
'diagnostics-toggle--neutral',
74+
'diagnostics-toggle--ok',
7075
'diagnostics-toggle--pending',
7176
'diagnostics-toggle--error',
7277
)
@@ -108,7 +113,10 @@ export const createDiagnosticsUiController = ({
108113

109114
if (hasHeadline) {
110115
const headingNode = document.createElement('div')
111-
headingNode.className = 'type-diagnostics-heading'
116+
headingNode.className =
117+
state.level === 'ok'
118+
? 'type-diagnostics-heading type-diagnostics-heading--ok'
119+
: 'type-diagnostics-heading'
112120
headingNode.textContent = state.headline
113121
root.append(headingNode)
114122
}

src/styles/diagnostics.css

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@
2020
margin: 0;
2121
}
2222

23+
.type-diagnostics-heading--ok::before {
24+
content: '\2713';
25+
color: #22c55e;
26+
font-weight: 700;
27+
margin-right: 6px;
28+
}
29+
2330
.type-diagnostics-list {
2431
margin: 8px 0 0;
2532
padding-left: 0;
@@ -60,6 +67,17 @@
6067
color: var(--shell-text);
6168
}
6269

70+
.diagnostics-toggle--ok {
71+
border-color: color-mix(in srgb, #22c55e 52%, var(--border-control));
72+
background: color-mix(in srgb, #22c55e 14%, transparent);
73+
color: color-mix(in srgb, #22c55e 88%, var(--panel-text));
74+
}
75+
76+
.diagnostics-toggle--ok::after {
77+
content: ' \2713';
78+
font-weight: 700;
79+
}
80+
6381
.diagnostics-toggle--pending {
6482
border-color: color-mix(in srgb, var(--accent) 55%, var(--border-control));
6583
background: color-mix(in srgb, var(--accent) 18%, transparent);

0 commit comments

Comments
 (0)