Implement custom Windows title bar and theme refactor

Adds a frameless window with custom title bar controls for Windows, including minimize, maximize/restore, and close buttons. Refactors theme color application to use CSS variables and color-mix for improved consistency and dynamic theming across home, settings, and main UI. Updates renderer and styles to support the new title bar, platform detection, and improved color handling. No changes to lock files.
This commit is contained in:
2026-01-01 15:25:45 +13:00
parent 1b71a4001d
commit 26126982e2
6 changed files with 398 additions and 188 deletions
+46 -50
View File
@@ -49,14 +49,14 @@ body, html {
padding: 4rem 2rem 2rem;
}
.edit-btn { position: fixed; top: 16px; right: 16px; z-index: 5; background: rgba(255,255,255,0.1); color:#fff; border:1px solid rgba(255,255,255,0.2); border-radius:8px; padding:6px 10px; cursor:pointer; backdrop-filter: blur(6px); }
.edit-btn[aria-pressed="true"] { background: rgba(255,255,255,0.22); }
.edit-btn { position: fixed; top: 16px; right: 16px; z-index: 5; background: color-mix(in srgb, var(--text) 10%, transparent); color: var(--text); border:1px solid color-mix(in srgb, var(--text) 20%, transparent); border-radius:8px; padding:6px 10px; cursor:pointer; backdrop-filter: blur(6px); }
.edit-btn[aria-pressed="true"] { background: color-mix(in srgb, var(--text) 22%, transparent); }
.edit-mode .edit-btn { display:none; }
.edit-mode .greeting-title, .edit-mode .search-container, .edit-mode .top-sites-card, .edit-mode .glance { outline: 2px dashed rgba(255,255,255,0.35); outline-offset: 4px; cursor: grab; }
.edit-mode .greeting-title, .edit-mode .search-container, .edit-mode .top-sites-card, .edit-mode .glance { outline: 2px dashed color-mix(in srgb, var(--text) 35%, transparent); outline-offset: 4px; cursor: grab; }
.edit-mode .glance.dragging { cursor: grabbing; }
/* Edit toolbar */
.edit-toolbar { position: fixed; top: 16px; right: 16px; display:none; gap:10px; z-index:6; backdrop-filter: blur(8px); background: rgba(8,10,16,0.5); border:1px solid rgba(255,255,255,0.15); padding:8px 10px; border-radius:12px; box-shadow: 0 12px 30px -14px rgba(0,0,0,.7); }
.edit-toolbar { position: fixed; top: 16px; right: 16px; display:none; gap:10px; z-index:6; backdrop-filter: blur(8px); background: color-mix(in srgb, var(--bg) 50%, transparent); border:1px solid color-mix(in srgb, var(--text) 15%, transparent); padding:8px 10px; border-radius:12px; box-shadow: 0 12px 30px -14px color-mix(in srgb, var(--bg) 70%, transparent); }
.edit-mode .edit-toolbar { display:flex; }
.edit-toolbar[hidden] { display: none !important; }
@@ -65,17 +65,17 @@ body, html {
.edit-btn.pos-bl, .edit-toolbar.pos-bl { left:16px; bottom:16px; right:auto; top:auto; }
.edit-btn.pos-tr, .edit-toolbar.pos-tr { right:16px; top:16px; left:auto; bottom:auto; }
.edit-btn.pos-tl, .edit-toolbar.pos-tl { left:16px; top:16px; right:auto; bottom:auto; }
.edit-toolbar .btn { min-width:90px; padding:8px 12px; border-radius:8px; border:1px solid transparent; color:#fff; cursor:pointer; }
.edit-toolbar .btn { min-width:90px; padding:8px 12px; border-radius:8px; border:1px solid transparent; color: var(--text); cursor:pointer; }
.edit-toolbar .btn.primary { background: linear-gradient(135deg, var(--accent), var(--primary)); }
.edit-toolbar .btn.secondary { background: rgba(255,255,255,0.14); border-color: rgba(255,255,255,0.2); }
.edit-toolbar .btn.secondary { background: color-mix(in srgb, var(--text) 14%, transparent); border-color: color-mix(in srgb, var(--text) 20%, transparent); }
/* Greeting hero title */
.greeting-title {
font-size: clamp(2rem, 5vw, 3.5rem);
font-weight: 700;
letter-spacing: 0.3px;
color: #cfd4ff;
text-shadow: 0 4px 22px rgba(0,0,0,0.6);
color: var(--text);
text-shadow: 0 4px 22px color-mix(in srgb, var(--bg) 60%, transparent);
margin-bottom: 1.25rem;
position: relative;
top: var(--home-greeting-y);
@@ -119,14 +119,10 @@ body, html {
z-index: 300; /* ensure dropdown overlays bookmarks/top-sites stacking contexts */
top: var(--home-search-y);
/* Unified glassy pill */
background: linear-gradient(
180deg,
rgba(255,255,255,0.14),
rgba(255,255,255,0.10)
);
border: 1px solid rgba(255,255,255,0.20);
background: color-mix(in srgb, var(--text) 12%, transparent);
border: 1px solid color-mix(in srgb, var(--text) 20%, transparent);
border-radius: 9999px;
box-shadow: 0 18px 50px -22px rgba(0,0,0,0.8), inset 0 1px 0 rgba(255,255,255,0.12);
box-shadow: 0 18px 50px -22px color-mix(in srgb, var(--bg) 80%, transparent), inset 0 1px 0 color-mix(in srgb, var(--text) 12%, transparent);
backdrop-filter: blur(10px) saturate(140%);
-webkit-backdrop-filter: blur(10px) saturate(140%);
padding: 6px 8px;
@@ -134,13 +130,13 @@ body, html {
}
.search-container:hover {
background: linear-gradient(180deg, rgba(255,255,255,0.18), rgba(255,255,255,0.12));
border-color: rgba(255,255,255,0.28);
background: color-mix(in srgb, var(--text) 16%, transparent);
border-color: color-mix(in srgb, var(--text) 28%, transparent);
}
.search-container:focus-within {
box-shadow: 0 22px 60px -24px rgba(0,0,0,0.9), 0 0 0 2px rgba(123,46,255,0.45), inset 0 1px 0 rgba(255,255,255,0.16);
border-color: rgba(123,46,255,0.55);
box-shadow: 0 22px 60px -24px color-mix(in srgb, var(--bg) 90%, transparent), 0 0 0 2px color-mix(in srgb, var(--primary) 45%, transparent), inset 0 1px 0 color-mix(in srgb, var(--text) 16%, transparent);
border-color: color-mix(in srgb, var(--primary) 55%, transparent);
}
/* Search bar */
@@ -161,18 +157,18 @@ body, html {
padding: 0 10px 0 8px;
font-size: 1.05rem;
line-height: 1;
color: #ffffff;
color: var(--text);
caret-color: var(--accent);
}
.search-bar input.search-input::placeholder {
color: rgba(255,255,255,0.55);
color: color-mix(in srgb, var(--text) 55%, transparent);
}
.search-bar button.search-btn {
border: 1px solid rgba(255,255,255,0.14);
background: rgba(12,14,20,0.45);
color: white;
border: 1px solid color-mix(in srgb, var(--text) 14%, transparent);
background: color-mix(in srgb, var(--bg) 45%, transparent);
color: var(--text);
width: 40px;
height: 40px;
border-radius: 9999px;
@@ -184,7 +180,7 @@ body, html {
transition: transform 120ms ease, background 160ms ease, border-color 160ms ease;
}
.search-bar button.search-btn:hover { transform: scale(1.02); background: rgba(24,26,34,0.55); border-color: rgba(255,255,255,0.24); }
.search-bar button.search-btn:hover { transform: scale(1.02); background: color-mix(in srgb, var(--bg) 55%, transparent); border-color: color-mix(in srgb, var(--text) 24%, transparent); }
.search-bar button.search-btn:active { transform: scale(0.98); }
.search-bar button.search-btn .material-symbols-outlined {
@@ -194,8 +190,8 @@ body, html {
/* Search engine trigger unified look */
.search-engine-selector { position: relative; display: flex; align-items: center; }
.search-engine-btn {
background: rgba(12,14,20,0.45);
border: 1px solid rgba(255,255,255,0.14);
background: color-mix(in srgb, var(--bg) 45%, transparent);
border: 1px solid color-mix(in srgb, var(--text) 14%, transparent);
border-radius: 9999px;
padding: 8px 10px 8px 12px;
cursor: pointer;
@@ -207,7 +203,7 @@ body, html {
box-shadow: none;
transition: background 160ms ease, border-color 160ms ease, transform 120ms ease;
}
.search-engine-btn:hover { background: rgba(24,26,34,0.55); border-color: rgba(255,255,255,0.24); }
.search-engine-btn:hover { background: color-mix(in srgb, var(--bg) 55%, transparent); border-color: color-mix(in srgb, var(--text) 24%, transparent); }
.search-engine-btn:active { transform: scale(0.98); }
.search-engine-btn img { width: 22px; height: 22px; filter: none; }
@@ -220,7 +216,7 @@ body, html {
top: 8px;
bottom: 8px;
width: 1px;
background: linear-gradient(to bottom, rgba(255,255,255,0.06), rgba(255,255,255,0.24), rgba(255,255,255,0.06));
background: linear-gradient(to bottom, color-mix(in srgb, var(--text) 6%, transparent), color-mix(in srgb, var(--text) 24%, transparent), color-mix(in srgb, var(--text) 6%, transparent));
pointer-events: none;
}
@@ -244,10 +240,10 @@ body, html {
position: absolute;
top: 110%;
left: 0;
background: linear-gradient(180deg, rgba(18,20,24,0.96), rgba(18,20,24,0.9));
background: color-mix(in srgb, var(--bg) 94%, #000 6%);
border-radius: 10px;
border: 1px solid rgba(255,255,255,0.12);
box-shadow: 0 18px 50px -22px rgba(0,0,0,0.8), inset 0 1px 0 rgba(255,255,255,0.06);
border: 1px solid color-mix(in srgb, var(--text) 12%, transparent);
box-shadow: 0 18px 50px -22px color-mix(in srgb, var(--bg) 80%, transparent), inset 0 1px 0 color-mix(in srgb, var(--text) 6%, transparent);
z-index: 100;
padding: 0.5rem;
display: flex;
@@ -310,9 +306,9 @@ body, html {
margin-top: 1.25rem;
padding: 1rem 1rem 1.25rem;
border-radius: 16px;
background: radial-gradient(120% 140% at 0% 0%, rgba(255,255,255,0.06), rgba(255,255,255,0.03) 45%, rgba(255,255,255,0.02));
border: 1px solid rgba(255,255,255,0.12);
box-shadow: 0 18px 50px -20px rgba(0,0,0,0.6), inset 0 1px 0 rgba(255,255,255,0.06);
background: color-mix(in srgb, var(--text) 6%, transparent);
border: 1px solid color-mix(in srgb, var(--text) 12%, transparent);
box-shadow: 0 18px 50px -20px color-mix(in srgb, var(--bg) 60%, transparent), inset 0 1px 0 color-mix(in srgb, var(--text) 6%, transparent);
backdrop-filter: blur(6px);
position: relative;
top: var(--home-bookmarks-y);
@@ -321,18 +317,18 @@ body, html {
display:flex; align-items:center; justify-content:space-between;
margin-bottom: 0.75rem; padding: 0 0.25rem;
}
.top-sites-header h2 { font-size: 1rem; font-weight: 700; color: #dfe3ff; opacity: .9; }
.top-sites-header h2 { font-size: 1rem; font-weight: 700; color: var(--text); opacity: .9; }
.link-btn {
background: none; border: none; color: #9aa8ff; cursor: pointer; font-size: .9rem;
background: none; border: none; color: var(--accent); cursor: pointer; font-size: .9rem;
}
.link-btn:hover { color: #c7d0ff; text-decoration: underline; }
.link-btn:hover { color: var(--primary); text-decoration: underline; }
/* Individual bookmark tile */
.bookmark {
background: rgba(255,255,255,0.05);
border: 1px solid rgba(255,255,255,0.1);
background: color-mix(in srgb, var(--text) 5%, transparent);
border: 1px solid color-mix(in srgb, var(--text) 10%, transparent);
backdrop-filter: blur(6px);
box-shadow: 0 4px 16px rgba(0,0,0,0.3);
box-shadow: 0 4px 16px color-mix(in srgb, var(--bg) 30%, transparent);
transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
color: var(--text);
width: 100px;
@@ -349,7 +345,7 @@ body, html {
.bookmark:hover {
transform: translateY(-4px) scale(1.1);
box-shadow: 0 8px 24px rgba(0,0,0,0.5);
box-shadow: 0 8px 24px color-mix(in srgb, var(--bg) 50%, transparent);
}
.bookmark-icon {
@@ -462,7 +458,7 @@ body[data-theme="dark"] .bookmark .material-symbols-outlined,
left: 0;
right: 0;
bottom: 0;
background: rgba(18,20,24,0.8);
background: color-mix(in srgb, var(--bg) 80%, transparent);
display: flex;
align-items: center;
justify-content: center;
@@ -563,18 +559,18 @@ body[data-theme="dark"] .bookmark .material-symbols-outlined,
.glance.pos-tr { right:22px; top:22px; left:auto; bottom:auto; }
.glance.pos-tl { left:22px; top:22px; right:auto; bottom:auto; }
.glance-card {
min-width: 280px; background: rgba(12,16,26,0.55); border: 1px solid rgba(255,255,255,0.1);
border-radius: 16px; padding: 1rem; box-shadow: 0 14px 40px -18px rgba(0,0,0,.8), inset 0 1px 0 rgba(255,255,255,0.05);
min-width: 280px; background: color-mix(in srgb, var(--bg) 55%, transparent); border: 1px solid color-mix(in srgb, var(--text) 10%, transparent);
border-radius: 16px; padding: 1rem; box-shadow: 0 14px 40px -18px color-mix(in srgb, var(--bg) 80%, transparent), inset 0 1px 0 color-mix(in srgb, var(--text) 5%, transparent);
backdrop-filter: blur(8px);
}
.glance { transition: transform 0.06s linear; will-change: transform; }
.glance.dragging { transform: translate3d(var(--drag-x, 0px), var(--drag-y, 0px), 0) scale(1.02); }
.glance.dragging .glance-card { box-shadow: 0 24px 60px -24px rgba(0,0,0,.9), 0 0 0 2px rgba(255,255,255,.12) inset; }
.glance-title { font-size: .95rem; color: #dfe3ff; opacity: .9; margin-bottom: .65rem; }
.glance.dragging .glance-card { box-shadow: 0 24px 60px -24px color-mix(in srgb, var(--bg) 90%, transparent), 0 0 0 2px color-mix(in srgb, var(--text) 12%, transparent) inset; }
.glance-title { font-size: .95rem; color: var(--text); opacity: .9; margin-bottom: .65rem; }
.glance-grid { display: grid; grid-template-columns: 1fr 1fr; gap: .6rem; }
.glance-tile { background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.1); border-radius: 12px; padding: .6rem .75rem; text-align:left; }
.glance-label { font-size: .7rem; color: #b8c1ff; opacity: .85; margin-bottom: .25rem; }
.glance-value { font-size: 1.05rem; letter-spacing: .3px; color:#fff; }
.glance-tile { background: color-mix(in srgb, var(--text) 5%, transparent); border: 1px solid color-mix(in srgb, var(--text) 10%, transparent); border-radius: 12px; padding: .6rem .75rem; text-align:left; }
.glance-label { font-size: .7rem; color: var(--accent); opacity: .85; margin-bottom: .25rem; }
.glance-value { font-size: 1.05rem; letter-spacing: .3px; color: var(--text); }
@media (max-width: 700px) {
.glance { position: static; margin-top: 1rem; }