Skip to content

macOS setPadding is implemented for only 4 widget classes and silently no-ops on the rest (Button, labels, etc.) #10159

Description

@steinybot

Summary

On macOS, setPadding (and the deprecated widgetSetEdgeInsets it aliases) is implemented for only four AppKit class families. It silently no-ops on every other widget, including Button and text labels, which the design system needs to pad. A caller has no way to tell that the call did nothing.

Environment

  • Perry 0.5.1531 (local build)
  • macOS, Darwin 25.6.0, arm64
  • Native macOS target (perry-ui-macos)

Cause (confirmed in source)

setPadding and widgetSetEdgeInsets compile to the same FFI, perry_ui_widget_set_edge_insets (crates/perry-codegen/src/lower_call/ui_styling.rs), which calls set_edge_insets in crates/perry-ui-macos/src/widgets/padding.rs. That function branches on four classes only — NSStackView, NSTextField (and only when the widget installed the Perry inset cell), NSTextView, NSScrollView — and then ends. There is no catch-all, so any other widget class falls through and the call is a no-op. Labels install no inset cell (only textfield.rs and securefield.rs do), so an NSTextField label also no-ops.

What works vs what no-ops

Padding works:

Handled class Widgets
NSStackView hstack, vstack, zstack, navstack, bottom_nav, toggle
NSTextField + inset cell textfield, securefield
NSTextView textarea, rich_text
NSScrollView scrollview, image_gallery

Padding no-ops:

Unhandled class Widgets
NSButton button
NSTextField label (no inset cell) text, toast, attributed_text, text_registry
NSImageView image, qrcode
NSDatePicker date_picker, calendar
NSComboBox combobox
NSPopUpButton picker
NSSlider slider
NSProgressIndicator progressview
NSBox divider, form
NSTableView table, lazyvstack, command_palette
NSOutlineView tree_view
plain NSView adbanner, spacer
NSWindow sheet

Impact

Button and text labels are the clear cases: the design system sizes a medium button by its horizontal padding (0 var(--space-5)), and pads label chips. With the no-op, a button cannot be padded, so its width has to be hard-coded. Other controls (slider, progress, spacer) may not need padding, but the silent no-op gives a caller no signal either way.

For comparison, iOS applies button padding — UIButton via configuration.setContentInsets (fallback setContentEdgeInsets) in perry-ui-ios/src/widgets/padding.rs — so this is a macOS-specific gap, not a cross-platform limitation.

Suggested fix

Give the common leaf widgets a real padding path on macOS, starting with the two the design system needs: NSButton (content insets via NSButton.Configuration.contentInsets, or a content wrapper) and NSTextField labels. Where a widget genuinely cannot be padded, consider a debug-time warning rather than a silent no-op so a caller learns the call had no effect.

Related

Scope

macOS target. Every widget whose backing class is not one of the four handled families.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions