Add type safe style classes

This commit is contained in:
david-swift 2024-05-18 11:35:23 +02:00
parent c7eb2120a4
commit be9cf996a0
25 changed files with 293 additions and 39 deletions

View File

@ -28,7 +28,7 @@ struct Counter: View {
count -= 1 count -= 1
} }
Text("\(count)") Text("\(count)")
.style("title-1") .title1()
.frame(minWidth: 100) .frame(minWidth: 100)
Button(icon: .default(icon: .goNext)) { Button(icon: .default(icon: .goNext)) {
count += 1 count += 1

View File

@ -0,0 +1,18 @@
//
// CheckButton+.swift
// Adwaita
//
// Created by david-swift on 18.05.24.
//
/// A button widget.
extension CheckButton {
/// Apply the selection mode style class.
/// - Parameter active: Whether it is applied.
/// - Returns: A view.
public func selectionMode(_ active: Bool = true) -> View {
style("selection-mode", active: active)
}
}

View File

@ -14,4 +14,11 @@ extension ActionRow {
self = self.title(title) self = self.title(title)
} }
/// Deemphasize the row title and emphasize the subtitle.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
public func property(_ active: Bool = true) -> View {
style("property", active: active)
}
} }

View File

@ -10,10 +10,13 @@ public struct HStack: View {
/// The content. /// The content.
var content: () -> Body var content: () -> Body
/// Whether the linked style should be used.
var linked = false
/// The view's body. /// The view's body.
public var view: Body { public var view: Body {
VStack(horizontal: true, content: content) VStack(horizontal: true, content: content)
.linked(linked)
} }
/// Initialize a `HStack`. /// Initialize a `HStack`.
@ -22,4 +25,11 @@ public struct HStack: View {
self.content = content self.content = content
} }
/// Link the children.
public func linked(_ active: Bool = true) -> Self {
var newSelf = self
newSelf.linked = active
return newSelf
}
} }

View File

@ -59,8 +59,17 @@ extension List {
} }
/// Add the "navigation-sidebar" style class. /// Add the "navigation-sidebar" style class.
public func sidebarStyle() -> View { /// - Parameter active: Whether the style is applied.
style("navigation-sidebar") /// - Returns: A view.
public func sidebarStyle(_ active: Bool = true) -> View {
style("navigation-sidebar", active: active)
}
/// Apply the boxed list style class.
/// - Parameter active: Whether the style is applied.
/// - Returns: A view.
public func boxedList(_ active: Bool = true) -> View {
style("boxed-list", active: active)
} }
} }

View File

@ -128,6 +128,204 @@ extension View {
} }
} }
/// Make a button or similar widget use accent colors.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
public func suggested(_ active: Bool = true) -> View {
style("suggested-action", active: active)
}
/// Make a button or similar widget use destructive colors.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
public func destructive(_ active: Bool = true) -> View {
style("destructive-action", active: active)
}
/// Make a button or similar widget use flat appearance.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
public func flat(_ active: Bool = true) -> View {
style("flat", active: active)
}
/// Make a button or similar widget use the regular appearance instead of the flat one.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
public func raised(_ active: Bool = true) -> View {
style("raised", active: active)
}
/// Make a button or similar widget round.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
public func circular(_ active: Bool = true) -> View {
style("circular", active: active)
}
/// Make a button or similar widget appear as a pill.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
public func pill(_ active: Bool = true) -> View {
style("pill", active: active)
}
/// Make the view partially transparent.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
public func dimLabel(_ active: Bool = true) -> View {
style("dim-label", active: active)
}
/// Use a title typography style.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
public func title1(_ active: Bool = true) -> View {
style("title-1", active: active)
}
/// Use a title typography style.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
public func title2(_ active: Bool = true) -> View {
style("title-2", active: active)
}
/// Use a title typography style.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
public func title3(_ active: Bool = true) -> View {
style("title-3", active: active)
}
/// Use a title typography style.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
public func title4(_ active: Bool = true) -> View {
style("title-4", active: active)
}
/// Use the heading typography style.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
public func heading(_ active: Bool = true) -> View {
style("heading", active: active)
}
/// Use the body typography style.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
public func body(_ active: Bool = true) -> View {
style("body", active: active)
}
/// Use the caption heading typography style.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
public func captionHeading(_ active: Bool = true) -> View {
style("caption-heading", active: active)
}
/// Use the caption typography style.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
public func caption(_ active: Bool = true) -> View {
style("caption", active: active)
}
/// Use the monospace typography style.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
public func monospace(_ active: Bool = true) -> View {
style("monospace", active: active)
}
/// Use the numeric typography style.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
public func numeric(_ active: Bool = true) -> View {
style("numeric", active: active)
}
/// Apply the accent color.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
public func accent(_ active: Bool = true) -> View {
style("accent", active: active)
}
/// Apply the success color.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
public func success(_ active: Bool = true) -> View {
style("success", active: active)
}
/// Apply the warning color.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
public func warning(_ active: Bool = true) -> View {
style("warning", active: active)
}
/// Apply the error color.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
public func error(_ active: Bool = true) -> View {
style("error", active: active)
}
/// Apply the card style.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
public func card(_ active: Bool = true) -> View {
style("card", active: active)
}
/// Apply an icon dropshadow.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
///
/// Use for icons larger than 32x32 pixels.
public func iconDropshadow(_ active: Bool = true) -> View {
style("icon-dropshadow", active: active)
}
/// Use for icons smaller than or equal to 32x32 pixels.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
public func lowresIcon(_ active: Bool = true) -> View {
style("lowres-icon", active: active)
}
/// Use the OSD style class.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
public func osd(_ active: Bool = true) -> View {
style("osd", active: active)
}
/// Give a view the default window background and foreground colors.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
public func backgroundStyle(_ active: Bool = true) -> View {
style("background", active: active)
}
/// Give a view the default view background and foreground colors.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
public func viewStyle(_ active: Bool = true) -> View {
style("view", active: active)
}
/// Give a view the default border.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
public func frameStyle(_ active: Bool = true) -> View {
style("frame", active: active)
}
/// Run a function when the view gets an update. /// Run a function when the view gets an update.
/// - Parameter onUpdate: The function. /// - Parameter onUpdate: The function.
/// - Returns: A view. /// - Returns: A view.

