Skip to content

feat(ui): expose textSetTextAlignment API for Text widget #3621

@lzxb

Description

@lzxb

Summary

Perry's Text widget currently has no way to set horizontal text alignment (equivalent to CSS text-align). The underlying platform APIs all support this, but Perry doesn't expose it.

Evidence

All three platforms have the capability but none is wired to a user-callable FFI function:

Platform Underlying API Used internally? Exposed to user?
macOS NSTextField.setAlignment: ✅ toast.rs, chart.rs, bottom_nav.rs
iOS UILabel.setTextAlignment: ✅ toast.rs
Android TextView.setGravity(Gravity.CENTER_HORIZONTAL) ✅ image.rs, qrcode.rs

Verified by inspecting:

  • crates/perry-ui-macos/src/lib_ffi/core_widgets.rs — all perry_ui_text_set_* functions listed, no alignment
  • crates/perry-ui-ios/src/ffi/widgets_basic.rs — same
  • crates/perry-ui-android/src/ — same

Proposed API

// perry/ui type declaration
export function textSetTextAlignment(widget: Widget, alignment: number): void;

Alignment values (follow NSTextAlignment / UITextAlignment conventions):

  • 0 = left
  • 1 = right
  • 2 = center
  • 4 = natural (follows locale direction)

Current Workaround

Without this API, centering text requires wrapping in an extra container:

// Workaround: wrap Text in a VStack with CenterX alignment
function centeredText(content: string, parentWidth: number): Widget {
    const t = Text(content);
    const col = VStack(0, [t]);
    stackSetAlignment(col, 9);        // NSLayoutAttribute.centerX
    widgetSetWidth(col, parentWidth); // required reference width
    return col;
}

This adds an extra layout layer for what should be a single property.

Implementation Notes

The pattern already exists in the codebase — Perry uses setTextAlignment internally. Adding the public binding would follow the same 3-step pattern as other text setters:

  1. Rust impl (crates/perry-ui-macos/src/lib_ffi/core_widgets.rs):
#[no_mangle]
pub extern "C" fn perry_ui_text_set_text_alignment(handle: i64, alignment: i64) {
    if let Some(view) = get_widget(handle) {
        unsafe { let _: () = msg_send![&*view, setAlignment: alignment]; }
    }
}
  1. Dispatch table (crates/perry-dispatch/src/ui_table.rs): add a MethodRow entry

  2. JS codegen (crates/perry-codegen-js/src/emit/calls.rs): add the method name → runtime symbol mapping

Android would use setGravity with the appropriate gravity flags for horizontal alignment.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions