Flatten dashboard sections and emphasize data regions
This commit is contained in:
@@ -10,9 +10,9 @@ type MetricCardProps = {
|
||||
|
||||
export function MetricCard({ label, value, delta, positive = true, className }: MetricCardProps) {
|
||||
return (
|
||||
<div className={cn('rounded-xl border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] p-4', className)}>
|
||||
<p className="text-xs uppercase tracking-[0.2em] text-[color:var(--terminal-muted)]">{label}</p>
|
||||
<p className="mt-2 text-2xl font-semibold text-[color:var(--terminal-bright)]">{value}</p>
|
||||
<div className={cn('min-w-0 border-t border-[color:var(--line-weak)] pt-3', className)}>
|
||||
<p className="panel-heading text-[11px] uppercase tracking-[0.18em] text-[color:var(--terminal-muted)]">{label}</p>
|
||||
<p className="mt-2 text-3xl font-semibold text-[color:var(--terminal-bright)]">{value}</p>
|
||||
{delta ? (
|
||||
<p className={cn('mt-2 text-xs', positive ? 'text-[#96f5bf]' : 'text-[#ff9898]')}>
|
||||
{delta}
|
||||
|
||||
@@ -20,9 +20,9 @@ export function TaskFeed({ tasks }: TaskFeedProps) {
|
||||
}
|
||||
|
||||
return (
|
||||
<ul className="space-y-2">
|
||||
<ul>
|
||||
{tasks.slice(0, 8).map((task) => (
|
||||
<li key={task.id} className="flex items-center justify-between rounded-lg border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] px-3 py-2">
|
||||
<li key={task.id} className="flex items-center justify-between gap-3 border-b border-[color:var(--line-weak)] py-3 last:border-b-0 last:pb-0 first:pt-0">
|
||||
<div>
|
||||
<p className="text-sm text-[color:var(--terminal-bright)]">{taskLabels[task.task_type]}</p>
|
||||
<p className="text-xs text-[color:var(--terminal-muted)]">
|
||||
|
||||
@@ -41,12 +41,12 @@ export function FinancialControlBar({
|
||||
className
|
||||
}: FinancialControlBarProps) {
|
||||
return (
|
||||
<section className={cn('rounded-xl border border-[color:var(--line-weak)] bg-[color:var(--panel)] px-4 py-3', className)}>
|
||||
<section className={cn('border-t border-[color:var(--line-weak)] pt-4', className)}>
|
||||
<div className="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
|
||||
<div className="min-w-0">
|
||||
<h3 className="text-sm font-semibold text-[color:var(--terminal-bright)]">{title}</h3>
|
||||
<h3 className="text-base font-semibold text-[color:var(--terminal-bright)]">{title}</h3>
|
||||
{subtitle ? (
|
||||
<p className="mt-1 text-xs text-[color:var(--terminal-muted)]">{subtitle}</p>
|
||||
<p className="mt-1 text-sm text-[color:var(--terminal-muted)]">{subtitle}</p>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
@@ -68,29 +68,29 @@ export function FinancialControlBar({
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<div className="mt-3 grid grid-cols-1 gap-2">
|
||||
{sections.map((section) => (
|
||||
<div
|
||||
key={section.id}
|
||||
className="rounded-lg border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] px-3 py-2"
|
||||
>
|
||||
<span className="mb-2 block text-[10px] uppercase tracking-[0.16em] text-[color:var(--terminal-muted)]">{section.label}</span>
|
||||
<div className="flex flex-wrap items-center gap-1.5">
|
||||
{section.options.map((option) => (
|
||||
<Button
|
||||
key={`${section.id}-${option.value}`}
|
||||
type="button"
|
||||
variant={option.value === section.value ? 'primary' : 'ghost'}
|
||||
disabled={option.disabled}
|
||||
className="px-2 py-1 text-xs sm:min-h-9"
|
||||
onClick={() => section.onChange(option.value)}
|
||||
>
|
||||
{option.label}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
<div className="mt-4 grid grid-cols-1 gap-3">
|
||||
{sections.map((section) => (
|
||||
<div
|
||||
key={section.id}
|
||||
className="data-surface px-3 py-3"
|
||||
>
|
||||
<span className="mb-2 block text-[10px] uppercase tracking-[0.16em] text-[color:var(--terminal-muted)]">{section.label}</span>
|
||||
<div className="flex flex-wrap items-center gap-1.5">
|
||||
{section.options.map((option) => (
|
||||
<Button
|
||||
key={`${section.id}-${option.value}`}
|
||||
type="button"
|
||||
variant={option.value === section.value ? 'primary' : 'ghost'}
|
||||
disabled={option.disabled}
|
||||
className="px-2 py-1 text-xs sm:min-h-9"
|
||||
onClick={() => section.onChange(option.value)}
|
||||
>
|
||||
{option.label}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
||||
@@ -447,8 +447,8 @@ export function AppShell({ title, subtitle, actions, activeTicker, breadcrumbs,
|
||||
<div className="ambient-grid" aria-hidden="true" />
|
||||
<div className="noise-layer" aria-hidden="true" />
|
||||
|
||||
<div className="relative z-10 mx-auto flex min-h-screen w-full max-w-[1300px] gap-4 px-3 pb-10 pt-4 sm:px-4 sm:pb-12 sm:pt-6 md:px-8 lg:gap-6">
|
||||
<aside className="hidden w-72 shrink-0 flex-col gap-6 rounded-2xl border border-[color:var(--line-weak)] bg-[color:var(--panel)] p-5 shadow-[0_0_0_1px_rgba(0,255,180,0.06),0_20px_60px_rgba(1,4,10,0.55)] lg:flex">
|
||||
<div className="relative z-10 mx-auto flex min-h-screen w-full max-w-[1440px] gap-6 px-4 pb-10 pt-4 sm:px-5 sm:pb-12 sm:pt-6 md:px-8 lg:gap-8">
|
||||
<aside className="hidden w-72 shrink-0 flex-col gap-6 border-r border-[color:var(--line-weak)] pr-6 lg:flex">
|
||||
<div>
|
||||
<p className="terminal-caption text-xs uppercase tracking-[0.25em] text-[color:var(--terminal-muted)]">Fiscal Clone</p>
|
||||
<h1 className="mt-2 text-2xl font-semibold text-[color:var(--terminal-bright)]">Neon Desk</h1>
|
||||
@@ -472,10 +472,10 @@ export function AppShell({ title, subtitle, actions, activeTicker, breadcrumbs,
|
||||
onMouseEnter={() => prefetchForHref(item.href)}
|
||||
onFocus={() => prefetchForHref(item.href)}
|
||||
className={cn(
|
||||
'flex items-center gap-3 rounded-xl border px-3 py-2 text-sm transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[color:var(--line-strong)] focus-visible:ring-offset-2 focus-visible:ring-offset-transparent',
|
||||
'flex items-center gap-3 rounded-xl px-3 py-2 text-sm transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[color:var(--line-strong)] focus-visible:ring-offset-2 focus-visible:ring-offset-transparent',
|
||||
item.active
|
||||
? 'border-[color:var(--line-strong)] bg-[color:var(--panel-bright)] text-[color:var(--terminal-bright)] shadow-[0_0_18px_rgba(0,255,180,0.16)]'
|
||||
: 'border-transparent text-[color:var(--terminal-muted)] hover:border-[color:var(--line-weak)] hover:bg-[color:var(--panel-soft)] hover:text-[color:var(--terminal-bright)]'
|
||||
? 'bg-[color:rgba(10,25,33,0.75)] text-[color:var(--terminal-bright)] shadow-[inset_2px_0_0_var(--accent)]'
|
||||
: 'text-[color:var(--terminal-muted)] hover:bg-[color:rgba(10,25,33,0.42)] hover:text-[color:var(--terminal-bright)]'
|
||||
)}
|
||||
>
|
||||
<Icon className="size-4" />
|
||||
@@ -487,7 +487,7 @@ export function AppShell({ title, subtitle, actions, activeTicker, breadcrumbs,
|
||||
))}
|
||||
</nav>
|
||||
|
||||
<div className="mt-auto rounded-xl border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] p-3">
|
||||
<div className="mt-auto rounded-[1rem] border border-[color:var(--line-weak)] bg-[color:rgba(8,19,26,0.52)] p-3">
|
||||
<p className="text-xs uppercase tracking-[0.2em] text-[color:var(--terminal-muted)]">Runtime</p>
|
||||
<p className="mt-1 truncate text-sm text-[color:var(--terminal-bright)]">{displayName}</p>
|
||||
{role ? <p className="mt-1 text-xs uppercase tracking-[0.16em] text-[color:var(--terminal-muted)]">Role: {role}</p> : null}
|
||||
@@ -502,7 +502,7 @@ export function AppShell({ title, subtitle, actions, activeTicker, breadcrumbs,
|
||||
</aside>
|
||||
|
||||
<div className="min-w-0 flex-1 pb-24 lg:pb-0">
|
||||
<header className="relative mb-4 rounded-2xl border border-[color:var(--line-weak)] bg-[color:var(--panel)] px-4 py-4 pr-16 shadow-[0_0_0_1px_rgba(0,255,180,0.05),0_14px_40px_rgba(1,4,10,0.5)] sm:px-6 sm:py-5 sm:pr-20">
|
||||
<header className="relative mb-4 border-b border-[color:var(--line-weak)] pb-4 pr-16 sm:pb-5 sm:pr-20">
|
||||
<div className="absolute right-4 top-4 z-10 sm:right-5 sm:top-5">
|
||||
<TaskNotificationsTrigger
|
||||
unreadCount={notifications.unreadCount}
|
||||
@@ -539,7 +539,7 @@ export function AppShell({ title, subtitle, actions, activeTicker, breadcrumbs,
|
||||
|
||||
<nav
|
||||
aria-label="Breadcrumb"
|
||||
className="mb-6 overflow-x-auto rounded-xl border border-[color:var(--line-weak)] bg-[color:var(--panel)] px-3 py-2"
|
||||
className="mb-6 overflow-x-auto border-b border-[color:var(--line-weak)] pb-3"
|
||||
>
|
||||
<ol className="flex min-w-max items-center gap-2 text-xs text-[color:var(--terminal-muted)] sm:min-w-0 sm:flex-wrap">
|
||||
{breadcrumbItems.map((item, index) => {
|
||||
|
||||
@@ -8,8 +8,8 @@ type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {
|
||||
|
||||
const variantMap: Record<ButtonVariant, string> = {
|
||||
primary: 'border-[color:var(--line-strong)] bg-[color:var(--accent)] text-[#001515] hover:bg-[color:var(--accent-strong)]',
|
||||
secondary: 'border-[color:var(--line-weak)] bg-[color:var(--panel-bright)] text-[color:var(--terminal-bright)] hover:border-[color:var(--line-strong)] hover:bg-[color:var(--panel)]',
|
||||
ghost: 'border-[color:var(--line-weak)] bg-transparent text-[color:var(--terminal-bright)] hover:border-[color:var(--line-strong)] hover:bg-[color:var(--panel-soft)]',
|
||||
secondary: 'border-[color:var(--line-weak)] bg-[color:rgba(10,25,33,0.72)] text-[color:var(--terminal-bright)] hover:border-[color:var(--line-strong)] hover:bg-[color:var(--panel-bright)]',
|
||||
ghost: 'border-[color:var(--line-weak)] bg-transparent text-[color:var(--terminal-bright)] hover:border-[color:var(--line-strong)] hover:bg-[color:rgba(10,25,33,0.4)]',
|
||||
danger: 'border-[color:var(--danger)] bg-[color:var(--danger-soft)] text-[#ffc9c9] hover:bg-[color:var(--danger)] hover:text-[#1e0d0d]'
|
||||
};
|
||||
|
||||
@@ -17,7 +17,7 @@ export function Button({ className, variant = 'primary', ...props }: ButtonProps
|
||||
return (
|
||||
<button
|
||||
className={cn(
|
||||
'inline-flex min-h-11 items-center justify-center gap-2 rounded-lg border px-3 py-2 text-sm font-medium transition duration-200 disabled:cursor-not-allowed disabled:opacity-50',
|
||||
'inline-flex min-h-11 items-center justify-center gap-2 rounded-xl border px-3 py-2 text-sm font-medium transition duration-200 disabled:cursor-not-allowed disabled:opacity-50',
|
||||
variantMap[variant],
|
||||
className
|
||||
)}
|
||||
|
||||
@@ -6,7 +6,7 @@ export function Input({ className, ...props }: InputProps) {
|
||||
return (
|
||||
<input
|
||||
className={cn(
|
||||
'min-h-11 w-full rounded-lg border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] px-3 py-2 text-sm text-[color:var(--terminal-bright)] outline-none transition placeholder:text-[color:var(--terminal-muted)] focus:border-[color:var(--line-strong)] focus:shadow-[0_0_0_3px_rgba(0,255,180,0.14)]',
|
||||
'min-h-11 w-full rounded-xl border border-[color:var(--line-weak)] bg-[color:rgba(8,19,26,0.72)] px-3 py-2 text-sm text-[color:var(--terminal-bright)] outline-none transition placeholder:text-[color:var(--terminal-muted)] focus:border-[color:var(--line-strong)] focus:shadow-[0_0_0_3px_rgba(0,255,180,0.12)]',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -6,13 +6,16 @@ type PanelProps = {
|
||||
actions?: React.ReactNode;
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
variant?: 'flat' | 'surface';
|
||||
};
|
||||
|
||||
export function Panel({ title, subtitle, actions, children, className }: PanelProps) {
|
||||
export function Panel({ title, subtitle, actions, children, className, variant = 'flat' }: PanelProps) {
|
||||
return (
|
||||
<section
|
||||
className={cn(
|
||||
'min-w-0 rounded-2xl border border-[color:var(--line-weak)] bg-[color:var(--panel)] p-4 shadow-[0_0_0_1px_rgba(0,255,180,0.03),0_12px_30px_rgba(1,4,10,0.45)] sm:p-5',
|
||||
variant === 'surface'
|
||||
? 'min-w-0 rounded-[1.25rem] border border-[color:var(--line-weak)] bg-[color:var(--panel)] p-4 sm:p-5'
|
||||
: 'min-w-0 border-t border-[color:var(--line-weak)] pt-4',
|
||||
className
|
||||
)}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user