Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 5 additions & 16 deletions apps/website/src/app/docs/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -285,13 +285,7 @@ const helperLinkStyle = {
fontWeight: 600,
} as const;

const accentCardStyle = {
height: '100%',
background: tokens.colors.accentSurface,
border: `1px solid ${tokens.colors.accentBorder}`,
} as const;

const plainCardStyle = {
const fillHeightStyle = {
height: '100%',
} as const;

Expand All @@ -305,11 +299,6 @@ const dividerStyle = {
export default function DocsLandingPage() {
return (
<>
<style>{`
[data-ui="docs-card"] { transition: border-color 160ms ease, box-shadow 160ms ease, transform 160ms ease; }
[data-ui="docs-card"]:hover { border-color: ${tokens.colors.accentBorderHover}; box-shadow: ${tokens.shadows.md}; transform: translateY(-1px); }
@media (prefers-reduced-motion: reduce) { [data-ui="docs-card"]:hover { transform: none; } }
`}</style>

{/* Hero */}
<Section surface="canvas" ariaLabelledBy="docs-heading">
Expand Down Expand Up @@ -357,7 +346,7 @@ export default function DocsLandingPage() {
<div style={gridStyle}>
{BACKENDS.map((b) => (
<Link key={b.href} href={b.href} style={{ textDecoration: 'none' }}>
<Card padding="lg" data-ui="docs-card" style={accentCardStyle}>
<Card padding="lg" hoverable accent style={fillHeightStyle}>
<div style={cardHeaderStyle}>
<LogoChip src={b.logoSrc} />
<div>
Expand Down Expand Up @@ -392,7 +381,7 @@ export default function DocsLandingPage() {
<div style={gridStyle}>
{GENERATIVE_UI.map((g) => (
<Link key={g.href} href={g.href} style={{ textDecoration: 'none' }}>
<Card padding="lg" data-ui="docs-card" style={accentCardStyle}>
<Card padding="lg" hoverable accent style={fillHeightStyle}>
<div style={cardHeaderStyle}>
<LogoChip src={g.logoSrc} />
<div>
Expand Down Expand Up @@ -421,7 +410,7 @@ export default function DocsLandingPage() {
<div style={dividerStyle} />
<StepLabel id="chat-heading" step={3}>Chat UI</StepLabel>
<Link href="/docs/chat/getting-started/introduction" style={{ textDecoration: 'none' }}>
<Card padding="lg" data-ui="docs-card" style={plainCardStyle}>
<Card padding="lg" hoverable style={fillHeightStyle}>
<div style={cardHeaderStyle}>
<GlyphChip size={30}><ChatGlyph /></GlyphChip>
<div>
Expand Down Expand Up @@ -449,7 +438,7 @@ export default function DocsLandingPage() {
const Glyph = GLYPHS[s.glyph];
return (
<Link key={s.href} href={s.href} style={{ textDecoration: 'none' }}>
<Card padding="lg" data-ui="docs-card" style={plainCardStyle}>
<Card padding="lg" hoverable style={fillHeightStyle}>
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
<GlyphChip size={26}><Glyph /></GlyphChip>
<div>
Expand Down
33 changes: 30 additions & 3 deletions apps/website/src/app/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -188,17 +188,44 @@ html {
.docs-prose td { padding: 0.5rem 0.75rem; border-bottom: 1px solid rgba(0, 64, 144, 0.08); color: #555770; }
.docs-prose td code { font-size: 0.8em; }

/* UI primitive — Card hover.
* Hoverable cards are virtually always links; pointer is the right default.
/* UI primitive — Card.
* Resting background / border / shadow live here (not inline on the element)
* so the :hover rules below can override border-color and box-shadow. Inline
* styles beat any stylesheet :hover rule, which previously left the lift
* rendering only the transform. See components/ui/Card.tsx. */
[data-ui="card"] {
background: var(--color-surface);
border: 1px solid var(--color-border);
box-shadow: var(--shadow-sm);
transition: box-shadow 160ms ease, border-color 160ms ease, transform 160ms ease;
}
[data-ui="card"][data-surface="tinted"] {
background: var(--color-surface-tinted);
}
[data-ui="card"][data-surface="dim"] {
background: var(--color-surface-dim);
}
/* Accent-filled cards (e.g. docs backend / generative-UI cards). */
[data-ui="card"][data-accent] {
background: var(--color-accent-surface);
border-color: var(--color-accent-border);
}

/* Hoverable cards are virtually always links; pointer is the right default.
* If a non-link gets `data-hoverable`, override inline. */
[data-ui="card"][data-hoverable] {
cursor: pointer;
}
[data-ui="card"][data-hoverable]:hover {
[data-ui="card"][data-hoverable]:not([data-accent]):hover {
box-shadow: var(--shadow-md);
border-color: var(--color-border-strong);
transform: translateY(-1px);
}
/* Accent cards keep their accent border and gain an accent ring on hover. */
[data-ui="card"][data-hoverable][data-accent]:hover {
box-shadow: 0 0 0 3px var(--color-accent-glow), var(--shadow-md);
transform: translateY(-1px);
}
@media (prefers-reduced-motion: reduce) {
[data-ui="card"][data-hoverable]:hover {
transform: none;
Expand Down
9 changes: 2 additions & 7 deletions apps/website/src/components/docs/DocsPrevNext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,9 @@ export function DocsPrevNext({ library, section, slug }: Props) {
marginBottom: 16,
}}
>
<style>{`
[data-ui="docs-card"] { transition: border-color 160ms ease, box-shadow 160ms ease, transform 160ms ease; }
[data-ui="docs-card"]:hover { border-color: ${tokens.colors.accentBorderHover}; box-shadow: ${tokens.shadows.md}; transform: translateY(-1px); }
@media (prefers-reduced-motion: reduce) { [data-ui="docs-card"]:hover { transform: none; } }
`}</style>
{prev ? (
<Link href={prev.href} style={{ textDecoration: 'none' }}>
<Card padding="md" data-ui="docs-card" style={{ height: '100%' }}>
<Card padding="md" hoverable style={{ height: '100%' }}>
<Eyebrow style={{ marginBottom: 8 }}>← Previous</Eyebrow>
<div
style={{
Expand All @@ -81,7 +76,7 @@ export function DocsPrevNext({ library, section, slug }: Props) {
)}
{next ? (
<Link href={next.href} style={{ textDecoration: 'none' }}>
<Card padding="md" data-ui="docs-card" style={{ height: '100%', textAlign: 'right' }}>
<Card padding="md" hoverable style={{ height: '100%', textAlign: 'right' }}>
<Eyebrow style={{ marginBottom: 8 }}>Next →</Eyebrow>
<div
style={{
Expand Down
25 changes: 14 additions & 11 deletions apps/website/src/components/ui/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,19 @@ type Padding = 'md' | 'lg';

interface CardProps extends HTMLAttributes<HTMLDivElement> {
children: ReactNode;
/** If true, applies a subtle hover lift via CSS. */
/** If true, applies a subtle hover lift (border + shadow + translate) via CSS. */
hoverable?: boolean;
/**
* If true, renders an accent-tinted surface + border, and — when hoverable —
* the hover lift uses an accent ring instead of the neutral border treatment.
*/
accent?: boolean;
/** Internal padding tier. */
padding?: Padding;
/** Override the surface color. */
surface?: Surface;
}

const SURFACE: Record<Surface, string> = {
white: tokens.surfaces.surface,
tinted: tokens.surfaces.surfaceTinted,
dim: tokens.surfaces.surfaceDim,
};

const PADDING: Record<Padding, string> = {
md: '20px',
lg: '28px',
Expand All @@ -29,24 +28,28 @@ const PADDING: Record<Padding, string> = {
export function Card({
children,
hoverable = false,
accent = false,
padding = 'md',
surface = 'white',
className,
style,
...rest
}: CardProps) {
// Resting background / border / shadow live in the `[data-ui="card"]`
// stylesheet (apps/website/src/app/global.css) — never inline — so the
// :hover rules can actually override border-color and box-shadow. Inline
// styles beat any stylesheet :hover rule, which previously left the lift
// rendering only the transform.
return (
<div
data-ui="card"
data-hoverable={hoverable || undefined}
data-accent={accent || undefined}
data-surface={surface !== 'white' ? surface : undefined}
className={cn(className)}
style={{
background: SURFACE[surface],
border: `1px solid ${tokens.surfaces.border}`,
borderRadius: tokens.radius.lg,
boxShadow: tokens.shadows.sm,
padding: PADDING[padding],
transition: 'box-shadow 160ms ease, border-color 160ms ease, transform 160ms ease',
...style,
}}
{...rest}
Expand Down
Loading