Workspaces in Workspaces all around

This commit is contained in:
2026-02-19 01:49:15 +00:00
parent 72bca6cd42
commit dd8ab84df5
84 changed files with 3047 additions and 749 deletions
+1 -1
View File
@@ -5,7 +5,7 @@ export const ColorPicker = (props: ColorPickerProps) => {
const { value = '#000000', name, label } = props;
return (
<div style={{ borderWidth: '1px' }} className="relative w-full rounded">
{label && <span className="text-muted-foreground absolute z-10 -mt-2 ml-5 bg-white px-2 text-xs">{label}</span>}
{label && <span className="text-muted-foreground absolute z-10 -mt-2 ml-5 bg-background px-2 text-xs">{label}</span>}
<div className="flex items-center justify-between">
<div className="h-12 overflow-hidden rounded-full p-0">
<Input
@@ -21,7 +21,7 @@ export const PaginationBar = <T,>(props: PaginationBarProps<T>) => {
};
const buttonClass =
'h-8 w-8 p-0 hover:bg-white text-muted-foreground disabled:opacity-100 disabled:pointer-events-none';
'h-8 w-8 p-0 hover:bg-background text-muted-foreground disabled:opacity-100 disabled:pointer-events-none';
return (
<div className="bg-muted/50 flex w-full items-center justify-between border-t p-4">
@@ -44,7 +44,7 @@ export const PaginationBar = <T,>(props: PaginationBarProps<T>) => {
justify-between
bg-transparent
text-muted-foreground
hover:bg-white
hover:bg-background
data-[state=open]:bg-muted
"
aria-label="Rows per page"
+1 -1
View File
@@ -69,7 +69,7 @@ export function MarkdownEditor({
) : (
<div className="w-full h-full overflow-auto bg-slate-50 dark:bg-slate-900 p-4">
{/* Email wrapper simulation */}
<div className="mx-auto max-w-2xl rounded-lg bg-white dark:bg-slate-800 p-8 shadow-lg">
<div className="mx-auto max-w-2xl rounded-lg bg-background p-8 shadow-lg">
{/* Logo */}
<div className="mb-8 text-center">
<img src="https://app.pertento.ai/logo.png" alt="Pertento" className="h-16 mx-auto" />
@@ -14,7 +14,7 @@ export const AppPicker = ({ registry, onSelect }: AppPickerProps) => {
<button
key={key}
type="button"
className="flex flex-col items-center gap-1.5 rounded-lg border border-duck-teal/25 bg-white/80 backdrop-blur-sm px-3 py-3 text-duck-teal hover:border-duck-teal/40 hover:bg-white/90 transition-colors cursor-pointer"
className="flex flex-col items-center gap-1.5 rounded-lg border border-duck-teal/25 bg-background/80 backdrop-blur-sm px-3 py-3 text-duck-teal hover:border-duck-teal/40 hover:bg-background/90 transition-colors cursor-pointer"
onClick={() => onSelect(key)}
>
<entry.icon className="h-5 w-5" />
@@ -20,6 +20,8 @@ export type WorkspaceDefinition = {
id: string;
name: string;
cwd: string;
description?: string;
templateIdx?: number;
};
export type AppRegistryEntry = {
+20 -25
View File
@@ -1,45 +1,40 @@
import { createContext, useContext, useEffect, useState } from 'react';
type ColorMode = 'light' | 'dark';
const initialState = {
theme: 'light',
setTheme: (theme: string) => {
theme;
return null;
},
colorMode: 'light' as ColorMode,
setColorMode: (_mode: ColorMode) => {},
};
type ThemeProviderProps = { children: React.ReactNode; defaultTheme?: string; storageKey?: string };
type ColorModeProviderProps = { children: React.ReactNode; defaultMode?: ColorMode; storageKey?: string };
const ThemeProviderContext = createContext(initialState);
const ColorModeContext = createContext(initialState);
export function ThemeProvider(props: ThemeProviderProps) {
const { children, defaultTheme = 'light', storageKey = 'theme' } = props;
const [theme, setTheme] = useState(() => localStorage.getItem(storageKey) || defaultTheme);
export function ColorModeProvider(props: ColorModeProviderProps) {
const { children, defaultMode = 'light', storageKey = 'officer-color-mode' } = props;
const [colorMode, setColorModeState] = useState<ColorMode>(
() => (localStorage.getItem(storageKey) as ColorMode) || defaultMode,
);
useEffect(() => {
const root = window.document.documentElement;
root.classList.remove('light', 'dark');
root.classList.add(colorMode);
}, [colorMode]);
root.classList.add(theme);
}, [theme]);
const value = {
theme,
setTheme: (newTheme: string) => {
localStorage.setItem(storageKey, newTheme);
setTheme(newTheme);
return null;
},
const setColorMode = (mode: ColorMode) => {
localStorage.setItem(storageKey, mode);
setColorModeState(mode);
};
return <ThemeProviderContext.Provider value={value}>{children}</ThemeProviderContext.Provider>;
return <ColorModeContext.Provider value={{ colorMode, setColorMode }}>{children}</ColorModeContext.Provider>;
}
export const useTheme = () => {
const context = useContext(ThemeProviderContext);
export const useColorMode = () => {
const context = useContext(ColorModeContext);
if (context === undefined) throw new Error('useTheme must be used within a ThemeProvider');
if (context === undefined) throw new Error('useColorMode must be used within a ColorModeProvider');
return context;
};
+6 -6
View File
@@ -1,19 +1,19 @@
import { Moon, Sun } from 'lucide-react';
import { cn } from 'helpers/cn';
import { useTheme } from './ThemeProvider';
import { useColorMode } from './ThemeProvider';
type ThemeToggleProps = { colorDark?: boolean; colorLight?: boolean };
export const ThemeToggle = (props: ThemeToggleProps) => {
const { colorDark, colorLight } = props;
const { theme, setTheme } = useTheme();
const { colorMode, setColorMode } = useColorMode();
const changeTheme = () => {
setTheme(theme === 'dark' ? 'light' : 'dark');
const toggle = () => {
setColorMode(colorMode === 'dark' ? 'light' : 'dark');
};
return (
<div className="cursor-pointer" onClick={changeTheme}>
<div className="cursor-pointer" onClick={toggle}>
<Sun
className={cn(
'h-[1.2rem] w-[1.2rem] origin-center rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0',
@@ -26,7 +26,7 @@ export const ThemeToggle = (props: ThemeToggleProps) => {
colorDark && 'text-black',
)}
/>
<span className="sr-only">Toggle theme</span>
<span className="sr-only">Toggle color mode</span>
</div>
);
};
+4 -4
View File
@@ -1,25 +1,25 @@
import * as React from 'react';
import { Moon, Sun } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { useTheme } from '@/components/ui/ThemeProvider';
import { useColorMode } from '@/components/ui/ThemeProvider';
import { cn } from 'helpers/cn';
export const ModeToggle = React.forwardRef<React.ElementRef<typeof Button>, React.ComponentProps<typeof Button>>(
({ className, ...props }, ref) => {
const { theme, setTheme } = useTheme();
const { colorMode, setColorMode } = useColorMode();
return (
<Button
ref={ref}
variant="outline"
size="icon"
onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}
onClick={() => setColorMode(colorMode === 'light' ? 'dark' : 'light')}
className={cn('h-9 w-9', className)}
{...props}
>
<Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
<Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
<span className="sr-only">Toggle theme</span>
<span className="sr-only">Toggle color mode</span>
</Button>
);
},