Files
Ely-GPUI-Components/tasks/ch01-10.md
T
ZacharyZhang-NY 3f1597fa28 Port · Parity: every page matches gpui 0.2.2's; the rules re-tested
Every page and scripted state was shot with gpui 0.2.2 and with the
port, light and dark, full width and at 280px, judged pair by pair by
agents with skeptics, and every page's log diffed. What differed is
fixed, each with a test that fails without it where the test platform
can show it:

- The gallery's harness takes posted mouse moves (gpui_macos listens
  to a tracking area), posts each drag move twice (it no longer
  replays a held drag), and waits three frames before each shot.
- Rolling digits: a block column, so taffy 0.13 lends the cell no
  baseline, and a line of whole device pixels, since gpui snaps each
  length on its own. DescriptionList's row aligns ends.
- Margins that taffy 0.13 collapses through a plain block: the
  drawer's pull and snap, the stagger and transition rise, the dialog
  and palette rises, the fullscreen dialog's slide.
- An Input keeps room to type in a squeezed row; the field rows drop
  w_full, whose reason was taffy 0.9's.

AGENTS.md's rules that named gpui 0.2.2 or taffy 0.9 were re-tested
against both sources and rewritten, and new ones say what the port
changed. TASKS.md's tags follow: what the new gpui makes possible is
prove. Captions, doc comments and README say what holds now.
2026-09-29 10:39:55 -04:00

