gpt-taste
gpt taste
Comprehensive guide to UI/UX design principles, architectural patterns, and animation techniques for building high-quality iOS apps with Swift.
Full skill instructions
Follow Apple’s Design Principles: Adhere to the Human Interface Guidelines (HIG) emphasis on clarity, deference, and depth in your app’s design:contentReference[oaicite:0]{index=0}. Ensure every element has a clear purpose and is easily understood (clarity), UI chrome does not distract from content (deference), and use layering and subtle effects to convey hierarchy (depth):contentReference[oaicite:1]{index=1}:contentReference[oaicite:2]{index=2}. A user interface that embodies these principles will feel intuitive and engaging.
Design for All Devices: Build adaptive layouts that work across various iPhone and iPad screen sizes and orientations. Use Auto Layout (UIKit) or responsive layouts in SwiftUI to accommodate different screen dimensions and safe areas. For example, ensure iPad interfaces support both portrait and landscape with appropriate spacing and that important controls remain easily accessible:contentReference[oaicite:3]{index=3}. Consistent UI behaviors across devices improve familiarity and usability:contentReference[oaicite:4]{index=4}.
Touch-Friendly Interfaces: Make interactive controls comfortable for touch. Use native UIKit controls (like UIButton, UISwitch, etc.) or SwiftUI controls which are optimized for touch interactions:contentReference[oaicite:5]{index=5}. Ensure hit targets are at least 44×44 points:contentReference[oaicite:6]{index=6} so buttons aren’t too small to tap. Spacing between tappable elements should prevent accidental touches on the wrong item.
Typography and Readability: Use a minimum font size of 11 points for body text to ensure legibility without zooming:contentReference[oaicite:7]{index=7}. Support Dynamic Type so that text scales for users who prefer larger text sizes:contentReference[oaicite:8]{index=8}. In Swift, this means using text styles (e.g. .body, .headline) or UIFont.preferredFont(forTextStyle:) and enabling adjustsFontForContentSizeCategory on UIKit labels. Ensure sufficient contrast between text and background colors for readability:contentReference[oaicite:9]{index=9}, especially in various lighting conditions or Dark Mode. Avoid using ultra-light font weights on small text and prefer system fonts (San Francisco) for optimal readability and accessibility:contentReference[oaicite:10]{index=10}.
Spacing and Alignment: Design clean layouts with appropriate whitespace. Avoid overcrowding the interface or overlapping elements:contentReference[oaicite:11]{index=11}. Use padding and margins consistently – for example, use stack views or SwiftUI’s VStack/HStack to distribute elements with regular spacing. Align text, images, and controls in a logical way to convey relationships (e.g. aligning labels and text fields in a form):contentReference[oaicite:12]{index=12}. As a general rule, avoid placing more than 2-3 controls side by side to prevent a cramped, confusing layout:contentReference[oaicite:13]{index=13}. A well-organized interface with visual hierarchy helps users navigate content at a glance.
Use High-Quality Assets & Adaptivity: Provide @2x and @3x image assets for all graphics so they render sharply on Retina and high-resolution displays:contentReference[oaicite:14]{index=14}. Always display images at their natural aspect ratio to avoid distortion:contentReference[oaicite:15]{index=15}. Opt for vector resources like SF Symbols for icons when possible – these scale beautifully on all devices and automatically align with Dynamic Type and weight changes. Ensure your color choices and images look good in both Light and Dark Mode. Use dynamic system colors (e.g. .label, .systemBackground) that automatically adapt to light/dark appearances:contentReference[oaicite:16]{index=16} so your app maintains good contrast and consistent feel in either mode. Test your app in both Light and Dark themes to confirm that text and icons remain legible and visually pleasing:contentReference[oaicite:17]{index=17}.
Platform Consistency: Stick to iOS conventions for a familiar user experience. Utilize system UI components (tab bars for primary navigation, navigation bars for hierarchical screens, modals for transient tasks, etc.) instead of custom reinvented controls:contentReference[oaicite:18]{index=18}. Users expect standard gestures and behaviors – e.g. swiping from the edge to go back, pull-to-refresh, etc. – so leverage UIKit/SwiftUI components that come with these behaviors built-in. Maintain consistency in iconography and terminology with iOS standards (for example, use the term “Edit” for edit actions, use the system share sheet for sharing). By leveraging Apple’s built-in UI elements and patterns, your app will feel “at home” on iOS and automatically gain functionalities like Dynamic Type and VoiceOver support:contentReference[oaicite:19]{index=19}.
Accessibility First: Incorporate accessibility from the start. Label your UI elements for VoiceOver and test that all features are usable with assistive technologies. Ensure Dynamic Type works throughout (no clipped or misaligned text when fonts scale up):contentReference[oaicite:20]{index=20}. Use semantic colors and symbols (which convey meaning even with the default accessibility settings). Provide descriptive alternatives for images (via accessibilityLabel in SwiftUI or UIAccessibility properties in UIKit). Avoid conveying information solely by color or animations – combine with text or haptic feedback so everyone can perceive it. Remember to support Reduce Motion and Increase Contrast settings: for example, if the user has Reduce Motion on, tone down or replace elaborate animations with simpler cross-fades:contentReference[oaicite:21]{index=21}. Designing with accessibility in mind not only broadens your audience but often improves overall app quality and clarity.
Choosing the right app architecture in Swift iOS development is crucial for maintainability and scalability. Below are common patterns and when to use each:
MVC (Model-View-Controller): The traditional iOS architecture. The Model represents data/business logic, the View displays UI, and the Controller mediates between them:contentReference[oaicite:22]{index=22}. MVC is straightforward and quick to develop, making it ideal for small to medium apps with simple UIs:contentReference[oaicite:23]{index=23}:contentReference[oaicite:24]{index=24}. It offers clear separation of concerns in theory, but in practice iOS View Controllers often become bloated (“Massive View Controller”) as they handle too much logic:contentReference[oaicite:25]{index=25}. Pros: Simple, low learning curve:contentReference[oaicite:26]{index=26}. Great for rapid prototyping or when one developer handles the whole app. Cons: Can become unmanageable as complexity grows; view controllers tightly couple UI and logic, hindering testing:contentReference[oaicite:27]{index=27}. Use MVC for simpler projects or early in development, but be cautious about putting too much code in controllers – factor out data code into model classes or use helpers to avoid the Massive VC problem:contentReference[oaicite:28]{index=28}.
MVVM (Model-View-ViewModel): An architecture that introduces a ViewModel layer between Model and View to handle presentation logic:contentReference[oaicite:29]{index=29}. The ViewModel transforms model data into a form that the View can easily consume, often with data binding so that UI updates automatically when data changes:contentReference[oaicite:30]{index=30}:contentReference[oaicite:31]{index=31}. Pros: Better separation of concerns – the UI layer is dumb and simply reflects state from the ViewModel. This leads to improved testability (ViewModels can be unit tested without UI):contentReference[oaicite:32]{index=32}:contentReference[oaicite:33]{index=33}. MVVM works especially well with SwiftUI, which has state binding built-in (e.g. using @Observable objects and @Published properties to automatically update views):contentReference[oaicite:34]{index=34}:contentReference[oaicite:35]{index=35}. Cons: Higher complexity and more boilerplate for simple screens:contentReference[oaicite:36]{index=36} – you need to set up binding mechanisms or use Combine/Reactive frameworks in UIKit. There’s a learning curve to structuring data flow. When to use: MVVM is ideal for apps with dynamic, complex UIs or real-time data updates (e.g. dashboards, social feeds) where decoupling UI and logic pays off:contentReference[oaicite:37]{index=37}. It’s also a natural choice if you’re building with SwiftUI, since SwiftUI’s design encourages a MVVM-like state management. Use MVVM to keep view controllers lightweight or when you anticipate needing to unit-test a lot of presentation logic.
VIPER (View-Interactor-Presenter-Entity-Router): A highly modular clean architecture splitting responsibilities into five distinct components:contentReference[oaicite:38]{index=38}. The View is the user interface (i.e. a UIViewController or SwiftUI View) and only displays data and forwards user input. The Presenter contains the presentation logic, receiving input from the View and requesting data from the Interactor. The Interactor holds the business logic and interacts with data Entities (model objects):contentReference[oaicite:39]{index=39}. The Router (or Wireframe) handles navigation and screen flow. Pros: VIPER offers very clear separation of concerns and small, single-purpose classes, which leads to extremely high testability and maintainability:contentReference[oaicite:40]{index=40}. Teams can work in parallel on different components (one dev on the Interactor, another on UI, etc.), so it scales well for large projects with big teams:contentReference[oaicite:41]{index=41}:contentReference[oaicite:42]{index=42}. Cons: It has a lot of overhead and boilerplate code, increasing project complexity:contentReference[oaicite:43]{index=43}. There’s a steep learning curve and development can be slower due to the many moving parts. When to use: VIPER is recommended for large, enterprise-level applications or those requiring long-term maintainability where scalability is critical:contentReference[oaicite:44]{index=44}. For example, if you have a very complex app (many features, many developers) or need extremely robust modularization, VIPER can impose order. It’s likely overkill for simple apps or small teams, but in a huge codebase it helps isolate functionality and facilitates adding new features without breaking others:contentReference[oaicite:45]{index=45}.
(Other architectural patterns like MVP or Coordinator are also used in iOS, but the above three are among the most common. You can mix patterns too – e.g., use MVVM within a VIPER module for UI, etc. The key is to balance complexity with app needs.)
Architecture Best Practices: No matter which pattern you choose, aim to keep code loosely coupled and high in cohesion:
Choosing the right architecture pattern depends on the app’s complexity and team needs. Simpler apps thrive with MVC or a lightweight MVVM, whereas very complex apps benefit from MVVM or VIPER for clarity. It’s common to start with MVC and gradually refactor portions to MVVM or others as the project grows.
Animations and transitions can greatly enhance the user experience on iOS when used appropriately. Swift (via UIKit or SwiftUI) provides powerful APIs for smooth animations. Here are best practices for implementing effective animations:
Use Core Animation Under the Hood: All iOS animations are backed by Core Animation, which is optimized to deliver high frame rates and smooth animations without burdening the CPU:contentReference[oaicite:48]{index=48}. Whenever possible, leverage the system’s animation APIs (UIKit or SwiftUI) rather than manually redrawing in a loop. The system will handle refresh synchronization and GPU usage for you. Core Animation can run most animations on the GPU, freeing the CPU to keep your app responsive.
Prefer High-Level Animation APIs: For UIKit, use UIView.animate(withDuration:animations:) and related methods for simple animations (fades, moves, transforms). They are easy to use and automatically use Core Animation under the hood. For more control (e.g., interactive animations or chaining), UIViewPropertyAnimator is very powerful – it lets you pause, scrub, or reverse animations smoothly, which is great for interactive UIs (like dragging a card and having it animate to a position):contentReference[oaicite:49]{index=49}. In SwiftUI, take advantage of implicit animations by simply altering state variables with withAnimation or using .animation() modifiers; SwiftUI will animate the changes smoothly. You can also use explicit animations (e.g., with the Animation struct and .animation modifiers on views) and transitions (.transition(...)) for inserting/removing views with effects. These high-level tools cover most use cases and adapt to user preferences (e.g. they automatically reduce motion if the user enabled that in settings).
Keep Animations Short and Sweet: Timing is crucial. As a rule of thumb, aim for animation durations around 200ms to 400ms for standard UI interactions:contentReference[oaicite:50]{index=50}. Animations in this range feel natural – anything significantly longer can make the app feel sluggish or unresponsive, while anything too short might be jarring. For example, a button tap feedback might animate over 0.2 seconds, a view transition or modal presentation around 0.3 seconds. Use easing curves (such as .curveEaseInOut in UIKit or .easeInOut in SwiftUI) to make motions feel gentle – easing in and out prevents abrupt starts/stops. Swift’s frameworks default to easing curves that feel “iOS-like.” For more springy or bouncy effects (like a physics feel), UIKit offers spring animations (usingSpringWithDamping parameter) and SwiftUI has spring interpolations (e.g. .spring() animation), which can add playful realism. Test different durations and curves to match the purpose of the animation (e.g., use snappier, faster animations for frequent, minor state changes; use slightly longer, more eased animations for significant transitions).
Optimize for Performance: A smooth 60 frames-per-second (FPS) (or up to 120 FPS on ProMotion devices) is the goal for animations. This means the work to update each frame must complete very quickly – ideally under 16ms per frame for 60Hz displays, or ~8ms for 120Hz:contentReference[oaicite:51]{index=51}. To achieve this:
transform.translation or center is typically more efficient than animating its frame:contentReference[oaicite:52]{index=52}. Similarly, animating alpha/opacity is cheap, but animating complex subview addition/removal might be heavier.UIVisualEffectView which is optimized for blur.Use Core Animation for Complex Sequences: When UIKit’s convenience methods aren’t enough, you can work with Core Animation classes (CABasicAnimation, CAKeyframeAnimation, CAAnimationGroup, etc.) directly. Core Animation allows animating layer properties with fine-grained timing and grouping. For example, you might use a CAAnimationGroup to run multiple animations in sync (movement, opacity, scaling all together). Core Animation also enables keyframe animations for non-linear movement or custom easing curves (via CAMediaTimingFunction or UIBezierPath motion). The good news: you often don’t need to manually create a CADisplayLink and do per-frame updates – you describe the start/end and the system will interpolate frames efficiently. Direct Core Animation is lower-level, so use it when you require something the higher-level APIs can’t do (e.g., animating along a path, or repeating/pinging an animation indefinitely, etc.), but remember that maintaining 60 FPS is still the priority. Profile if needed to ensure these complex animations remain smooth.
Leverage UIKit Dynamics (for UIKit apps): For physically interactive animations, UIKit Dynamics can simulate gravity, collisions, springs, and more using the UIDynamicAnimator system. This is useful for specific UI effects (like a bouncing card or a draggable, snapping element) without having to write the physics calculations yourself. It’s more specialized, but worth knowing it exists for cases where you want real-world inspired motions (e.g., a slide-out menu with bouncy overshoot). In SwiftUI, while there isn’t an exact Dynamics equivalent, you can achieve springs and interpolating animations via the .spring() functions and by linking animations to gesture state (e.g., using DragGesture with .onEnded to create a momentum effect).
Match Animation to Purpose: Animations should enhance understanding of the UI, not distract. Use them to draw attention to changes or provide feedback:
.transition(.slide) for inserting a subview, which slides it in smoothly. Animated transitions maintain context and are better than abrupt changes.Respect User Preferences and Accessibility: Always consider that some users prefer or require reduced motion. iOS provides the “Reduce Motion” accessibility setting. Check for UIAccessibility.isReduceMotionEnabled (or in SwiftUI, the Environment value \ .accessibilityReduceMotion) and modify or skip animations accordingly:contentReference[oaicite:55]{index=55}. For example, you might replace a complex zooming animation with a simple fade when reduce-motion is on. Also, ensure that no critical information is conveyed only through an animation. If something changes state, also update a label or provide a sound/haptic so users with animations off still get the feedback. Providing haptic feedback alongside animations (using UIFeedbackGenerator) can also reinforce the experience (e.g., a slight tap vibration when a long press reorders a list, or a success vibration on a completed action) – this can substitute some of the cognitive effect of an animation for those who can’t see it well:contentReference[oaicite:56]{index=56}.
By following these animation best practices, you’ll create an app that feels lively and responsive. Animations should make the interface feel smoother and more natural, not slower. Always test your animations on real devices (especially older hardware, if you support it) to ensure they run well. A polished app uses animation sparingly and smartly to direct user focus and provide feedback, all while maintaining excellent performance and honoring user accessibility settings.
Follow this step-by-step workflow to apply the above best practices when designing and developing a Swift iOS app:
1. Planning & Design:
2. Setup Xcode Project & Resources:
3. Implement UI Layouts:
UIStackView) and layout guides or SwiftUI’s stacks, spacers, and alignment options to construct adaptive interfaces. Ensure base font styles are set to Dynamic Type text styles (e.g., Title1, Body in Interface Builder or .font(.title) in SwiftUI) so they will auto-adjust.NavigationView and layout will handle this, but you can also use SafeAreaInset or padding to adjust.4. Choose and Apply Architecture Pattern:
viewDidLoad or appropriate lifecycle methods, and respond to user actions (IBActions or delegate callbacks). For MVVM, establish the binding between your View and ViewModel. In UIKit, that could mean setting up your ViewModel to have callbacks or using Combine publishers that the ViewController observes to update UI. In SwiftUI, use @StateObject for your ViewModel and bind published properties to UI elements. For VIPER, wire up the communication: e.g., when the View (ViewController) loads, it notifies the Presenter, which asks the Interactor for data, then the Presenter formats it and updates the View via the interface protocol.5. Implement Features & Iterate:
tableView.reloadData() after updating the model).6. Enhance with Animations & Transitions:
viewDidAppear. If using SwiftUI, simply apply transitions or animated state changes. Keep animations consistent with the platform – for navigation, using the built-in UINavigationController push/pop animations is recommended (it already matches iOS style). For custom interface elements, use subtle animations to clarify changes (e.g., animate a background color change to highlight selection).UIView.animateKeyframes for sequenced animations might work better than chaining multiple animate calls).7. Final Polishing:
By following this workflow, you ensure that you start with a strong design foundation, implement it with a suitable architecture, and finish with an app that is not only functional but also user-friendly, consistent with iOS design language, and smooth in operation.
Below are some concrete examples illustrating the best practices:
1. Adaptive UI Layout (UIKit): Using Auto Layout programmatically with stack views for a responsive design. This code creates a centered vertical stack that adapts to content, demonstrating alignment, spacing, and Dynamic Type fonts.
import UIKit
class WelcomeViewController: UIViewController {
let titleLabel = UILabel()
let continueButton = UIButton(type: .system)
let stack = UIStackView()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemBackground // adapts to light/dark
// Configure title label (uses Dynamic Type text style)
titleLabel.text = "Welcome"
titleLabel.font = UIFont.preferredFont(forTextStyle: .largeTitle)
titleLabel.adjustsFontForContentSizeCategory = true // dynamic type support
titleLabel.textAlignment = .center
// Configure button
continueButton.setTitle("Continue", for: .normal)
continueButton.titleLabel?.font = UIFont.preferredFont(forTextStyle: .headline)
continueButton.titleLabel?.adjustsFontForContentSizeCategory = true
// Configure stack view
stack.axis = .vertical
stack.spacing = 20
stack.alignment = .center
stack.translatesAutoresizingMaskIntoConstraints = false
// Add arranged subviews
stack.addArrangedSubview(titleLabel)
stack.addArrangedSubview(continueButton)
view.addSubview(stack)
// Center the stack in the view with Auto Layout
NSLayoutConstraint.activate([
stack.centerXAnchor.constraint(equalTo: view.centerXAnchor),
stack.centerYAnchor.constraint(equalTo: view.centerYAnchor),
stack.leadingAnchor.constraint(greaterThanOrEqualTo: view.leadingAnchor, constant: 20),
stack.trailingAnchor.constraint(lessThanOrEqualTo: view.trailingAnchor, constant: -20)
])
}
}
gpt taste
Premium brand-kit image generation for high-end identity systems, logo concepts, and visual-world presentations.
Premium website design-to-code skill that generates visual references first, then builds faithful frontend implementations.
Premium frontend image direction for landing pages and marketing sites, generating one distinct horizontal image per section.
Premium mobile app screen concepts and flows with clean hierarchy, strong imagery, and distinctive art direction.
Emil Kowalski's philosophy on UI polish, component design, and the invisible details that make software feel good.
Frontend design and iteration for production-grade interfaces, from concept to ship.
Reverse-engineer design tokens from public websites into starter token files for your project.
Builds an animation from scratch by making the decisions in the order that determines whether it feels right.
Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.
Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.
Toolkit for styling artifacts with a theme. These artifacts can be slides, docs, reportings, HTML landing pages, etc. There are 10 pre-set themes with colors/fonts that you can apply to any artifact that has been creating, or can generate a new theme on-the-fly.
Chat-to-edit AI studio for product photos, portraits, branding, and video.
Generate your dream room in seconds.
Redesign your interior in seconds using AI
Transform rooms with AI-generated designs.
Transform Your Space with AI-Powered Japanese Interior Designs by Jife
AI-powered wireframes for non-designers.
Revolutionize Property Viewing with AI-Generated Floor Plans and Virtual Tours
Transform sketches into stunning architectural renders with AI.