From bb6452c3336af13e93e30969f88c5f424970785b Mon Sep 17 00:00:00 2001 From: EtienneLescot Date: Sat, 22 Aug 2026 11:45:26 +0200 Subject: [PATCH 1/2] fix(editor): make the gradient picker and a couple of dialogs follow the light theme MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two contrast bugs reported directly against the gradient picker: the "remove color" icon read as invisible until hover, and the brightness slider's thumb disappeared into the popover background in light mode. Both buttons/icons in gradient-editor.tsx were colored for the dark color-wheel canvas above them, but the brightness-slider row has no canvas of its own — it sits directly on the (theme-dependent) popover surface, where the near-white thumb (`#f5f5f5`) all but vanished against the light theme's near-white surface. Gave that row its own dark backing, consistent with the canvas and angle-knob beside it (deliberately dark-by-design, like most pro color pickers), and bumped the icon buttons from 60% to 80% white so they don't need hover to read. A light-theme sweep for the same class of bug found two more hardcoded surfaces: ShortcutsConfigDialog.tsx (`bg-[#09090b] text-white`, so the whole dialog stayed dark regardless of theme) and App.tsx's editor Suspense fallback (same dark hex, flashes on every editor load before the real light UI paints). Both now use the design-tokens.css custom properties already used everywhere else in the app. While auditing accent-colored surfaces for the same sweep, found a separate but related bug: a few primary buttons (`.exportBtn`, `.bigRecBtn`, `.previewEmptyPrimaryButton`, and VirtualPreview's icon-button hover state) put white/near-white text directly on the mint `--accent`/`--brand` background instead of `--accent-on` — the token design-tokens.css defines specifically for text on that background. White-on-mint measures under WCAG's contrast minimums in both themes; switched all four to `--accent-on`, matching the pattern already used correctly everywhere else (NewEditorShell.module.css's `.paneTabs button.isActive`, `.btnPrimary`, Modals.tsx, ExportDialog.tsx). Finally, the default gradient presets: 16 swatches built from four grays plus the single mint accent, so half the grid paired a gray with the same green, reading as "we only have one color." Recolored with the same hue spread already offered in the solid-color tab just below it (blue, purple, pink, orange, green) with a couple of mint blends so the brand color still shows up without dominating. Co-Authored-By: Claude Sonnet 5 --- src/App.tsx | 6 +-- .../ai-edition/NewEditorShell.module.css | 2 +- src/components/ai-edition/RightPanes.tsx | 29 +++++++------- .../ai-edition/VirtualPreview.module.css | 1 + .../ai-edition/v4/EditorShellV4.module.css | 4 +- src/components/ui/gradient-editor.tsx | 17 +++++---- .../video-editor/ShortcutsConfigDialog.tsx | 38 +++++++++---------- 7 files changed, 52 insertions(+), 45 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 517ad7abd..aa7619d26 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -116,9 +116,9 @@ export default function App() { +
- {tEditor("loadingEditor")} + {tEditor("loadingEditor")}
} > diff --git a/src/components/ai-edition/NewEditorShell.module.css b/src/components/ai-edition/NewEditorShell.module.css index 155b665eb..c842a535a 100644 --- a/src/components/ai-edition/NewEditorShell.module.css +++ b/src/components/ai-edition/NewEditorShell.module.css @@ -594,7 +594,7 @@ padding: var(--sp-3) var(--sp-4); border-radius: var(--r-sm); background: var(--primary, #34B27B); - color: #fff; + color: var(--accent-on); border: none; font-weight: 500; font-size: 0.875rem; diff --git a/src/components/ai-edition/RightPanes.tsx b/src/components/ai-edition/RightPanes.tsx index 5f76e355d..d12fe248a 100644 --- a/src/components/ai-edition/RightPanes.tsx +++ b/src/components/ai-edition/RightPanes.tsx @@ -143,22 +143,25 @@ function Pane({ title, icon, helpText, children }: PaneProps) { // keep the gradient palette small and curated — every block renders // in the picker and gets serialized to legacyEditor on save. +// Spans the same hues as COLOR_PALETTE below rather than leaning on the +// brand mint for half the grid — a wall of green reads as "we only +// have one color" rather than "pick a gradient." const GRAD_PRESETS: readonly string[] = [ "linear-gradient(135deg, #eaebed, #bcc0c6)", - "linear-gradient(135deg, #10b981, #eaebed)", - "linear-gradient(135deg, #6b7280, #bcc0c6)", - "linear-gradient(135deg, #eaebed, #10b981)", - "linear-gradient(135deg, #16171d, #6b7280)", - "linear-gradient(135deg, #bcc0c6, #16171d)", - "linear-gradient(135deg, #10b981, #6b7280)", - "linear-gradient(135deg, #eaebed, #10b981)", + "linear-gradient(135deg, #3b82f6, #8b5cf6)", + "linear-gradient(135deg, #8b5cf6, #ec4899)", + "linear-gradient(135deg, #f97316, #ec4899)", + "linear-gradient(135deg, #f59e0b, #f97316)", + "linear-gradient(135deg, #10b981, #3b82f6)", + "linear-gradient(135deg, #22c55e, #10b981)", "linear-gradient(135deg, #6b7280, #16171d)", - "linear-gradient(135deg, #bcc0c6, #10b981)", - "linear-gradient(135deg, #16171d, #6b7280)", - "linear-gradient(135deg, #eaebed, #bcc0c6)", - "linear-gradient(135deg, #10b981, #bcc0c6)", - "linear-gradient(135deg, #eaebed, #16171d)", - "linear-gradient(135deg, #6b7280, #10b981)", + "linear-gradient(135deg, #ec4899, #ef4444)", + "linear-gradient(135deg, #3b82f6, #22c55e)", + "linear-gradient(135deg, #8b5cf6, #3b82f6)", + "linear-gradient(135deg, #f59e0b, #ef4444)", + "linear-gradient(135deg, #16171d, #1e293b)", + "linear-gradient(135deg, #34d399, #3b82f6)", + "linear-gradient(135deg, #ef4444, #8b5cf6)", "linear-gradient(135deg, #bcc0c6, #eaebed)", ]; diff --git a/src/components/ai-edition/VirtualPreview.module.css b/src/components/ai-edition/VirtualPreview.module.css index 78d84a06f..6177a9f52 100644 --- a/src/components/ai-edition/VirtualPreview.module.css +++ b/src/components/ai-edition/VirtualPreview.module.css @@ -60,6 +60,7 @@ .iconButton:hover:not(:disabled) { background: var(--accent); + color: var(--accent-on); } .iconButton:disabled { diff --git a/src/components/ai-edition/v4/EditorShellV4.module.css b/src/components/ai-edition/v4/EditorShellV4.module.css index 342cedd4c..6d47a11aa 100644 --- a/src/components/ai-edition/v4/EditorShellV4.module.css +++ b/src/components/ai-edition/v4/EditorShellV4.module.css @@ -389,7 +389,7 @@ padding: 0 14px; border-radius: 9px; background: var(--accent); - color: #fff; + color: var(--accent-on); border: 1px solid var(--accent); font-size: 13px; font-weight: 600; @@ -1126,7 +1126,7 @@ padding: 0 26px; border-radius: 16px; border: 1px solid var(--accent); - color: #fff; + color: var(--accent-on); background: var(--accent); font-size: 14px; font-weight: 600; diff --git a/src/components/ui/gradient-editor.tsx b/src/components/ui/gradient-editor.tsx index a29e1b923..c9e2525dc 100644 --- a/src/components/ui/gradient-editor.tsx +++ b/src/components/ui/gradient-editor.tsx @@ -462,7 +462,7 @@ export default function GradientEditor({ onChange }: GradientEditorProps) { aria-valuemin={0} aria-valuemax={360} aria-valuenow={Math.round(((mainAngle % 360) + 360) % 360)} - className="absolute w-11 h-11 rounded-full cursor-grab shadow-[0_0_0_4px_#f5f5f5,0_4px_14px_rgba(0,0,0,0.35)] transition-shadow z-10 active:cursor-grabbing focus:outline-none focus:ring-2 focus:ring-[#34B27B]" + className="absolute w-11 h-11 rounded-full cursor-grab shadow-[0_0_0_4px_#f5f5f5,0_4px_14px_rgba(0,0,0,0.35)] transition-shadow z-10 active:cursor-grabbing focus:outline-none focus:ring-2 focus:ring-[var(--brand)]" style={{ left: `${mainX}%`, top: `${mainY}%`, @@ -478,7 +478,7 @@ export default function GradientEditor({ onChange }: GradientEditorProps) { type="button" onClick={addPoint} disabled={totalColors >= MAX_COLORS} - className={`w-6 h-6 rounded-full flex items-center justify-center border-none bg-transparent transition-all text-white/60 hover:text-white ${ + className={`w-6 h-6 rounded-full flex items-center justify-center border-none bg-transparent transition-all text-white/80 hover:text-white ${ totalColors >= MAX_COLORS ? "opacity-40 cursor-not-allowed" : "hover:bg-white/10 cursor-pointer" @@ -492,7 +492,7 @@ export default function GradientEditor({ onChange }: GradientEditorProps) { type="button" onClick={removePoint} disabled={totalColors <= 1} - className={`w-6 h-6 rounded-full flex items-center justify-center border-none bg-transparent transition-all text-white/60 hover:text-white ${ + className={`w-6 h-6 rounded-full flex items-center justify-center border-none bg-transparent transition-all text-white/80 hover:text-white ${ totalColors <= 1 ? "opacity-40 cursor-not-allowed" : "hover:bg-white/10 cursor-pointer" @@ -506,7 +506,7 @@ export default function GradientEditor({ onChange }: GradientEditorProps) { type="button" onClick={cycleHarmony} disabled={eligibleHarmonies.length <= 1} - className={`w-6 h-6 rounded-full flex items-center justify-center border-none bg-transparent transition-all text-white/60 hover:text-white ${ + className={`w-6 h-6 rounded-full flex items-center justify-center border-none bg-transparent transition-all text-white/80 hover:text-white ${ eligibleHarmonies.length <= 1 ? "opacity-40 cursor-not-allowed" : "hover:bg-white/10 cursor-pointer" @@ -520,7 +520,10 @@ export default function GradientEditor({ onChange }: GradientEditorProps) { {/* Bottom controls: Brightness + Angle */}
- {/* Brightness wavy slider */} + {/* Brightness wavy slider. Its thumb/track are colored for the dark + canvas above, so it needs its own dark backing here too — this row + otherwise sits directly on the (theme-dependent) popover background, + where the light thumb disappears in light mode. */}
diff --git a/src/components/video-editor/ShortcutsConfigDialog.tsx b/src/components/video-editor/ShortcutsConfigDialog.tsx index add21681b..118e6e716 100644 --- a/src/components/video-editor/ShortcutsConfigDialog.tsx +++ b/src/components/video-editor/ShortcutsConfigDialog.tsx @@ -138,17 +138,17 @@ export function ShortcutsConfigDialog() { if (!open) handleClose(); }} > - + - + {t("title")}
-

+

{t("configurable")}

{SHORTCUT_ACTIONS.map((action) => { @@ -156,8 +156,8 @@ export function ShortcutsConfigDialog() { const hasConflict = conflict?.forAction === action; return (
-
- {t(`actions.${action}`)} +
+ {t(`actions.${action}`)}
{hasConflict && conflict?.conflictWith.type === "configurable" && ( -
- +
+ ⚠{" "} {t("alreadyUsedBy", { action: t(`actions.${conflict.conflictWith.action}`), @@ -189,14 +189,14 @@ export function ShortcutsConfigDialog() { @@ -209,32 +209,32 @@ export function ShortcutsConfigDialog() {
-

+

{t("fixed")}

{FIXED_SHORTCUTS.map(({ i18nKey, label, display }) => (
- + {t(`fixedActions.${i18nKey}`, { defaultValue: label })} - + {display}
))}
-

{t("helpText")}

+

{t("helpText")}

{hasConflict && conflict?.conflictWith.type === "configurable" && ( -
+
⚠{" "} {t("alreadyUsedBy", { @@ -189,7 +189,7 @@ export function ShortcutsConfigDialog() {