mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-22 13:28:04 -05:00
dark mode (#45)
* dark mode * fix(ui): cleaned up dark mode --------- Co-authored-by: Emir Karabeg <emirkarabeg@berkeley.edu>
This commit is contained in:
@@ -19,7 +19,7 @@ export function ActionBar({ blockId }: ActionBarProps) {
|
||||
)
|
||||
|
||||
return (
|
||||
<div className="absolute top-0 -right-20 flex flex-col items-center gap-2 p-2 bg-white rounded-md shadow-sm border border-gray-200">
|
||||
<div className="absolute top-0 -right-20 flex flex-col items-center gap-2 p-2 bg-background rounded-md shadow-sm border border-gray-200 dark:border-gray-800">
|
||||
{/* <Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
|
||||
@@ -9,7 +9,6 @@ import ReactFlow, {
|
||||
NodeTypes,
|
||||
Position,
|
||||
ReactFlowProvider,
|
||||
useOnViewportChange,
|
||||
useReactFlow,
|
||||
} from 'reactflow'
|
||||
import 'reactflow/dist/style.css'
|
||||
@@ -44,7 +43,7 @@ function WorkflowContent() {
|
||||
// Hooks
|
||||
const params = useParams()
|
||||
const router = useRouter()
|
||||
const { project, setViewport } = useReactFlow()
|
||||
const { project } = useReactFlow()
|
||||
|
||||
// Store access
|
||||
const { addNotification } = useNotificationStore()
|
||||
|
||||
@@ -253,11 +253,11 @@ export function ControlBar() {
|
||||
</DropdownMenu>
|
||||
|
||||
<Button
|
||||
className="gap-2 bg-[#7F2FFF] hover:bg-[#7F2FFF]/90"
|
||||
className="gap-2 bg-[#7F2FFF] hover:bg-[#7F2FFF]/90 text-white"
|
||||
onClick={handleRunWorkflow}
|
||||
disabled={isExecuting}
|
||||
>
|
||||
<Play fill="currentColor" className="!h-3.5 !w-3.5" />
|
||||
<Play fill="white" stroke="white" className="!h-3.5 !w-3.5" />
|
||||
{isExecuting ? 'Running...' : 'Run'}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -12,6 +12,13 @@ import {
|
||||
} from '@/components/ui/alert-dialog'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@/components/ui/select'
|
||||
import { Switch } from '@/components/ui/switch'
|
||||
import { useGeneralStore } from '@/stores/settings/general/store'
|
||||
import { resetAllStores } from '@/stores'
|
||||
@@ -22,6 +29,8 @@ export function General() {
|
||||
const toggleAutoConnect = useGeneralStore((state) => state.toggleAutoConnect)
|
||||
const isDebugModeEnabled = useGeneralStore((state) => state.isDebugModeEnabled)
|
||||
const toggleDebugMode = useGeneralStore((state) => state.toggleDebugMode)
|
||||
const theme = useGeneralStore((state) => state.theme)
|
||||
const setTheme = useGeneralStore((state) => state.setTheme)
|
||||
|
||||
const handleResetData = () => {
|
||||
resetAllStores()
|
||||
@@ -33,6 +42,20 @@ export function General() {
|
||||
<div>
|
||||
<h2 className="text-lg font-medium mb-4">General Settings</h2>
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between py-1">
|
||||
<Label htmlFor="theme-select" className="font-medium">
|
||||
Theme
|
||||
</Label>
|
||||
<Select value={theme} onValueChange={setTheme}>
|
||||
<SelectTrigger className="w-[180px]">
|
||||
<SelectValue placeholder="Select theme" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="light">Light</SelectItem>
|
||||
<SelectItem value="dark">Dark</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="flex items-center justify-between py-1">
|
||||
<Label htmlFor="debug-mode" className="font-medium">
|
||||
Debug mode
|
||||
|
||||
@@ -50,7 +50,6 @@ export function Sidebar() {
|
||||
<AgentIcon className="text-white transition-all group-hover:scale-110 -translate-y-[0.5px] w-5 h-5" />
|
||||
<span className="sr-only">Sim Studio</span>
|
||||
</Link>
|
||||
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
|
||||
@@ -35,8 +35,8 @@ export function ToolbarTabs({ activeTab, onTabChange }: ToolbarTabsProps) {
|
||||
<button
|
||||
ref={blocksRef}
|
||||
onClick={() => onTabChange('blocks')}
|
||||
className={`text-sm font-medium transition-colors hover:text-black ${
|
||||
activeTab === 'blocks' ? 'text-black' : 'text-muted-foreground'
|
||||
className={`text-sm font-medium transition-colors hover:text-foreground ${
|
||||
activeTab === 'blocks' ? 'text-foreground' : 'text-muted-foreground'
|
||||
}`}
|
||||
>
|
||||
Blocks
|
||||
@@ -44,8 +44,8 @@ export function ToolbarTabs({ activeTab, onTabChange }: ToolbarTabsProps) {
|
||||
<button
|
||||
ref={toolsRef}
|
||||
onClick={() => onTabChange('tools')}
|
||||
className={`text-sm font-medium transition-colors hover:text-black ${
|
||||
activeTab === 'tools' ? 'text-black' : 'text-muted-foreground'
|
||||
className={`text-sm font-medium transition-colors hover:text-foreground ${
|
||||
activeTab === 'tools' ? 'text-foreground' : 'text-muted-foreground'
|
||||
}`}
|
||||
>
|
||||
Tools
|
||||
@@ -53,9 +53,9 @@ export function ToolbarTabs({ activeTab, onTabChange }: ToolbarTabsProps) {
|
||||
</div>
|
||||
|
||||
<div className="relative mt-2">
|
||||
<div className="absolute bottom-0 h-[1px] w-full bg-[#E2E8F0]" />
|
||||
<div className="absolute bottom-0 h-[1px] w-full border-b" />
|
||||
<div
|
||||
className="absolute bottom-0 h-[1.5px] bg-black transition-transform duration-200"
|
||||
className="absolute bottom-0 h-[1.5px] bg-foreground transition-transform duration-200"
|
||||
style={{
|
||||
width: `${underlineStyle.width}px`,
|
||||
transform: underlineStyle.transform,
|
||||
|
||||
@@ -4,7 +4,7 @@ import { ControlBar } from './components/control-bar/control-bar'
|
||||
import { ErrorBoundary } from './components/error-boundary/error-boundary'
|
||||
import { Sidebar } from './components/sidebar/sidebar'
|
||||
import { Toolbar } from './components/toolbar/toolbar'
|
||||
import Providers from './providers'
|
||||
import Providers from './providers/providers'
|
||||
|
||||
export default function WorkspaceLayout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
'use client'
|
||||
|
||||
import { TooltipProvider } from '@/components/ui/tooltip'
|
||||
|
||||
export default function Providers({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<TooltipProvider delayDuration={100} skipDelayDuration={0}>
|
||||
{children}
|
||||
</TooltipProvider>
|
||||
)
|
||||
}
|
||||
14
app/w/providers/providers.tsx
Normal file
14
app/w/providers/providers.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
'use client'
|
||||
|
||||
import { TooltipProvider } from '@/components/ui/tooltip'
|
||||
import { ThemeProvider } from './theme-provider'
|
||||
|
||||
export default function Providers({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<ThemeProvider>
|
||||
<TooltipProvider delayDuration={100} skipDelayDuration={0}>
|
||||
{children}
|
||||
</TooltipProvider>
|
||||
</ThemeProvider>
|
||||
)
|
||||
}
|
||||
16
app/w/providers/theme-provider.tsx
Normal file
16
app/w/providers/theme-provider.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect } from 'react'
|
||||
import { useGeneralStore } from '@/stores/settings/general/store'
|
||||
|
||||
export function ThemeProvider({ children }: { children: React.ReactNode }) {
|
||||
const theme = useGeneralStore((state) => state.theme)
|
||||
|
||||
useEffect(() => {
|
||||
const root = window.document.documentElement
|
||||
root.classList.remove('light', 'dark')
|
||||
root.classList.add(theme)
|
||||
}, [theme])
|
||||
|
||||
return children
|
||||
}
|
||||
@@ -30,6 +30,9 @@ import { cn } from '@/lib/utils'
|
||||
// This file is not typed correctly from shadcn, so we're disabling the type checker
|
||||
// @ts-nocheck
|
||||
|
||||
// This file is not typed correctly from shadcn, so we're disabling the type checker
|
||||
// @ts-nocheck
|
||||
|
||||
const Command = React.forwardRef<
|
||||
React.ElementRef<typeof CommandPrimitive>,
|
||||
React.ComponentPropsWithoutRef<typeof CommandPrimitive> & {
|
||||
|
||||
@@ -4,11 +4,13 @@ import { devtools, persist } from 'zustand/middleware'
|
||||
interface General {
|
||||
isAutoConnectEnabled: boolean
|
||||
isDebugModeEnabled: boolean
|
||||
theme: 'light' | 'dark'
|
||||
}
|
||||
|
||||
interface GeneralActions {
|
||||
toggleAutoConnect: () => void
|
||||
toggleDebugMode: () => void
|
||||
setTheme: (theme: 'light' | 'dark') => void
|
||||
}
|
||||
|
||||
type GeneralStore = General & GeneralActions
|
||||
@@ -19,9 +21,11 @@ export const useGeneralStore = create<GeneralStore>()(
|
||||
(set) => ({
|
||||
isAutoConnectEnabled: true,
|
||||
isDebugModeEnabled: false,
|
||||
theme: 'light',
|
||||
toggleAutoConnect: () =>
|
||||
set((state) => ({ isAutoConnectEnabled: !state.isAutoConnectEnabled })),
|
||||
toggleDebugMode: () => set((state) => ({ isDebugModeEnabled: !state.isDebugModeEnabled })),
|
||||
setTheme: (theme: 'light' | 'dark') => set({ theme }),
|
||||
}),
|
||||
{
|
||||
name: 'general-settings',
|
||||
|
||||
Reference in New Issue
Block a user