View File

@ -26,4 +26,11 @@ extension StatusPage {
self = self.child(content) self = self.child(content)
} }
/// Make the status page more compact.
/// - Parameter active: Whether the style is applied.
/// - Returns: A view.
public func compact(_ active: Bool = true) -> View {
style("compact", active: active)
}
} }

View File

@ -28,4 +28,9 @@ extension VStack {
} }
} }
/// Link the children.
public func linked(_ active: Bool = true) -> View {
style("linked", active: active)
}
} }

View File

@ -19,8 +19,8 @@ struct AlertDialogDemo: View {
Button("Show Dialog") { Button("Show Dialog") {
dialog = true dialog = true
} }
.style("pill") .pill()
.style("suggested-action") .suggested()
.frame(maxWidth: 100) .frame(maxWidth: 100)
.padding() .padding()
} }

View File

@ -32,7 +32,7 @@ struct CarouselDemo: View {
} }
.vexpand() .vexpand()
.hexpand() .hexpand()
.style("card") .card()
.onClick { print(element.id) } .onClick { print(element.id) }
.padding(20) .padding(20)
.frame(minWidth: 300, minHeight: 200) .frame(minWidth: 300, minHeight: 200)

View File

@ -19,7 +19,7 @@ struct CounterDemo: View {
HStack { HStack {
CountButton(count: $count, icon: .goPrevious) { $0 -= 1 } CountButton(count: $count, icon: .goPrevious) { $0 -= 1 }
Text("\(count)") Text("\(count)")
.style("title-1") .title1()
.frame(minWidth: 100) .frame(minWidth: 100)
CountButton(count: $count, icon: .goNext) { $0 += 1 } CountButton(count: $count, icon: .goNext) { $0 += 1 }
} }
@ -39,7 +39,7 @@ struct CounterDemo: View {
Button(icon: .default(icon: icon)) { Button(icon: .default(icon: icon)) {
action(&count) action(&count)
} }
.style("circular") .circular()
} }
} }

View File

@ -21,8 +21,8 @@ struct DialogDemo: View {
Button("Show Dialog") { Button("Show Dialog") {
dialog = true dialog = true
} }
.style("pill") .pill()
.style("suggested-action") .suggested()
.frame(maxWidth: 100) .frame(maxWidth: 100)
.padding() .padding()
} }

View File

@ -26,8 +26,8 @@ struct DiceDemo: View {
Button(label) { Button(label) {
number = .random(in: 1...6) number = .random(in: 1...6)
} }
.style("pill") .pill()
.style("suggested-action") .suggested()
.frame(maxWidth: 100) .frame(maxWidth: 100)
} }
.valign(.center) .valign(.center)

View File

@ -28,8 +28,8 @@ struct FlowBoxDemo: View {
selectedItem = items[safe: index]?.id ?? items[safe: index ?? 0 - 1]?.id ?? items.first?.id ?? "" selectedItem = items[safe: index]?.id ?? items[safe: index ?? 0 - 1]?.id ?? items.first?.id ?? ""
} }
} }
.linked()
.padding() .padding()
.style("linked")
.halign(.center) .halign(.center)
if !items.isEmpty { if !items.isEmpty {
FlowBox(items, selection: $selectedItem) { item in FlowBox(items, selection: $selectedItem) { item in

View File

@ -18,8 +18,8 @@ struct FormDemo: View {
Button("View Demo") { Button("View Demo") {
app.showWindow("form-demo") app.showWindow("form-demo")
} }
.style("suggested-action") .suggested()
.style("pill") .pill()
.frame(maxWidth: 100) .frame(maxWidth: 100)
} }
} }
@ -43,7 +43,7 @@ struct FormDemo: View {
EntryRow("Entry Row", text: $text) EntryRow("Entry Row", text: $text)
.suffix { .suffix {
Button(icon: .default(icon: .editCopy)) { State<Any>.copy(text) } Button(icon: .default(icon: .editCopy)) { State<Any>.copy(text) }
.style("flat") .flat()
.verticalCenter() .verticalCenter()
} }
EntryRow(password, text: $password) EntryRow(password, text: $password)

View File

@ -37,7 +37,7 @@ struct IdleDemo: View {
} }
} }
.padding() .padding()
.style("pill") .pill()
.hexpand() .hexpand()
.halign(.center) .halign(.center)
.insensitive(activeProcess) .insensitive(activeProcess)

View File

@ -28,8 +28,8 @@ struct ListDemo: View {
selectedItem = items[safe: index]?.id ?? items[safe: index ?? 0 - 1]?.id ?? items.first?.id ?? "" selectedItem = items[safe: index]?.id ?? items[safe: index ?? 0 - 1]?.id ?? items.first?.id ?? ""
} }
} }
.linked()
.padding() .padding()
.style("linked")
.halign(.center) .halign(.center)
if !items.isEmpty { if !items.isEmpty {
List(items, selection: $selectedItem) { item in List(items, selection: $selectedItem) { item in
@ -39,8 +39,8 @@ struct ListDemo: View {
} }
.padding() .padding()
} }
.boxedList()
.valign(.center) .valign(.center)
.style("boxed-list")
.padding() .padding()
} }
} }

View File

@ -18,8 +18,8 @@ struct NavigationViewDemo: View {
Button("View Demo") { Button("View Demo") {
app.showWindow("navigation") app.showWindow("navigation")
} }
.style("suggested-action") .suggested()
.style("pill") .pill()
.frame(maxWidth: 100) .frame(maxWidth: 100)
.padding() .padding()
} }

View File

@ -31,8 +31,8 @@ struct PictureDemo: View {
app.addWindow("picture", parent: window) app.addWindow("picture", parent: window)
} }
.halign(.center) .halign(.center)
.style("pill") .pill()
.style("suggested-action") .suggested()
.padding() .padding()
} }

View File

@ -18,8 +18,8 @@ struct PopoverDemo: View {
Button("Present Popover") { Button("Present Popover") {
visible = true visible = true
} }
.style("suggested-action") .suggested()
.style("pill") .pill()
.frame(maxWidth: 100) .frame(maxWidth: 100)
.popover(visible: $visible) { .popover(visible: $visible) {
CounterDemo() CounterDemo()

View File

@ -18,8 +18,8 @@ struct ToastDemo: View {
Button("Add Toast") { Button("Add Toast") {
toast.signal() toast.signal()
} }
.style("suggested-action") .suggested()
.style("pill") .pill()
.frame(maxWidth: 100) .frame(maxWidth: 100)
} }
} }

View File

@ -18,8 +18,8 @@ struct ToolbarDemo: View {
Button("View Demo") { Button("View Demo") {
app.showWindow("toolbar-demo") app.showWindow("toolbar-demo")
} }
.style("suggested-action") .suggested()
.style("pill") .pill()
.frame(maxWidth: 100) .frame(maxWidth: 100)
} }
} }
@ -34,8 +34,8 @@ struct ToolbarDemo: View {
Button("Toggle Toolbar") { Button("Toggle Toolbar") {
visible.toggle() visible.toggle()
} }
.style("suggested-action") .suggested()
.style("pill") .pill()
.frame(maxWidth: 100) .frame(maxWidth: 100)
.padding(15) .padding(15)
} }

View File

@ -18,21 +18,21 @@ struct TransitionDemo: View {
if firstView { if firstView {
Text("First View") Text("First View")
.transition(.slideDown) .transition(.slideDown)
.style("accent") .accent()
} else { } else {
Text("Second View") Text("Second View")
.transition(.slideUp) .transition(.slideUp)
.style("success") .success()
} }
} }
.modifyContent(Text.self) { $0.style("title-2").padding() } .modifyContent(Text.self) { $0.title2().padding() }
.style("card") .card()
.frame(maxWidth: 200) .frame(maxWidth: 200)
.padding() .padding()
Button("Toggle View") { Button("Toggle View") {
firstView.toggle() firstView.toggle()
} }
.style("pill") .pill()
.padding() .padding()
.frame(maxWidth: 100) .frame(maxWidth: 100)
} }

View File

@ -18,8 +18,8 @@ struct ViewSwitcherDemo: View {
Button("View Demo") { Button("View Demo") {
app.showWindow("switcher-demo") app.showWindow("switcher-demo")
} }
.style("suggested-action") .suggested()
.style("pill") .pill()
.frame(maxWidth: 100) .frame(maxWidth: 100)
} }
} }

View File

@ -25,8 +25,8 @@ struct WindowsDemo: View {
} }
.hexpand() .hexpand()
} }
.linked()
.valign(.center) .valign(.center)
.style("linked")
.padding() .padding()
} }
.frame(maxWidth: 100) .frame(maxWidth: 100)