mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-23 08:00:45 +00:00
feat: add light mode for navigation sidebar (#8057)
* feat: add light mode support for navigation sidebar Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: use custom selected background for sidebar items Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: darken sidebar section separators in light mode Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: lighten sidebar bg to #F3F3F7 and use border-light for separators Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: use text-secondary for sidebar labels and text-hint for icons Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: extract dark sidebar background color to constant Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -20,8 +20,8 @@
|
||||
|
||||
<button
|
||||
class={twMerge(
|
||||
'text-2xs text-white m-1 p-2 rounded-lg flex flex-row gap-2 justify-center hover:bg-gray-600',
|
||||
forcedDarkMode ? 'text-white hover:bg-gray-600' : 'text-primary hover:bg-surface-hover'
|
||||
'text-2xs m-1 p-2 rounded-lg flex flex-row gap-2 justify-center',
|
||||
forcedDarkMode ? 'text-white hover:bg-gray-600' : 'text-secondary hover:bg-surface-hover'
|
||||
)}
|
||||
on:click={toggle}
|
||||
>
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<script module lang="ts">
|
||||
export const sidebarClasses = {
|
||||
text: 'text-primary-inverse dark:text-primary data-[light-mode=true]:text-primary text-xs font-normal',
|
||||
selectedText: 'text-emphasis-inverse dark:text-emphasis text-xs font-normal',
|
||||
sublabelText: 'text-secondary-inverse dark:text-secondary text-2xs font-normal',
|
||||
hoverBg:
|
||||
'transition-colors hover:bg-surface-hover-inverse dark:hover:bg-surface-hover data-[light-mode=true]:hover:bg-surface-hover'
|
||||
text: 'text-secondary text-xs font-normal',
|
||||
iconText: 'text-hint',
|
||||
selectedText: 'text-emphasis text-xs font-semibold',
|
||||
sublabelText: 'text-secondary text-2xs font-normal',
|
||||
hoverBg: 'transition-colors hover:bg-surface-hover',
|
||||
selectedBg: 'bg-surface-hover'
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -113,7 +114,7 @@
|
||||
<foreignObject x="5" y="5" width="16" height="16">
|
||||
<SvelteComponent
|
||||
size={16}
|
||||
class={twMerge(sidebarClasses.text, 'transition-colors', iconClasses)}
|
||||
class={twMerge(sidebarClasses.iconText, 'transition-colors', iconClasses)}
|
||||
{...iconProps}
|
||||
/>
|
||||
</foreignObject>
|
||||
@@ -121,7 +122,7 @@
|
||||
{:else}
|
||||
<SvelteComponent
|
||||
size={16}
|
||||
class={twMerge('flex-shrink-0', sidebarClasses.text, 'transition-colors', iconClasses)}
|
||||
class={twMerge('flex-shrink-0', sidebarClasses.iconText, 'transition-colors', iconClasses)}
|
||||
{...iconProps}
|
||||
/>
|
||||
{/if}
|
||||
@@ -140,7 +141,7 @@
|
||||
>
|
||||
{label}
|
||||
<span
|
||||
class="pl-2 text-xs dark:text-secondary light:text-secondary-inverse font-semibold"
|
||||
class="pl-2 text-xs text-secondary font-semibold"
|
||||
>
|
||||
{shortcut}
|
||||
</span>
|
||||
|
||||
@@ -61,9 +61,9 @@
|
||||
}}
|
||||
{onclick}
|
||||
class={twMerge(
|
||||
'group flex items-center px-2 py-2 text-sm font-light rounded-md h-8 gap-3',
|
||||
'group flex items-center px-2 py-2 text-sm font-light rounded-md h-8 gap-2',
|
||||
isSelected
|
||||
? 'bg-surface-selected-inverse dark:bg-surface-selected'
|
||||
? sidebarClasses.selectedBg
|
||||
: sidebarClasses.hoverBg,
|
||||
isSelected ? sidebarClasses.selectedText : sidebarClasses.text,
|
||||
classNames
|
||||
@@ -77,7 +77,7 @@
|
||||
>
|
||||
{#if icon}
|
||||
{@const SvelteComponent = icon}
|
||||
<SvelteComponent size={16} class={twMerge('flex-shrink-0 transition-all')} />
|
||||
<SvelteComponent size={16} class={twMerge('flex-shrink-0 transition-all', isSelected ? sidebarClasses.selectedText : sidebarClasses.iconText)} />
|
||||
{/if}
|
||||
|
||||
{#if !isCollapsed}
|
||||
|
||||
@@ -551,7 +551,7 @@
|
||||
</div>
|
||||
<div class="pt-4">
|
||||
<div
|
||||
class="text-gray-400 text-[0.5rem] uppercase transition-opacity"
|
||||
class="text-secondary text-[0.5rem] uppercase transition-opacity"
|
||||
class:opacity-0={isCollapsed}>Triggers</div
|
||||
>
|
||||
<Menubar class="flex flex-col gap-1">
|
||||
@@ -566,8 +566,8 @@
|
||||
aiId="sidebar-menu-link-add-trigger"
|
||||
aiDescription="Button to add a new trigger. Can be HTTP, WebSocket, Postgres, Kafka, NATS, SQS, GCP Pub/Sub, or MQTT"
|
||||
class={twMerge(
|
||||
'w-full text-gray-400 text-2xs flex flex-row gap-1 py-1 items-center px-2 hover:bg-[#2A3648] dark:hover:bg-[#30404e] rounded',
|
||||
'data-[highlighted]:bg-[#2A3648] dark:data-[highlighted]:bg-[#30404e]'
|
||||
'w-full text-secondary text-2xs flex flex-row gap-1 py-1 items-center px-2 hover:bg-surface-hover rounded',
|
||||
'data-[highlighted]:bg-surface-hover'
|
||||
)}
|
||||
meltElement={trigger}
|
||||
>
|
||||
|
||||
@@ -158,7 +158,7 @@
|
||||
<div
|
||||
class={twMerge(
|
||||
'font-mono text-2xs whitespace-nowrap truncate text-left font-normal',
|
||||
isSelected ? 'text-accent/80' : 'text-hint'
|
||||
isSelected ? 'text-accent/80' : 'text-secondary'
|
||||
)}
|
||||
title={workspace.id}
|
||||
>
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
import { DEFAULT_HUB_BASE_URL } from '$lib/hub'
|
||||
import DBManagerDrawer from '$lib/components/DBManagerDrawer.svelte'
|
||||
import { watchOnce } from 'runed'
|
||||
import { useIsDarkMode } from '$lib/components/DarkModeObserver.svelte'
|
||||
interface Props {
|
||||
children?: import('svelte').Snippet
|
||||
}
|
||||
@@ -85,6 +86,11 @@
|
||||
let userSettings: UserSettings | undefined = $state()
|
||||
let superadminSettings: SuperadminSettings | undefined = $state()
|
||||
let menuHidden = $state(false)
|
||||
let isDarkMode = useIsDarkMode()
|
||||
let darkMode = $derived(isDarkMode.val)
|
||||
|
||||
const SIDEBAR_BG = '#F3F3F7'
|
||||
const SIDEBAR_BG_DARK = '#1e232e'
|
||||
|
||||
if ($page.status == 404) {
|
||||
goto('/user/login')
|
||||
@@ -475,7 +481,7 @@
|
||||
>
|
||||
<div
|
||||
class={classNames(
|
||||
'fixed inset-0 dark:bg-[#1e232e] bg-[#202125] dark:bg-opacity-75 bg-opacity-75 transition-opacity ease-linear duration-300 z-40 !dark',
|
||||
'fixed inset-0 bg-black/50 transition-opacity ease-linear duration-300 z-40',
|
||||
|
||||
menuOpen ? 'opacity-100' : 'opacity-0'
|
||||
)}
|
||||
@@ -519,16 +525,19 @@
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="dark:bg-[#1e232e] bg-[#202125] h-full !dark flex flex-col">
|
||||
<div class="flex gap-x-2 flex-shrink-0 p-4 font-semibold text-gray-200 w-40">
|
||||
<WindmillIcon white={true} height="20px" width="20px" />
|
||||
<div
|
||||
class="h-full flex flex-col"
|
||||
style:background-color={darkMode ? SIDEBAR_BG_DARK : SIDEBAR_BG}
|
||||
>
|
||||
<div class="flex gap-x-2 flex-shrink-0 p-4 font-semibold text-emphasis w-40">
|
||||
<WindmillIcon white={darkMode} height="20px" width="20px" />
|
||||
{#if $whitelabelNameStore}
|
||||
{$whitelabelNameStore}
|
||||
{:else}
|
||||
Windmill
|
||||
{/if}
|
||||
</div>
|
||||
<div class="px-2 py-4 border-y border-gray-500">
|
||||
<div class="px-2 py-4 border-y border-light dark:border-gray-700">
|
||||
<Menubar>
|
||||
{#snippet children({ createMenu })}
|
||||
<WorkspaceMenu {createMenu} />
|
||||
@@ -554,7 +563,7 @@
|
||||
}}
|
||||
label="Ask AI"
|
||||
class="!text-xs"
|
||||
iconClasses="!text-ai-inverse dark:!text-ai"
|
||||
iconClasses="!text-ai"
|
||||
shortcut={`${getModifierKey()}L`}
|
||||
/>
|
||||
</div>
|
||||
@@ -573,13 +582,14 @@
|
||||
<div
|
||||
id="sidebar"
|
||||
class={classNames(
|
||||
'flex flex-col fixed inset-y-0 transition-all ease-in-out duration-200 shadow-md z-40 ',
|
||||
'flex flex-col fixed inset-y-0 transition-all ease-in-out duration-200 z-40 ',
|
||||
isCollapsed ? 'md:w-12' : 'md:w-40',
|
||||
devOnly ? '!hidden' : ''
|
||||
)}
|
||||
>
|
||||
<div
|
||||
class="flex-1 flex flex-col min-h-0 h-screen shadow-lg dark:bg-[#1e232e] bg-[#202125] !dark"
|
||||
class="flex-1 flex flex-col min-h-0 h-screen border-r border-light dark:border-gray-700"
|
||||
style:background-color={darkMode ? SIDEBAR_BG_DARK : SIDEBAR_BG}
|
||||
>
|
||||
<button
|
||||
onclick={() => {
|
||||
@@ -591,10 +601,10 @@
|
||||
class:w-40={!isCollapsed}
|
||||
>
|
||||
<div class:mr-1={!isCollapsed}>
|
||||
<WindmillIcon white={true} height="20px" width="20px" />
|
||||
<WindmillIcon white={darkMode} height="20px" width="20px" />
|
||||
</div>
|
||||
{#if !isCollapsed}
|
||||
<div class="text-sm mt-0.5 text-white">
|
||||
<div class="text-sm mt-0.5 text-emphasis">
|
||||
{#if $whitelabelNameStore}{capitalize(
|
||||
$whitelabelNameStore
|
||||
)}{:else}Windmill{/if}
|
||||
@@ -602,7 +612,7 @@
|
||||
{/if}
|
||||
</div>
|
||||
</button>
|
||||
<div class="px-2 py-4 border-y border-gray-700 flex flex-col gap-1">
|
||||
<div class="px-2 py-4 border-y border-light dark:border-gray-700 flex flex-col gap-1">
|
||||
<Menubar class="flex flex-col gap-1">
|
||||
{#snippet children({ createMenu })}
|
||||
<WorkspaceMenu {createMenu} {isCollapsed} />
|
||||
@@ -632,7 +642,7 @@
|
||||
}}
|
||||
label="Ask AI"
|
||||
class="!text-xs"
|
||||
iconClasses="!text-ai-inverse dark:!text-ai"
|
||||
iconClasses="!text-ai"
|
||||
shortcut={`${getModifierKey()}L`}
|
||||
/>
|
||||
</div>
|
||||
@@ -653,7 +663,7 @@
|
||||
<ArrowLeft
|
||||
size={16}
|
||||
class={classNames(
|
||||
'flex-shrink-0 h-4 w-4 transition-all ease-in-out duration-200 text-white',
|
||||
'flex-shrink-0 h-4 w-4 transition-all ease-in-out duration-200 text-secondary',
|
||||
isCollapsed ? 'rotate-180' : 'rotate-0'
|
||||
)}
|
||||
/>
|
||||
@@ -670,7 +680,7 @@
|
||||
<!-- Legacy menu -->
|
||||
<div
|
||||
class={classNames(
|
||||
'fixed inset-0 dark:bg-[#1e232e] bg-[#202125] dark:bg-opacity-75 bg-opacity-75 transition-opacity ease-linear duration-300 !dark',
|
||||
'fixed inset-0 bg-black/50 transition-opacity ease-linear duration-300',
|
||||
'opacity-0 pointer-events-none'
|
||||
)}
|
||||
>
|
||||
@@ -708,18 +718,18 @@
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="dark:bg-[#1e232e] bg-[#202125] h-full !dark">
|
||||
<div class="h-full" style:background-color={darkMode ? SIDEBAR_BG_DARK : SIDEBAR_BG}>
|
||||
<div
|
||||
class="flex gap-x-2 flex-shrink-0 p-4 font-semibold text-gray-200 w-10"
|
||||
class="flex gap-x-2 flex-shrink-0 p-4 font-semibold text-emphasis w-10"
|
||||
class:w-40={!isCollapsed}
|
||||
>
|
||||
<WindmillIcon white={true} height="20px" width="20px" />
|
||||
<WindmillIcon white={darkMode} height="20px" width="20px" />
|
||||
{#if !isCollapsed}{#if $whitelabelNameStore}{capitalize(
|
||||
$whitelabelNameStore
|
||||
)}{:else}Windmill{/if}{/if}
|
||||
</div>
|
||||
|
||||
<div class="px-2 py-4 space-y-2 border-y border-gray-500">
|
||||
<div class="px-2 py-4 space-y-2 border-y border-light dark:border-gray-700">
|
||||
<Menubar>
|
||||
{#snippet children({ createMenu })}
|
||||
<WorkspaceMenu {createMenu} />
|
||||
@@ -745,7 +755,7 @@
|
||||
}}
|
||||
label="Ask AI"
|
||||
class="!text-xs"
|
||||
iconClasses="!text-ai-inverse dark:!text-ai"
|
||||
iconClasses="!text-ai"
|
||||
shortcut={`${getModifierKey()}L`}
|
||||
/>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user