On this page
A good Figma file does not automatically become good SwiftUI.
The handoff is where design intent either turns into a durable interface or dissolves into screenshots, one-off spacing values, and arguments about whether a card is "basically the same" as the other card with three more properties and a slightly different shadow.
The problem is not that designers and engineers use different tools. The problem is that too many teams hand off pixels when they should be handing off decisions.
SwiftUI rewards clear structure. It punishes vague structure slowly, then all at once, usually when the product needs a new state, a larger Dynamic Type size, or a small visual change across twenty screens.
The handoff should make implementation cheaper without pretending the Figma file is the app.
1. Start with the product contract, not the artboard
Before implementation starts, the team should agree on what the screen is responsible for.
A useful handoff answers:
- What job is the user trying to complete?
- Which information is required to make that decision?
- Which actions are primary, secondary, destructive, or optional?
- What should the screen do while data is loading?
- What happens when the user has no data?
- What happens when the operation fails?
- Which parts are reusable product patterns and which parts are screen-specific?
This matters because SwiftUI implementation is not just drawing rectangles. It is modeling state, hierarchy, interaction, accessibility, and change over time.
If the design only shows the happy path at one device size, the engineer has to invent the rest. That invention may be reasonable. It may also quietly create product behavior nobody reviewed.
A clean handoff starts by naming the contract: this screen lets the user review invoice details, fix missing fields, and submit when validation passes. Now the UI has a job. The artboard is evidence, not the whole specification.
2. Translate visual choices into semantic tokens
Figma is good at showing visual values. Code needs stable meaning.
A design handoff should identify the semantic decisions behind the values:
- spacing roles, not just
16px - text roles, not just
17pt semibold - color roles, not just
#1A73E8 - radius roles, not just
12px - elevation or border rules, not just a copied shadow
Raw values are easy to copy and hard to maintain. Semantic roles survive change better.
For example, a Figma label saying Blue / 600 is less useful to SwiftUI than knowing the value represents actionPrimary, link, selectedBackground, or brandAccent. Those are different product meanings even if the color is temporarily the same.
A practical mapping might look like this:
enum AppColorRole {
static let actionPrimary = Color.accentColor
static let surfaceRaised = Color(uiColor: .secondarySystemBackground)
static let borderSubtle = Color(uiColor: .separator)
static let textPrimary = Color.primary
static let textSecondary = Color.secondary
}The point is not to mirror Figma into Swift by force. The point is to make repeated design decisions addressable in code.
When the brand changes later, engineers should update the meaning once. They should not search the app for every place somebody pasted a hex value during a heroic sprint.
3. Define components by behavior, not appearance
A component is not reusable because it looks similar.
It is reusable when it has the same job, the same state model, and the same interaction rules.
This is where handoff needs discipline. A row used for settings, search results, account selection, and error recovery may all look like "title, subtitle, trailing thing." That does not mean it should become one universal AppRow with fourteen parameters and a long future in resentment.
Before extracting a component, ask:
- What product pattern does this represent?
- Which states does it own?
- Which interactions are built in?
- What content can vary?
- What is intentionally fixed?
- Where should this component not be used?
A good component contract might say:
PlanCardshows subscription plan comparison- supports selected, disabled, loading-price, and current-plan states
- primary action is external to the card
- price text can wrap to two lines
- badge is optional, but only one badge is allowed
- not used for generic marketing cards
That is a handoff an engineer can implement.
A Figma component named Card/Variant 7 with hidden layers and unclear usage rules is not a contract. It is a visual artifact that still needs product meaning.
4. Handoff states before engineers discover them in production
Static designs hide the expensive parts.
Every meaningful SwiftUI view should have state coverage before implementation is called done:
- loading
- empty
- populated
- partial data
- validation error
- network error
- permission denied
- disabled action
- destructive confirmation
- success or completion
- long localized text
- large Dynamic Type
The point is not to design every possible screen permutation in high fidelity. That becomes theater quickly.
The point is to make the product decisions explicit.
If an invoice list is empty, should the app show an educational empty state, a create button, or a quiet blank state? If a price fails to load, should checkout block, retry inline, or show a fallback? If an upload is still processing, can the user leave the screen?
Those are design questions. They become engineering bugs only when nobody answers them early.
For SwiftUI, state coverage also protects architecture. If the view has to represent loading, failure, retry, and success, the model should probably expose those states clearly instead of handing the view a pile of optional values and letting it guess what tragedy occurred.
5. Specify layout rules, not just frame positions
Figma can make a screen look precise at one size.
SwiftUI has to survive real devices, Split View, Dynamic Type, localization, different content, safe areas, keyboards, toolbars, and the user's impressive talent for having a longer name than your mock data allowed.
A design handoff should define layout behavior:
- which content scrolls
- which action stays pinned
- which groups compress first
- which text can wrap
- which images crop or scale
- where minimum tap targets are required
- how the layout changes in accessibility sizes
- what happens when the keyboard appears
This is more useful than redlines alone.
Redlines can tell an engineer that a button is 24 points below a text block. They do not explain whether that spacing should remain when the title wraps to three lines, when an error appears, or when the bottom safe area changes.
For SwiftUI, layout rules are implementation guidance. They help engineers choose between VStack, Grid, List, ScrollView, pinned safe-area insets, custom layouts, and environment-driven adjustments.
Without those rules, the implementation may match the screenshot and still fail the product.
6. Treat interaction details as part of the design
A handoff that only describes the resting UI is incomplete.
The app also needs rules for:
- tap targets
- pressed and disabled states
- focus behavior
- keyboard dismissal
- validation timing
- async progress
- cancellation
- retry
- confirmation
- navigation after success
- haptics where they matter
SwiftUI makes it easy to wire a button. It does not decide whether validation should run on every keystroke, after focus leaves the field, or only on submit. It does not decide whether a destructive action needs a confirmation dialog or an undo affordance.
Those choices shape the user's trust more than the corner radius.
A useful handoff for a submit button says more than "primary button, full width." It says:
- disabled until required fields are valid
- shows progress while request is in flight
- prevents duplicate submissions
- remains visible above the keyboard
- shows field-level errors after failure
- navigates to confirmation only after server acceptance
Now the engineer can build the real interaction instead of guessing from a blue rectangle.
7. Keep Figma and SwiftUI components close, not identical
The design system in Figma and the implementation in SwiftUI should share language.
They do not need to share shape perfectly.
Figma components are optimized for design exploration, variants, documentation, and visual consistency. SwiftUI components are optimized for state, composition, performance, accessibility, and testability. Pretending those are the same model usually creates trouble.
A healthy relationship looks like this:
- Figma defines visual language, product patterns, and state examples
- SwiftUI defines the implementation API and runtime behavior
- both use the same semantic names where possible
- both document intentional differences
- neither side invents new terminology casually
If Figma has Primary Button, SwiftUI should probably not call the implementation CustomCallToActionView. If SwiftUI splits PrimaryButtonStyle from LoadingButton, Figma should know why.
The naming does not have to be precious. It has to be shared enough that design review and code review are talking about the same object.
That one habit prevents a surprising amount of drift.
8. Build a review loop around previews
The best handoff does not end when the engineer starts coding.
It ends when the implemented UI has been reviewed in the environment where it actually lives.
For SwiftUI, previews are a useful bridge because they can show components and screens across states quickly:
- normal content
- empty content
- error state
- loading state
- long text
- accessibility text sizes
- dark mode
- right-to-left layout if relevant
Designers should be able to review those states before the branch is considered visually complete. Not as a ceremonial approval meeting. As a fast correction loop while changes are cheap.
This catches the real issues:
- the title wraps badly
- the empty state is too tall
- the button hierarchy is wrong in context
- dark mode contrast is weak
- the error state pushes the primary action below the fold
- a component looks reusable in isolation but awkward in the actual screen
A screenshot from the simulator is often more honest than the original artboard. It has fewer assumptions and more constraints.
9. Decide what belongs in code review
Design handoff should leave traces that reviewers can enforce.
For UI work, code review should not only ask whether the diff compiles. It should ask whether the implementation preserved the product decisions:
- Are semantic tokens used instead of raw values?
- Are repeated patterns using existing styles or components?
- Are new components narrow and named by product meaning?
- Are required states represented explicitly?
- Does Dynamic Type still work?
- Are loading, error, and empty states covered?
- Are primary actions protected from duplicate submission?
- Does the implementation match the agreed interaction rules?
This prevents design quality from depending on memory and goodwill.
It also gives engineers permission to push back when a design requires a one-off exception. Sometimes the exception is correct. Sometimes it is accidental drift wearing a nice outfit.
The point is not to make every screen identical. The point is to make deviations visible and intentional.
10. The practical handoff checklist
For most SwiftUI teams, I would keep the handoff lightweight and consistent.
Before implementation, collect:
- Screen contract: user goal, required information, primary and secondary actions.
- Token mapping: semantic color, type, spacing, radius, and surface roles.
- Component contracts: reusable patterns, owned states, content limits, and escape rules.
- State coverage: loading, empty, error, disabled, success, long content, accessibility sizes.
- Layout behavior: scrolling, pinning, wrapping, safe areas, keyboard handling, and compression rules.
- Interaction rules: validation timing, progress, retry, confirmation, cancellation, and navigation outcomes.
- Review loop: SwiftUI previews or simulator captures across the states that matter.
- Code-review expectations: what must use shared language, what may be custom, and what needs a product decision.
That is enough structure to stop the common failure mode: a beautiful Figma file becoming a brittle SwiftUI implementation because the important decisions lived between the pixels.
Design handoff is not about making engineers obey the file.
It is about making product intent clear enough that implementation can preserve it when the app meets real data, real devices, and real users.
That is the part worth systematizing.