Skip to content

Release 0.6.3

Latest

Choose a tag to compare

@idexus idexus released this 14 Oct 17:11
Immutable release. Only release title and notes can be modified.
bf1d51c

StateUI 0.6.3 gathers 0.6.1, 0.6.2 and 0.6.3 since 0.6.0.

Highlights

  • Button roles. Button("Delete").role(.destructive) draws as the platform marks it; Style<Button>(role:) styles a role once for the whole application.
  • The platform's own look. .style(.platform) keeps a control native under an application's styles.
  • Icons by meaning. Image(.icon(.share)) and Button("Share").icon(.icon(.share)) show the platform's own icon - SF Symbols on Apple's platforms, Material Symbols on Android, Segoe Fluent Icons on WinUI, the theme's symbolic icons on GTK - in the colour of what holds it. ImageSource(bytes:) shows a PNG or a JPEG the application makes.
  • The capsule, and a shape's fill first. Capsule(.teal) is a pill whose ends stay round at every size; Rectangle, Ellipse and Capsule take their fill - a colour, a gradient, a colour's state - in their initializer.
  • Keyboard. keyboardShortcut(_:modifiers:) on buttons and menu entries, onKeyPressed on a view holding the keyboard, submitLabel(.next) to move between fields.
  • Menus. menu { } opens a menu from a button; menu(.split) { } splits the arrow from the click; MenuItem(...).isOn(_:) checks an entry.
  • Pickers. Picker(items, selection: $choice) over any Equatable items, as a menu, segments or radio buttons.
  • Localization in typed Swift resources, and dialogs in the system's language.
  • What the platform honours. device.honours(PickerContract.isOpen) lets an application offer only what its platform does.
  • Every view takes a tooltip(_:); Text.isSelectable(true); showsTitle(false); Divider in stacks.
HStack {
    Capsule(.teal).width(120).height(32)
    Rectangle(.cornflowerBlue).cornerRadius(8).width(32).height(32)
    Ellipse(.linearGradient([GradientStop(.gold, 0), GradientStop(.tomato, 1)])).width(32).height(32)
}

Breaking changes

struct Order: View {
    // SharedGate is Gatekeeper, kept in a state: the work through it runs one at a time.
    @State private var saving = Gatekeeper(.ignoreWhileRunning)
    @State private var size = "Small"

    var body: some View {
        VStack {
            // ColorBox is gone: a block of colour is a Rectangle.
            Rectangle(.blue).height(4)

            // Picker takes its items and a binding to the chosen one.
            Picker(["Small", "Large"], selection: $size).presentation(.segmented)

            // The save awaits its work: the button stands dimmed while it runs, and a press meanwhile is ignored.
            Button("Save")
                .isEnabled(!saving.isBusy)
                .onClicked(gate: saving) { try await send(size) }
        }
    }

    /// Sends the order - work that takes its time, as a server's answer does.
    private func send(_ size: String) async throws {
        try await Task.sleep(for: .seconds(1))
    }
}

A shape offers only the modifiers it can honour: corners stand on cornered shapes alone.

Hosts

  • Sidebars slide with their detail on every host; frames are reported in the layout pass on AppKit and GTK.
  • Words follow each platform's type ramp; WinUI's largest style is its largest title.
  • WinUI reads every SVG by its file's address - the Gallery's private memory falls from 2.7 GB to under 100 MB - and a tab view with a heading stands its tabs under it.
  • Android icons stand opaque in their words' colour, labels in the theme's primary colour, and a picture shown smaller than it was made keeps its detail.
  • AppKit draws an icon in its words' colour and gives a tall button a bezel as tall as it.

Requirements

The GTK host needs GTK 4.20 or newer (Ubuntu 26.04). The systems and toolchains each host is tested on: docs/tested-setups.md.