Capsule
Capsule shape.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// Usage for component capsule
//
$render(
<vstack frame="max">
<capsule frame="50,30" color="blue"></capsule>
</vstack>
);
Browse every JSX component mapped to SwiftUI with runnable examples.
Capsule shape.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// Usage for component capsule
//
$render(
<vstack frame="max">
<capsule frame="50,30" color="blue"></capsule>
</vstack>
);
Ellipse shape.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// Usage for component ellipse
//
$render(
<vstack frame="max">
<ellipse frame="50,30" color="blue"></ellipse>
</vstack>
);
Circular progress ring.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// component: ring
//
$render(
<vstack frame="max" padding="12">
<ring value="0.68" thickness="10" color="#22c55e" trackColor="#e2e8f0" frame="72" />
</vstack>
);
Rounded rectangle block shape.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// component: roundedrect
//
$render(
<vstack frame="max" padding="12">
<roundedrect radius="12" color="#38bdf8" frame="140,60" />
</vstack>
);
Compact pill for status tags.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// component: badge
//
$render(
<vstack frame="max" padding="12" spacing="8">
<badge text="PRO" background="#22c55e" color="#ffffff" />
<badge text="BETA" background="#0f172a" color="#e2e8f0" />
</vstack>
);
Outlined tag with optional border color.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// component: chip
//
$render(
<hstack frame="max" padding="12" spacing="8">
<chip text="Today" />
<chip text="Focus" borderColor="#38bdf8" color="#0f172a" />
</hstack>
);
Horizontal stack layout.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// Usage for component hstack
//
$render(
<hstack>
<text>First</text>
<text>Second</text>
</hstack>
);
SF Symbol icon with size and color.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// component: icon
//
$render(
<hstack frame="max" padding="12" spacing="12">
<icon systemName="bolt.fill" size="24" color="#fbbf24" />
<icon systemName="moon.stars.fill" size="24" color="#6366f1" />
</hstack>
);
Text with SF Symbol icon.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// component: label
//
$render(
<vstack frame="max" padding="12" spacing="8">
<label title="Sunrise" systemName="sunrise.fill" color="#f59e0b" />
<label title="Battery" systemName="battery.100" color="#22c55e" />
</vstack>
);
Rectangle shape.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// Usage for component rect
//
$render(
<vstack frame="max">
<rect frame="50,30" color="blue"></rect>
<rect frame="50,30" color="blue" corner="5"></rect>
</vstack>
);
Metric display with title/value/subtitle.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// component: stat
//
$render(
<hstack frame="max" padding="12" spacing="16">
<stat title="Downloads" value="12.4k" subtitle="Today" color="#0f172a" />
<stat title="Streak" value="18" subtitle="Days" color="#22c55e" />
</hstack>
);
Vertical stack layout.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// Usage for component vstack
//
$render(
<vstack>
<text>First</text>
<text>Second</text>
</vstack>
);
Overlay layout.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// Usage for component vstack
//
$render(
<zstack>
<text>First</text>
<text>Second</text>
</zstack>
);
Horizontal or vertical separator line.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// component: divider
//
$render(
<vstack frame="max" padding="12">
<text font="caption">Section A</text>
<divider thickness="1" color="#94a3b8" />
<text font="caption">Section B</text>
</vstack>
);
Animated GIF (iOS only).
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// Shape Template
//
// Description: Shape Example
//
$render(
<vstack>
<gif file="test" />
</vstack>
);
Linear or circular progress indicator.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// component: progress
//
$render(
<vstack frame="max" padding="12">
<text font="caption">Loading</text>
<progress value="0.72" total="1" color="#3b82f6" />
<progress value="0.45" total="1" style="circular" color="#10b981" frame="32" />
</vstack>
);
Circle shape.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// Usage for component circle
//
$render(
<hstack frame="max">
<circle frame="40,40" color="blue"></circle>
<circle frame="40,40" color="blue" stroke="10"></circle>
<circle frame="40,40" color="blue" stroke="10" trim="0.2"></circle>
<circle frame="40,40" color="blue" stroke="10" trim="0.2" rotation="90"></circle>
</hstack>
);
Date rendering with formatting options.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// Usage for component date
//
$render(
<vstack>
<date font="caption" date="now" style="time" />
<date font="caption" date="now" style="date" />
<date font="caption" date="start of today" style="timer" />
<date font="title" date={Date.now()} style="timer" />
</vstack>
);
Fixed-length line segment.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// component: line
//
$render(
<vstack frame="max" padding="12" spacing="8">
<line length="120" thickness="2" color="#94a3b8" />
<hstack spacing="8">
<line axis="vertical" length="24" thickness="2" color="#f59e0b" />
<text font="caption">Vertical line</text>
</hstack>
</vstack>
);
Group multiple children without wrapper.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
//
var aaa = (
<>
<text>a text</text>
<text>a text</text>
</>
)
$render(
<vstack frame="max">
{aaa}
<text>a text</text>
</vstack>
);
Gauge visualization for numeric values.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// Usage for component guage
//
$render(
<vstack frame="max">
<gauge
type="system"
value="0.6"
text="hello"
style="circular" // default
>
</gauge>
</vstack>
);
Text rendering with font/color modifiers.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// Usage for component text
//
$render(
<vstack frame="max">
<text font="title">Hello ScriptWidget</text>
<text font="caption" color="red">
Hello ScriptWidget
</text>
<text font="caption" background="blue" color="white">
Hello ScriptWidget
</text>
</vstack>
);
Toggle control for boolean state.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// Usage for component capsule
//
const onToggleClick = () => {
console.log("toggle tapped");
}
const widget_size = $getenv("widget-size");
const value = Math.random() >= 0.5;
$render(
<vstack frame="max">
<toggle on={value} onClick="onToggleClick">
<image systemName="mosaic.fill" />
<text>{widget_size}</text>
</toggle>
</vstack>
);
Tap action via AppIntent. Use action="reload" to refresh the widget.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// Usage for component button
//
const onButtonClick = () => {
console.log("button tapped");
};
const widget_size = $getenv("widget-size");
$render(
<vstack frame="max">
<button onClick="onButtonClick">
<image systemName="mosaic.fill" />
<text>{widget_size}</text>
</button>
<button action="reload">
<text>Refresh Widget</text>
</button>
</vstack>
);
Image from asset, URL, or base64 data.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// Usage for component image
//
/*
<image />
<image systemName="mosaic.fill" />
<image id="image0" />
<image id="image" mode="fit" ratio="0.6" />
<image id="image" mode="fill" frame="260,60" />
<image id="image" mode="fill" clip frame="200,100"/>
<image id="image" mode="fill" clip="rect" frame="200,100"/>
<image id="image" mode="fill" clip="ellipse" frame="200,100"/>
<image id="image" mode="fill" clip="circle" frame="200,100"/>
<image id="image" mode="fill" clip="capsule" frame="200,100"/>
<image id="image" mode="fill" corner="30" frame="200,100"/>
*/
$render(
<vstack>
<image url="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" frame="20,20"/>
<image id="image" frame="260,60"/>
</vstack>
);
Open URLs or app scheme links.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// Usage for component link
//
$render(
<vstack frame="max" linkurl="https://xnu.app/scriptwidget">
<link url="https://www.baidu.com" background="blue">
<text font="title">Hello Baidu</text>
</link>
<link url="https://www.google.com" background="green">
<hstack>
<text>Hello</text>
<text>Google</text>
</hstack>
</link>
<link url="https://www.bing.com" background="yellow">
<vstack>
<text>Hello</text>
<text>Bing</text>
</vstack>
</link>
</vstack>
);
Dynamic Island / Live Activity layouts.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// Usage for component Live Activity and Dynamic Island
//
// $render is also for lock screen live activity
$render(
<vstack frame="max">
<text>hello live activity</text>
</vstack>
);
// $dynamic_island is for dynamic island
// on iPhone 14 Pro/ProMax and iOS16.1+
$dynamic_island({
expanded: { // expanded is required , at least one of the four child below is required
leading: <text>leading</text>,
trailing: <text>trailing</text>,
center: <text>center</text>,
bottom: <text>bottom</text>,
},
compactLeading: <text>compactLeading</text>, // required
compactTrailing: <text>compactTrailing</text>, // required
minimal: <text>minimal</text>, // required
});
Chart visualization with sections.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// Usage for component chart
//
let data = [
{ label: "jan/22", value: 5 },
{ label: "feb/22", value: 4 },
{ label: "mar/22", value: 7 },
{ label: "apr/22", value: 15 },
{ label: "may/22", value: 14 },
{ label: "jun/22", value: 27 },
{ label: "jul/22", value: 27 },
]
$render(
<vstack frame="max">
<chart
type="bar" // required
data={$json(data)} // required
color="red" // optional , default black
padding="20" // optional , general
// hideLegend="true"
// hideXAxis="true"
// hideYAxis="true"
>
</chart>
</vstack>
);
Frame and sizing attributes.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// Usage for component attribute frame
//
/*
frame="max"
frame="max,topLeading"
frame="10,20"
frame="10,20,topLeading"
frame="max,20"
frame="10,max"
frame="max,20,topLeading"
frame="10,max,topLeading"
the "topLeading" represent alignment, could be one of the values below:
"center"
"leading"
"trailing"
"top"
"bottom"
"topLeading"
"topTrailing"
"bottomLeading"
"bottomTrailing"
*/
$render(
<vstack frame="max">
<rect frame="50,30" color="green"></rect>
<rect frame="50,30" color="blue" corner="5"></rect>
</vstack>
);
Horizontal grid layout.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// grid component
//
/*
iOS
{ type: "adaptive", min: "30"},
{ type: "fixed", value: "30"},
{ type: "flexible"},
macOS
{ type: "adaptive", min: "30", max: "100"},
{ type: "fixed", value: "30"},
{ type: "flexible"},
*/
// {} will default to { type: "flexible"},
// let columns = [
// {},
// {},
// {},
// {},
// ]
// let columns = [
// { type: "fixed", value: "30"},
// { type: "fixed", value: "30"},
// { type: "fixed", value: "30"},
// ]
let columns = [
{ type: "adaptive", min: "70", max: "100"},
]
$render(
<vstack frame="max">
<hgrid columns={$json(columns)}>
<circle color="red"/>
<circle color="red"/>
<circle color="red"/>
<circle color="red"/>
<circle color="red"/>
<circle color="red"/>
<circle color="red"/>
<circle color="red"/>
<circle color="red"/>
</hgrid>
</vstack>
);
Vertical grid layout.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// grid component
//
/*
iOS
{ type: "adaptive", min: "30"},
{ type: "fixed", value: "30"},
{ type: "flexible"},
macOS
{ type: "adaptive", min: "30", max: "100"},
{ type: "fixed", value: "30"},
{ type: "flexible"},
*/
// {} will default to { type: "flexible"},
// let columns = [
// {},
// {},
// {},
// {},
// ]
// let columns = [
// { type: "fixed", value: "30"},
// { type: "fixed", value: "30"},
// { type: "fixed", value: "30"},
// ]
let columns = [
{ type: "adaptive", min: "70", max: "100"},
]
$render(
<vstack frame="max">
<vgrid columns={$json(columns)}>
<circle color="red"/>
<circle color="red"/>
<circle color="red"/>
<circle color="red"/>
<circle color="red"/>
<circle color="red"/>
<circle color="red"/>
<circle color="red"/>
<circle color="red"/>
</vgrid>
</vstack>
);
Define reusable JSX components with $component.
//
// ScriptWidget
// https://xnu.app/scriptwidget
//
// Custom Component
// Thanks for Reina for telling me this good idea
//
// Custom component is a JavaScript function
// with one parameter composed with : prop1,prop2... and children
// As a convention,
// the first letter of custom component's name must be uppercase.
// For example : LeftAlign , MyCustomComponent ... etc...
// prototype:
// 1. new style
// const MyComponent = ({prop1, prop2, children}) => { /* ... */ }
//
// 2. old style
// const MyComponent = (props) => {
// let prop1 = props.prop1;
// let prop2 = props.prop2;
// let children = props.children;
// }
const LeftAlign = ({ message, children }) => {
return (
<hstack>
{children}
<text> ({message}) </text>
<spacer />
</hstack>
)
}
const RightAlign = ({ message, children }) => {
return (
<hstack>
<spacer />
<text> ({message}) </text>
{children}
</hstack>
)
}
$render(
<vstack
background="blue"
frame="max,center"
>
<LeftAlign message="L">
<text> this text left aligned</text>
</LeftAlign>
<RightAlign message="R">
<text> text right aligned</text>
</RightAlign>
</vstack>
);