feat(ui): add surface layout primitives
This commit is contained in:
parent
f37fd480fe
commit
48ad3deb7f
100
packages/ui/src/components/Surface.tsx
Normal file
100
packages/ui/src/components/Surface.tsx
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { clsx } from 'clsx';
|
||||||
|
|
||||||
|
export interface SurfaceProps extends React.HTMLAttributes<HTMLElement> {
|
||||||
|
as?: 'section' | 'aside' | 'article' | 'div';
|
||||||
|
variant?: 'default' | 'muted' | 'elevated' | 'outline' | 'plain';
|
||||||
|
padding?: 'none' | 'sm' | 'md' | 'lg';
|
||||||
|
}
|
||||||
|
|
||||||
|
const surfaceVariants: Record<NonNullable<SurfaceProps['variant']>, string> = {
|
||||||
|
default: 'border border-[var(--bl-border)] bg-[var(--bl-surface-card)]',
|
||||||
|
muted: 'border border-[var(--bl-border)] bg-[var(--bl-surface-muted)]',
|
||||||
|
elevated: 'border border-[var(--bl-border)] bg-[var(--bl-bg-elevated)] shadow-sm',
|
||||||
|
outline: 'border border-[var(--bl-border)] bg-transparent',
|
||||||
|
plain: 'border-transparent bg-transparent',
|
||||||
|
};
|
||||||
|
|
||||||
|
const surfacePadding: Record<NonNullable<SurfaceProps['padding']>, string> = {
|
||||||
|
none: '',
|
||||||
|
sm: 'p-3',
|
||||||
|
md: 'p-4',
|
||||||
|
lg: 'p-6',
|
||||||
|
};
|
||||||
|
|
||||||
|
export function Surface({
|
||||||
|
as: Comp = 'section',
|
||||||
|
variant = 'default',
|
||||||
|
padding = 'md',
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
}: SurfaceProps) {
|
||||||
|
return (
|
||||||
|
<Comp
|
||||||
|
className={clsx(
|
||||||
|
'rounded-lg text-[var(--bl-text-primary)]',
|
||||||
|
surfaceVariants[variant],
|
||||||
|
surfacePadding[padding],
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Comp>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SurfaceListProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||||
|
density?: 'compact' | 'normal' | 'spacious';
|
||||||
|
divided?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const listDensity: Record<NonNullable<SurfaceListProps['density']>, string> = {
|
||||||
|
compact: 'gap-1',
|
||||||
|
normal: 'gap-2',
|
||||||
|
spacious: 'gap-3',
|
||||||
|
};
|
||||||
|
|
||||||
|
export function SurfaceList({
|
||||||
|
density = 'normal',
|
||||||
|
divided,
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
}: SurfaceListProps) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={clsx(
|
||||||
|
'grid',
|
||||||
|
listDensity[density],
|
||||||
|
divided &&
|
||||||
|
'divide-y divide-[var(--bl-border)] overflow-hidden rounded-lg border border-[var(--bl-border)]',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SurfaceListItemProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||||
|
selected?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SurfaceListItem({ selected, className, children, ...props }: SurfaceListItemProps) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
data-selected={selected ? 'true' : undefined}
|
||||||
|
className={clsx(
|
||||||
|
'rounded-md border border-[var(--bl-border)] bg-[var(--bl-surface-muted)] p-3 text-[var(--bl-text-primary)]',
|
||||||
|
selected && 'border-[var(--bl-accent)] bg-[var(--bl-accent-muted,var(--bl-surface-card))]',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -33,6 +33,14 @@ export {
|
|||||||
type PanelProps,
|
type PanelProps,
|
||||||
type PanelTitleProps,
|
type PanelTitleProps,
|
||||||
} from './components/Panel';
|
} from './components/Panel';
|
||||||
|
export {
|
||||||
|
Surface,
|
||||||
|
SurfaceList,
|
||||||
|
SurfaceListItem,
|
||||||
|
type SurfaceListItemProps,
|
||||||
|
type SurfaceListProps,
|
||||||
|
type SurfaceProps,
|
||||||
|
} from './components/Surface';
|
||||||
export { ListItemButton, type ListItemButtonProps } from './components/ListItemButton';
|
export { ListItemButton, type ListItemButtonProps } from './components/ListItemButton';
|
||||||
export { Timeline, type TimelineItem, type TimelineProps } from './components/Timeline';
|
export { Timeline, type TimelineItem, type TimelineProps } from './components/Timeline';
|
||||||
export { DiffCard, type DiffCardProps } from './components/DiffCard';
|
export { DiffCard, type DiffCardProps } from './components/DiffCard';
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user