- Reduce Palette protocol from 18 to 13 essential properties
- Add BlockPalette protocol with surfaceBackground, surfaceHeaderBackground, elevatedBackground
- BlockPalette defaults compute via lighter(by:) from background
- Add Color.rgbComponents for universal ANSI/256/RGB conversion
- Make lighter(by:), darker(by:), opacity() work on all color types
- Migrate views to use BlockPalette accessors
- Remove NCursesPalette (to be reworked later)
- Update all 6 palette structs to BlockPalette conformance
- Update DocC articles, topic index, and palette-preview.html
- All 492 tests in 83 suites passing
Remove borderFocused, separator, selection, selectionBackground, disabled,
statusBarForeground, statusBarHighlight from Palette protocol and all
consumers. Views now use palette essentials directly (e.g. palette.accent
instead of palette.borderFocused, palette.foregroundTertiary instead of
palette.disabled). Update tests and DocC articles accordingly.
Remove explicit borderFocused, selection, selectionBackground,
statusBarForeground, statusBarHighlight from all palette implementations.
These remain as default-derived properties on the protocol extension.
Add foregroundPlaceholder as 4th foreground level for input field
placeholder text, dimmer than foregroundTertiary.
Fix SwiftLint force_try violations in luminance tests.
- Add BluePalette (VFD-style, #00AAFF base) and VioletPalette (HSL-generated from hue 270°)
- Remove GeneratedPalette entirely (replaced by dedicated VioletPalette)
- Reorder palette cycling: Green → Amber → Red → Violet → Blue → White → NCurses
- Sync all landing page CSS theme colors with exact Swift palette values
- Add blue theme to landing page with matching VFD colors
- Fix theme switcher FOUC: useEffect syncs React state after hydrate
- Update default theme to Green (was Amber)
- Update landing page logo to latest DocC version
- Added comparison table (border, padding, background, title, footer, rendering) to all three
- Documented typical use cases for each container type
- Box: minimal border wrapper, no padding/background/title
- Card: padded container with optional title, footer, and background
- Panel: always-titled container, less padding, no background
- Split dependency graph into two LR diagrams (Ownership + Runtime References)
- Replace ASCII event loop in Architecture article with Mermaid diagram
- All diagrams with Light/Dark variants, transparent background, rounded nodes
- Remove old lifecycle-dependency-graph PNGs (replaced by dep-graph-ownership + dep-graph-references)
- Replace EnvironmentStorage.shared with EnvironmentStorage.active
(settable static property)
- Make EnvironmentStorage.init() public instead of private
- Update all 12 source references across Environment.swift, App.swift,
RenderLoop.swift, Focus.swift, Theme.swift, Appearance.swift,
ThemeManager.swift
- Update all 17 test references across EnvironmentTests, FocusTests,
StatusBarTests, ButtonTests
This is the last singleton in the TUIkit framework.
- Replace AppState.shared with AppState.active (settable static property)
- Make AppState.init() public instead of private
- Update all 15 source references across State.swift, App.swift,
StatusBarState.swift, ThemeManager.swift, AppStorage.swift
- Update all 28 test references in AppStateTests and StatePropertyTests
- Serialize Environment Property Wrapper tests (shared-state race fix)
- Remove Terminal.shared static property
- Make Terminal.init() public instead of private
- Update default parameters in ViewRenderer and RenderContext to use Terminal()
- WindowGroup.renderScene now uses context.terminal instead of Terminal.shared
- Remove JSONFileStorage.shared static property
- Delete StorageManager class entirely (was only a singleton wrapper)
- Add StorageDefaults enum with settable backend property
- @AppStorage inits now use StorageDefaults.backend instead of
StorageManager.shared.backend
Delete dead code classes that were fully replaced by LifecycleManager
in TUIContext. Remove deprecated .shared properties from
KeyEventDispatcher and PreferenceStorage (zero live call-sites).
@preconcurrency import Glibc does not suppress the Swift 6 strict
concurrency error for stdout (shared mutable global). Instead of
fighting the type system, bypass stdout entirely by writing directly
to STDOUT_FILENO via the POSIX write() syscall. This is concurrency-
safe, avoids buffering issues, and works on all platforms.
The previous nonisolated(unsafe) approach failed because the concurrency
check triggers on the read of stdout itself, not on the local binding.
@preconcurrency import suppresses all concurrency diagnostics for the
imported module, which is the correct fix for C library globals that
Swift 6 cannot reason about.
- Wrap fflush(stdout) in nonisolated(unsafe) to satisfy Swift 6 strict
concurrency on Linux where stdout is a shared mutable global
- Replace separate lint + linux-build jobs with a single build matrix
(macOS + Linux) that runs SwiftLint, swift build, and swift test
on both platforms
- Install SwiftLint on Linux via release binary (no Homebrew available)
- DocC build-docs job now depends on the matrix build job
Document the View/Renderable dual rendering system across 9 files:
- Renderable.swift: Full protocol doc with conformance catalog and decision order
- renderToBuffer(): Dispatch logic with example flow and priority comments
- View.swift: Dual system overview with composite vs primitive examples
- ViewRenderer.swift: Clarify wrapper role, explain centralized Renderable extensions
- RenderLoop.swift: Full pipeline diagram (8 steps per frame)
- App.swift: SceneRenderable bridge from Scene to View rendering
- ViewModifier.swift: ModifiedView body:Never contract explanation
- Box.swift: Only composite view (no Renderable, delegates via body)
- ForEach.swift: No standalone rendering, depends on ViewBuilder flattening
- Environment.swift: EnvironmentModifier.body is dead code (Renderable wins)
- Replace #if os(Linux) with #if canImport(Glibc/Musl/Darwin) import guards
- Add TermFlag typealias to fix termios flag width mismatch (UInt vs UInt32)
- Add platform import guard to SignalManager for POSIX signal visibility
- Replace DispatchQueue.global with Task.detached in AppStorage
- Add XDG_CONFIG_HOME fallback for config directory resolution
- Add Linux Build & Test CI job (swift:6.0 container on ubuntu-latest)
Add /// doc comments to 26 public declarations across 5 files:
- StatusBar.swift: StatusBarItemOrder properties/init/operator,
StatusBarItem 5 stored properties, StatusBarItemProtocol.matches(),
StatusBarItemBuilder 6 result builder methods
- Button.swift: ButtonRowBuilder 5 result builder methods
- Appearance.swift: Appearance.ID rawValue and init
- PaddingModifier.swift: Edge rawValue and init
- Preferences.swift: NavigationTitleKey.defaultValue
All public API is now fully documented for DocC generation.
Both preference keys were speculative code — no Tab or Scroll system
exists in TUIKit. NavigationTitleKey is kept (used by .navigationTitle()
convenience modifier). Keys can be re-added when the features are built.