Files
phranck 5ad97132b8 Feat: Add @Observable support with Observation framework
- Replace custom Observable protocol and @Published with Apple's @Observable macro
- Add withObservationTracking in renderToBuffer for automatic per-property dependency tracking
- Add type-based @Environment(Type.self) and .environment(object) for observable objects
- Add ObjectEnvironmentModifier for injecting observable objects into the environment
- Add needsCacheClear flag to AppState for thread-safe cache invalidation
- Add cross-platform test script (scripts/test-linux.sh) for Docker-based Linux verification
- Add DemoAppHeader with system info display (OS, version, architecture)
- Consolidate Example App: extract ImageDemoHelpers, KeyboardHelpSection, ValueDisplayRow
- Add pre-push verification rule to CLAUDE.md
- Verified on both macOS and Linux (swift:6.0 container), 1155 tests passing
2026-02-15 23:49:34 +01:00

91 lines
2.8 KiB
Swift

// 🖥️ TUIKit — Terminal UI Kit for Swift
// ButtonsPage.swift
//
// Created by LAYERED.work
// License: MIT
import TUIkit
/// Buttons and focus demo page.
///
/// Shows interactive button features including:
/// - Different button styles (default, primary, success, destructive)
/// - Disabled buttons
/// - Plain style (no border)
/// - ButtonRow for horizontal groups
/// - Focus navigation with Tab
/// - Live click counter demonstrating `@State` persistence across re-renders
struct ButtonsPage: View {
@State var clickCount: Int = 0
var body: some View {
VStack(alignment: .leading, spacing: 1) {
DemoSection("Interactive Counter (@State)") {
HStack(spacing: 2) {
Button("+1", style: .primary) {
clickCount += 1
}
Button("+10", style: .success) {
clickCount += 10
}
Button("Reset", style: .destructive) {
clickCount = 0
}
Text("Clicks: \(clickCount)")
.bold()
.foregroundStyle(.palette.accent)
}
}
DemoSection("Button Styles") {
HStack(spacing: 2) {
Button("Default") {
clickCount += 1
}
Button("Primary", style: .primary) {
clickCount += 1
}
Button("Success", style: .success) {
clickCount += 1
}
Button("Destructive", style: .destructive) {
clickCount += 1
}
}
}
DemoSection("Disabled Button") {
HStack(spacing: 2) {
Button("Enabled") { clickCount += 1 }
Button("Disabled") {}.disabled()
}
}
DemoSection("Plain Style (No Border)") {
HStack(spacing: 2) {
Button("Link 1", style: .plain) { clickCount += 1 }
Button("Link 2", style: .plain) { clickCount += 1 }
}
}
DemoSection("ButtonRow (Horizontal Group)") {
ButtonRow(spacing: 3) {
Button("Cancel") { clickCount += 1 }
Button("Save", style: .primary) { clickCount += 1 }
}
}
KeyboardHelpSection("Focus Navigation", shortcuts: [
"Use [Tab] to move focus between buttons",
"Use [Enter] or [Space] to press the focused button",
])
Spacer()
}
.appHeader {
DemoAppHeader("Buttons & Focus Demo")
}
}
}