diff --git a/public/css/style.css b/public/css/style.css index 3349e40..9caa02f 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -13,20 +13,22 @@ --label-h: 26px; } -html, body { height: 100%; overflow: hidden; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: var(--bg); color: var(--text); } +html, body { height: 100%; overflow: hidden; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: var(--bg); color: var(--text); display: flex; flex-direction: column; } /* Toolbar */ .toolbar { - height: var(--toolbar-h); + min-height: var(--toolbar-h); display: flex; align-items: center; justify-content: space-between; - padding: 0 12px; + padding: 4px 12px; background: var(--surface); border-bottom: 1px solid var(--border); gap: 8px; + flex-wrap: wrap; } -.toolbar-left, .toolbar-right { display: flex; align-items: center; gap: 8px; } +.toolbar-left, .toolbar-right { display: flex; align-items: center; gap: 8px; flex-shrink: 1; min-width: 0; } +.toolbar-right { flex-wrap: wrap; } .logo { font-weight: 700; font-size: 16px; color: var(--accent); text-decoration: none; } #title-input { background: transparent; border: 1px solid transparent; color: var(--text); @@ -52,7 +54,7 @@ button:hover { background: var(--accent-hover); } display: grid; grid-template-columns: 1fr 4px 1fr; grid-template-rows: 1fr 4px 1fr; - height: calc(100vh - var(--toolbar-h)); + flex: 1; min-height: 0; } .panel { position: relative; border: 1px solid var(--border); overflow: hidden; display: flex; flex-direction: column; } .panel-label { @@ -155,7 +157,20 @@ body.resizing iframe { pointer-events: none; } } .editor-container.active { display: block; } -#preview-frame { flex: 1; border: none; background: #fff; width: 100%; } +/* Preview viewport + responsive device toggles */ +.preview-viewport { flex: 1; min-height: 0; display: flex; justify-content: center; overflow: auto; background: inherit; } +#preview-frame { border: none; background: #fff; width: 100%; height: 100%; } +.preview-viewport.device-tablet #preview-frame { max-width: 768px; } +.preview-viewport.device-mobile #preview-frame { max-width: 375px; } +.preview-viewport.device-tablet, .preview-viewport.device-mobile { background: #111; } + +.device-toggles { display: flex; gap: 2px; } +.device-btn { + background: transparent; border: none; color: var(--text-dim); padding: 2px 5px; + cursor: pointer; border-radius: 3px; display: flex; align-items: center; justify-content: center; +} +.device-btn:hover { color: var(--text); background: rgba(255,255,255,0.06); } +.device-btn.active { color: var(--accent); background: rgba(0,120,212,0.12); } /* Console */ #console-output { @@ -211,7 +226,7 @@ body.resizing iframe { pointer-events: none; } .divider { background: var(--border); transition: background 0.15s; z-index: 2; } /* Layout/keybinding/preview-theme selects — match framework select */ -#layout-mode, #keybinding-mode, #preview-theme { +#layout-mode, #keybinding-mode, #preview-theme, #editor-theme { background: var(--bg); color: var(--text); border: 1px solid var(--border); padding: 4px 6px; border-radius: 4px; font-size: 12px; cursor: pointer; } @@ -343,3 +358,240 @@ body.resizing iframe { pointer-events: none; } #title-input, .tags-input-wrap { display: none; } .modal-content { margin: 8px; min-width: unset !important; width: calc(100% - 16px); } } + +/* ===================== Devtools Tabs ===================== */ +.devtools-tabs { + height: var(--label-h); + display: flex; + align-items: center; + background: var(--surface); + border-bottom: 1px solid var(--border); + flex-shrink: 0; + gap: 0; + padding: 0 4px; +} +.devtools-tab { + background: transparent; + color: var(--text-dim); + border: none; + border-bottom: 2px solid transparent; + padding: 0 10px; + font-size: 10px; + font-weight: 600; + text-transform: uppercase; + cursor: pointer; + height: 100%; + border-radius: 0; + display: flex; + align-items: center; + position: relative; +} +.devtools-tab:hover { color: var(--text); background: rgba(255,255,255,0.04); } +.devtools-tab.active { color: var(--text); border-bottom-color: var(--accent); } +.devtools-tab .badge { + background: #f44747; + color: #fff; + font-size: 9px; + font-weight: 700; + padding: 0 4px; + border-radius: 8px; + margin-left: 4px; + min-width: 14px; + text-align: center; + line-height: 14px; +} +.devtools-spacer { flex: 1; } +.devtools-panels { flex: 1; overflow: hidden; position: relative; min-height: 0; } +.devtools-panel { + position: absolute; + top: 0; left: 0; right: 0; bottom: 0; + display: none; + flex-direction: column; + overflow: hidden; +} +.devtools-panel.active { display: flex; } + +/* Console output (unchanged, just nested deeper now) */ +#console-output { flex: 1; overflow-y: auto; } + +/* ===================== Network Tab ===================== */ +.network-table { + width: 100%; + border-collapse: collapse; + font-family: 'Cascadia Code', 'Fira Code', monospace; + font-size: 11px; +} +.network-table th { + position: sticky; + top: 0; + background: var(--surface); + color: var(--text-dim); + font-size: 10px; + font-weight: 600; + text-transform: uppercase; + text-align: left; + padding: 4px 8px; + border-bottom: 1px solid var(--border); +} +.network-table td { + padding: 3px 8px; + border-bottom: 1px solid #2a2a2a; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 300px; +} +.network-table tr:hover { background: rgba(255,255,255,0.03); } +.net-type { + font-size: 9px; + font-weight: 700; + text-transform: uppercase; + padding: 1px 4px; + border-radius: 2px; + display: inline-block; +} +.net-type-script { background: #4d3b00; color: #dcdcaa; } +.net-type-link, .net-type-css { background: #264f78; color: #9cdcfe; } +.net-type-img { background: #1e4620; color: #6a9955; } +.net-type-fetch, .net-type-xmlhttprequest { background: #3b1f6e; color: #c586c0; } +.net-type-other { background: var(--border); color: var(--text-dim); } +.network-footer { + position: sticky; + bottom: 0; + background: var(--surface); + padding: 4px 8px; + font-size: 10px; + color: var(--text-dim); + border-top: 1px solid var(--border); + display: flex; + gap: 16px; +} +#network-output { + flex: 1; + overflow-y: auto; + display: flex; + flex-direction: column; +} + +/* ===================== Elements Tab ===================== */ +#elements-output { + flex: 1; + overflow: auto; + padding: 6px 0; + font-family: 'Cascadia Code', 'Fira Code', monospace; + font-size: 12px; + line-height: 1.5; +} +.el-node { padding-left: 16px; } +.el-node-header { + display: flex; + align-items: center; + gap: 2px; + cursor: pointer; + padding: 1px 4px; + border-radius: 2px; +} +.el-node-header:hover { background: rgba(255,255,255,0.04); } +.el-toggle { + width: 14px; + font-size: 10px; + color: var(--text-dim); + flex-shrink: 0; + text-align: center; + user-select: none; +} +.el-tag { color: #c586c0; } +.el-attr-name { color: #9cdcfe; } +.el-attr-value { color: #ce9178; } +.el-text { color: var(--text-dim); font-style: italic; } +.el-children { display: none; } +.el-children.expanded { display: block; } +.el-refresh { + margin-left: 8px; + font-size: 10px; + padding: 1px 6px; +} + +/* ===================== Performance Tab ===================== */ +#performance-output { + flex: 1; + overflow-y: auto; + padding: 12px; + display: flex; + flex-wrap: wrap; + gap: 10px; + align-content: flex-start; +} +.perf-card { + background: var(--surface); + border: 1px solid var(--border); + border-radius: 6px; + padding: 12px 16px; + min-width: 140px; + flex: 1; +} +.perf-card-label { + font-size: 10px; + font-weight: 600; + text-transform: uppercase; + color: var(--text-dim); + margin-bottom: 4px; +} +.perf-card-value { + font-family: 'Cascadia Code', 'Fira Code', monospace; + font-size: 20px; + font-weight: 700; +} +.perf-green { color: #6a9955; } +.perf-yellow { color: #cca700; } +.perf-red { color: #f44747; } +.perf-neutral { color: var(--text); } + +/* ===================== Format / Diff Buttons ===================== */ +.tab-bar-spacer { flex: 1; } +.tab-bar-btn { + background: transparent; + color: var(--text-dim); + border: none; + border-bottom: 2px solid transparent; + padding: 0 10px; + font-size: 11px; + font-weight: 500; + cursor: pointer; + border-radius: 0; + display: flex; + align-items: center; + white-space: nowrap; +} +.tab-bar-btn:hover { color: var(--text); background: rgba(255,255,255,0.04); } +.tab-bar-btn.active { color: var(--accent); border-bottom-color: var(--accent); } + +/* ===================== Templates Gallery ===================== */ +.templates-modal-content { min-width: 560px; max-width: 640px; } +.templates-grid { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 12px; + max-height: 420px; + overflow-y: auto; + padding: 4px; +} +.template-card { + background: var(--bg); + border: 1px solid var(--border); + border-radius: 8px; + padding: 14px; + cursor: pointer; + transition: border-color 0.15s, background 0.15s; + text-align: left; +} +.template-card:hover { border-color: var(--accent); background: rgba(0,120,212,0.06); } +.template-card-icon { font-size: 22px; margin-bottom: 6px; } +.template-card-title { font-size: 13px; font-weight: 600; color: var(--text); margin-bottom: 4px; } +.template-card-desc { font-size: 11px; color: var(--text-dim); line-height: 1.4; } +.template-card-mode { font-size: 9px; font-weight: 600; text-transform: uppercase; color: var(--accent); margin-top: 6px; } + +@media (max-width: 480px) { + .templates-modal-content { min-width: unset !important; } + .templates-grid { grid-template-columns: 1fr; } +} diff --git a/public/index.html b/public/index.html index 6d549eb..9b78785 100644 --- a/public/index.html +++ b/public/index.html @@ -32,6 +32,14 @@ +
@@ -43,6 +51,7 @@ +
-
Preview
- +
+ Preview + + + + + +
+
+ +
-
Console
-
+
+ + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -114,6 +158,8 @@ Ctrl/Cmd + EnterRun code Ctrl/Cmd + SSave fiddle ?Show shortcuts + Shift + Alt + FFormat code (Prettier) + Ctrl/Cmd + DToggle diff view Keybinding Modes VimFull vim keybindings (select in toolbar) EmacsFull emacs keybindings (select in toolbar) @@ -133,6 +179,16 @@
+ + + +
+

{greeting}

+ +
+ + {count} (doubled: {doubled}) + +
+
+ +`, + }, +];