iOS 16.4+ iPadOS 16.4+
Shows a placeholder while content is loading.
import SwiftUI struct SkeletonUsageExample : View { var body: some View { HStack ( spacing : FLXSpacing.lg ) { FLXSkeleton () . frame ( width : 48 , height : 48 ) . clipShape ( Circle ()) VStack ( alignment : .leading, spacing : FLXSpacing.sm ) { FLXSkeleton () . frame ( width : 220 , height : 16 ) FLXSkeleton () . frame ( width : 160 , height : 16 ) } } . padding ( FLXSpacing.xl ) } } Show more
Installation
Requires the design system foundation (tokens and theme).
CLI Manual
pnpm dlx shadcn@latest add @swiftui-flx/ios-skeleton
Usage
FLXSkeleton fills the space it's given, so set its size with .frame and its shape with .clipShape.
FLXSkeleton () . frame ( width : 220 , height : 16 )
Card
Compose skeletons in the same layout as the content they stand in for, so nothing moves when it loads.
FLXCard { FLXCardHeader { FLXSkeleton () . frame ( width : 180 , height : 16 ) FLXSkeleton () . frame ( width : 120 , height : 12 ) } FLXCardContent { FLXSkeleton () . frame ( height : 120 ) } } Show more
Redacted
To turn a view you already have into a placeholder, use SwiftUI's .redacted(reason: .placeholder). It replaces text and images with blocks of the same size, so you don't build a second layout. Use .unredacted() on a part that should stay visible.
HStack ( spacing : FLXSpacing.md ) { Image ( systemName : "person.crop.circle.fill" ) . flxFont ( .largeTitle ) VStack ( alignment : .leading ) { Text ( "Olivia Martin" ) . flxFont ( .headline ) Text ( "olivia@example.com" ) . flxFont ( .subheadline ) } } . redacted ( reason : .placeholder )
Accessibility
FLXSkeleton is hidden from VoiceOver, and its pulse stops when Reduce Motion is on. Tell VoiceOver that the area is loading on the container:
VStack { FLXSkeleton () . frame ( height : 120 ) } . accessibilityElement () . accessibilityLabel ( "Loading" )
Custom styling
FLXSkeletonStyle is an FLX protocol. Override it for a subtree via .flxSkeletonStyle(_:):
struct FLXStaticSkeletonStyle : FLXSkeletonStyle { func makeBody ( configuration : Configuration) -> some View { Capsule () . fill ( .quaternary ) } } VStack ( alignment : .leading, spacing : FLXSpacing.sm ) { FLXSkeleton () . frame ( width : 220 , height : 16 ) FLXSkeleton () . frame ( width : 160 , height : 16 ) } . flxSkeletonStyle ( FLXStaticSkeletonStyle ()) Show more
API Reference
FLXSkeleton
Filled with theme.colors.accent and theme.radius.md, pulsing between full and half opacity.