Phase 1: Dashboard Polish + Theming (#457) #458
@@ -11,13 +11,7 @@ export default function DashboardPage(): ReactElement {
|
||||
return (
|
||||
<div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
|
||||
<DashboardMetrics />
|
||||
<div
|
||||
style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "1fr 320px",
|
||||
gap: 16,
|
||||
}}
|
||||
>
|
||||
<div className="dash-grid">
|
||||
<div style={{ display: "flex", flexDirection: "column", gap: 16, minWidth: 0 }}>
|
||||
<OrchestratorSessions />
|
||||
<QuickActions />
|
||||
|
||||
@@ -765,6 +765,62 @@ body::before {
|
||||
animation: scaleIn 0.1s ease-out;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
Dashboard Layout — Responsive Grids
|
||||
----------------------------------------------------------------------------- */
|
||||
.metrics-strip {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(var(--ms-cols, 6), 1fr);
|
||||
gap: 0;
|
||||
border-radius: var(--r-lg);
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.metric-cell {
|
||||
border-left: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.metric-cell:first-child {
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.metrics-strip {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
|
||||
.metric-cell:nth-child(3n + 1) {
|
||||
border-left: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.metrics-strip {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
.metric-cell:nth-child(3n + 1) {
|
||||
border-left: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.metric-cell:nth-child(2n + 1) {
|
||||
border-left: none;
|
||||
}
|
||||
}
|
||||
|
||||
.dash-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 320px;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.dash-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
Responsive Typography Adjustments
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
@@ -102,8 +102,8 @@ function ActivityItemRow({ item }: ActivityItemRowProps): ReactElement {
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "flex-start",
|
||||
gap: 10,
|
||||
padding: "8px 0",
|
||||
gap: 12,
|
||||
padding: "10px 0",
|
||||
borderBottom: "1px solid var(--border)",
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -169,7 +169,7 @@ function OrchCard({ session }: OrchCardProps): ReactElement {
|
||||
style={{
|
||||
background: "var(--bg-mid)",
|
||||
border: "1px solid var(--border)",
|
||||
borderRadius: "var(--r-md)",
|
||||
borderRadius: "var(--r)",
|
||||
padding: "12px 14px",
|
||||
marginBottom: 10,
|
||||
}}
|
||||
|
||||
@@ -12,10 +12,10 @@ interface QuickAction {
|
||||
}
|
||||
|
||||
const actions: QuickAction[] = [
|
||||
{ id: "new-project", label: "New Project", icon: "🚀", iconBg: "rgba(47,128,255,0.15)" },
|
||||
{ id: "spawn-agent", label: "Spawn Agent", icon: "🤖", iconBg: "rgba(139,92,246,0.15)" },
|
||||
{ id: "view-telemetry", label: "View Telemetry", icon: "📊", iconBg: "rgba(20,184,166,0.15)" },
|
||||
{ id: "review-tasks", label: "Review Tasks", icon: "📋", iconBg: "rgba(245,158,11,0.15)" },
|
||||
{ id: "new-project", label: "New Project", icon: "🚀", iconBg: "rgba(47,128,255,0.12)" },
|
||||
{ id: "spawn-agent", label: "Spawn Agent", icon: "🤖", iconBg: "rgba(139,92,246,0.12)" },
|
||||
{ id: "view-telemetry", label: "View Telemetry", icon: "📊", iconBg: "rgba(20,184,166,0.12)" },
|
||||
{ id: "review-tasks", label: "Review Tasks", icon: "📋", iconBg: "rgba(245,158,11,0.12)" },
|
||||
];
|
||||
|
||||
interface ActionButtonProps {
|
||||
@@ -36,24 +36,25 @@ function ActionButton({ action }: ActionButtonProps): ReactElement {
|
||||
}}
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
gap: 8,
|
||||
padding: "16px 12px",
|
||||
borderRadius: "var(--r-md)",
|
||||
padding: "10px 12px",
|
||||
borderRadius: "var(--r)",
|
||||
border: `1px solid ${hovered ? "var(--ms-border-700)" : "var(--border)"}`,
|
||||
background: hovered ? "var(--surface)" : "var(--bg-mid)",
|
||||
cursor: "pointer",
|
||||
transition: "border-color 0.15s, background 0.15s",
|
||||
transition: "border-color 0.15s, background 0.15s, color 0.15s",
|
||||
width: "100%",
|
||||
fontSize: "0.8rem",
|
||||
fontWeight: 600,
|
||||
color: hovered ? "var(--text)" : "var(--text-2)",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
width: 24,
|
||||
height: 24,
|
||||
borderRadius: 6,
|
||||
borderRadius: 5,
|
||||
background: action.iconBg,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
@@ -63,15 +64,7 @@ function ActionButton({ action }: ActionButtonProps): ReactElement {
|
||||
>
|
||||
{action.icon}
|
||||
</div>
|
||||
<span
|
||||
style={{
|
||||
fontSize: "0.8rem",
|
||||
fontWeight: 600,
|
||||
color: "var(--text)",
|
||||
}}
|
||||
>
|
||||
{action.label}
|
||||
</span>
|
||||
<span>{action.label}</span>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
@@ -84,7 +77,7 @@ export function QuickActions(): ReactElement {
|
||||
style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "1fr 1fr",
|
||||
gap: 10,
|
||||
gap: 8,
|
||||
}}
|
||||
>
|
||||
{actions.map((action) => (
|
||||
|
||||
@@ -356,7 +356,7 @@ function NavItem({ item, isActive, collapsed }: NavItemProps): React.JSX.Element
|
||||
alignItems: "center",
|
||||
gap: "11px",
|
||||
padding: "9px 10px",
|
||||
borderRadius: "6px",
|
||||
borderRadius: "var(--r-sm)",
|
||||
fontSize: "0.875rem",
|
||||
fontWeight: 500,
|
||||
color: isActive ? "var(--text)" : "var(--muted)",
|
||||
|
||||
@@ -16,7 +16,7 @@ export interface MetricsStripProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
function MetricCellItem({ cell, isFirst }: { cell: MetricCell; isFirst: boolean }): ReactElement {
|
||||
function MetricCellItem({ cell }: { cell: MetricCell }): ReactElement {
|
||||
const [hovered, setHovered] = useState(false);
|
||||
|
||||
const trendColor =
|
||||
@@ -28,6 +28,7 @@ function MetricCellItem({ cell, isFirst }: { cell: MetricCell; isFirst: boolean
|
||||
|
||||
return (
|
||||
<div
|
||||
className="metric-cell"
|
||||
onMouseEnter={(): void => {
|
||||
setHovered(true);
|
||||
}}
|
||||
@@ -37,7 +38,6 @@ function MetricCellItem({ cell, isFirst }: { cell: MetricCell; isFirst: boolean
|
||||
style={{
|
||||
padding: "14px 16px",
|
||||
background: hovered ? "var(--surface-2)" : "var(--surface)",
|
||||
borderLeft: isFirst ? "none" : "1px solid var(--border)",
|
||||
borderTop: `2px solid ${cell.color}`,
|
||||
transition: "background 0.15s ease",
|
||||
}}
|
||||
@@ -82,17 +82,15 @@ function MetricCellItem({ cell, isFirst }: { cell: MetricCell; isFirst: boolean
|
||||
export function MetricsStrip({ cells, className = "" }: MetricsStripProps): ReactElement {
|
||||
return (
|
||||
<div
|
||||
className={className}
|
||||
style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: `repeat(${String(cells.length)}, 1fr)`,
|
||||
borderRadius: "var(--r-lg)",
|
||||
overflow: "hidden",
|
||||
border: "1px solid var(--border)",
|
||||
}}
|
||||
className={`metrics-strip ${className}`.trim()}
|
||||
style={
|
||||
{
|
||||
"--ms-cols": String(cells.length),
|
||||
} as React.CSSProperties
|
||||
}
|
||||
>
|
||||
{cells.map((cell, index) => (
|
||||
<MetricCellItem key={cell.label} cell={cell} isFirst={index === 0} />
|
||||
{cells.map((cell) => (
|
||||
<MetricCellItem key={cell.label} cell={cell} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user