import { Avatar, Row, Stage } from '../kit' import './contrasts.css' import './composition.css' export const compositionLessons = [ { id: 'framing', title: 'Give the product room', note: 'The same exports window and status in a small frame. Protect the header and useful rows; let the window continue beyond a deliberate edge.', bad: 'Tight edges and a status over the content', good: 'Clear gutters and an intentional bottom crop' }, { id: 'ui-anatomy', title: 'Make the UI read like a product', note: 'The same project, tasks and action. Type hierarchy and shared alignment make the relationships clear without adding decoration.', bad: 'Labels, metadata and actions compete', good: 'A clear heading and consistent reading columns' }, { id: 'visual-restraint', title: 'Choose where emphasis belongs', note: 'The same plan details and action. When every edge and value is emphasized, the primary action loses its place.', bad: 'Borders, shadows and color on every part', good: 'Quiet details and one clear action' }, { id: 'compact-reflow', title: 'Reflow a small composition', note: 'The same three tasks in a 300px slot. A smaller host needs a readable arrangement, not a miniature desktop table.', bad: 'The desktop table is scaled to half size', good: 'The same content reflows at readable sizes' }, { id: 'edge-separation', title: 'Make edges feel deliberate', note: 'The same sync panel and confirmation. Nearly touching edges look accidental; a clear gap makes two surfaces easy to distinguish.', bad: 'The confirmation almost touches the panel', good: 'A deliberate gap separates the two surfaces' }, { id: 'nested-spacing', title: 'Carry padding around every edge', note: 'The same preferences and action. Check the bottom and the corners as carefully as the space above the first label.', bad: 'The inner surface and action crowd the bottom', good: 'Each layer has a consistent inset' }, { id: 'control-alignment', title: 'Fit the contents of a control', note: 'The same search field and actions. Shared content alignment balances labels and icons within their actual controls.', bad: 'Icons sit low and labels crowd the upper edge', good: 'Icons and labels share a balanced content row' }, { id: 'content-density', title: 'Give whitespace a job', note: 'The same three appointments. Keep each time with its subject and separate the appointments, rather than spreading every line equally.', bad: 'Uniform gaps weaken the appointment groups', good: 'Tighter groups make the schedule easier to scan' }, { id: 'surface-contrast', title: 'Keep the foreground readable', note: 'The same sharing controls on a tinted ground. A quiet surface still needs enough contrast for its text and available actions.', bad: 'Foreground, surface and ground blend together', good: 'Readable text and a distinct foreground surface' }, { id: 'icon-consistency', title: 'Give icons a shared construction', note: 'The same three destinations. Similar boxes do not guarantee similar visual weight; compare the shapes, stroke and visible size.', bad: 'Mixed fill, stroke weight and visible size', good: 'One construction with balanced optical weight' }, { id: 'decorative-noise', title: 'Let the information lead', note: 'The same activity report and chart. Gradients and glow can compete with a useful result even when the layout is orderly.', bad: 'Decorative effects compete with the report', good: 'The value and chart carry the emphasis' }, { id: 'product-anatomy', title: 'Choose chrome that serves the task', note: 'The same document, permission and sharing action. Familiar browser shapes are misleading when the task is a small sharing panel.', bad: 'Browser chrome disguises a sharing task', good: 'Document, permission and action have clear roles' }, { id: 'unread-gutter', title: 'Never push only the unread rows in', note: 'The same inbox with two unread messages. An unread dot must not move its row: pushing only unread rows in makes the column zigzag, and every read changes the layout. Hang the dot in the margin, as here, reserve a dot column on every row as Mail and Messages do, or put it by the time as Gmail does; follow the product.', bad: 'Unread rows push their avatar in; the column zigzags', good: 'Every avatar on one edge; the dot hangs in the margin' }, ] as const type LessonId = typeof compositionLessons[number]['id'] const EXPORTS = [['Campaign assets', '24 files'], ['Brand library', '18 files'], ['Product launch', '32 files'], ['Homepage', '8 files']] const TASKS = [ { name: 'Design review', owner: 'Maya', due: 'Today', status: 'Ready' }, { name: 'Onboarding', owner: 'Jon', due: 'Tomorrow', status: 'In review' }, { name: 'Billing audit', owner: 'Ana', due: 'Friday', status: 'Ready' }, ] function FileIcon() { return } function ExportWindow() { return
Due Friday · 4 tasks
Launch brief
18 more than last week
{lesson.note}