feat(client): add Card header/footer, DescriptionList, and portal ContextMenu
- add Card header prop (primary/secondary variants) and footer prop (sticks to bottom) - add Breadcrumbs to all 5 pages; remove duplicate h1 headings - add pageToolbar layout for breadcrumbs + danger button aligned right - add DescriptionList component replacing raw dl/dt/dd markup; supports truncate+tooltip - rewrite ContextMenu to render dropdown via React portal to avoid clip/overflow issues - update EnvironmentCard to use Card header (primary), footer (Timestamp), and truncated DescriptionList - fix cog button contrast, square sizing, and right-edge alignment on colored header - add border to Timestamp pill for dark-mode visibility - add id badge pill styling to environment card header
This commit is contained in:
@@ -6,6 +6,44 @@
|
||||
font-family: var(--font-family);
|
||||
}
|
||||
|
||||
.header {
|
||||
padding: var(--space-3) var(--space-6);
|
||||
font-weight: 600;
|
||||
font-size: var(--font-size-sm);
|
||||
border-radius: calc(var(--radius-lg) - var(--border-width)) calc(var(--radius-lg) - var(--border-width)) 0 0;
|
||||
}
|
||||
|
||||
.header-primary {
|
||||
background: var(--color-primary);
|
||||
color: var(--color-primary-fg);
|
||||
border-bottom: var(--border-width) solid var(--color-primary-active);
|
||||
}
|
||||
|
||||
.header-secondary {
|
||||
background: var(--color-secondary);
|
||||
color: var(--color-secondary-fg);
|
||||
border-bottom: var(--border-width) solid var(--color-secondary-border);
|
||||
}
|
||||
|
||||
.withFooter {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.withFooter .body {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.body { }
|
||||
|
||||
.footer {
|
||||
padding: var(--space-2) var(--space-6);
|
||||
border-top: var(--border-width) solid var(--color-border);
|
||||
font-size: var(--font-size-xs);
|
||||
color: var(--color-text-muted);
|
||||
background: var(--color-bg-subtle);
|
||||
}
|
||||
|
||||
.sm { padding: var(--space-3) var(--space-4); }
|
||||
.md { padding: var(--space-4) var(--space-6); }
|
||||
.lg { padding: var(--space-6) var(--space-8); }
|
||||
|
||||
@@ -5,12 +5,30 @@ export interface CardProps {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
padding?: 'sm' | 'md' | 'lg';
|
||||
header?: React.ReactNode;
|
||||
headerVariant?: 'primary' | 'secondary';
|
||||
footer?: React.ReactNode;
|
||||
}
|
||||
|
||||
export function Card({ children, className, padding = 'md' }: CardProps) {
|
||||
export function Card({
|
||||
children,
|
||||
className,
|
||||
padding = 'md',
|
||||
header,
|
||||
headerVariant = 'primary',
|
||||
footer,
|
||||
}: CardProps) {
|
||||
return (
|
||||
<div className={[styles.card, styles[padding], className].filter(Boolean).join(' ')}>
|
||||
{children}
|
||||
<div
|
||||
className={[styles.card, footer !== undefined ? styles.withFooter : '', className]
|
||||
.filter(Boolean)
|
||||
.join(' ')}
|
||||
>
|
||||
{header !== undefined && (
|
||||
<div className={[styles.header, styles[`header-${headerVariant}`]].join(' ')}>{header}</div>
|
||||
)}
|
||||
<div className={[styles.body, styles[padding]].join(' ')}>{children}</div>
|
||||
{footer !== undefined && <div className={styles.footer}>{footer}</div>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user