Add support for dialogs

This commit is contained in:
david-swift 2024-03-21 06:25:09 +01:00
parent 2146a4f268
commit 6ee069ebd9
49 changed files with 263 additions and 146 deletions

View File

@ -0,0 +1,97 @@
//
// Dialog.swift
// Adwaita
//
// Created by david-swift on 20.03.24.
//
import CAdw
/// The dialog widget.
struct Dialog: Widget {
/// Whether the dialog is visible.
@Binding var visible: Bool
/// The dialog's title.
var title: String?
/// The wrapped view.
var child: View
/// The content of the dialog.
var content: Body
/// The ID for the dialog's storage.
let dialogID = "dialog"
/// The ID for the content's storage.
let contentID = "content"
/// Get the container of the child.
/// - Parameter modifiers: Modify views before being updated.
/// - Returns: The view storage.
func container(modifiers: [(View) -> View]) -> ViewStorage {
let storage = child.storage(modifiers: modifiers)
update(storage, modifiers: modifiers, updateProperties: true)
return storage
}
/// Update the view storage of the child, dialog, and dialog content.
/// - Parameters:
/// - storage: The view storage.
/// - modifiers: Modify views before being updated.
/// - updateProperties: Whether to update properties.
func update(_ storage: ViewStorage, modifiers: [(View) -> View], updateProperties: Bool) {
child.widget(modifiers: modifiers).update(storage, modifiers: modifiers, updateProperties: updateProperties)
if let storage = storage.content[contentID]?.first as? ViewStorage {
content
.widget(modifiers: modifiers)
.update(storage, modifiers: modifiers, updateProperties: updateProperties)
}
guard updateProperties else {
return
}
if visible {
if storage.content[dialogID]?.first == nil {
createDialog(storage: storage, modifiers: modifiers)
adw_dialog_present(storage.content[dialogID]?.first?.pointer?.cast(), storage.pointer?.cast())
}
adw_dialog_set_title(storage.content[dialogID]?.first?.pointer?.cast(), title ?? "")
} else {
if storage.content[dialogID]?.first != nil {
adw_dialog_close(storage.content[dialogID]?.first?.pointer?.cast())
}
}
}
/// Create a new instance of the dialog.
/// - Parameters:
/// - storage: The wrapped view's storage.
/// - modifiers: The view modifiers.
func createDialog(storage: ViewStorage, modifiers: [(View) -> View]) {
let pointer = adw_dialog_new()
let dialog = ViewStorage(pointer?.opaque())
storage.content[dialogID] = [dialog]
let contentStorage = content.widget(modifiers: modifiers).storage(modifiers: modifiers)
adw_dialog_set_child(pointer, contentStorage.pointer?.cast())
storage.content[contentID] = [contentStorage]
dialog.connectSignal(name: "closed") {
storage.content[dialogID] = []
storage.content[contentID] = []
if visible {
visible = false
}
}
}
}
extension View {
/// Add a dialog to the parent window.
/// - Parameters:
/// - visible: Whether the dialog is presented.
/// - title: The dialog's title.
/// - content: The dialog's content.
public func dialog(visible: Binding<Bool>, title: String? = nil, @ViewBuilder content: () -> Body) -> View {
Dialog(visible: visible, title: title, child: self, content: content())
}
}

View File

@ -2,7 +2,7 @@
// ActionRow.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -2,7 +2,7 @@
// Avatar.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -2,7 +2,7 @@
// Banner.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -2,7 +2,7 @@
// Bin.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -2,7 +2,7 @@
// Box.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -2,7 +2,7 @@
// Button.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -2,7 +2,7 @@
// ButtonContent.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw
@ -29,12 +29,13 @@ import LevenshteinTransformations
///
/// ```
/// buttoncontent
/// box
/// image
/// label
/// ```
///
/// `AdwButtonContent`'s CSS node is called `buttoncontent`. It contains the
/// subnodes `image` and `label`.
/// `AdwButtonContent`'s CSS node is called `buttoncontent`. It contains a `box`
/// subnode that serves as a container for the `image` and `label` nodes.
///
/// When inside a `GtkButton` or `AdwSplitButton`, the button will receive the
/// `.image-text-button` style class. When inside a `GtkMenuButton`, the

