Spatial SwiftUI: Window Ornaments
Ornaments allow us to decorate our windows with information and controls that may not fit in the main window region.
Overview
We can add a simple ornament to our windows like so.
{...} // root view
.ornament(attachmentAnchor: .scene(.topLeading)) {
Text("Ornament")
.padding(20)
.cornerRadius(20)
}This will create a text view that is anchored to the top leading area of the window. Anchors in this context refer to UnitPoint values. We can use one of the pre-built properties (.top, .center .leading, etc.). We can also specify an X and Y value if we need a custom position.
We can control ornament visibility if we need to show and hide these. This will only show when ourState is true.
{...} // root view
.ornament(visibility: ourState, attachmentAnchor: .scene(.topLeading)) {
Text("Ornament")
.padding(20)
.cornerRadius(20)
}We can set the alignment of the view on the anchor as well.
{...} // root view
.ornament(visibility: ourState, attachmentAnchor: .scene(ourAnchor), contentAlignment: ourAlignment) {
Text("Ornament")
.padding(20)
.cornerRadius(20)
}Later–in the labs–we will combine ornament with rotation and transforms to create more advanced layouts.
Video Demo
Full Example Code
Please excuse my repetitive code…
struct Example037: View {
@State var ornamentVisibility: Visibility = .hidden
@State var ornamentAnchor: UnitPoint = .top
@State var ornamentAlignment: Alignment = .center
// convenience functions so I don't have to repeat "withAnimation" in every button
func setAnchor(_ newAnchor: UnitPoint) {
withAnimation {
ornamentAnchor = newAnchor
}
}
func setAlignment(_ newAlignment: Alignment) {
withAnimation {
ornamentAlignment = newAlignment
}
}
var body: some View {
ZStack {
VStack(spacing: 20) {
Button{
withAnimation {
ornamentVisibility = ornamentVisibility == .visible ? .hidden : .visible
}
} label: {
Text("Toggle Ornament")
}
Spacer()
HStack(spacing: 40) {
// Anchor buttons
VStack {
Text("Anchor")
HStack(alignment: .center) {
Button{
setAnchor(.topLeading)
} label: {
Image(systemName: "arrow.up.left")
}
Button{
setAnchor(.top)
} label: {
Image(systemName: "arrow.up")
}
Button{
setAnchor(.topTrailing)
} label: {
Image(systemName: "arrow.up.right")
}
}
HStack(alignment: .center) {
Button{
setAnchor(.leading)
} label: {
Image(systemName: "arrow.left")
}
Button{
setAnchor(.center)
} label: {
Image(systemName: "square")
}
Button{
setAnchor(.trailing)
} label: {
Image(systemName: "arrow.right")
}
}
HStack(alignment: .center) {
Button{
setAnchor(.bottomLeading)
} label: {
Image(systemName: "arrow.down.left")
}
Button{
setAnchor(.bottom)
} label: {
Image(systemName: "arrow.down")
}
Button{
setAnchor(.bottomTrailing)
} label: {
Image(systemName: "arrow.down.right")
}
}
}
// Alignment buttons
VStack {
Text("Alignment")
HStack(alignment: .center) {
Button{
setAlignment(.topLeading)
} label: {
Image(systemName: "arrow.up.left")
}
Button{
setAlignment(.top)
} label: {
Image(systemName: "arrow.up")
}
Button{
setAlignment(.topTrailing)
} label: {
Image(systemName: "arrow.up.right")
}
}
HStack(alignment: .center) {
Button{
setAlignment(.leading)
} label: {
Image(systemName: "arrow.left")
}
Button{
setAlignment(.center)
} label: {
Image(systemName: "square")
}
Button{
setAlignment(.trailing)
} label: {
Image(systemName: "arrow.right")
}
}
HStack(alignment: .center) {
Button{
setAlignment(.bottomLeading)
} label: {
Image(systemName: "arrow.down.left")
}
Button{
setAlignment(.bottom)
} label: {
Image(systemName: "arrow.down")
}
Button{
setAlignment(.bottomTrailing)
} label: {
Image(systemName: "arrow.down.right")
}
}
}
}
}
.padding(100)
.ornament(
visibility: ornamentVisibility,
attachmentAnchor: .scene(ornamentAnchor),
contentAlignment: ornamentAlignment
) {
Text("Ornament")
.padding(20)
.background(.stepBlue)
.cornerRadius(20)
}
}
}
}Support our work so we can continue to bring you new examples and articles.

Follow Step Into Vision