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 { useLayoutEffect } from 'react'
|
||||||
import { useActiveOverallTheme } from './use-active-overall-theme'
|
import { useActiveOverallTheme } from './use-active-overall-theme'
|
||||||
|
import { useUserSettingsContext } from '@/shared/context/user-settings-context'
|
||||||
|
|
||||||
export default function useThemedPage(featureFlag?: string) {
|
export default function useThemedPage(featureFlag?: string) {
|
||||||
const activeOverallTheme = useActiveOverallTheme(featureFlag)
|
const activeOverallTheme = useActiveOverallTheme(featureFlag)
|
||||||
|
const {
|
||||||
|
userSettings: { overallTheme },
|
||||||
|
} = useUserSettingsContext()
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
// Sets the body's data-theme attribute for theming
|
|
||||||
document.body.dataset.theme =
|
document.body.dataset.theme =
|
||||||
activeOverallTheme === 'dark' ? 'default' : 'light'
|
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 'sidebar-v2-dash-pane';
|
||||||
@import 'editor/ide';
|
@import 'editor/ide';
|
||||||
@import 'editor/ide-redesign';
|
@import 'editor/ide-redesign';
|
||||||
|
@import 'editor/ide-lumiere';
|
||||||
@import 'editor/rail';
|
@import 'editor/rail';
|
||||||
@import 'editor/settings';
|
@import 'editor/settings';
|
||||||
@import 'editor/toolbar';
|
@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: #1a2e3b;
|
||||||
$lum-text-sub: #64748b;
|
$lum-text-sub: #64748b;
|
||||||
$lum-text-muted: #94a3b8;
|
$lum-text-muted: #94a3b8;
|
||||||
$lum-bg: #f0f4f8;
|
|
||||||
$lum-border: #e2eaf2;
|
$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 {
|
.project-list-lumiere {
|
||||||
|
|
||||||
// ══════════════════════════════════════════════════════════════════════════
|
// ══════════════════════════════════════════════════════════════════════════
|
||||||
@@ -21,7 +24,6 @@ $lum-border: #e2eaf2;
|
|||||||
// ══════════════════════════════════════════════════════════════════════════
|
// ══════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
.navbar-default {
|
.navbar-default {
|
||||||
// Lift the hard border; replace with soft shadow
|
|
||||||
border-bottom: none !important;
|
border-bottom: none !important;
|
||||||
box-shadow: 0 1px 0 rgba(0, 0, 0, 0.06), 0 2px 8px rgba(0, 0, 0, 0.04);
|
box-shadow: 0 1px 0 rgba(0, 0, 0, 0.06), 0 2px 8px rgba(0, 0, 0, 0.04);
|
||||||
background-color: #ffffff !important;
|
background-color: #ffffff !important;
|
||||||
@@ -43,9 +45,7 @@ $lum-border: #e2eaf2;
|
|||||||
.navbar-nav > li > .dropdown-toggle {
|
.navbar-nav > li > .dropdown-toggle {
|
||||||
border-color: transparent !important;
|
border-color: transparent !important;
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
transition:
|
transition: background-color 0.15s ease, color 0.15s ease;
|
||||||
background-color 0.15s ease,
|
|
||||||
color 0.15s ease;
|
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
&:focus,
|
&:focus,
|
||||||
@@ -56,7 +56,6 @@ $lum-border: #e2eaf2;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The instance title (e.g. "Verso V0.185 Alpha")
|
|
||||||
.navbar-title {
|
.navbar-title {
|
||||||
color: $lum-text !important;
|
color: $lum-text !important;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
@@ -87,9 +86,7 @@ $lum-border: #e2eaf2;
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
border-radius: 10px !important;
|
border-radius: 10px !important;
|
||||||
box-shadow: 0 2px 8px rgba($lum-teal, 0.25);
|
box-shadow: 0 2px 8px rgba($lum-teal, 0.25);
|
||||||
transition:
|
transition: box-shadow 0.18s ease, filter 0.18s ease;
|
||||||
box-shadow 0.18s ease,
|
|
||||||
filter 0.18s ease;
|
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
&:focus {
|
&:focus {
|
||||||
@@ -98,7 +95,6 @@ $lum-border: #e2eaf2;
|
|||||||
color: #ffffff !important;
|
color: #ffffff !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Caret color
|
|
||||||
&::after {
|
&::after {
|
||||||
border-top-color: rgba(255, 255, 255, 0.8);
|
border-top-color: rgba(255, 255, 255, 0.8);
|
||||||
}
|
}
|
||||||
@@ -116,9 +112,7 @@ $lum-border: #e2eaf2;
|
|||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: $lum-text-sub;
|
color: $lum-text-sub;
|
||||||
transition:
|
transition: background-color 0.15s ease, color 0.15s ease;
|
||||||
background-color 0.15s ease,
|
|
||||||
color 0.15s ease;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
> li:hover button {
|
> li:hover button {
|
||||||
@@ -132,7 +126,6 @@ $lum-border: #e2eaf2;
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tags section header
|
|
||||||
.dropdown-header {
|
.dropdown-header {
|
||||||
font-size: 0.7rem;
|
font-size: 0.7rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
@@ -142,7 +135,6 @@ $lum-border: #e2eaf2;
|
|||||||
padding: 0.85rem 0.75rem 0.35rem;
|
padding: 0.85rem 0.75rem 0.35rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Individual tag items
|
|
||||||
> li.tag {
|
> li.tag {
|
||||||
button.tag-name {
|
button.tag-name {
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
@@ -152,21 +144,9 @@ $lum-border: #e2eaf2;
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.45rem;
|
gap: 0.45rem;
|
||||||
|
|
||||||
&:hover {
|
&:hover { color: $lum-teal; }
|
||||||
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 {
|
.tag-menu button.dropdown-toggle {
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
transition: background-color 0.15s ease;
|
transition: background-color 0.15s ease;
|
||||||
@@ -180,13 +160,11 @@ $lum-border: #e2eaf2;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr { border-color: $lum-border; }
|
||||||
border-color: $lum-border;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ══════════════════════════════════════════════════════════════════════════
|
// ══════════════════════════════════════════════════════════════════════════
|
||||||
// SIDEBAR — lower section (help / account icons + Verso logo)
|
// SIDEBAR — lower section
|
||||||
// ══════════════════════════════════════════════════════════════════════════
|
// ══════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
.ds-nav-sidebar-lower {
|
.ds-nav-sidebar-lower {
|
||||||
@@ -194,30 +172,24 @@ $lum-border: #e2eaf2;
|
|||||||
padding-top: 0.75rem;
|
padding-top: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ds-nav-icon-dropdown {
|
.ds-nav-icon-dropdown .dropdown-toggle {
|
||||||
.dropdown-toggle {
|
border-radius: 50% !important;
|
||||||
border-radius: 50% !important;
|
color: $lum-text-sub !important;
|
||||||
color: $lum-text-sub !important;
|
transition: background-color 0.15s ease, color 0.15s ease, box-shadow 0.15s ease;
|
||||||
transition:
|
|
||||||
background-color 0.15s ease,
|
|
||||||
color 0.15s ease,
|
|
||||||
box-shadow 0.15s ease;
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: rgba($lum-teal, 0.09) !important;
|
background-color: rgba($lum-teal, 0.09) !important;
|
||||||
color: $lum-teal !important;
|
color: $lum-teal !important;
|
||||||
box-shadow: 0 0 0 3px rgba($lum-teal, 0.12);
|
box-shadow: 0 0 0 3px rgba($lum-teal, 0.12);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.show {
|
&.show {
|
||||||
background-color: rgba($lum-teal, 0.15) !important;
|
background-color: rgba($lum-teal, 0.15) !important;
|
||||||
color: $lum-teal !important;
|
color: $lum-teal !important;
|
||||||
box-shadow: 0 0 0 3px rgba($lum-teal, 0.18);
|
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 {
|
.ds-nav-verso-logo {
|
||||||
border-top: 1px solid $lum-border;
|
border-top: 1px solid $lum-border;
|
||||||
padding-top: 0.6rem;
|
padding-top: 0.6rem;
|
||||||
@@ -225,12 +197,9 @@ $lum-border: #e2eaf2;
|
|||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
transition: opacity 0.15s ease;
|
transition: opacity 0.15s ease;
|
||||||
|
|
||||||
&:hover {
|
&:hover { opacity: 1; }
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Theme toggle: teal selected indicator
|
|
||||||
.theme-toggle-radios {
|
.theme-toggle-radios {
|
||||||
background-color: rgba($lum-teal, 0.07);
|
background-color: rgba($lum-teal, 0.07);
|
||||||
}
|
}
|
||||||
@@ -239,17 +208,38 @@ $lum-border: #e2eaf2;
|
|||||||
background-color: $lum-teal !important;
|
background-color: $lum-teal !important;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
|
|
||||||
.material-symbols {
|
.material-symbols { color: #ffffff; }
|
||||||
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 {
|
.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 ────────────────────────────────────────────────────────────
|
// ── Page header ────────────────────────────────────────────────────────────
|
||||||
@@ -304,18 +294,19 @@ $lum-border: #e2eaf2;
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
border-radius: 10px;
|
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);
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.07);
|
||||||
transition:
|
transition: transform 0.18s ease, box-shadow 0.18s ease;
|
||||||
transform 0.18s ease,
|
|
||||||
box-shadow 0.18s ease;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
&:focus-visible {
|
&:focus-visible {
|
||||||
transform: translateY(-3px);
|
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;
|
text-decoration: none;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
}
|
}
|
||||||
@@ -427,18 +418,18 @@ $lum-border: #e2eaf2;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.lumiere-format-badge--latex {
|
.lumiere-format-badge--latex {
|
||||||
background: #e8f5ee;
|
background: rgba(#e8f5ee, 0.9);
|
||||||
color: $lum-teal;
|
color: $lum-teal;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lumiere-format-badge--typst {
|
.lumiere-format-badge--typst {
|
||||||
background: #e0f2fe;
|
background: rgba(#e0f2fe, 0.9);
|
||||||
color: $lum-blue;
|
color: $lum-blue;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lumiere-format-badge--quarto,
|
.lumiere-format-badge--quarto,
|
||||||
.lumiere-format-badge--quarto-slides {
|
.lumiere-format-badge--quarto-slides {
|
||||||
background: #ede9fe;
|
background: rgba(#ede9fe, 0.9);
|
||||||
color: #7c4dff;
|
color: #7c4dff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user