381 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Chapters 1–10
## T01 Primitives — `src/primitives`
- [x] Box / View — native `div()`
- [x] Text — native: strings and `StyledText` are elements
- [x] Icon (T00)
- [x] IconSet / IconRegistry (T00)
- [x] Svg — native `svg()`
- [x] Image — loading, failed, placeholder over `img()`
- [x] Canvas — native `canvas()`
- [x] Divider / Separator
- [x] Spacer — native `div().flex_1()`
- [x] Portal — native `deferred(anchored())`
- [x] Overlay / Backdrop
- [x] Slot — native `impl IntoElement` params and `ParentElement`
- [x] Show / When — native `.when()` / `.when_some()`
- [x] For / Each — native `.children(iter)`
- [x] Fragment — native: children take iterators
- [ ] VisuallyHidden — prove: gpui builds an AccessKit tree on macOS, Windows and Linux, not the web, from elements with an id and a `role`; a box that draws nothing, with an `aria_label`, must reach the macOS tree with its label
- [x] FocusRing
- [x] FocusScope / FocusTrap
- [x] ClickOutside — native `on_mouse_down_out`
- [x] HoverArea — native `on_hover` / `.hover()`
- [x] Pressable — press state, long press
- [x] KeyboardHandler — native `on_key_down` / `on_action`
- [x] Measure
- [x] ResizeObserver → `primitives::Measure`
- [x] IntersectionObserver
- [x] Clipboard — native `write_to_clipboard` / `read_from_clipboard`
- [x] Tooltip Trigger — owns `Tooltip`: delay, follow mouse, rich content
## T02 Typography — `src/typography`
- [x] Heading (H1–H6)
- [x] Title / Subtitle
- [x] Paragraph
- [x] Label
- [x] Caption
- [x] Overline
- [x] Code
- [x] Kbd — ⌘ / Ctrl by platform
- [x] KbdCombo
- [x] Blockquote
- [x] Highlight / Mark
- [x] Truncate → `typography::Ellipsis`; gpui's `.truncate()` holds only in a block of fixed width
- [x] LineClamp — native `.line_clamp(n)`
- [x] MiddleEllipsis
- [x] EllipsisTooltip
- [x] Link
- [x] ExternalLink
- [x] RelativeTime
- [x] DateTimeText
- [x] NumberText
- [x] CurrencyText
- [x] PercentText
- [x] FileSizeText
- [x] DurationText
- [x] PluralText
- [x] CopyableText
- [x] SelectableText — prove: selection over `StyledText` layout
- [x] Emoji — shortcodes
- [x] Latex / MathInline — prove: TeX subset
- [x] AnimatedNumber
- [x] Typewriter
- [x] GradientText — per-glyph tonal ramp
- [x] ShimmerText
## T03 Layout — `src/layout`
- [x] Stack / HStack / VStack
- [x] Flex — native `.flex()`
- [x] Grid / GridItem — native `.grid()`, `.col_span()`
- [x] SimpleGrid
- [x] Masonry
- [x] Center — native `.flex().items_center().justify_center()`
- [x] Container
- [x] AspectRatio
- [x] Inset / Padding — native `.p_*()`
- [x] Wrap — native `.flex_wrap()`
- [x] Absolute / Positioned — native `.absolute()`
- [x] Layer / ZStack
- [x] ScrollArea
- [x] Scrollbar
- [x] ScrollShadow
- [x] ScrollToTop
- [x] StickyHeader
- [x] SplitPane — horizontal, vertical, nested
- [x] ResizablePanel / ResizablePanelGroup → `layout::SplitPane`
- [x] ResizeHandle
- [x] Collapsible
- [x] Accordion / AccordionItem
- [x] Card / CardHeader / CardBody / CardFooter
- [x] Panel / PanelHeader
- [x] Section / SectionHeader
- [x] Group / Fieldset
- [x] Frame
- [x] Well
- [x] Sidebar
- [x] Drawer
- [x] Sheet
- [x] Page / PageHeader / PageContent
- [x] AppShell
- [x] MasterDetail
- [x] ThreeColumnLayout → `layout::SplitPane`
- [x] Dock / DockPanel
- [x] DockZone / DropIndicator
- [x] FloatingPanel
- [x] Pane / PaneGroup
- [x] Workspace — versioned layout snapshot
- [x] Viewport
## T04 Window & Shell — `src/shell`
- [x] TitleBar
- [x] WindowControls — macOS, Windows, Linux
- [x] TrafficLights → `shell::WindowControls`
- [x] WindowDragRegion — `shell::drag_region`: native drag area, Linux move, double-click zoom
- [x] WindowResizeBorder — `shell::ResizeBorder`: client decorations only; macOS and Windows resize natively
- [x] MenuBar → `menus::MenuBar` (T08b): the NativeMenu definitions, drawn in the window
- [x] NativeMenu — native `cx.set_menus()`
- [x] Toolbar / ToolbarGroup / ToolbarSeparator
- [x] StatusBar / StatusBarItem
- [x] ActivityBar
- [x] NavigationRail → `shell::ActivityBar`
- [x] TabBar
- [x] SplashScreen
- [x] AboutDialog
- [x] TrayIcon / TrayMenu — macOS `NSStatusItem`; other systems get an error
- [x] DockBadge — macOS dock tile; other systems get an error
- [x] JumpList — native `cx.set_dock_menu()`
- [ ] SystemNotification — prove: on macOS `cx.show_system_notification` posts only from an app bundle; unbundled, as `cargo run` starts it, gpui logs and drops the call, so Ely must check the bundle identifier and fail loud. A bundled gallery must post one and hand its response to the owner through `on_system_notification_response`
- [x] MultiWindow Manager
- [x] WindowSwitcher
- [x] QuickLauncher → `navigation::QuickLauncher` (T07c): a SearchPalette in an always-on-top window
- [x] MiniWindow / CompactMode
- [x] AlwaysOnTop — native `WindowKind::PopUp`
- [x] PictureInPicture → `shell::MiniWindow` at a screen corner; the host supplies the view
- [x] UpdateBanner / UpdateDialog
- [x] CrashReporter
- [x] OfflineIndicator
- [x] ZoomControl
## T05 Buttons & Actions — `src/buttons`
- [x] Button (T00)
- [x] IconButton (T00)
- [x] ButtonGroup
- [x] SplitButton → `menus::SplitButton` (T08a): its dropdown is a Menu
- [x] DropdownButton / MenuButton → `menus::DropdownMenu` (T08a)
- [x] ToggleButton
- [x] ToggleGroup
- [x] SegmentedControl
- [x] FloatingActionButton
- [x] LoadingButton → `buttons::Button` loading state, lands with Spinner (T11)
- [x] ConfirmButton — hold or click twice
- [x] HoldToConfirm → `buttons::ConfirmButton`
- [x] CopyButton
- [x] ShareButton
- [x] CloseButton
- [x] BackButton
- [x] MoreButton
- [x] ActionBar
- [x] BulkActionBar
- [x] ActionSheet
- [x] QuickActions
- [x] ShortcutHint → `buttons::Button::shortcut`
## T06a Forms · Text — `src/forms`
- [x] Input / TextField
- [x] TextArea → `forms::TextInput::multi_line`
- [x] PasswordInput
- [x] SearchInput
- [x] NumberInput
- [x] ScrubInput
- [x] CurrencyInput → `forms::NumberInput::currency`
- [x] PercentInput → `forms::NumberInput::percent`
- [x] UnitInput
- [x] EmailInput
- [x] UrlInput
- [x] PhoneInput
- [x] MaskedInput
- [x] PinInput / OTPInput
- [x] InlineEdit / EditableText
- [x] InputGroup / InputAddon
- [x] ClearableInput → `forms::Input::clearable`
- [x] AutoResizeInput → `forms::TextInput::multi_line`
- [x] MentionInput
- [x] HashtagInput → `forms::MentionInput` with `#`
- [x] TagInput / TokenInput
- [x] KeyValueInput
- [x] ListInput
- [x] PathInput — native dialog via `prompt_for_paths`
- [x] RegexInput
- [x] ExpressionInput
- [x] HotkeyInput / ShortcutRecorder
## T06b Forms · Selection
- [x] Checkbox
- [x] CheckboxGroup
- [x] CheckboxCard
- [x] Radio / RadioGroup
- [x] RadioCard
- [x] Switch / Toggle
- [x] Select
- [x] NativeSelect — blocked: gpui has no native popup menu
- [x] Combobox
- [x] Autocomplete → `forms::Combobox::free`
- [x] MultiSelect
- [x] CascadeSelect / Cascader
- [x] TreeSelect → `lists::TreeSelect` (T13b): forms cannot import lists
- [x] TransferList
- [x] ListBox
- [x] ChoiceChips / FilterChips
- [x] Rating
- [x] Slider
- [x] RangeSlider
- [x] VerticalSlider → `forms::Slider::vertical`
- [x] Knob / Dial
- [x] Stepper
## T06c Forms · Date & Time
- [x] Calendar
- [x] DatePicker
- [x] DateRangePicker
- [x] TimePicker
- [x] DateTimePicker
- [x] MonthPicker / YearPicker / QuarterPicker
- [x] WeekPicker
- [x] RelativeDatePicker
- [x] TimezoneSelect
- [x] DurationPicker
- [x] CronEditor
## T06d Forms · Color
- [x] ColorPicker — HSV, RGB, HEX, alpha → `forms::ColorPicker`
- [x] ColorSwatch → `forms::ColorSwatch`
- [x] ColorPalette → `forms::ColorPalette`
- [x] EyeDropper — proved: `NSColorSampler`; sRGB read tested (`read_srgb`), the sampler draws out of process → `forms::EyeDropper`
- [x] GradientEditor → `forms::GradientEditor`
## T06e Forms · Files
- [x] FilePicker / FileInput → `forms::FileInput`
- [x] FolderPicker → `forms::PathInput::directories` (T06a)
- [x] DropZone → `forms::DropZone`
- [x] UploadList → `forms::UploadList`, built with Loading & Motion (T11b): its rows are ProgressBars
- [x] ImageUpload — preview, crop → lands with Media (T26): its crop is the ImageCropper
- [x] AvatarUpload → `forms::AvatarUpload`, built with Data Display (T12a): it is an Avatar you replace
## T06f Forms · Other
- [x] SignaturePad → `forms::SignaturePad`
- [x] CodeInput → `forms::CodeInput`, colored by `code_highlights`
- [x] JsonInput → `forms::JsonInput`, colored by `json_highlights`
- [x] FontPicker → `forms::FontPicker`
- [x] IconPicker → `forms::IconPicker`
- [x] EmojiPicker → `forms::EmojiPicker`
- [x] LanguageSelect → `forms::Combobox::languages`
- [x] CountrySelect → `forms::Combobox::countries`
- [x] CurrencySelect → `forms::Combobox::currencies`
## T06g Forms · Structure
- [x] Form → `forms::Form`, Cmd-Enter submits
- [x] FormField → `forms::FormField`
- [x] FormLabel — required mark, help tip → `forms::FormLabel`
- [x] FormDescription / HelperText → `typography::Caption`, placed by `FormField::description`
- [x] FormError / ValidationMessage → `forms::FormError`
- [x] FormSection → `forms::FormSection`
- [x] FormActions → `buttons::ActionBar`
- [x] FieldArray → `forms::FieldArray`; ListInput and KeyValueInput use it
- [x] InlineForm → `forms::InlineForm`
- [x] WizardForm / MultiStepForm → lands with Navigation (T07): its frame is the Wizard
- [x] DirtyIndicator → `forms::DirtyIndicator`
## T07a Navigation · Tabs & paths — `src/navigation`
- [x] Tabs — top, left, bottom → `navigation::Tabs`
- [x] EditorTabs → `navigation::EditorTabs`
- [x] TabOverflowMenu → `navigation::TabOverflowMenu`
- [x] Breadcrumb → `navigation::Breadcrumb`
- [x] Pagination → `navigation::Pagination`
- [x] LoadMore → lands with Loading (T11a): its busy state is a Spinner
- [x] Stepper / Steps / Wizard → `navigation::Steps`, `navigation::Wizard`; also T06g WizardForm
## T07b Navigation · Places
- [x] Sidebar Navigation / NavItem / NavGroup → `navigation::NavItem`, `navigation::NavGroup`
- [x] NavigationMenu → `navigation::NavigationMenu`
- [x] ActivityBar Item → `shell::ActivityBar`
- [x] BackForwardNavigation → `navigation::BackForwardNavigation`
- [x] History Navigation → `navigation::BackForwardNavigation`
- [x] Anchor / TableOfContents → `navigation::Anchor`, `navigation::TableOfContents`
- [x] JumpTo / GoToLine → `navigation::GoToLine`
## T07c Navigation · Palettes & tour
- [x] CommandPalette → `navigation::CommandPalette`
- [x] QuickOpen → `navigation::QuickOpen`
- [x] QuickSwitcher → `navigation::QuickSwitcher`
- [x] SearchPalette → `navigation::SearchPalette`
- [x] SpotlightSearch → `navigation::SearchPalette`; T04 QuickLauncher opens it always on top
- [x] Tour / Onboarding → `overlays::Tour` (T09b): its steps are Spotlights
## T08a Menus · Menu & hosts — `src/menus`
- [x] Menu / MenuItem / MenuGroup / MenuSeparator → `menus::Menu` (`group`, `separator`), `menus::MenuItem`
- [x] SubMenu → `menus::MenuItem::submenu`
- [x] CheckboxMenuItem → `menus::MenuItem::check`
- [x] RadioMenuItem → `menus::MenuItem::radio`
- [x] MenuItemShortcut → `menus::MenuItem::keys`
- [x] MenuItemIcon → `menus::MenuItem::icon`
- [x] ContextMenu → `menus::ContextMenu`
- [x] DropdownMenu → `menus::DropdownMenu`; also T05 DropdownButton / MenuButton, and SplitButton as `menus::SplitButton`
- [x] OverflowMenu → `menus::OverflowMenu`
## T08b Menus · Bar, search & pie
- [x] MenuBar Menu → `menus::MenuBar`; also T04 MenuBar: the native menus, drawn in the window
- [x] MegaMenu → `navigation::NavigationMenu`: each entry opens a panel of links with a line of detail
- [x] SearchableMenu → `menus::SearchableMenu`
- [x] PieMenu / RadialMenu → `menus::PieMenu`, `menus::PieItem`
## T09a Overlays · Popovers & dialogs — `src/overlays`
- [x] Tooltip → `primitives::Tooltip`
- [x] Popover → `overlays::Popover`
- [x] HoverCard → `overlays::HoverCard`
- [x] Dialog / Modal → `overlays::Dialog`
- [x] AlertDialog → `overlays::AlertDialog`
- [x] ConfirmDialog → `overlays::ConfirmDialog`
- [x] PromptDialog → `overlays::PromptDialog`
- [x] FullscreenDialog → `overlays::Dialog::fullscreen`
- [x] Sheet → `layout::Sheet`
- [x] Drawer → `layout::Drawer`
## T09b Overlays · Guides & floats
- [x] Lightbox → `overlays::Lightbox`, `overlays::Slide`
- [x] Spotlight / Coachmark → `overlays::Spotlight`; also T07c Tour / Onboarding and T37 WelcomeTour as `overlays::Tour`
- [x] FloatingToolbar → `overlays::FloatingToolbar`
- [x] Callout / Peek → `overlays::Peek`
- [x] DropdownPanel → `overlays::Popover`
- [x] InlinePopup → `overlays::Popover` with the Link variant
- [x] ToastViewport → lands with Feedback (T10): it holds Toasts
## T10a Feedback · Messages — `src/feedback`
- [x] Toast — success, error, warning, info, action, undo; also T09b ToastViewport → `feedback::Toast`, `feedback::Toaster`, `feedback::ToastViewport`
- [x] Notification → `feedback::Notification`
- [x] NotificationCenter → `feedback::NotificationCenter`; also T10b EmptyState, which it shows when empty
- [x] Alert → `feedback::Alert`
- [x] Banner → `feedback::Banner`
- [x] Callout / Admonition → `feedback::Callout`
- [x] InlineMessage → `feedback::InlineMessage`
- [x] StatusMessage → `feedback::StatusMessage`
- [x] Snackbar → `feedback::Toast`
- [x] UndoToast → `feedback::Toast`
## T10b Feedback · States
- [x] ErrorView → `feedback::ErrorView`
- [x] ErrorBoundary — renders and logs a `Result` error; never catches panics → `feedback::ErrorBoundary`
- [x] NotFound / 404 → `feedback::ErrorView::not_found`
- [x] NoPermission / 403 → `feedback::ErrorView::no_permission`
- [x] Maintenance → `feedback::ErrorView::maintenance`
- [x] Offline → `feedback::ErrorView::offline`
- [x] EmptyState → `feedback::EmptyState`, built with T10a
- [x] Result → `feedback::ResultView`; a plain `Result` would shadow std's
- [x] ConfirmationCard → `feedback::ConfirmationCard`
- [x] SavingIndicator → `feedback::SavingIndicator`
- [x] SyncStatus → `feedback::SyncStatus`
- [x] ConnectionStatus → `feedback::ConnectionStatus`; its dot is `shell::OfflineIndicator`'s
- [x] Countdown → `feedback::Countdown`
- [x] Timer → `feedback::Timer`