From craft-workspace-webconsulting-skills
Provides watchOS design guidelines for glanceable interfaces, Digital Crown interaction, and screen dimensions to build effective Apple Watch apps.
How this skill is triggered — by the user, by Claude, or both
Slash command
/craft-workspace-webconsulting-skills:watchos-designThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Apple Watch is a personal, glanceable device worn on the wrist. Interactions are measured in seconds, not minutes. Every design decision must prioritize speed of comprehension and brevity of interaction.
Apple Watch is a personal, glanceable device worn on the wrist. Interactions are measured in seconds, not minutes. Every design decision must prioritize speed of comprehension and brevity of interaction.
The defining constraint of watchOS. If a user cannot extract the key information within 2 seconds of raising their wrist, the design has failed.
| Device | Screen Width | Screen Height | Corner Radius |
|---|---|---|---|
| 41mm (Series 9) | 176px | 215px | 36px |
| 45mm (Series 9) | 198px | 242px | 39px |
| 42mm (Series 10) | 180px | 220px | 37px |
| 46mm (Series 10) | 205px | 251px | 40px |
| 49mm (Ultra 2) | 205px | 251px | 40px |
The Digital Crown is the primary physical input for scrolling and precise value selection. It provides haptic feedback and should feel purposeful.
Correct — Crown binding with haptic detents:
struct VolumePickerView: View {
@State private var volume: Double = 0.5
var body: some View {
VStack {
Text("\(Int(volume * 100))%")
.font(.title.bold())
Image(systemName: "speaker.wave.3")
}
.focusable()
.digitalCrownRotation(
$volume,
from: 0.0,
through: 1.0,
by: 0.05,
sensitivity: .medium,
isContinuous: false,
isHapticFeedbackEnabled: true
)
}
}
Incorrect — ignoring the Crown and forcing touch-only interaction:
struct VolumePickerView: View {
@State private var volume: Double = 0.5
var body: some View {
Slider(value: $volume)
// No .digitalCrownRotation — Crown input is ignored
// Users must use touch-only, which is imprecise and frustrating on Watch
}
}
Watch navigation must be shallow and predictable. Users should never feel lost or unable to return to a known state.
TabView for top-level sections (max 5 tabs). Swipe horizontally between tabs. Each tab is a distinct functional area.NavigationStack for hierarchical drill-down. Limit hierarchy to 2-3 levels maximum. Every pushed view must have a back button (provided automatically by the system).| Pattern | Use Case | Gesture |
|---|---|---|
| Vertical scroll | Long-form content within a single view | Digital Crown / swipe up-down |
| TabView (horizontal pages) | Top-level app sections | Swipe left-right |
| NavigationStack (push/pop) | Hierarchical drill-down | Tap to push, swipe right or back button to pop |
| Modal sheet | Confirmation, focused input | Presented programmatically, dismiss via button or swipe down |
Complications are the most visible surface of a Watch app. They live on the watch face and provide at-a-glance data without launching the app.
accessoryCircular, accessoryCorner, and accessoryRectangular (WidgetKit, watchOS 9+).TimelineProvider. Provide future timeline entries when data is predictable (e.g., next calendar event, weather forecast). Keep data fresh -- stale complications erode trust.Correct — WidgetKit TimelineProvider for an accessoryCircular complication:
struct StepCountProvider: TimelineProvider {
func placeholder(in context: Context) -> StepEntry {
StepEntry(date: Date(), steps: 5000)
}
func getSnapshot(in context: Context, completion: @escaping (StepEntry) -> Void) {
completion(StepEntry(date: Date(), steps: HealthStore.shared.todaySteps))
}
func getTimeline(in context: Context, completion: @escaping (Timeline<StepEntry>) -> Void) {
let entry = StepEntry(date: Date(), steps: HealthStore.shared.todaySteps)
// Refresh in 15 minutes
let nextUpdate = Calendar.current.date(byAdding: .minute, value: 15, to: Date())!
completion(Timeline(entries: [entry], policy: .after(nextUpdate)))
}
}
struct StepCountComplicationView: View {
let entry: StepEntry
var body: some View {
Gauge(value: Double(entry.steps), in: 0...10000) {
Image(systemName: "figure.walk")
} currentValueLabel: {
Text("\(entry.steps / 1000)k")
}
.gaugeStyle(.accessoryCircular)
}
}
Use WidgetFamily values:
| Family | Shape | Typical Content |
|---|---|---|
accessoryCircular | Small circle | Single value, icon, or gauge |
accessoryCorner | Curved, top corners | Gauge with label, or text with icon |
accessoryRectangular | Wide rectangle | Multi-line text, chart, or detailed view |
accessoryInline | Text row | Short label or value |
When the user's wrist is down, watchOS enters an Always On state showing a dimmed version of the current app. This must be handled intentionally.
TimelineView with a .everyMinute schedule for time-sensitive content.Workout and health apps have unique requirements: extended sessions, live metrics, and body-awareness features.
Watch notifications must be brief and actionable. The user's wrist is raised for only a moment.
.notification for standard alerts, .directionUp for positive events, .directionDown for negative events, .success/.failure/.retry for outcomes.| Haptic | Use Case |
|---|---|
.notification | General alerts |
.directionUp | Positive event (goal reached, stock up) |
.directionDown | Negative event (stock down, weather warning) |
.success | Action completed successfully |
.failure | Action failed |
.retry | Try again prompt |
.start | Activity beginning |
.stop | Activity ending |
.click | Discrete selection (Crown detent, picker) |
Apple Watch supports VoiceOver and other assistive technologies. Complications and app UI must be accessible.
.accessibilityLabel() on image-only buttons..accessibilityValue() and .accessibilityHint().@Environment(\.accessibilityReduceMotion).@Environment(\.legibilityWeight).@Environment(\.colorSchemeContrast) to detect the user's preference.Correct:
Button(action: startWorkout) {
Image(systemName: "play.fill")
}
.accessibilityLabel("Start workout")
Incorrect:
Button(action: startWorkout) {
Image(systemName: "play.fill")
}
// VoiceOver reads "play" — not clear what action this performs
Use this checklist when reviewing a watchOS design or implementation.
.accessibilityValue() / .accessibilityHint()@Environment(\.accessibilityReduceMotion))@Environment(\.legibilityWeight))This skill is based on the excellent work by ehmo.
Original repository: https://github.com/ehmo/platform-design-skills
Special thanks to ehmo for their generous open-source contributions, which helped shape this skill collection. Adapted by webconsulting.at for this skill collection
npx claudepluginhub dirnbauer/webconsulting-skillsProvides Apple HIG guidance for system experience components: widgets, live activities, notifications, complications, home screen quick actions, top shelf, app clips, and app shortcuts.
Generates SwiftUI and UIKit components for iOS apps following Apple's HIG. Validates designs, ensures accessibility compliance for iPhone, iPad, and Apple Watch.
Provides Apple HIG guidelines for system experiences: widgets, Live Activities, notifications, complications, home screen quick actions, top shelf, watch faces, app clips, and shortcuts.