feat(lumiere): grainy gradient background + editor chrome theme
Build and Deploy Verso / deploy (push) Successful in 15m0s
Build and Deploy Verso / deploy (push) Successful in 15m0s
- Replace flat #f0f4f8 main content bg with layered grainy gradient: soft radial teal/blue orbs (background-attachment: fixed) plus SVG feTurbulence noise tile for organic depth - Cards get backdrop-filter glass effect over the textured surface - New ide-lumiere.scss: sets body[data-lumiere] via useThemedPage, then overrides toolbar (white + 3px teal→blue accent stripe), rail (teal active states), and file-tree (teal selected/hover) CSS variables Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,12 +1,16 @@
|
||||
import { useLayoutEffect } from 'react'
|
||||
import { useActiveOverallTheme } from './use-active-overall-theme'
|
||||
import { useUserSettingsContext } from '@/shared/context/user-settings-context'
|
||||
|
||||
export default function useThemedPage(featureFlag?: string) {
|
||||
const activeOverallTheme = useActiveOverallTheme(featureFlag)
|
||||
const {
|
||||
userSettings: { overallTheme },
|
||||
} = useUserSettingsContext()
|
||||
|
||||
useLayoutEffect(() => {
|
||||
// Sets the body's data-theme attribute for theming
|
||||
document.body.dataset.theme =
|
||||
activeOverallTheme === 'dark' ? 'default' : 'light'
|
||||
}, [activeOverallTheme])
|
||||
document.body.dataset.lumiere = overallTheme === 'lumiere-' ? 'true' : 'false'
|
||||
}, [activeOverallTheme, overallTheme])
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
@import 'sidebar-v2-dash-pane';
|
||||
@import 'editor/ide';
|
||||
@import 'editor/ide-redesign';
|
||||
@import 'editor/ide-lumiere';
|
||||
@import 'editor/rail';
|
||||
@import 'editor/settings';
|
||||
@import 'editor/toolbar';
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
// Verso Lumière — editor chrome overrides.
|
||||
// Scoped to body[data-lumiere='true'] so zero impact on Classic themes.
|
||||
// Sets CSS variable overrides and adds the signature teal/blue accent stripe.
|
||||
|
||||
$lum-teal: #2a9d8f;
|
||||
$lum-blue: #3d7ebf;
|
||||
$lum-border: #e2eaf2;
|
||||
|
||||
// ── CSS variable overrides ─────────────────────────────────────────────────
|
||||
|
||||
[data-lumiere='true'] {
|
||||
// Toolbar
|
||||
--redesign-toolbar-background: #ffffff;
|
||||
--redesign-toolbar-border-divider: #{$lum-border};
|
||||
--redesign-toolbar-home-button-hover-background: rgba(#{$lum-teal}, 0.08);
|
||||
--redesign-subdued-button-hover-background: rgba(42, 157, 143, 0.08);
|
||||
--redesign-subdued-button-color: #1a2e3b;
|
||||
|
||||
// Rail
|
||||
--ide-rail-background: #ffffff;
|
||||
--ide-rail-border-colour: #{$lum-border};
|
||||
--ide-rail-color: #1a2e3b;
|
||||
--ide-rail-link-background: #ffffff;
|
||||
--ide-rail-link-hover-background: rgba(42, 157, 143, 0.08);
|
||||
--ide-rail-link-hover-color: #{$lum-teal};
|
||||
--ide-rail-link-active-color: #ffffff;
|
||||
--ide-rail-link-active-background: #{$lum-teal};
|
||||
--ide-rail-header-subdued-button-color: #1a2e3b;
|
||||
--ide-rail-header-subdued-button-hover-background: rgba(42, 157, 143, 0.08);
|
||||
|
||||
// File tree
|
||||
--file-tree-bg: #ffffff;
|
||||
--file-tree-item-color: #1a2e3b;
|
||||
--file-tree-icon-colour: #64748b;
|
||||
--file-tree-item-hover-bg: rgba(42, 157, 143, 0.07);
|
||||
--file-tree-item-selected-bg: rgba(42, 157, 143, 0.14);
|
||||
--file-tree-item-selected-color: #{$lum-teal};
|
||||
--file-tree-expand-button-color: #1a2e3b;
|
||||
}
|
||||
|
||||
// ── Toolbar — gradient accent stripe ──────────────────────────────────────
|
||||
|
||||
[data-lumiere='true'] .ide-redesign-toolbar {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-bottom-color: $lum-border;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
|
||||
|
||||
// 3px teal→blue stripe at the very top (same motif as the dashboard navbar)
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 3px;
|
||||
background: linear-gradient(90deg, $lum-teal 0%, $lum-blue 100%);
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
// ── Rail — active tab indicator uses teal ─────────────────────────────────
|
||||
|
||||
[data-lumiere='true'] .ide-rail-tab-link.open-rail::after {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
// ── Rail panel headers ─────────────────────────────────────────────────────
|
||||
|
||||
[data-lumiere='true'] .rail-panel-title {
|
||||
color: #1a2e3b;
|
||||
}
|
||||
|
||||
// ── File tree toolbar ──────────────────────────────────────────────────────
|
||||
|
||||
[data-lumiere='true'] .file-tree-toolbar {
|
||||
border-bottom-color: $lum-border;
|
||||
}
|
||||
@@ -11,9 +11,12 @@ $lum-blue: #3d7ebf;
|
||||
$lum-text: #1a2e3b;
|
||||
$lum-text-sub: #64748b;
|
||||
$lum-text-muted: #94a3b8;
|
||||
$lum-bg: #f0f4f8;
|
||||
$lum-border: #e2eaf2;
|
||||
|
||||
// Grainy SVG noise tile (fractalNoise, greyscale, stitched for seamless tiling).
|
||||
// The rect opacity (0.06) controls grain intensity — increase for more texture.
|
||||
$lum-noise: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.75' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.06'/%3E%3C/svg%3E");
|
||||
|
||||
.project-list-lumiere {
|
||||
|
||||
// ══════════════════════════════════════════════════════════════════════════
|
||||
@@ -21,7 +24,6 @@ $lum-border: #e2eaf2;
|
||||
// ══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
.navbar-default {
|
||||
// Lift the hard border; replace with soft shadow
|
||||
border-bottom: none !important;
|
||||
box-shadow: 0 1px 0 rgba(0, 0, 0, 0.06), 0 2px 8px rgba(0, 0, 0, 0.04);
|
||||
background-color: #ffffff !important;
|
||||
@@ -43,9 +45,7 @@ $lum-border: #e2eaf2;
|
||||
.navbar-nav > li > .dropdown-toggle {
|
||||
border-color: transparent !important;
|
||||
border-radius: 20px;
|
||||
transition:
|
||||
background-color 0.15s ease,
|
||||
color 0.15s ease;
|
||||
transition: background-color 0.15s ease, color 0.15s ease;
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
@@ -56,7 +56,6 @@ $lum-border: #e2eaf2;
|
||||
}
|
||||
}
|
||||
|
||||
// The instance title (e.g. "Verso V0.185 Alpha")
|
||||
.navbar-title {
|
||||
color: $lum-text !important;
|
||||
font-weight: 600;
|
||||
@@ -87,9 +86,7 @@ $lum-border: #e2eaf2;
|
||||
font-weight: 600;
|
||||
border-radius: 10px !important;
|
||||
box-shadow: 0 2px 8px rgba($lum-teal, 0.25);
|
||||
transition:
|
||||
box-shadow 0.18s ease,
|
||||
filter 0.18s ease;
|
||||
transition: box-shadow 0.18s ease, filter 0.18s ease;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
@@ -98,7 +95,6 @@ $lum-border: #e2eaf2;
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
// Caret color
|
||||
&::after {
|
||||
border-top-color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
@@ -116,9 +112,7 @@ $lum-border: #e2eaf2;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
color: $lum-text-sub;
|
||||
transition:
|
||||
background-color 0.15s ease,
|
||||
color 0.15s ease;
|
||||
transition: background-color 0.15s ease, color 0.15s ease;
|
||||
}
|
||||
|
||||
> li:hover button {
|
||||
@@ -132,7 +126,6 @@ $lum-border: #e2eaf2;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
// Tags section header
|
||||
.dropdown-header {
|
||||
font-size: 0.7rem;
|
||||
font-weight: 700;
|
||||
@@ -142,7 +135,6 @@ $lum-border: #e2eaf2;
|
||||
padding: 0.85rem 0.75rem 0.35rem;
|
||||
}
|
||||
|
||||
// Individual tag items
|
||||
> li.tag {
|
||||
button.tag-name {
|
||||
border-radius: 8px;
|
||||
@@ -152,21 +144,9 @@ $lum-border: #e2eaf2;
|
||||
align-items: center;
|
||||
gap: 0.45rem;
|
||||
|
||||
&:hover {
|
||||
color: $lum-teal;
|
||||
}
|
||||
&:hover { color: $lum-teal; }
|
||||
}
|
||||
|
||||
&.active button.tag-name {
|
||||
color: #ffffff !important;
|
||||
|
||||
// The colored dot inherits white from the active button — keep it visible
|
||||
.badge {
|
||||
opacity: 0.9;
|
||||
}
|
||||
}
|
||||
|
||||
// Overflow "..." menu button
|
||||
.tag-menu button.dropdown-toggle {
|
||||
border-radius: 50%;
|
||||
transition: background-color 0.15s ease;
|
||||
@@ -180,13 +160,11 @@ $lum-border: #e2eaf2;
|
||||
}
|
||||
}
|
||||
|
||||
hr {
|
||||
border-color: $lum-border;
|
||||
}
|
||||
hr { border-color: $lum-border; }
|
||||
}
|
||||
|
||||
// ══════════════════════════════════════════════════════════════════════════
|
||||
// SIDEBAR — lower section (help / account icons + Verso logo)
|
||||
// SIDEBAR — lower section
|
||||
// ══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
.ds-nav-sidebar-lower {
|
||||
@@ -194,30 +172,24 @@ $lum-border: #e2eaf2;
|
||||
padding-top: 0.75rem;
|
||||
}
|
||||
|
||||
.ds-nav-icon-dropdown {
|
||||
.dropdown-toggle {
|
||||
border-radius: 50% !important;
|
||||
color: $lum-text-sub !important;
|
||||
transition:
|
||||
background-color 0.15s ease,
|
||||
color 0.15s ease,
|
||||
box-shadow 0.15s ease;
|
||||
.ds-nav-icon-dropdown .dropdown-toggle {
|
||||
border-radius: 50% !important;
|
||||
color: $lum-text-sub !important;
|
||||
transition: background-color 0.15s ease, color 0.15s ease, box-shadow 0.15s ease;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba($lum-teal, 0.09) !important;
|
||||
color: $lum-teal !important;
|
||||
box-shadow: 0 0 0 3px rgba($lum-teal, 0.12);
|
||||
}
|
||||
&:hover {
|
||||
background-color: rgba($lum-teal, 0.09) !important;
|
||||
color: $lum-teal !important;
|
||||
box-shadow: 0 0 0 3px rgba($lum-teal, 0.12);
|
||||
}
|
||||
|
||||
&.show {
|
||||
background-color: rgba($lum-teal, 0.15) !important;
|
||||
color: $lum-teal !important;
|
||||
box-shadow: 0 0 0 3px rgba($lum-teal, 0.18);
|
||||
}
|
||||
&.show {
|
||||
background-color: rgba($lum-teal, 0.15) !important;
|
||||
color: $lum-teal !important;
|
||||
box-shadow: 0 0 0 3px rgba($lum-teal, 0.18);
|
||||
}
|
||||
}
|
||||
|
||||
// Verso wordmark at the very bottom — subtle separator + gentle fade
|
||||
.ds-nav-verso-logo {
|
||||
border-top: 1px solid $lum-border;
|
||||
padding-top: 0.6rem;
|
||||
@@ -225,12 +197,9 @@ $lum-border: #e2eaf2;
|
||||
opacity: 0.7;
|
||||
transition: opacity 0.15s ease;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
&:hover { opacity: 1; }
|
||||
}
|
||||
|
||||
// Theme toggle: teal selected indicator
|
||||
.theme-toggle-radios {
|
||||
background-color: rgba($lum-teal, 0.07);
|
||||
}
|
||||
@@ -239,17 +208,38 @@ $lum-border: #e2eaf2;
|
||||
background-color: $lum-teal !important;
|
||||
color: #ffffff;
|
||||
|
||||
.material-symbols {
|
||||
color: #ffffff;
|
||||
}
|
||||
.material-symbols { color: #ffffff; }
|
||||
}
|
||||
|
||||
// ══════════════════════════════════════════════════════════════════════════
|
||||
// MAIN CONTENT AREA
|
||||
// MAIN CONTENT AREA — grainy gradient background
|
||||
//
|
||||
// Three layers, back to front:
|
||||
// 1. Solid base colour (#fafbff — cool off-white)
|
||||
// 2. Two soft radial-gradient "orbs" (teal top-right, blue bottom-left),
|
||||
// rendered fixed so they stay in the corner as the user scrolls.
|
||||
// 3. SVG feTurbulence noise tile (200×200, repeating, scrolls with content)
|
||||
// at 6% opacity — the "grain" effect seen in Linear / Raycast / UmbrelOS.
|
||||
// ══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
.project-ds-nav-content {
|
||||
background-color: $lum-bg;
|
||||
background-image:
|
||||
#{$lum-noise},
|
||||
radial-gradient(ellipse 80% 60% at 88% 0%, rgba($lum-teal, 0.14) 0%, transparent 60%),
|
||||
radial-gradient(ellipse 70% 55% at 4% 98%, rgba($lum-blue, 0.10) 0%, transparent 55%);
|
||||
background-size:
|
||||
200px 200px,
|
||||
cover,
|
||||
cover;
|
||||
background-repeat:
|
||||
repeat,
|
||||
no-repeat,
|
||||
no-repeat;
|
||||
background-attachment:
|
||||
scroll, // grain tiles with scroll — seamless
|
||||
fixed, // teal orb stays pinned to viewport corner
|
||||
fixed; // blue orb stays pinned to viewport corner
|
||||
background-color: #fafbff;
|
||||
}
|
||||
|
||||
// ── Page header ────────────────────────────────────────────────────────────
|
||||
@@ -304,18 +294,19 @@ $lum-border: #e2eaf2;
|
||||
flex-direction: column;
|
||||
text-decoration: none;
|
||||
border-radius: 10px;
|
||||
background: #ffffff;
|
||||
background: rgba(255, 255, 255, 0.82);
|
||||
backdrop-filter: blur(8px);
|
||||
-webkit-backdrop-filter: blur(8px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.6);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.07);
|
||||
transition:
|
||||
transform 0.18s ease,
|
||||
box-shadow 0.18s ease;
|
||||
transition: transform 0.18s ease, box-shadow 0.18s ease;
|
||||
overflow: hidden;
|
||||
color: inherit;
|
||||
|
||||
&:hover,
|
||||
&:focus-visible {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.13);
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
@@ -427,18 +418,18 @@ $lum-border: #e2eaf2;
|
||||
}
|
||||
|
||||
.lumiere-format-badge--latex {
|
||||
background: #e8f5ee;
|
||||
background: rgba(#e8f5ee, 0.9);
|
||||
color: $lum-teal;
|
||||
}
|
||||
|
||||
.lumiere-format-badge--typst {
|
||||
background: #e0f2fe;
|
||||
background: rgba(#e0f2fe, 0.9);
|
||||
color: $lum-blue;
|
||||
}
|
||||
|
||||
.lumiere-format-badge--quarto,
|
||||
.lumiere-format-badge--quarto-slides {
|
||||
background: #ede9fe;
|
||||
background: rgba(#ede9fe, 0.9);
|
||||
color: #7c4dff;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user