Settings panes

Your droplet's own page inside Droppy's Settings.

A droplet with anything to configure provides a settings pane. It is rendered on the droplet's page in Droppy's Settings window, in the same content column every native page uses.

Build it from the SDK's settings components and it matches the rest of the app — including after Droppy's styling moves, because those components are kept in step with the host.

Providing one

extension WorldClockDroplet: SettingsPaneProviding {
    public func makeSettingsPane(context: SettingsPaneContext) -> AnyView {
        AnyView(WorldClockSettings(droplet: self))
    }

    public var settingsSearchEntries: [SettingsSearchEntry] {
        [SettingsSearchEntry(title: "Show seconds", keywords: ["time", "clock"])]
    }
}

settingsSearchEntries puts your rows in Droppy's Settings search, so a user who types "seconds" lands on your pane instead of failing to find it.

The components

VStack(alignment: .leading, spacing: DroppySpacing.lg) {
    DropletSettingsCard {
        DropletToggleRow(
            title: "Show seconds",
            subtitle: "Ticks the shelf widget every second instead of every minute.",
            isOn: droplet.showsSecondsBinding
        )
        DropletSettingsDivider()
        DropletSliderRow(
            title: "Refresh",
            value: "\(Int(interval))s",
            binding: $interval,
            range: 1...60
        )
        DropletSettingsDivider()
        DropletControlRow(title: "Clocks") {
            DropletValuePill(text: "\(droplet.clockCount)")
        }
    }
}
ComponentFor
DropletSettingsCardThe card every group of rows sits in
DropletControlRowA title with a trailing control
DropletToggleRowA switch
DropletSliderRowA value with a slider
DropletStackedRowA title over full-width content
DropletGroupedPickerRowA segmented picker inside a card
DropletSettingsDividerThe hairline between rows
DropletValuePillA read-only value

Sentence case

Section headers and row titles are sentence case: only the first word is capitalised, and proper nouns keep their capitals wherever they appear. Droppy enforces this on its own pages, and a droplet in Title Case is visibly a guest.

Picker rows sit in a group

DropletGroupedPickerRow takes a SettingsGroupPosition describing where it sits in its card — .only, .top, .middle, or .bottom. Pass the right one: the selected segment's highlight rounds its outer corners to match, and a .bottom picker with a divider and another row beneath it renders a curve against a straight edge.

Storage

Rows bind to DropletPreferencesService, which namespaces every key to your droplet:

var showsSecondsBinding: Binding<Bool> {
    Binding(
        get: { self.host?.preferences.value(forKey: "showsSeconds", default: true) ?? true },
        set: { self.host?.preferences.setValue($0, forKey: "showsSeconds") }
    )
}

See also