Appearance
控件组件和修饰符
控件可用的组件和修饰符。
文本
typescript
Text("Hello, World!")
Text(`${entry.name}: ${entry.value}`)文本修饰符
typescript
const t = Text("Styled");
t.font("title"); // .title, .headline, .body, .caption, etc.
t.color("blue"); // Named color or hex
t.bold();布局
VStack
typescript
VStack([
Text("Top"),
Text("Bottom"),
])HStack
typescript
HStack([
Text("Left"),
Spacer(),
Text("Right"),
])ZStack
typescript
ZStack([
Image("background"),
Text("Overlay"),
])Spacer
Flexible space that expands to fill available room:
typescript
HStack([
Text("Left"),
Spacer(),
Text("Right"),
])Image
Display SF Symbols or asset images:
typescript
Image("star.fill") // SF Symbol
Image("cloud.sun.rain.fill") // SF SymbolForEach
Iterate over array entry fields to render a list of components:
typescript
ForEach(entry.items, (item) =>
HStack([
Text(item.name),
Spacer(),
Text(`${item.value}`),
])
)Divider
A visual separator line:
typescript
VStack([
Text("Above"),
Divider(),
Text("Below"),
])Label
A label with text and an SF Symbol icon:
typescript
Label("Downloads", "arrow.down.circle")
Label(`${entry.count} items`, "folder.fill")Gauge
A circular or linear progress indicator:
typescript
Gauge(entry.progress, 0, 100) // value, min, max
Gauge(entry.battery, 0, 1.0)Modifiers
Widget components support SwiftUI-style modifiers:
Font
typescript
Text("Title").font("title")
Text("Body").font("body")
Text("Caption").font("caption")Color
typescript
Text("Red text").color("red")
Text("Custom").color("#FF6600")Padding
typescript
VStack([...]).padding(16)Frame
typescript
widget.frame(width, height)Max Width
typescript
widget.maxWidth("infinity") // Expand to fill available widthMinimum Scale Factor
Allow text to shrink to fit:
typescript
Text("Long text").minimumScaleFactor(0.5)Container Background
Set background color for the widget container:
typescript
VStack([...]).containerBackground("blue")Widget URL
Make the widget tappable with a deep link:
typescript
VStack([...]).url("myapp://detail/123")Edge-Specific Padding
Apply padding to specific edges:
typescript
VStack([...]).paddingEdge("top", 8)
VStack([...]).paddingEdge("horizontal", 16)Conditionals
Render different components based on entry data:
typescript
render: (entry) =>
VStack([
entry.isOnline
? Text("Online").color("green")
: Text("Offline").color("red"),
]),Complete Example
typescript
import { Widget, Text, VStack, HStack, Image, Spacer } from "perry/widget";
Widget({
kind: "StatsWidget",
displayName: "Stats",
description: "Shows daily stats",
entryFields: {
steps: "number",
calories: "number",
distance: "string",
},
render: (entry) =>
VStack([
HStack([
Image("figure.walk"),
Text("Daily Stats").font("headline"),
]),
Spacer(),
HStack([
VStack([
Text(`${entry.steps}`).font("title").bold(),
Text("steps").font("caption").color("gray"),
]),
Spacer(),
VStack([
Text(`${entry.calories}`).font("title").bold(),
Text("cal").font("caption").color("gray"),
]),
Spacer(),
VStack([
Text(entry.distance).font("title").bold(),
Text("km").font("caption").color("gray"),
]),
]),
]).padding(16),
});Next Steps
- Creating Widgets — Widget() API
- Overview — Widget system overview