- TextField now expands to fill available width (SwiftUI behavior)
- Label parameter is for accessibility only, not rendered visually
- Use prompt: parameter for placeholder text
- Update example app to use prompt: correctly
- SecureField also expands to fill available width
TextFields should not automatically expand to fill available width.
They now use a fixed defaultContentWidth (20 chars). Use .frame()
modifier to explicitly set a different width if needed.
TextField now properly renders its label before the input field and
subtracts the label width from available space. This prevents the
input field from overflowing when hasExplicitWidth is true.
AppearanceRegistry.all now starts with .rounded instead of .line.
Since ThemeManager starts with currentIndex=0, this ensures the
default appearance is rounded corners as intended.
- Make Box struct internal (use .border() modifier instead)
- Update example app to use .border() instead of Box
- Simplify resolveContainerWidth to just return content width
- Simplify resolveContainerHeight to just return content height
- Remove auto-expansion logic from containers
- Containers now size to fit their content, not fill available space
- Spacers in HStack still expand correctly to fill remaining space
- Update tests for renamed BorderViaContainerViewTests
- Add hasExplicitHeight flag to RenderContext
- Add forBorderedContent() helper for bordered container context
- Add resolveContainerWidth/Height helpers for container sizing
- Add withAvailableSize() for setting both dimensions at once
- Update ContainerView to subtract padding from available width
- Update NavigationSplitView to use withAvailableSize()
- Fix HStack Spacer expansion to respect hasExplicitWidth
- Update RenderLoop to set both hasExplicitWidth/Height
- Add ToggleStyle protocol matching SwiftUI's pattern
- Add .automatic, .checkbox, .switch built-in styles
- Add .toggleStyle(_:) view modifier via Environment
- All styles render as [ ]/[x] in TUI (documented constraint)
- Remove old ToggleStyle enum (.toggle/.checkbox)
- Update example app and tests for new API
All focusable views now use persistedFocusID from StateStorage instead of
generating a new focusID on each render. This ensures focus tracking
remains stable across re-renders.
- Slider: Use persistedFocusID, dim unfocused arrows (50% opacity)
- Stepper: Use persistedFocusID, dim unfocused arrows (50% opacity)
- Button: Consistent focus indicator with persistedFocusID
- RadioButton: Add pulsing focus indicator when focused
- Add cursorColor to Palette protocol with HSL-computed values for all SystemPalette presets
- Create TextCursorStyle with shapes (block, bar, underscore) and animations (none, blink, pulse)
- Add .textCursor(_:) View modifier propagating through environment
- Update TextField and SecureField to use cursorColor and respect cursor style
- Add 17 tests for TextCursorStyle
- Badge values are now extracted from BadgeModifier during row extraction
- Added extractBadgeValue() function using Mirror reflection
- ListRow and SelectableListRow now store badge value
- withAvailableWidth() now sets hasExplicitWidth for proper List expansion
TUI-specific changes:
- Separator is now a space instead of vertical line to avoid double borders
- Sidebar (20 chars) and content (30 chars) have fixed widths
- Only the rightmost column adapts to terminal width changes
- Column content is padded to fill the full column width
- Fix escape sequence parsing for fast key repeat (read byte-by-byte)
- Ctrl+A: Select all text
- Ctrl+C: Copy selection to system clipboard (pbcopy/xclip)
- Ctrl+X: Cut selection to clipboard
- Ctrl+V: Paste from clipboard (pbpaste/xsel)
- Ctrl+Z: Undo last change (up to 50 states)
- 12 new tests (998 total)
- SecureField with masked display using ● (U+25CF) bullets
- Reuses TextFieldHandler for key input handling
- SwiftUI API parity: init(_:text:) and init(_:text:prompt:)
- Supports .onSubmit() and .disabled() modifiers
- Focus indicator with pulsing vertical bars
- 15 tests for masking behavior and rendering
- Example app page with password validation demo
- Slider: Interactive track control with keyboard navigation (arrow keys, +/-, Home/End)
- Stepper: Increment/decrement control with value or custom callbacks
- TrackStyle: Renamed from ProgressBarStyle, shared between ProgressView and Slider
- TrackRenderer: Extracted utility for track rendering
- 59 new tests (892 total), Example app demo pages for both components
- Remove textInputAutocapitalization (not relevant for TUI)
- TextField now has fixed width with horizontal scrolling
- New visual style: background color + focus indicator bars
- Increase frame rate to 30 FPS and process up to 5 events/frame
- Fix Space key handling in ActionHandler (.space instead of .character)
- VStack centers children relative to available width when spacers present
- CodePreview: Add Preview button that shows terminal screenshot
- Smooth fade-in animation with blur backdrop
- ESC or click outside to close
- Caption overlay on image
- Add hasExplicitWidth flag to RenderContext
- FlexibleFrameView sets flag when width constraints are specified
- ContainerView expands to fill available width when flag is set
- List calculates row width based on frame constraints
- InsetGroupedListStyle: disable alternating row colors by default
- InsetGroupedListStyle: move row padding into renderRow() so backgrounds extend to borders
Phase 4 & 6 of List SwiftUI API Parity:
- .selectionDisabled() prevents row selection in List
- .listRowSeparator() stub with warning (not supported in TUI)
- SelectionDisabledKey environment key
- Visibility and VerticalEdge.Set types for API compatibility
- 11 new tests (738 total)
- List now uses SelectableListRow<ID> instead of ListRow<ID> internally
- Section headers/footers are non-selectable (.header/.footer types)
- extractRows() detects SectionRowExtractor and flattens to typed rows
- selectableIndices populated for focus navigation skip logic
- renderRow() skips focus/selection background for headers/footers
- Alternating colors restart per section (sectionContentIndex)
- Added Sendable constraint to List<SelectionValue> for Swift 6
- Section conforms to ListRowExtractor (delegates to content ForEach)
- 10 new integration tests (732 total)
Foundation for integrating Section headers/footers with List row rendering:
- Create SelectableListRow.swift with ListRowType enum (header/content/footer)
and SelectableListRow struct for type-safe row classification
- Add FrameBuffer Sendable + Equatable conformance (required for SelectableListRow)
- Enhance ItemListHandler with selectableIndices property to track which rows
can be selected/focused (for skipping non-selectable headers/footers)
- Implement focus skip-logic in moveFocus() to jump over non-selectable rows
- Update Home/End keys to navigate to first/last selectable row
- Add comprehensive documentation to all new types
This foundation enables Phase 2c3 (List flattening and per-section styling).
All tests passing (722). Build + swiftlint clean.