mirror of
https://github.com/phranck/TUIkit.git
synced 2026-05-21 09:50:35 +00:00
5ad97132b8
- 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
91 lines
2.8 KiB
Swift
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")
|
||
}
|
||
}
|
||
}
|