mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-07-01 01:23:06 +08:00
style(ui): rework light/dark theme to make it visually consistent
Rework the color system around warm neutrals and route hardcoded surfaces through theme tokens for consistency. - Theme tokens (index.css, ThemeContext): warm cream light mode and neutral charcoal dark mode, replacing the pure-white/blue-tinted palette; update PWA theme-color meta - Code blocks: soft grey background in light mode via oneLight/oneDark, and drop the Tailwind Typography <pre> shell that framed the highlighter in a dark box - Dropdowns/panels: convert CommandMenu, Quick Settings, and the JSON response block from hardcoded gray/slate to popover/muted/border tokens - Git panel: Publish button purple -> primary blue - Composer: drop top padding so the input sits flush with the thread
This commit is contained in:
@@ -197,7 +197,7 @@ export default function ChatComposer({
|
||||
const hasPendingPermissions = pendingPermissionRequests.length > 0;
|
||||
|
||||
return (
|
||||
<div className="chat-composer-shell flex-shrink-0 p-2 pb-2 sm:p-4 sm:pb-4 md:p-4 md:pb-6">
|
||||
<div className="chat-composer-shell flex-shrink-0 px-2 pb-2 pt-0 sm:px-4 sm:pb-4 md:px-4 md:pb-6">
|
||||
{!hasPendingPermissions && (
|
||||
<ActivityIndicator activity={activity} onAbort={onAbortSession} />
|
||||
)}
|
||||
|
||||
@@ -226,7 +226,7 @@ export default function CommandMenu({
|
||||
return renderInPortal(
|
||||
<div
|
||||
ref={menuRef}
|
||||
className="command-menu command-menu-empty border border-gray-200 bg-white/95 text-sm text-gray-500 dark:border-gray-700/80 dark:bg-gray-900/95 dark:text-gray-400"
|
||||
className="command-menu command-menu-empty border border-border bg-popover/95 text-sm text-muted-foreground"
|
||||
style={{
|
||||
...menuBaseStyle,
|
||||
...menuPosition,
|
||||
@@ -247,15 +247,15 @@ export default function CommandMenu({
|
||||
ref={menuRef}
|
||||
role="listbox"
|
||||
aria-label="Available commands"
|
||||
className="command-menu border border-gray-200/90 bg-white/95 text-gray-900 dark:border-slate-700/80 dark:bg-slate-950/95 dark:text-slate-100"
|
||||
className="command-menu border border-border bg-popover/95 text-popover-foreground"
|
||||
style={{ ...menuBaseStyle, ...menuPosition, opacity: 1, transform: 'translateY(0)' }}
|
||||
>
|
||||
{orderedNamespaces.map((namespace) => (
|
||||
<div key={namespace} className="command-group">
|
||||
{orderedNamespaces.length > 1 && (
|
||||
<div className="flex items-center justify-between px-2 pb-1.5 pt-2 text-[10px] font-semibold uppercase tracking-wide text-gray-500 dark:text-slate-400">
|
||||
<div className="flex items-center justify-between px-2 pb-1.5 pt-2 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground">
|
||||
<span>{namespaceLabels[namespace] || namespace}</span>
|
||||
<span className="rounded border border-gray-200 bg-gray-50 px-1.5 py-0.5 text-[10px] text-gray-500 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-400">
|
||||
<span className="rounded border border-border bg-muted px-1.5 py-0.5 text-[10px] text-muted-foreground">
|
||||
{(groupedCommands[namespace] || []).length}
|
||||
</span>
|
||||
</div>
|
||||
@@ -273,15 +273,15 @@ export default function CommandMenu({
|
||||
aria-selected={isSelected}
|
||||
className={`command-item group relative mb-1 flex cursor-pointer items-start gap-2 rounded-md border px-2.5 py-2 transition-all ${
|
||||
isSelected
|
||||
? 'border-sky-200 bg-sky-50 shadow-sm dark:border-cyan-400/30 dark:bg-cyan-400/10'
|
||||
: 'border-transparent bg-transparent hover:border-gray-200 hover:bg-gray-50/90 dark:hover:border-slate-700 dark:hover:bg-slate-900/80'
|
||||
? 'border-primary/30 bg-primary/10 shadow-sm'
|
||||
: 'border-transparent bg-transparent hover:border-border hover:bg-accent'
|
||||
}`}
|
||||
onMouseEnter={() => onSelect && commandIndex >= 0 && onSelect(command, commandIndex, true)}
|
||||
onClick={() => onSelect && commandIndex >= 0 && onSelect(command, commandIndex, false)}
|
||||
onMouseDown={(event) => event.preventDefault()}
|
||||
>
|
||||
{isSelected && (
|
||||
<span className="absolute bottom-1.5 left-1.5 top-1.5 w-0.5 rounded-full bg-sky-500 dark:bg-cyan-300" />
|
||||
<span className="absolute bottom-1.5 left-1.5 top-1.5 w-0.5 rounded-full bg-primary" />
|
||||
)}
|
||||
<span className={`mt-0.5 flex h-7 w-7 shrink-0 items-center justify-center rounded-md border ${accentClass}`}>
|
||||
<NamespaceIcon aria-hidden="true" size={14} strokeWidth={2.2} />
|
||||
@@ -289,20 +289,20 @@ export default function CommandMenu({
|
||||
<div className="min-w-0 flex-1 pr-1">
|
||||
<div className={`flex min-w-0 items-center gap-2 ${command.description ? 'mb-1' : 'mb-0'}`}>
|
||||
<span
|
||||
className="min-w-0 truncate font-mono text-[13px] font-semibold text-gray-950 dark:text-slate-50"
|
||||
className="min-w-0 truncate font-mono text-[13px] font-semibold text-foreground"
|
||||
title={command.name}
|
||||
>
|
||||
{command.name}
|
||||
</span>
|
||||
{command.metadata?.type && (
|
||||
<span className="command-metadata-badge shrink-0 rounded border border-gray-200 bg-white px-1.5 py-0.5 text-[10px] font-medium text-gray-500 shadow-sm dark:border-slate-700 dark:bg-slate-900 dark:text-slate-300">
|
||||
<span className="command-metadata-badge shrink-0 rounded border border-border bg-muted px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground shadow-sm">
|
||||
{command.metadata.type}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{command.description && (
|
||||
<div
|
||||
className="truncate whitespace-nowrap text-[12px] leading-4 text-gray-500 dark:text-slate-400"
|
||||
className="truncate whitespace-nowrap text-[12px] leading-4 text-muted-foreground"
|
||||
title={command.description}
|
||||
>
|
||||
{command.description}
|
||||
@@ -310,7 +310,7 @@ export default function CommandMenu({
|
||||
)}
|
||||
</div>
|
||||
{isSelected && (
|
||||
<span className="mt-1 flex h-6 w-6 shrink-0 items-center justify-center rounded border border-sky-200 bg-white text-sky-600 shadow-sm dark:border-cyan-400/30 dark:bg-slate-950 dark:text-cyan-200">
|
||||
<span className="mt-1 flex h-6 w-6 shrink-0 items-center justify-center rounded border border-primary/30 bg-card text-primary shadow-sm">
|
||||
<CornerDownLeft aria-hidden="true" size={13} strokeWidth={2.2} />
|
||||
</span>
|
||||
)}
|
||||
|
||||
@@ -4,11 +4,12 @@ import remarkGfm from 'remark-gfm';
|
||||
import remarkMath from 'remark-math';
|
||||
import rehypeKatex from 'rehype-katex';
|
||||
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
||||
import { oneDark } from 'react-syntax-highlighter/dist/esm/styles/prism';
|
||||
import { oneDark, oneLight } from 'react-syntax-highlighter/dist/esm/styles/prism';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { normalizeInlineCodeFences } from '../../utils/chatFormatting';
|
||||
import { copyTextToClipboard } from '../../../../utils/clipboard';
|
||||
import { usePaletteOps } from '../../../../contexts/PaletteOpsContext';
|
||||
import { useTheme } from '../../../../contexts/ThemeContext';
|
||||
|
||||
type MarkdownProps = {
|
||||
children: React.ReactNode;
|
||||
@@ -59,6 +60,7 @@ type CodeBlockProps = {
|
||||
|
||||
const CodeBlock = ({ node, inline, className, children, ...props }: CodeBlockProps) => {
|
||||
const { t } = useTranslation('chat');
|
||||
const { isDarkMode } = useTheme();
|
||||
const [copied, setCopied] = useState(false);
|
||||
const raw = Array.isArray(children) ? children.join('') : String(children ?? '');
|
||||
const looksMultiline = /[\r\n]/.test(raw);
|
||||
@@ -96,7 +98,7 @@ const CodeBlock = ({ node, inline, className, children, ...props }: CodeBlockPro
|
||||
}
|
||||
})
|
||||
}
|
||||
className="absolute right-2 top-2 z-10 rounded-md border border-gray-600 bg-gray-700/80 px-2 py-1 text-xs text-white opacity-0 transition-opacity hover:bg-gray-700 focus:opacity-100 active:opacity-100 group-hover:opacity-100"
|
||||
className="absolute right-2 top-2 z-10 rounded-md border border-border bg-card/90 px-2 py-1 text-xs text-foreground/80 opacity-0 transition-opacity hover:bg-muted focus:opacity-100 active:opacity-100 group-hover:opacity-100"
|
||||
title={copied ? t('codeBlock.copied') : t('codeBlock.copyCode')}
|
||||
aria-label={copied ? t('codeBlock.copied') : t('codeBlock.copyCode')}
|
||||
>
|
||||
@@ -132,17 +134,20 @@ const CodeBlock = ({ node, inline, className, children, ...props }: CodeBlockPro
|
||||
|
||||
<SyntaxHighlighter
|
||||
language={language}
|
||||
style={oneDark}
|
||||
style={isDarkMode ? oneDark : oneLight}
|
||||
customStyle={{
|
||||
margin: 0,
|
||||
borderRadius: '0.5rem',
|
||||
borderRadius: '0.75rem',
|
||||
fontSize: '0.875rem',
|
||||
padding: language && language !== 'text' ? '2rem 1rem 1rem 1rem' : '1rem',
|
||||
// ChatGPT-style soft grey block in light mode; keep oneDark's own bg in dark.
|
||||
...(isDarkMode ? {} : { background: 'hsl(var(--muted))' }),
|
||||
}}
|
||||
codeTagProps={{
|
||||
style: {
|
||||
fontFamily:
|
||||
'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace',
|
||||
...(isDarkMode ? {} : { background: 'transparent' }),
|
||||
},
|
||||
}}
|
||||
>
|
||||
@@ -154,6 +159,10 @@ const CodeBlock = ({ node, inline, className, children, ...props }: CodeBlockPro
|
||||
|
||||
const markdownComponents = {
|
||||
code: CodeBlock,
|
||||
// CodeBlock renders its own syntax-highlighted <pre>; this passthrough stops
|
||||
// react-markdown (and Tailwind Typography) from wrapping it in a second,
|
||||
// dark-themed <pre> shell that would frame the block.
|
||||
pre: ({ children }: { children?: React.ReactNode }) => <>{children}</>,
|
||||
blockquote: ({ children }: { children?: React.ReactNode }) => (
|
||||
<blockquote className="my-2 border-l-4 border-gray-300 pl-4 italic text-gray-600 dark:border-gray-600 dark:text-gray-400">
|
||||
{children}
|
||||
|
||||
@@ -377,15 +377,15 @@ const MessageComponent = memo(({ message, prevMessage, createDiff, onFileOpen, a
|
||||
|
||||
return (
|
||||
<div className="my-2">
|
||||
<div className="mb-2 flex items-center gap-2 text-sm text-gray-600 dark:text-gray-400">
|
||||
<div className="mb-2 flex items-center gap-2 text-sm text-muted-foreground">
|
||||
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" />
|
||||
</svg>
|
||||
<span className="font-medium">{t('json.response')}</span>
|
||||
</div>
|
||||
<div className="overflow-hidden rounded-lg border border-gray-600/30 bg-gray-800 dark:border-gray-700 dark:bg-gray-900">
|
||||
<div className="overflow-hidden rounded-lg border border-border bg-muted">
|
||||
<pre className="overflow-x-auto p-4">
|
||||
<code className="block whitespace-pre font-mono text-sm text-gray-100 dark:text-gray-200">
|
||||
<code className="block whitespace-pre font-mono text-sm text-foreground">
|
||||
{formatted}
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { useState } from 'react';
|
||||
import type { ComponentProps } from 'react';
|
||||
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
||||
import { oneDark as prismOneDark } from 'react-syntax-highlighter/dist/esm/styles/prism';
|
||||
import { oneDark as prismOneDark, oneLight as prismOneLight } from 'react-syntax-highlighter/dist/esm/styles/prism';
|
||||
import { copyTextToClipboard } from '../../../../../utils/clipboard';
|
||||
import { useTheme } from '../../../../../contexts/ThemeContext';
|
||||
|
||||
type MarkdownCodeBlockProps = {
|
||||
inline?: boolean;
|
||||
@@ -16,6 +17,7 @@ export default function MarkdownCodeBlock({
|
||||
node: _node,
|
||||
...props
|
||||
}: MarkdownCodeBlockProps) {
|
||||
const { isDarkMode } = useTheme();
|
||||
const [copied, setCopied] = useState(false);
|
||||
const rawContent = Array.isArray(children) ? children.join('') : String(children ?? '');
|
||||
const looksMultiline = /[\r\n]/.test(rawContent);
|
||||
@@ -50,20 +52,22 @@ export default function MarkdownCodeBlock({
|
||||
setTimeout(() => setCopied(false), 2000);
|
||||
}
|
||||
})}
|
||||
className="absolute right-2 top-2 z-10 rounded-md border border-gray-600 bg-gray-700/80 px-2 py-1 text-xs text-white opacity-0 transition-opacity hover:bg-gray-700 group-hover:opacity-100"
|
||||
className="absolute right-2 top-2 z-10 rounded-md border border-border bg-card/90 px-2 py-1 text-xs text-foreground/80 opacity-0 transition-opacity hover:bg-muted group-hover:opacity-100"
|
||||
>
|
||||
{copied ? 'Copied!' : 'Copy'}
|
||||
</button>
|
||||
|
||||
<SyntaxHighlighter
|
||||
language={language}
|
||||
style={prismOneDark}
|
||||
style={isDarkMode ? prismOneDark : prismOneLight}
|
||||
customStyle={{
|
||||
margin: 0,
|
||||
borderRadius: '0.5rem',
|
||||
borderRadius: '0.75rem',
|
||||
fontSize: '0.875rem',
|
||||
padding: language !== 'text' ? '2rem 1rem 1rem 1rem' : '1rem',
|
||||
...(isDarkMode ? {} : { background: 'hsl(var(--muted))' }),
|
||||
}}
|
||||
codeTagProps={{ style: isDarkMode ? {} : { background: 'transparent' } }}
|
||||
>
|
||||
{rawContent}
|
||||
</SyntaxHighlighter>
|
||||
|
||||
@@ -12,6 +12,9 @@ type MarkdownPreviewProps = {
|
||||
|
||||
const markdownPreviewComponents: Components = {
|
||||
code: MarkdownCodeBlock,
|
||||
// MarkdownCodeBlock renders its own highlighted <pre>; passthrough prevents a
|
||||
// second Typography-styled <pre> shell from framing it.
|
||||
pre: ({ children }) => <>{children}</>,
|
||||
blockquote: ({ children }) => (
|
||||
<blockquote className="my-2 border-l-4 border-gray-300 pl-4 italic text-gray-600 dark:border-gray-600 dark:text-gray-400">
|
||||
{children}
|
||||
|
||||
@@ -189,7 +189,7 @@ export default function GitPanelHeader({
|
||||
<button
|
||||
onClick={requestPublishConfirmation}
|
||||
disabled={anyPending}
|
||||
className="flex items-center gap-1 rounded-lg bg-purple-600 px-2.5 py-1 text-sm text-white transition-colors hover:bg-purple-700 disabled:opacity-50"
|
||||
className="flex items-center gap-1 rounded-lg bg-primary px-2.5 py-1 text-sm text-primary-foreground transition-colors hover:bg-primary/90 disabled:opacity-50"
|
||||
title={`Publish "${currentBranch}" to ${remoteName}`}
|
||||
>
|
||||
<Upload className={`h-3 w-3 ${isPublishing ? 'animate-pulse' : ''}`} />
|
||||
|
||||
@@ -16,7 +16,7 @@ export const HANDLE_POSITION_MAX = 90;
|
||||
export const DRAG_THRESHOLD_PX = 5;
|
||||
|
||||
export const SETTING_ROW_CLASS =
|
||||
'flex items-center justify-between p-3 rounded-lg bg-gray-50 dark:bg-gray-800 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors border border-transparent hover:border-gray-300 dark:hover:border-gray-600';
|
||||
'flex items-center justify-between p-3 rounded-lg bg-muted/60 hover:bg-accent transition-colors border border-transparent hover:border-border';
|
||||
|
||||
export const TOGGLE_ROW_CLASS = `${SETTING_ROW_CLASS} cursor-pointer`;
|
||||
|
||||
|
||||
@@ -49,11 +49,11 @@ export default function QuickSettingsContent({
|
||||
<div className="flex-1 space-y-6 overflow-y-auto overflow-x-hidden bg-background p-4">
|
||||
<QuickSettingsSection title={t('quickSettings.sections.appearance')}>
|
||||
<div className={SETTING_ROW_CLASS}>
|
||||
<span className="flex items-center gap-2 text-sm text-gray-900 dark:text-white">
|
||||
<span className="flex items-center gap-2 text-sm text-foreground">
|
||||
{isDarkMode ? (
|
||||
<Moon className="h-4 w-4 text-gray-600 dark:text-gray-400" />
|
||||
<Moon className="h-4 w-4 text-muted-foreground" />
|
||||
) : (
|
||||
<Sun className="h-4 w-4 text-gray-600 dark:text-gray-400" />
|
||||
<Sun className="h-4 w-4 text-muted-foreground" />
|
||||
)}
|
||||
{t('quickSettings.darkMode')}
|
||||
</span>
|
||||
@@ -68,7 +68,7 @@ export default function QuickSettingsContent({
|
||||
|
||||
<QuickSettingsSection title={t('quickSettings.sections.inputSettings')}>
|
||||
{renderToggleRows(inputSettingToggles)}
|
||||
<p className="ml-3 text-xs text-gray-500 dark:text-gray-400">
|
||||
<p className="ml-3 text-xs text-muted-foreground">
|
||||
{t('quickSettings.sendByCtrlEnterDescription')}
|
||||
</p>
|
||||
</QuickSettingsSection>
|
||||
|
||||
@@ -5,9 +5,9 @@ export default function QuickSettingsPanelHeader() {
|
||||
const { t } = useTranslation('settings');
|
||||
|
||||
return (
|
||||
<div className="border-b border-gray-200 bg-gray-50 p-4 dark:border-gray-700 dark:bg-gray-900">
|
||||
<h3 className="flex items-center gap-2 text-lg font-semibold text-gray-900 dark:text-white">
|
||||
<Settings2 className="h-5 w-5 text-gray-600 dark:text-gray-400" />
|
||||
<div className="border-b border-border bg-muted/40 p-4">
|
||||
<h3 className="flex items-center gap-2 text-lg font-semibold text-foreground">
|
||||
<Settings2 className="h-5 w-5 text-muted-foreground" />
|
||||
{t('quickSettings.title')}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
@@ -13,7 +13,7 @@ export default function QuickSettingsSection({
|
||||
}: QuickSettingsSectionProps) {
|
||||
return (
|
||||
<div className={`space-y-2 ${className}`}>
|
||||
<h4 className="mb-2 text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400">
|
||||
<h4 className="mb-2 text-xs font-semibold uppercase tracking-wider text-muted-foreground">
|
||||
{title}
|
||||
</h4>
|
||||
{children}
|
||||
|
||||
@@ -17,8 +17,8 @@ function QuickSettingsToggleRow({
|
||||
}: QuickSettingsToggleRowProps) {
|
||||
return (
|
||||
<label className={TOGGLE_ROW_CLASS}>
|
||||
<span className="flex items-center gap-2 text-sm text-gray-900 dark:text-white">
|
||||
<Icon className="h-4 w-4 text-gray-600 dark:text-gray-400" />
|
||||
<span className="flex items-center gap-2 text-sm text-foreground">
|
||||
<Icon className="h-4 w-4 text-muted-foreground" />
|
||||
{label}
|
||||
</span>
|
||||
<input
|
||||
|
||||
@@ -41,7 +41,7 @@ export const ThemeProvider = ({ children }) => {
|
||||
|
||||
const themeColorMeta = document.querySelector('meta[name="theme-color"]');
|
||||
if (themeColorMeta) {
|
||||
themeColorMeta.setAttribute('content', '#0c1117'); // Dark background color (hsl(222.2 84% 4.9%))
|
||||
themeColorMeta.setAttribute('content', '#141414'); // Dark background color (hsl(0 0% 8%))
|
||||
}
|
||||
} else {
|
||||
document.documentElement.classList.remove('dark');
|
||||
@@ -55,7 +55,7 @@ export const ThemeProvider = ({ children }) => {
|
||||
|
||||
const themeColorMeta = document.querySelector('meta[name="theme-color"]');
|
||||
if (themeColorMeta) {
|
||||
themeColorMeta.setAttribute('content', '#ffffff'); // Light background color
|
||||
themeColorMeta.setAttribute('content', '#f6f4ef'); // Light background color (warm cream)
|
||||
}
|
||||
}
|
||||
}, [isDarkMode]);
|
||||
|
||||
@@ -23,37 +23,37 @@
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 222.2 84% 4.9%;
|
||||
--background: 44 22% 96%;
|
||||
--foreground: 36 25% 4%;
|
||||
--card: 0 0% 100%;
|
||||
--card-foreground: 222.2 84% 4.9%;
|
||||
--card-foreground: 36 25% 4%;
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 222.2 84% 4.9%;
|
||||
--popover-foreground: 36 25% 4%;
|
||||
--primary: 221.2 83.2% 53.3%;
|
||||
--primary-foreground: 210 40% 98%;
|
||||
--secondary: 210 40% 96.1%;
|
||||
--secondary-foreground: 222.2 47.4% 11.2%;
|
||||
--muted: 210 40% 96.1%;
|
||||
--muted-foreground: 215.4 16.3% 46.9%;
|
||||
--accent: 210 40% 96.1%;
|
||||
--accent-foreground: 222.2 47.4% 11.2%;
|
||||
--secondary: 44 15% 91%;
|
||||
--secondary-foreground: 36 15% 18%;
|
||||
--muted: 44 15% 91%;
|
||||
--muted-foreground: 40 5% 44%;
|
||||
--accent: 44 15% 91%;
|
||||
--accent-foreground: 36 15% 18%;
|
||||
--destructive: 0 84.2% 60.2%;
|
||||
--destructive-foreground: 210 40% 98%;
|
||||
--border: 214.3 31.8% 91.4%;
|
||||
--input: 214.3 31.8% 91.4%;
|
||||
--border: 44 14% 87%;
|
||||
--input: 44 14% 87%;
|
||||
--ring: 221.2 83.2% 53.3%;
|
||||
--radius: 0.5rem;
|
||||
|
||||
/* Nav design tokens */
|
||||
--nav-glass-bg: 0 0% 100% / 0.7;
|
||||
--nav-glass-bg: 44 22% 96% / 0.7;
|
||||
--nav-glass-blur: 20px;
|
||||
--nav-glass-saturate: 1.8;
|
||||
--nav-tab-glow: 221.2 83.2% 53.3% / 0.18;
|
||||
--nav-tab-ring: 221.2 83.2% 53.3% / 0.10;
|
||||
--nav-float-shadow: 0 0% 0% / 0.06;
|
||||
--nav-float-ring: 214.3 31.8% 91.4% / 0.5;
|
||||
--nav-divider-color: 214.3 31.8% 91.4% / 0.5;
|
||||
--nav-input-bg: 210 40% 96.1% / 0.5;
|
||||
--nav-float-ring: 44 14% 87% / 0.5;
|
||||
--nav-divider-color: 44 14% 87% / 0.5;
|
||||
--nav-input-bg: 44 15% 91% / 0.5;
|
||||
--nav-input-focus-ring: 221.2 83.2% 53.3% / 0.22;
|
||||
|
||||
/* Safe area CSS variables */
|
||||
@@ -85,36 +85,36 @@
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: 222.2 84% 4.9%;
|
||||
--foreground: 210 40% 98%;
|
||||
--card: 217.2 91.2% 8%;
|
||||
--card-foreground: 210 40% 98%;
|
||||
--popover: 217.2 91.2% 8%;
|
||||
--popover-foreground: 210 40% 98%;
|
||||
--background: 0 0% 8%;
|
||||
--foreground: 40 8% 93%;
|
||||
--card: 0 0% 12%;
|
||||
--card-foreground: 40 8% 93%;
|
||||
--popover: 0 0% 12%;
|
||||
--popover-foreground: 40 8% 93%;
|
||||
--primary: 217.2 91.2% 59.8%;
|
||||
--primary-foreground: 222.2 47.4% 11.2%;
|
||||
--secondary: 217.2 32.6% 17.5%;
|
||||
--secondary-foreground: 210 40% 98%;
|
||||
--muted: 217.2 32.6% 17.5%;
|
||||
--muted-foreground: 215 20.2% 65.1%;
|
||||
--accent: 217.2 32.6% 17.5%;
|
||||
--accent-foreground: 210 40% 98%;
|
||||
--primary-foreground: 0 0% 8%;
|
||||
--secondary: 0 0% 17%;
|
||||
--secondary-foreground: 40 8% 93%;
|
||||
--muted: 0 0% 17%;
|
||||
--muted-foreground: 0 0% 60%;
|
||||
--accent: 0 0% 17%;
|
||||
--accent-foreground: 40 8% 93%;
|
||||
--destructive: 0 62.8% 30.6%;
|
||||
--destructive-foreground: 210 40% 98%;
|
||||
--border: 217.2 32.6% 17.5%;
|
||||
--input: 220 13% 46%;
|
||||
--destructive-foreground: 40 8% 93%;
|
||||
--border: 0 0% 17%;
|
||||
--input: 0 0% 23%;
|
||||
--ring: 217.2 91.2% 59.8%;
|
||||
|
||||
/* Nav design tokens — dark overrides */
|
||||
--nav-glass-bg: 217.2 91.2% 8% / 0.55;
|
||||
--nav-glass-bg: 0 0% 12% / 0.55;
|
||||
--nav-glass-blur: 24px;
|
||||
--nav-glass-saturate: 1.6;
|
||||
--nav-tab-glow: 217.2 91.2% 59.8% / 0.25;
|
||||
--nav-tab-ring: 217.2 91.2% 59.8% / 0.15;
|
||||
--nav-float-shadow: 0 0% 0% / 0.35;
|
||||
--nav-float-ring: 217.2 32.6% 17.5% / 0.3;
|
||||
--nav-divider-color: 217.2 32.6% 17.5% / 0.5;
|
||||
--nav-input-bg: 217.2 32.6% 17.5% / 0.5;
|
||||
--nav-float-ring: 0 0% 17% / 0.3;
|
||||
--nav-divider-color: 0 0% 17% / 0.5;
|
||||
--nav-input-bg: 0 0% 17% / 0.5;
|
||||
--nav-input-focus-ring: 217.2 91.2% 59.8% / 0.25;
|
||||
}
|
||||
}
|
||||
@@ -350,7 +350,7 @@
|
||||
}
|
||||
|
||||
.dark .scrollbar-thin::-webkit-scrollbar-track {
|
||||
background: rgba(31, 41, 55, 0.3);
|
||||
background: rgba(38, 38, 38, 0.3);
|
||||
}
|
||||
|
||||
.dark .scrollbar-thin::-webkit-scrollbar-thumb {
|
||||
@@ -369,7 +369,7 @@
|
||||
}
|
||||
|
||||
.dark::-webkit-scrollbar-track {
|
||||
background: rgba(31, 41, 55, 0.5);
|
||||
background: rgba(38, 38, 38, 0.5);
|
||||
}
|
||||
|
||||
.dark::-webkit-scrollbar-thumb {
|
||||
@@ -384,7 +384,7 @@
|
||||
/* Firefox scrollbar styles */
|
||||
.dark {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: rgba(107, 114, 128, 0.5) rgba(31, 41, 55, 0.5);
|
||||
scrollbar-color: rgba(115, 115, 115, 0.5) rgba(38, 38, 38, 0.5);
|
||||
}
|
||||
|
||||
/* Ensure checkbox styling is preserved */
|
||||
@@ -475,7 +475,7 @@
|
||||
|
||||
/* Fix focus-within container issues in dark mode */
|
||||
.dark .focus-within\:ring-2:focus-within {
|
||||
background-color: rgb(31 41 55) !important; /* gray-800 */
|
||||
background-color: rgb(20 20 20) !important;
|
||||
}
|
||||
|
||||
/* Ensure textarea remains transparent with visible text */
|
||||
@@ -873,12 +873,12 @@
|
||||
|
||||
/* Fix focus ring offset color in dark mode */
|
||||
.dark [class*="ring-offset"] {
|
||||
--tw-ring-offset-color: rgb(31 41 55); /* gray-800 */
|
||||
--tw-ring-offset-color: rgb(20 20 20);
|
||||
}
|
||||
|
||||
|
||||
/* Ensure buttons don't show white backgrounds in dark mode */
|
||||
.dark button:focus {
|
||||
--tw-ring-offset-color: rgb(31 41 55); /* gray-800 */
|
||||
--tw-ring-offset-color: rgb(20 20 20);
|
||||
}
|
||||
|
||||
/* Fix mobile select dropdown styling */
|
||||
@@ -921,8 +921,8 @@
|
||||
}
|
||||
|
||||
.dark select option {
|
||||
background-color: rgb(31 41 55) !important;
|
||||
color: rgb(243 244 246) !important;
|
||||
background-color: rgb(31 31 31) !important;
|
||||
color: rgb(237 235 230) !important;
|
||||
}
|
||||
|
||||
/* Tool details chevron animation */
|
||||
|
||||
Reference in New Issue
Block a user