Widgets
Perry provides native widgets that map to each platform’s native controls.
Text
Displays read-only text.
import { Text } from "perry/ui";
const label = Text("Hello, World!");
label.setFontSize(18);
label.setColor("#333333");
label.setFontFamily("Menlo");
Methods:
setText(text: string)— Update the text contentsetFontSize(size: number)— Set font size in pointssetColor(hex: string)— Set text color (hex string)setFontFamily(family: string)— Set font family (e.g.,"Menlo"for monospaced)setAccessibilityLabel(label: string)— Set accessibility label
Text widgets inside template literals with State.get() update automatically:
const count = State(0);
Text(`Count: ${count.get()}`); // Updates when count changes
Button
A clickable button.
import { Button } from "perry/ui";
const btn = Button("Click Me", () => {
console.log("Clicked!");
});
btn.setCornerRadius(8);
btn.setBackgroundColor("#007AFF");
Methods:
setOnClick(callback: () => void)— Set click handlersetImage(sfSymbolName: string)— Set SF Symbol icon (macOS/iOS)setContentTintColor(hex: string)— Set tint colorsetImagePosition(position: number)— Set image position relative to textsetEnabled(enabled: boolean)— Enable/disable the buttonsetAccessibilityLabel(label: string)— Set accessibility label
TextField
An editable text input.
import { TextField, State } from "perry/ui";
const text = State("");
const field = TextField(text, "Placeholder...");
TextField takes a State for two-way binding — the state updates as the user types, and setting the state updates the field.
Methods:
setText(text: string)— Set the text programmaticallysetPlaceholder(text: string)— Set placeholder textsetEnabled(enabled: boolean)— Enable/disable editing
SecureField
A password input field (text is masked).
import { SecureField, State } from "perry/ui";
const password = State("");
SecureField(password, "Enter password...");
Same API as TextField but input is hidden.
Toggle
A boolean on/off switch.
import { Toggle, State } from "perry/ui";
const enabled = State(false);
Toggle("Enable notifications", enabled);
The State is bound two-way — toggling updates the state, and setting the state updates the toggle.
Slider
A numeric slider.
import { Slider, State } from "perry/ui";
const value = State(50);
Slider(value, 0, 100); // state, min, max
Picker
A dropdown selection control.
import { Picker, State } from "perry/ui";
const selected = State(0);
Picker(["Option A", "Option B", "Option C"], selected);
Image
Displays an image.
import { Image } from "perry/ui";
const img = Image("path/to/image.png");
img.setWidth(200);
img.setHeight(150);
On macOS/iOS, you can also use SF Symbol names:
Image("star.fill"); // SF Symbol
ProgressView
An indeterminate or determinate progress indicator.
import { ProgressView } from "perry/ui";
const progress = ProgressView();
// Or with a value (0.0 to 1.0)
const progress = ProgressView(0.5);
Form and Section
Group controls into a form layout.
import { Form, Section, TextField, Toggle, State } from "perry/ui";
const name = State("");
const notifications = State(true);
Form([
Section("Personal Info", [
TextField(name, "Name"),
]),
Section("Settings", [
Toggle("Notifications", notifications),
]),
]);
Table
A data table with rows and columns.
import { Table } from "perry/ui";
const table = Table(10, 3, (row, col) => {
return `Cell ${row},${col}`;
});
table.setColumnHeader(0, "Name");
table.setColumnHeader(1, "Email");
table.setColumnHeader(2, "Role");
table.setColumnWidth(0, 200);
table.setColumnWidth(1, 250);
table.setOnRowSelect((row) => {
console.log(`Selected row: ${row}`);
});
Methods:
setColumnHeader(col: number, title: string)— Set column header textsetColumnWidth(col: number, width: number)— Set column widthupdateRowCount(count: number)— Update the number of rowssetOnRowSelect(callback: (row: number) => void)— Row selection handlergetSelectedRow()— Get currently selected row index
TextArea
A multi-line text input.
import { TextArea, State } from "perry/ui";
const content = State("");
TextArea(content, "Enter text...");
Methods:
setText(text: string)— Set the text programmaticallygetText()— Get the current text
QRCode
Generates and displays a QR code.
import { QRCode } from "perry/ui";
const qr = QRCode("https://example.com", 200); // data, size
qr.setData("https://other-url.com"); // Update data
Canvas
A drawing surface. See Canvas for the full drawing API.
import { Canvas } from "perry/ui";
const canvas = Canvas(400, 300, (ctx) => {
ctx.fillRect(10, 10, 100, 100);
ctx.strokeRect(50, 50, 100, 100);
});
Common Widget Methods
All widgets support these methods:
| Method | Description |
|---|---|
setWidth(width) | Set width |
setHeight(height) | Set height |
setBackgroundColor(hex) | Set background color |
setCornerRadius(radius) | Set corner radius |
setOpacity(alpha) | Set opacity (0.0–1.0) |
setEnabled(enabled) | Enable/disable interaction |
setHidden(hidden) | Show/hide widget |
setTooltip(text) | Set tooltip text |
setOnClick(callback) | Set click handler |
setOnHover(callback) | Set hover handler |
setOnDoubleClick(callback) | Set double-click handler |
See Styling and Events for complete details.
Next Steps
- Layout — Arranging widgets with stacks and containers
- Styling — Colors, fonts, borders
- State Management — Reactive bindings