View File

@ -2,7 +2,7 @@
// Carousel.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw
@ -56,8 +56,10 @@ public struct Carousel<Element>: Widget where Element: Identifiable {
/// This signal is emitted after a page has been changed.
///
/// It can be used to implement "infinite scrolling" by amending the pages
/// after every scroll. Note that an empty carousel is indicated by
/// `(int)index == -1`.
/// after every scroll.
///
/// ::: note
/// An empty carousel is indicated by `(int)index == -1`.
var pageChanged: (() -> Void)?
/// The dynamic widget elements.
var elements: [Element]
@ -219,8 +221,10 @@ public struct Carousel<Element>: Widget where Element: Identifiable {
/// This signal is emitted after a page has been changed.
///
/// It can be used to implement "infinite scrolling" by amending the pages
/// after every scroll. Note that an empty carousel is indicated by
/// `(int)index == -1`.
/// after every scroll.
///
/// ::: note
/// An empty carousel is indicated by `(int)index == -1`.
public func pageChanged(_ pageChanged: @escaping () -> Void) -> Self {
var newSelf = self
newSelf.pageChanged = pageChanged

View File

@ -2,7 +2,7 @@
// CenterBox.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -2,7 +2,7 @@
// CheckButton.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -2,7 +2,7 @@
// Clamp.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -2,7 +2,7 @@
// ComboRow.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -2,7 +2,7 @@
// EntryRow.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw
@ -62,6 +62,8 @@ public struct EntryRow: Widget {
/// operation, e.g. network activity, to avoid triggering it after typing every
/// character.
var showApplyButton: Bool?
/// The length of the text in the entry row.
var textLength: UInt?
/// The title of the preference represented by this row.
///
/// The title is interpreted as Pango markup unless
@ -226,6 +228,14 @@ public struct EntryRow: Widget {
return newSelf
}
/// The length of the text in the entry row.
public func textLength(_ textLength: UInt?) -> Self {
var newSelf = self
newSelf.textLength = textLength
return newSelf
}
/// The title of the preference represented by this row.
///
/// The title is interpreted as Pango markup unless

View File

@ -2,7 +2,7 @@
// ExpanderRow.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -2,7 +2,7 @@
// FlowBox.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -2,7 +2,7 @@
// HeaderBar.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw
@ -16,6 +16,15 @@ import LevenshteinTransformations
/// features compared to it. Refer to `GtkHeaderBar` for details. It is typically
/// used as a top bar within [class@ToolbarView].
///
/// ## Dialog Integration
///
/// When placed inside an [class@Dialog], `AdwHeaderBar` will display the dialog
/// title intead of window title. It will also adjust the decoration layout to
/// ensure it always has a close button and nothing else. Set
/// [property@HeaderBar:show-start-title-buttons] and
/// [property@HeaderBar:show-end-title-buttons] to `FALSE` to remove it if it's
/// unwanted.
///
/// ## Navigation View Integration
///
/// When placed inside an [class@NavigationPage], `AdwHeaderBar` will display the
@ -24,9 +33,10 @@ import LevenshteinTransformations
/// When used together with [class@NavigationView] or [class@NavigationSplitView],
/// it will also display a back button that can be used to go back to the previous
/// page. The button also has a context menu, allowing to pop multiple pages at
/// once, potentially across multiple navigation views. In rare scenarios, set
/// [property@HeaderBar:show-back-button] to `FALSE` to disable the back button
/// if it's unwanted (e.g. in an extra header bar on the same page).
/// once, potentially across multiple navigation views.
///
/// Set [property@HeaderBar:show-back-button] to `FALSE` to disable this behavior
/// in rare scenarios where it's unwanted.
///
/// ## Split View Integration
///

View File

@ -2,7 +2,7 @@
// Label.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw
@ -15,7 +15,7 @@ import LevenshteinTransformations
///
/// ![An example GtkLabel](label.png)
///
/// # CSS nodes
/// ## CSS nodes
///
/// ```
/// label
@ -36,7 +36,7 @@ import LevenshteinTransformations
/// carry the link or visited state depending on whether they have been
/// visited. In this case, label node also gets a .link style class.
///
/// # GtkLabel as GtkBuildable
/// ## GtkLabel as GtkBuildable
///
/// The GtkLabel implementation of the GtkBuildable interface supports a
/// custom `<attributes>` element, which supports any number of `<attribute>`
@ -45,6 +45,7 @@ import LevenshteinTransformations
/// values for this label.
///
/// An example of a UI definition fragment specifying Pango attributes:
///
/// ```xml
/// <object class="GtkLabel"><attributes><attribute name="weight" value="PANGO_WEIGHT_BOLD"/><attribute name="background" value="red" start="5" end="10"/></attributes></object>
/// ```
@ -55,11 +56,11 @@ import LevenshteinTransformations
/// sense with translatable attributes. Use markup embedded in the translatable
/// content instead.
///
/// # Accessibility
/// ## Accessibility
///
/// `GtkLabel` uses the %GTK_ACCESSIBLE_ROLE_LABEL role.
///
/// # Mnemonics
/// ## Mnemonics
///
/// Labels may contain mnemonics. Mnemonics are underlined characters in the
/// label, used for keyboard navigation. Mnemonics are created by providing a
@ -100,7 +101,7 @@ import LevenshteinTransformations
/// gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
/// ```
///
/// # Markup (styled text)
/// ## Markup (styled text)
///
/// To make it easy to format text in a label (changing colors,
/// fonts, etc.), label text can be provided in a simple
@ -130,14 +131,14 @@ import LevenshteinTransformations
/// end_index for a [struct@Pango.Attribute] requires knowledge of the exact
/// string being displayed, so translations will cause problems.
///
/// # Selectable labels
/// ## Selectable labels
///
/// Labels can be made selectable with [method@Gtk.Label.set_selectable].
/// Selectable labels allow the user to copy the label contents to
/// the clipboard. Only labels that contain useful-to-copy information
/// such as error messages should be made selectable.
/// the clipboard. Only labels that contain useful-to-copy informationsuch
/// as error messagesshould be made selectable.
///
/// # Text layout
/// ## Text layout
///
/// A label can contain any number of paragraphs, but will have
/// performance problems if it contains more than a small number.
@ -160,7 +161,7 @@ import LevenshteinTransformations
/// is used as the natural width. Even if max-width-chars specified, wrapping
/// labels will be rewrapped to use all of the available width.
///
/// # Links
/// ## Links
///
/// GTK supports markup for clickable hyperlinks in addition to regular Pango
/// markup. The markup for links is borrowed from HTML, using the `<a>` with
@ -169,7 +170,7 @@ import LevenshteinTransformations
/// attribute is displayed as a tooltip on the link. The class attribute is
/// used as style class on the CSS node for the link.
///
/// An example looks like this:
/// An example of inline links looks like this:
///
/// ```c
/// const char *text =

View File

@ -2,7 +2,7 @@
// LevelBar.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -2,7 +2,7 @@
// LinkButton.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -2,7 +2,7 @@
// ListBox.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -2,7 +2,7 @@
// Menu.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -2,7 +2,7 @@
// NavigationView.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw
@ -51,7 +51,7 @@ import LevenshteinTransformations
/// at once, potentially across multiple navigation views.
///
/// Set [property@HeaderBar:show-back-button] to `FALSE` to disable this behavior
/// if it's unwanted.
/// in rare scenarios where it's unwanted.
///
/// `AdwHeaderBar` will also display the title of the `AdwNavigationPage` it's
/// placed into, so most applications shouldn't need to customize it at all.

View File

@ -2,7 +2,7 @@
// Overlay.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -2,7 +2,7 @@
// OverlaySplitView.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -2,7 +2,7 @@
// PasswordEntryRow.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw
@ -47,6 +47,8 @@ public struct PasswordEntryRow: Widget {
/// operation, e.g. network activity, to avoid triggering it after typing every
/// character.
var showApplyButton: Bool?
/// The length of the text in the entry row.
var textLength: UInt?
/// The title of the preference represented by this row.
///
/// The title is interpreted as Pango markup unless
@ -189,6 +191,14 @@ public struct PasswordEntryRow: Widget {
return newSelf
}
/// The length of the text in the entry row.
public func textLength(_ textLength: UInt?) -> Self {
var newSelf = self
newSelf.textLength = textLength
return newSelf
}
/// The title of the preference represented by this row.
///
/// The title is interpreted as Pango markup unless

View File

@ -2,7 +2,7 @@
// Popover.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -2,7 +2,7 @@
// PreferencesGroup.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw
@ -16,7 +16,7 @@ import LevenshteinTransformations
/// which in turn are represented by [class@PreferencesRow].
///
/// To summarize the role of the preferences it gathers, a group can have both a
/// title and a description. The title will be used by [class@PreferencesWindow]
/// title and a description. The title will be used by [class@PreferencesDialog]
/// to let the user look for a preference.
///
/// ## AdwPreferencesGroup as GtkBuildable

View File

@ -2,13 +2,13 @@
// PreferencesPage.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw
import LevenshteinTransformations
/// A page from [class@PreferencesWindow].
/// A page from [class@PreferencesDialog].
///
/// <picture><source srcset="preferences-page-dark.png" media="(prefers-color-scheme: dark)"><img src="preferences-page.png" alt="preferences-page"></picture>
///

View File

@ -2,7 +2,7 @@
// PreferencesRow.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw
@ -10,7 +10,7 @@ import LevenshteinTransformations
/// A [class@Gtk.ListBoxRow] used to present preferences.
///
/// The `AdwPreferencesRow` widget has a title that [class@PreferencesWindow]
/// The `AdwPreferencesRow` widget has a title that [class@PreferencesDialog]
/// will use to let the user look for a preference. It doesn't present the title
/// in any way and lets you present the preference as you please.
///

View File

@ -2,7 +2,7 @@
// ProgressBar.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -2,7 +2,7 @@
// ScrolledWindow.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -2,7 +2,7 @@
// SearchBar.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -2,7 +2,7 @@
// SearchEntry.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -2,7 +2,7 @@
// SpinRow.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -2,7 +2,7 @@
// Spinner.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -2,7 +2,7 @@
// SplitButton.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -2,7 +2,7 @@
// StatusPage.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -2,7 +2,7 @@
// SwitchRow.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -2,7 +2,7 @@
// ToastOverlay.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -2,7 +2,7 @@
// ToggleButton.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -2,7 +2,7 @@
// ToolbarView.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -2,7 +2,7 @@
// WindowTitle.swift
// Adwaita
//
// Created by auto-generation on 17.02.24.
// Created by auto-generation on 20.03.24.
//
import CAdw

View File

@ -254,7 +254,11 @@ struct GenerationConfiguration {
),
excludeProperties: ["selection-mode", "orientation"]
),
.init(class: "SearchEntry", bindings: [.init(property: "text")]),
.init(
class: "SearchEntry",
bindings: [.init(property: "text")],
excludeProperties: ["input-hints", "input-purpose"]
),
.init(class: "SearchBar")
]

View File

@ -24,11 +24,6 @@ struct Demo: App {
.icon(.default(icon: .applicationXExecutable))
.website(.init(string: "https://david-swift.gitbook.io/adwaita"))
.issues(.init(string: "https://github.com/AparokshaUI/adwaita-swift/issues"))
Window(id: "overlay", open: 0) { window in
OverlayWindowDemo.WindowContent(window: window)
}
.keyboardShortcut("Escape") { $0.close() }
.defaultSize(width: 300, height: 200)
}
HelperWindows()
}

37
Tests/DialogDemo.swift Normal file
View File

@ -0,0 +1,37 @@
//
// DialogDemo.swift
// Adwaita
//
// Created by david-swift on 20.13.24.
//
// swiftlint:disable missing_docs
import Adwaita
struct DialogDemo: View {
@State private var dialog = false
let padding = 20
var view: Body {
VStack {
Button("Show Dialog") {
dialog = true
}
.style("pill")
.frame(maxSize: 100)
.padding()
}
.dialog(visible: $dialog, title: "Counter") {
CounterDemo()
.padding(padding)
.topToolbar {
HeaderBar.empty()
}
}
}
}
// swiftlint:enable missing_docs

View File

@ -1,51 +0,0 @@
//
// OverlayWindowDemo.swift
// Adwaita
//
// Created by david-swift on 09.11.23.
//
// swiftlint:disable missing_docs implicitly_unwrapped_optional
import Adwaita
struct OverlayWindowDemo: View {
var app: GTUIApp!
var window: GTUIApplicationWindow
var view: Body {
VStack {
Button("Show Window") {
app.addWindow("overlay", parent: window)
}
.style("pill")
.frame(maxSize: 100)
.padding()
}
}
struct WindowContent: View {
var window: GTUIWindow
var view: Body {
VStack {
Button("Close Window") {
window.close()
}
.style("pill")
.padding()
.frame(maxSize: 100)
}
.valign(.center)
.topToolbar {
HeaderBar.empty()
}
}
}
}
// swiftlint:enable missing_docs implicitly_unwrapped_optional

View File

@ -17,7 +17,7 @@ enum Page: String, Identifiable, CaseIterable, Codable {
case toolbar
case transition
case dice
case overlayWindow
case dialog
case toast
case list
case carousel
@ -33,8 +33,6 @@ enum Page: String, Identifiable, CaseIterable, Codable {
var label: String {
switch self {
case .overlayWindow:
return "Overlay Window"
case .viewSwitcher:
return "View Switcher"
case .flowBox:
@ -58,35 +56,35 @@ enum Page: String, Identifiable, CaseIterable, Codable {
var description: String {
switch self {
case .welcome:
return "This is a collection of examples for the Swift Adwaita package."
return "This is a collection of examples for the Swift Adwaita package"
case .counter:
return "A simple sample view."
return "A simple sample view"
case .windows:
return "Showcase window management."
return "Showcase window management"
case .toolbar:
return "Toggle the bottom toolbar."
return "Toggle the bottom toolbar"
case .transition:
return "A slide transition between two views."
return "A slide transition between two views"
case .dice:
return "Roll the dice."
case .overlayWindow:
return "A window on top of another window."
return "Roll the dice"
case .dialog:
return "A window on top of another window"
case .toast:
return "Show a notification inside of your app."
return "Show a notification inside of your app"
case .list:
return "Organize content in multiple rows."
return "Organize content in multiple rows"
case .carousel:
return "Scroll horizontally on a touchpad or touchscreen, or scroll down on your mouse wheel."
return "Scroll horizontally on a touchpad or touchscreen, or scroll down on your mouse wheel"
case .viewSwitcher:
return "Switch the window's view."
return "Switch the window's view"
case .form:
return "Group controls used for data entry."
return "Group controls used for data entry"
case .popover:
return "Present content in a bubble-like context popup."
return "Present content in a bubble-like context popup"
case .flowBox:
return "Display views in a reflowing grid."
return "Display views in a reflowing grid"
case .navigationView:
return "A page-based navigation container."
return "A page-based navigation container"
}
}
@ -106,8 +104,8 @@ enum Page: String, Identifiable, CaseIterable, Codable {
TransitionDemo()
case .dice:
DiceDemo()
case .overlayWindow:
OverlayWindowDemo(app: app, window: window)
case .dialog:
DialogDemo()
case .toast:
ToastDemo(toast: toast)
case .list:

View File

@ -51,6 +51,7 @@ There are many more widgets available using auto-generation. Learn [how to use t
| `focus(_:)` | Bind a signal that focuses the view. |
| `verticalCenter()` | Wrap a view in a `VStack` and center vertically. |
| `horizontalCenter()` | Wrap a view in an `HStack` and center horizontally. |
| `dialog(visible:title:content:)` | Add a dialog to the window containing the view. |
### `Button` Modifiers
| Syntax | Description |