@hegemonart/get-design-done 1.14.8 → 1.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +5 -3
- package/.claude-plugin/plugin.json +15 -5
- package/CHANGELOG.md +97 -0
- package/README.md +30 -0
- package/SKILL.md +4 -1
- package/agents/a11y-mapper.md +25 -0
- package/agents/component-benchmark-harvester.md +112 -0
- package/agents/component-benchmark-synthesizer.md +88 -0
- package/agents/design-auditor.md +92 -8
- package/agents/design-context-builder.md +6 -0
- package/agents/design-executor.md +5 -2
- package/agents/design-pattern-mapper.md +2 -0
- package/agents/design-verifier.md +11 -0
- package/agents/motion-mapper.md +45 -0
- package/agents/token-mapper.md +36 -0
- package/agents/visual-hierarchy-mapper.md +29 -0
- package/connections/design-corpora.md +158 -0
- package/package.json +16 -2
- package/reference/anti-patterns.md +69 -0
- package/reference/audit-scoring.md +34 -3
- package/reference/brand-voice.md +199 -0
- package/reference/checklists.md +30 -3
- package/reference/components/README.md +90 -0
- package/reference/components/TEMPLATE.md +184 -0
- package/reference/components/accordion.md +217 -0
- package/reference/components/button.md +195 -0
- package/reference/components/card.md +200 -0
- package/reference/components/checkbox.md +207 -0
- package/reference/components/drawer.md +201 -0
- package/reference/components/input.md +208 -0
- package/reference/components/label.md +200 -0
- package/reference/components/link.md +193 -0
- package/reference/components/modal-dialog.md +210 -0
- package/reference/components/popover.md +197 -0
- package/reference/components/radio.md +203 -0
- package/reference/components/select-combobox.md +219 -0
- package/reference/components/switch.md +194 -0
- package/reference/components/tabs.md +213 -0
- package/reference/components/tooltip.md +201 -0
- package/reference/data/google-fonts.csv +51 -0
- package/reference/data/palettes.csv +41 -0
- package/reference/data/styles.csv +39 -0
- package/reference/design-system-guidance.md +177 -0
- package/reference/design-systems-catalog.md +151 -0
- package/reference/framer-motion-patterns.md +411 -0
- package/reference/gestalt.md +219 -0
- package/reference/iconography.md +231 -0
- package/reference/motion.md +102 -0
- package/reference/palette-catalog.md +82 -0
- package/reference/performance.md +304 -0
- package/reference/registry.json +359 -28
- package/reference/registry.schema.json +2 -1
- package/reference/review-format.md +2 -2
- package/reference/style-vocabulary.md +62 -0
- package/reference/surfaces.md +114 -0
- package/reference/typography.md +80 -0
- package/reference/visual-hierarchy-layout.md +306 -0
- package/skills/benchmark/SKILL.md +105 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# Design Systems Catalog — Quick Reference
|
|
2
|
+
|
|
3
|
+
An opinionated index of the 18 major design systems most relevant to digital product work. For each system, the entry covers core philosophy, distinctive strengths, canonical documentation URL, and the clearest signal for when to reach for it. This catalog is not exhaustive — it is a decision aid for the planning and research phases.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Material Design 3 (Google)
|
|
8
|
+
|
|
9
|
+
Material Design 3 (M3) is Google's most expressive design system to date, built around dynamic color — an algorithm that generates a full 5-palette color scheme (primary, secondary, tertiary, error, neutral) from a single seed color, enabling personalization and accessibility without manual token work. M3 introduced the concept of "tonal surfaces," where elevation is communicated through color tint rather than shadow depth, producing designs that work well in both light and dark environments. The component library is built on tokens and roles rather than hardcoded values, making it straightforward to implement across Android, web, and Flutter from a single specification. Reach for M3 when building products that will ship on Android, need to feel native to the Google ecosystem, or require automatic dark mode with a systematic color science approach.
|
|
10
|
+
|
|
11
|
+
**Canonical URL:** https://m3.material.io
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 2. Apple Human Interface Guidelines (HIG)
|
|
16
|
+
|
|
17
|
+
The Apple HIG is the definitive authority for UI on iOS, macOS, watchOS, visionOS, and tvOS. Unlike most design systems, the HIG is primarily a platform-convention guide — it documents the standard behaviors, controls, and interaction patterns that users expect on Apple hardware, rather than providing a token-based component system. Its core philosophy is that software should feel native to the platform: tapping into system behaviors (swipe-to-go-back, live text, share sheets) creates immediate familiarity that no custom UI can replicate as efficiently. The HIG is essential reading for any team building native Swift applications, and it also informs the right abstraction level for cross-platform apps — understanding platform conventions before deciding which to override.
|
|
18
|
+
|
|
19
|
+
**Canonical URL:** https://developer.apple.com/design/human-interface-guidelines
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 3. Radix UI + WAI-ARIA Authoring Practices Guide
|
|
24
|
+
|
|
25
|
+
Radix UI is a headless React component library built on the principle that accessibility should be the floor, not a feature to add later. Every Radix primitive — Dialog, Dropdown Menu, Tooltip, Select, Combobox — implements the corresponding WAI-ARIA authoring pattern exactly, including full keyboard navigation, focus management, and ARIA attribute wiring. Because Radix is headless (no styles included), it gives design teams complete visual control while eliminating the most error-prone aspect of component development: the accessibility behavior layer. The WAI-ARIA Authoring Practices Guide (APG) from the W3C is the authoritative specification that Radix implements — reading both together gives the complete picture of why each interaction pattern is designed as it is. Reach for Radix when building a custom design system from scratch, adopting shadcn/ui, or needing confidence that interactive components will pass WCAG 2.1 AA audit without custom accessibility engineering.
|
|
26
|
+
|
|
27
|
+
**Canonical URLs:** https://www.radix-ui.com / https://www.w3.org/WAI/ARIA/apg
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 4. shadcn/ui
|
|
32
|
+
|
|
33
|
+
shadcn/ui is not a traditional component library — it is a collection of copy-paste components built on Radix UI primitives, styled with Tailwind CSS, and distributed as source files rather than npm packages. The key insight is ownership: when you install a shadcn component, you own the code and can modify it freely without forking a library. Components are pre-wired with Radix's accessible behaviors and follow a consistent theming system using CSS custom properties for color tokens. The default aesthetic is clean, modern, and neutral — intentionally generic so that a brand layer can be applied on top. It has become the de facto starting point for new React applications that need accessible, customizable components quickly. Reach for shadcn/ui for SaaS products, dashboards, and admin interfaces where Tailwind is already in use and rapid iteration on component behavior is needed.
|
|
34
|
+
|
|
35
|
+
**Canonical URL:** https://ui.shadcn.com
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## 5. Polaris (Shopify)
|
|
40
|
+
|
|
41
|
+
Polaris is Shopify's design system for merchant-facing admin interfaces. Its core philosophy is that merchant clarity always wins over visual novelty — Polaris components are deliberately conservative in style to ensure that merchants can focus on their tasks rather than learning a new UI language. The system has deep expertise in e-commerce-specific patterns: product data tables with bulk actions, multi-step onboarding flows, fee and pricing displays, order status timelines, and multi-currency number formatting. Polaris's React components have granular TypeScript props that encode business logic (e.g., `criticalAction`, `destructive`, `loading`) as semantic variants rather than styling choices. Reach for Polaris when building Shopify apps or when the product domain is merchant-facing e-commerce operations — its patterns encode years of learnings about how merchants process information and make decisions.
|
|
42
|
+
|
|
43
|
+
**Canonical URL:** https://polaris.shopify.com
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 6. Carbon Design System (IBM)
|
|
48
|
+
|
|
49
|
+
Carbon is IBM's enterprise design system, optimized for data-heavy, information-dense interfaces in business, analytics, and scientific computing contexts. Its defining strength is the data table — Carbon's data table component supports sorting, filtering, batch actions, inline editing, pagination, and nested rows with a level of completeness that other systems do not approach. The system is built on a strict 8-column responsive grid and a precise 4px base-8 spacing scale, which makes pixel-perfect implementation across breakpoints reliable. Carbon has comprehensive dark theme support and strong accessibility compliance across its entire component set. Reach for Carbon when building enterprise dashboards, admin consoles, analytics platforms, or any interface where users will spend hours per day working with structured data at high information density.
|
|
50
|
+
|
|
51
|
+
**Canonical URL:** https://carbondesignsystem.com
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 7. Fluent 2 (Microsoft)
|
|
56
|
+
|
|
57
|
+
Fluent 2 is Microsoft's design language for Office 365, Windows 11, and cross-platform Microsoft products. It represents the evolution of the Fluent Design System toward a more expressive, accessible, and motion-rich visual language — particularly notable for its implementation of "emotional design" through subtle depth, layering, and light effects. Fluent 2's component library covers the full complexity of Office-class applications: ribbon toolbars, multi-pane layouts, collaborative presence indicators, and right-to-left language support. It ships implementations for React, Web Components, Blazor, iOS, and Android. Reach for Fluent 2 when building Microsoft Teams extensions, Office Add-ins, Microsoft 365 integrations, or Windows application software where visual alignment with the Microsoft ecosystem creates credibility and user familiarity.
|
|
58
|
+
|
|
59
|
+
**Canonical URL:** https://fluent2.microsoft.design
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## 8. Primer (GitHub)
|
|
64
|
+
|
|
65
|
+
Primer is GitHub's design system, optimized for developer tools, code review interfaces, and markdown-heavy content rendering. Its core philosophy is density with clarity — GitHub's users are experts who value information density and resent unnecessary visual chrome, so Primer components lean toward compact spacing and minimal decoration. Primer has particularly strong implementations of code-related components: syntax-highlighted code blocks, diff views, commit graphs, and inline comment threads. The markdown rendering system is comprehensive and well-tested across edge cases that arise in developer content. Primer also has deep investment in color accessibility — its color system was designed to meet WCAG AA across all combinations. Reach for Primer when building developer tools, code hosting features, documentation systems, or any product whose primary users are software engineers.
|
|
66
|
+
|
|
67
|
+
**Canonical URL:** https://primer.style
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## 9. Atlassian Design System
|
|
72
|
+
|
|
73
|
+
The Atlassian Design System governs the visual and interaction language of JIRA, Confluence, Trello, and Bitbucket — a family of products built around complex project management and collaborative workflows. Its defining expertise is in high-complexity form patterns: multi-step wizards, permission matrices, workflow configuration editors, and nested task hierarchies. The system provides comprehensive guidance on progressive disclosure — how to surface advanced configuration options without overwhelming occasional users — as well as patterns for collaborative real-time interfaces where multiple users edit the same content simultaneously. Atlassian's design tokens are production-ready and cover light and dark modes. Reach for the Atlassian system when designing products with JIRA-like complexity: multiple user roles, configurable workflows, permission systems, and nested content hierarchies.
|
|
74
|
+
|
|
75
|
+
**Canonical URL:** https://atlassian.design
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## 10. Ant Design
|
|
80
|
+
|
|
81
|
+
Ant Design is China's most widely deployed enterprise React component library, produced by Alibaba's Ant Group. It is extraordinarily feature-complete — the component library contains over 60 components covering every conceivable enterprise UI pattern, from complex data pickers and cascader inputs to statistical charts and map integrations. The visual language is formal and structured, with a consistent use of gray, blue, and red that reads as professional in enterprise business software contexts. Ant Design has dedicated design guidance for Chinese business conventions (date formats, number systems, address fields, bank card inputs) that is not available in Western-focused systems. Reach for Ant Design when building enterprise SaaS for business users, when the development team is comfortable with a mature but opinionated React API, or when the product targets Chinese markets where Ant Design patterns carry high recognition.
|
|
82
|
+
|
|
83
|
+
**Canonical URL:** https://ant.design
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 11. Mantine
|
|
88
|
+
|
|
89
|
+
Mantine is a full-featured React component and hooks library notable for the quality and breadth of its custom hooks alongside its component library. Beyond standard UI components, Mantine provides production-ready hooks for form management, clipboard access, scroll state, viewport detection, and OS-level preferences detection — hooks that typically require separate libraries. The component library has strong TypeScript support, a flexible theming system based on CSS custom properties, and first-class dark mode. Mantine's Form library is one of its differentiators: type-safe, nested form support with async validation without the boilerplate of React Hook Form or Formik. Reach for Mantine when building complex form-driven applications or data entry tools where the hook ecosystem adds as much value as the component library.
|
|
90
|
+
|
|
91
|
+
**Canonical URL:** https://mantine.dev
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## 12. Chakra UI
|
|
96
|
+
|
|
97
|
+
Chakra UI is a modular, accessible React component library built on the constraint-based styling principle: every layout and spacing prop maps to a design token, making it difficult to use arbitrary values that break the system. Its style props API (`mt`, `px`, `bg`, `color`) creates a tight coupling between design tokens and component props that enforces consistency at the implementation layer without requiring linter rules. Chakra has strong accessibility defaults across its component set and a straightforward theme extension system. Its dark mode implementation is one of the simplest in the ecosystem — toggling color mode is a one-line API call. Reach for Chakra UI when the design system's token enforcement needs to happen at the component-API level rather than in a separate linting layer, or when rapid prototyping with token-constrained styling is the priority.
|
|
98
|
+
|
|
99
|
+
**Canonical URL:** https://chakra-ui.com
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## 13. Base Web (Uber)
|
|
104
|
+
|
|
105
|
+
Base Web is Uber's open-source React component library, built for applications that prioritize data density, table-heavy interfaces, and complex form patterns at production scale. Its defining architectural feature is the "Overrides" pattern — every component exposes an override prop that allows any internal sub-component to be replaced or styled without forking the library. This makes Base Web uniquely flexible for organizations that need a coherent component system but have strict visual requirements that differ from any library's defaults. The data grid component is particularly capable, supporting row virtualization, column pinning, inline editing, and multi-sort. Reach for Base Web when building operations dashboards, logistics interfaces, or any data-intensive application where table density and performance at 10,000+ rows are primary requirements.
|
|
106
|
+
|
|
107
|
+
**Canonical URL:** https://baseweb.design
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## 14. Nord (Trivago)
|
|
112
|
+
|
|
113
|
+
Nord is Trivago's clean, minimal design system for travel and hospitality product interfaces. It is characterized by a restrained visual palette (predominantly white, light gray, and a single accent color), generous whitespace, and a focus on content legibility — appropriate for interfaces where the primary job is helping users compare options and make decisions. Nord's component documentation is exceptionally clear and includes detailed usage rationale and anti-pattern guidance alongside component specs. The system is smaller than enterprise-scale alternatives but is well-suited to consumer-facing products where visual sophistication and content clarity are more important than component count. Reach for Nord when building consumer products in travel, hospitality, or marketplace contexts where the brand aesthetic is premium, minimal, and content-forward.
|
|
114
|
+
|
|
115
|
+
**Canonical URL:** https://norddesignsystem.com
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## 15. Spectrum (Adobe)
|
|
120
|
+
|
|
121
|
+
Spectrum is Adobe's design system for Creative Cloud applications — Photoshop, Illustrator, Acrobat, XD, and the broader Adobe ecosystem. Its core philosophy is "density over decoration" — creative tool users need maximum canvas space and minimal chrome, so Spectrum components are compact, keyboard-navigable, and optimized for expert-user workflows rather than onboarding. Spectrum has particularly strong guidance for non-destructive editing patterns, panel layouts, property inspector interfaces, and contextual toolbars — patterns that rarely appear in general-purpose design systems. The Web Components implementation allows Spectrum to work across frameworks. Reach for Spectrum when building creative tools, editing interfaces, or professional applications where users are domain experts who value speed and control over visual novelty.
|
|
122
|
+
|
|
123
|
+
**Canonical URL:** https://spectrum.adobe.com
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## 16. Lightning Design System (Salesforce)
|
|
128
|
+
|
|
129
|
+
The Salesforce Lightning Design System governs the visual and behavioral language of Salesforce CRM and the Force.com platform. It is purpose-built for complex CRM patterns: record detail layouts, activity timelines, relationship panels, approval workflows, and configurable page builders. The system has deep guidance on form layout for dense data entry, which is the core user task in CRM — entering leads, logging calls, updating opportunity stages. Lightning's component implementations are available for Aura (Salesforce's older component model), LWC (Lightning Web Components), and React. Reach for Lightning when building Salesforce AppExchange products, Salesforce platform integrations, or CRM-adjacent applications where users switch between Salesforce and your product and visual consistency reduces cognitive switching cost.
|
|
130
|
+
|
|
131
|
+
**Canonical URL:** https://lightningdesignsystem.com
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## 17. Evergreen (Segment)
|
|
136
|
+
|
|
137
|
+
Evergreen is Segment's React UI framework for building B2B SaaS products. It was built to serve the Segment customer data platform — a product used by technical users (engineers and data analysts) who need to configure data pipelines, schema mappings, and integrations. Evergreen's components have a clean, professional aesthetic that signals "serious business tool" without the heaviness of traditional enterprise systems like Carbon or Lightning. The library is smaller and more focused than many alternatives, which makes it easier to learn completely and extend systematically. Reach for Evergreen when building developer-adjacent B2B SaaS — products used by technical business users who want a professional, efficient interface without the complexity of a full enterprise framework.
|
|
138
|
+
|
|
139
|
+
**Canonical URL:** https://evergreen.segment.com
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## 18. Gestalt (Pinterest)
|
|
144
|
+
|
|
145
|
+
Gestalt is Pinterest's design system, purpose-built for visual discovery and image-heavy content interfaces. Its defining expertise is in masonry grid layouts, image card components, and the interaction patterns around visual content — save, collection, board management, and visual search. Gestalt's pin component and board grid are among the most refined implementations of image-based browsing patterns in any open-source design system. The system also has strong documentation of hover and focus states in image-grid contexts, which are notoriously difficult to implement accessibly without disrupting visual flow. Reach for Gestalt when building visual discovery products, mood board tools, image collection managers, or any interface where the primary content unit is an image in a variable-height masonry grid.
|
|
146
|
+
|
|
147
|
+
**Canonical URL:** https://gestalt.pinterest.systems
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
*Use this catalog during the research phase to identify precedent, adapt established patterns, and avoid reinventing solutions that major organizations have already refined at scale.*
|
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
<!-- Source: nextlevelbuilder/ui-ux-pro-max-skill (MIT) — data/stacks/react.csv (framer-motion rows) -->
|
|
2
|
+
|
|
3
|
+
# Framer Motion Patterns
|
|
4
|
+
|
|
5
|
+
Framer Motion is the standard animation library for React. It abstracts the browser's animation primitives into a declarative API that stays out of your way for common cases while exposing full physics-based control when you need it. This reference covers implementation patterns — not just the API, but _why_ each pattern exists and when to apply it.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. Basics — motion components
|
|
10
|
+
|
|
11
|
+
Any HTML (or SVG) element can become a motion component by prefixing it with `motion.`. The most common variants are `motion.div`, `motion.span`, `motion.button`, and `motion.li`, but `motion.section`, `motion.a`, `motion.img`, and any other HTML element follow the same pattern.
|
|
12
|
+
|
|
13
|
+
The four primary animation props are:
|
|
14
|
+
|
|
15
|
+
- **`initial`** — the state the element starts in before it mounts (or before a transition begins). Without `initial`, the element won't animate _from_ anything — it'll just be in the `animate` state on mount. Always provide `initial` when you want an entrance animation.
|
|
16
|
+
- **`animate`** — the state the element should animate _to_. Framer drives the element toward this state whenever it changes.
|
|
17
|
+
- **`exit`** — the state the element animates _to_ when it unmounts. Requires `<AnimatePresence>` as a parent — see Section 3.
|
|
18
|
+
- **`transition`** — controls how the animation happens (spring, tween, duration, ease). If omitted, Framer applies a spring by default for layout/positional changes and a tween for opacity.
|
|
19
|
+
|
|
20
|
+
A basic fade-in example:
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
import { motion } from 'framer-motion'
|
|
24
|
+
|
|
25
|
+
function FadeIn({ children }: { children: React.ReactNode }) {
|
|
26
|
+
return (
|
|
27
|
+
<motion.div
|
|
28
|
+
initial={{ opacity: 0, y: 8 }}
|
|
29
|
+
animate={{ opacity: 1, y: 0 }}
|
|
30
|
+
transition={{ type: 'tween', duration: 0.2, ease: 'easeOut' }}
|
|
31
|
+
>
|
|
32
|
+
{children}
|
|
33
|
+
</motion.div>
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The slight `y: 8` offset on entry gives the element a sense of emerging from below — a common, subtle entrance pattern. The `easeOut` ease starts fast and slows at the end, which feels responsive.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 2. Spring vs. Tween Configuration
|
|
43
|
+
|
|
44
|
+
Framer Motion supports two fundamentally different animation models. Choosing between them is not arbitrary — each has a domain where it clearly wins.
|
|
45
|
+
|
|
46
|
+
### Spring physics (preferred for UI motion)
|
|
47
|
+
|
|
48
|
+
Springs model the physics of a real spring: the element overshoots slightly and settles. This is why spring motion _feels natural_ — real objects in the world have inertia and settle under physical forces. For UI, spring motion communicates responsiveness and quality.
|
|
49
|
+
|
|
50
|
+
`type: "spring"` is Framer's default for layout animations and positional changes. Key parameters:
|
|
51
|
+
|
|
52
|
+
- **`stiffness`** (100–800): controls how forcefully the spring pulls toward the target. High stiffness = arrives fast and decisively. Low stiffness = slow, lazy arrival.
|
|
53
|
+
- **`damping`** (10–30): controls oscillation resistance. High damping = settles without overshoot. Low damping = bouncy.
|
|
54
|
+
- **`mass`** (0.5–2): adds inertia. Higher mass makes the element feel heavier and slower to respond.
|
|
55
|
+
|
|
56
|
+
The relationship that matters in practice:
|
|
57
|
+
- **High stiffness + high damping = snappy** — fast arrival, no bounce. This is the production UI default.
|
|
58
|
+
- **Low stiffness + low damping = bouncy** — never use in production UI. Bounce feels playful and toy-like, which is wrong for most product contexts.
|
|
59
|
+
|
|
60
|
+
**Hard constraint: `bounce: 0` always for icon cross-fades and micro-interactions.** The `bounce` shorthand parameter is a convenience alias — setting it to 0 ensures no oscillation. "Bounce must be zero" is a non-negotiable rule for any interaction that fires frequently or in information-dense UI.
|
|
61
|
+
|
|
62
|
+
Recommended production preset:
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
transition={{ type: 'spring', stiffness: 400, damping: 30 }}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
This is snappy and clean. It arrives fast and settles without any visible oscillation. Use it as the default for hover lifts, modal entries, and element transitions.
|
|
69
|
+
|
|
70
|
+
### Tween (for duration-controlled, eased animations)
|
|
71
|
+
|
|
72
|
+
Tween animations run over a fixed duration with a specified easing curve. Use them when exact timing matters — opacity fades, color transitions, anything where you need predictable, duration-controlled behavior rather than physics.
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
transition={{ type: 'tween', duration: 0.2, ease: 'easeOut' }}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Ease guidance:
|
|
79
|
+
- **`"easeOut"`** for entrances — starts fast (feels responsive), decelerates to rest.
|
|
80
|
+
- **`"easeIn"`** for exits — accelerates away, gets out of the way quickly.
|
|
81
|
+
- **`"easeInOut"`** for emphasis transitions — smooth acceleration and deceleration, used when the same element transitions between states (not entering/exiting).
|
|
82
|
+
|
|
83
|
+
The rule of thumb: use springs for movement and scale; use tweens for opacity, color, and blur.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 3. AnimatePresence
|
|
88
|
+
|
|
89
|
+
`AnimatePresence` is the component that enables exit animations. Without it, React unmounts components immediately, and `exit` props are never executed — the element simply vanishes.
|
|
90
|
+
|
|
91
|
+
```tsx
|
|
92
|
+
import { AnimatePresence, motion } from 'framer-motion'
|
|
93
|
+
|
|
94
|
+
function ToastContainer({ toasts }) {
|
|
95
|
+
return (
|
|
96
|
+
<AnimatePresence>
|
|
97
|
+
{toasts.map(toast => (
|
|
98
|
+
<motion.div
|
|
99
|
+
key={toast.id}
|
|
100
|
+
initial={{ opacity: 0, y: -10 }}
|
|
101
|
+
animate={{ opacity: 1, y: 0 }}
|
|
102
|
+
exit={{ opacity: 0, y: -10 }}
|
|
103
|
+
transition={{ type: 'spring', stiffness: 400, damping: 30 }}
|
|
104
|
+
>
|
|
105
|
+
{toast.message}
|
|
106
|
+
</motion.div>
|
|
107
|
+
))}
|
|
108
|
+
</AnimatePresence>
|
|
109
|
+
)
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Every child of `AnimatePresence` that will be conditionally rendered **must have a `key` prop**. Framer uses the key to track which element is entering and which is exiting. Without a key, exit animations will not fire.
|
|
114
|
+
|
|
115
|
+
### AnimatePresence `mode` prop
|
|
116
|
+
|
|
117
|
+
The `mode` prop controls how entering and exiting elements interact during a transition:
|
|
118
|
+
|
|
119
|
+
- **`mode: "wait"`** — the exiting element completes its exit animation fully before the entering element begins its entrance. Use this for route transitions and tab panel swaps, where showing two elements simultaneously would be confusing.
|
|
120
|
+
- **`mode: "sync"`** — enter and exit animations run simultaneously. Use this when you're swapping UI elements (like icon cross-fades) and want both transitions to happen at once.
|
|
121
|
+
- **`mode: "popLayout"`** — the exiting element immediately pops out of the document flow so surrounding elements can animate into their new positions right away, while the exiting element still plays its exit animation. Ideal for list item removal.
|
|
122
|
+
|
|
123
|
+
### Critical rule: `<AnimatePresence initial={false}>`
|
|
124
|
+
|
|
125
|
+
When `AnimatePresence` wraps persistent UI that already exists on first render — like a tab panel that's visible on page load, or a sidebar that's open by default — you must pass `initial={false}`:
|
|
126
|
+
|
|
127
|
+
```tsx
|
|
128
|
+
<AnimatePresence initial={false}>
|
|
129
|
+
{isOpen && (
|
|
130
|
+
<motion.div key="panel" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }}>
|
|
131
|
+
{children}
|
|
132
|
+
</motion.div>
|
|
133
|
+
)}
|
|
134
|
+
</AnimatePresence>
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Without `initial={false}`, every component inside `AnimatePresence` will play its entrance animation on first mount, even when the user didn't trigger it. This is jarring and wrong — **never animate on initial load for existing UI**.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## 4. Layout Animations
|
|
142
|
+
|
|
143
|
+
The `layout` prop is one of Framer Motion's most powerful features. Add `layout` to a `motion` component, and Framer automatically detects when the component's position or size changes in the DOM and animates it from the old layout to the new one — even if the change was caused by other elements shifting around it.
|
|
144
|
+
|
|
145
|
+
```tsx
|
|
146
|
+
<motion.div layout className="card">
|
|
147
|
+
{isExpanded ? <FullContent /> : <Summary />}
|
|
148
|
+
</motion.div>
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
When `isExpanded` changes, Framer measures the old and new layouts and smoothly animates the transition. This works for position changes caused by sibling elements reordering, parent resizing, or content toggling.
|
|
152
|
+
|
|
153
|
+
**`layoutId` — shared element transitions:** Assign the same `layoutId` to two different components, and Framer will morph between them when one unmounts and the other mounts. This is the canonical implementation for expanding card → detail transitions and hero → full-view animations.
|
|
154
|
+
|
|
155
|
+
```tsx
|
|
156
|
+
// Card in list view
|
|
157
|
+
<motion.img layoutId={`product-image-${id}`} src={thumbnail} />
|
|
158
|
+
|
|
159
|
+
// Same image in expanded modal
|
|
160
|
+
<motion.img layoutId={`product-image-${id}`} src={fullImage} />
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
When the list-view card unmounts and the modal mounts, Framer animates the image from its list-view position to its modal position. The two components don't need to coexist — the transition bridges the gap.
|
|
164
|
+
|
|
165
|
+
**Important:** ensure only one component with a given `layoutId` is mounted at a time. Two simultaneously mounted components with the same `layoutId` will fight each other and produce broken animations.
|
|
166
|
+
|
|
167
|
+
**`layout="position"`:** Use this variant when you only want to animate the element's position, not its size. This prevents layout animation from attempting to smoothly resize the element when content-length changes cause size changes.
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## 5. Variants and Orchestration
|
|
172
|
+
|
|
173
|
+
Variants let you define named animation states as objects and apply them declaratively, rather than repeating animation values inline throughout your component tree.
|
|
174
|
+
|
|
175
|
+
```tsx
|
|
176
|
+
const containerVariants = {
|
|
177
|
+
hidden: { opacity: 0 },
|
|
178
|
+
visible: {
|
|
179
|
+
opacity: 1,
|
|
180
|
+
transition: {
|
|
181
|
+
staggerChildren: 0.05,
|
|
182
|
+
delayChildren: 0.1,
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const itemVariants = {
|
|
188
|
+
hidden: { opacity: 0, y: 10 },
|
|
189
|
+
visible: { opacity: 1, y: 0 },
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function AnimatedList({ items }) {
|
|
193
|
+
return (
|
|
194
|
+
<motion.ul
|
|
195
|
+
variants={containerVariants}
|
|
196
|
+
initial="hidden"
|
|
197
|
+
animate="visible"
|
|
198
|
+
>
|
|
199
|
+
{items.map(item => (
|
|
200
|
+
<motion.li key={item.id} variants={itemVariants}>
|
|
201
|
+
{item.label}
|
|
202
|
+
</motion.li>
|
|
203
|
+
))}
|
|
204
|
+
</motion.ul>
|
|
205
|
+
)
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
**Propagation:** When a parent has `variants` and `animate="visible"`, child `motion` components that also have `variants` will automatically receive the same `animate` value — they don't need their own `animate` prop. Framer propagates the state name down the tree.
|
|
210
|
+
|
|
211
|
+
**`staggerChildren`** delays each child's animation start by the specified seconds after the previous child. A value of `0.05` means each item enters 50ms after the previous — the standard for list entrance animations. More than `0.08` seconds starts to feel slow; more than 6–8 items should stagger in parallel (`staggerChildren` + `staggerDirection` with a cap).
|
|
212
|
+
|
|
213
|
+
**`delayChildren`** adds an initial delay before the first child begins, which gives the parent time to render visibly before its children start entering.
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## 6. Gesture-Driven Motion
|
|
218
|
+
|
|
219
|
+
Framer Motion provides props that animate elements in response to user gestures without requiring event handlers or state.
|
|
220
|
+
|
|
221
|
+
**`whileHover`:** The animation state while the pointer is hovering. Prefer subtle transforms — `scale: 1.02` for a gentle grow or `y: -2` for a subtle lift. Avoid large scale values (> 1.05) on UI elements; they feel unstable.
|
|
222
|
+
|
|
223
|
+
```tsx
|
|
224
|
+
<motion.button whileHover={{ scale: 1.02 }} transition={{ type: 'spring', stiffness: 400, damping: 30 }}>
|
|
225
|
+
Save draft
|
|
226
|
+
</motion.button>
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
**`whileTap`:** The animation state while the element is pressed. The canonical scale-on-press value is **0.96**. Never go below 0.95 (looks broken) and never above 0.98 (imperceptible) for primary interactive elements.
|
|
230
|
+
|
|
231
|
+
```tsx
|
|
232
|
+
<motion.button
|
|
233
|
+
whileHover={{ scale: 1.02 }}
|
|
234
|
+
whileTap={{ scale: 0.96 }}
|
|
235
|
+
transition={{ type: 'spring', stiffness: 400, damping: 30 }}
|
|
236
|
+
>
|
|
237
|
+
Confirm
|
|
238
|
+
</motion.button>
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
**`drag` + `dragConstraints`:** Enable drag with `drag` (either `true`, `"x"`, or `"y"`), and bound the drag region with `dragConstraints`. Use `dragElastic: 0.1` for a subtle resistance when dragging beyond the constraint boundaries — this gives physical feedback that the user has reached an edge.
|
|
242
|
+
|
|
243
|
+
```tsx
|
|
244
|
+
<motion.div
|
|
245
|
+
drag="x"
|
|
246
|
+
dragConstraints={{ left: -100, right: 100 }}
|
|
247
|
+
dragElastic={0.1}
|
|
248
|
+
whileDrag={{ scale: 1.05, cursor: 'grabbing' }}
|
|
249
|
+
>
|
|
250
|
+
Drag me
|
|
251
|
+
</motion.div>
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
**`whileDrag`:** Applies an animation state while the element is being dragged. Use it to provide visual feedback that the element is in motion (subtle scale-up, shadow, cursor change).
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## 7. Scroll-Linked Animations
|
|
259
|
+
|
|
260
|
+
**`useScroll()` + `useTransform()`:** For animations that respond continuously to scroll position, use `useScroll` to get `scrollYProgress` (a motion value from 0 to 1 representing document scroll) and `useTransform` to map that range to any animated value.
|
|
261
|
+
|
|
262
|
+
```tsx
|
|
263
|
+
import { useScroll, useTransform, motion } from 'framer-motion'
|
|
264
|
+
|
|
265
|
+
function ParallaxHero() {
|
|
266
|
+
const { scrollYProgress } = useScroll()
|
|
267
|
+
const y = useTransform(scrollYProgress, [0, 1], [0, -200])
|
|
268
|
+
|
|
269
|
+
return (
|
|
270
|
+
<motion.div style={{ y }}>
|
|
271
|
+
<HeroImage />
|
|
272
|
+
</motion.div>
|
|
273
|
+
)
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
Use `style={{ y }}` (not `animate`) for scroll-linked values because `animate` creates discrete state transitions, while `style` with a motion value creates continuous, real-time updates.
|
|
278
|
+
|
|
279
|
+
**`whileInView` + `viewport`:** For elements that should animate when they enter the viewport (the most common scroll animation pattern), `whileInView` is more reliable than `useScroll`. It triggers a state change rather than a continuous value mapping, which is easier to reason about and less prone to performance issues.
|
|
280
|
+
|
|
281
|
+
```tsx
|
|
282
|
+
<motion.section
|
|
283
|
+
initial={{ opacity: 0, y: 20 }}
|
|
284
|
+
whileInView={{ opacity: 1, y: 0 }}
|
|
285
|
+
viewport={{ once: true, margin: '-100px' }}
|
|
286
|
+
transition={{ type: 'tween', duration: 0.4, ease: 'easeOut' }}
|
|
287
|
+
>
|
|
288
|
+
<FeatureSection />
|
|
289
|
+
</motion.section>
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
**`viewport={{ once: true }}`** is the preferred option for entrance animations — the element animates in once and stays visible. Without `once: true`, the element will animate every time it enters the viewport, which is usually wrong for entrance effects (and can feel janky during fast scrolling).
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
## 8. prefers-reduced-motion Compliance
|
|
297
|
+
|
|
298
|
+
Respecting `prefers-reduced-motion` is **mandatory** for accessibility compliance. Some users have vestibular disorders or motion sensitivity — for them, unnecessary motion causes real physical discomfort. This is not optional polish; it is a WCAG 2.1 requirement.
|
|
299
|
+
|
|
300
|
+
### Per-component approach with `useReducedMotion`
|
|
301
|
+
|
|
302
|
+
```tsx
|
|
303
|
+
import { useReducedMotion, motion } from 'framer-motion'
|
|
304
|
+
|
|
305
|
+
function AnimatedCard() {
|
|
306
|
+
const prefersReducedMotion = useReducedMotion()
|
|
307
|
+
|
|
308
|
+
const transition = prefersReducedMotion
|
|
309
|
+
? { duration: 0 }
|
|
310
|
+
: { type: 'spring', stiffness: 400, damping: 30 }
|
|
311
|
+
|
|
312
|
+
return (
|
|
313
|
+
<motion.div
|
|
314
|
+
initial={{ opacity: 0, y: prefersReducedMotion ? 0 : 10 }}
|
|
315
|
+
animate={{ opacity: 1, y: 0 }}
|
|
316
|
+
transition={transition}
|
|
317
|
+
>
|
|
318
|
+
Content
|
|
319
|
+
</motion.div>
|
|
320
|
+
)
|
|
321
|
+
}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
When `prefersReducedMotion` is true, set `duration: 0` and remove any positional animation values — the element should appear instantly without motion.
|
|
325
|
+
|
|
326
|
+
### App-wide approach with `MotionConfig` (preferred)
|
|
327
|
+
|
|
328
|
+
The cleanest solution for most applications is to wrap the app root with `MotionConfig` using `reducedMotion: "user"`. This instructs Framer to automatically apply reduced-motion behavior for all motion components in the subtree when the OS preference is set — no per-component logic needed.
|
|
329
|
+
|
|
330
|
+
```tsx
|
|
331
|
+
import { MotionConfig } from 'framer-motion'
|
|
332
|
+
|
|
333
|
+
function App() {
|
|
334
|
+
return (
|
|
335
|
+
<MotionConfig reducedMotion="user">
|
|
336
|
+
<Router />
|
|
337
|
+
</MotionConfig>
|
|
338
|
+
)
|
|
339
|
+
}
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
`reducedMotion: "user"` reads the OS setting via `prefers-reduced-motion` media query and disables animations globally when it's set. This is the preferred approach because it's zero-maintenance — adding new animated components automatically inherits the behavior.
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
## 9. 60fps Performance Rules
|
|
347
|
+
|
|
348
|
+
Animation performance on the web comes down to a single principle: **only animate properties that the browser can handle on the GPU compositor thread**. Everything else requires the browser to recalculate layout or repaint pixels — work that happens on the main thread and causes dropped frames.
|
|
349
|
+
|
|
350
|
+
### Properties that are GPU-safe (always use these)
|
|
351
|
+
|
|
352
|
+
- `x`, `y` — map to `translateX()` and `translateY()` in `transform`
|
|
353
|
+
- `scale`, `scaleX`, `scaleY` — map to `scale()` in `transform`
|
|
354
|
+
- `rotate`, `rotateX`, `rotateY`, `rotateZ`
|
|
355
|
+
- `skewX`, `skewY`
|
|
356
|
+
- `opacity`
|
|
357
|
+
|
|
358
|
+
These properties run on the compositor thread and never block the main thread, regardless of how complex the rest of the page is.
|
|
359
|
+
|
|
360
|
+
### Properties that cause jank (never animate these)
|
|
361
|
+
|
|
362
|
+
- `width`, `height` — triggers layout recalculation on every frame
|
|
363
|
+
- `margin`, `padding` — shifts surrounding elements, triggers full reflow
|
|
364
|
+
- `border-width`
|
|
365
|
+
- `left`, `top`, `right`, `bottom` (on positioned elements) — triggers layout
|
|
366
|
+
- `font-size` — triggers layout and repaint
|
|
367
|
+
|
|
368
|
+
If you need to animate a size change, use `scale` on a wrapper. If you need to animate position, use `x`/`y` rather than `left`/`top`. This distinction is why Framer's layout animation system (Section 4) works — it uses `transform` internally even when responding to layout-driven position changes.
|
|
369
|
+
|
|
370
|
+
### `will-change: transform`
|
|
371
|
+
|
|
372
|
+
Only add `will-change: transform` when you observe a first-frame stutter on a specific element. Do not add it preemptively — it forces the browser to allocate a separate GPU layer for the element immediately, consuming GPU memory whether or not the animation is actually playing. Reserve it for elements with known performance issues after profiling.
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
## 10. MotionConfig
|
|
377
|
+
|
|
378
|
+
`MotionConfig` is a context provider that configures all `motion` components within its subtree. Use it for:
|
|
379
|
+
|
|
380
|
+
- **Reduced motion compliance** — as shown in Section 8, `reducedMotion: "user"` is the cleanest global solution.
|
|
381
|
+
- **Global transition defaults** — set a default transition for all motion components so individual components don't need to repeat the same `transition` prop.
|
|
382
|
+
- **Custom ease functions** — define a custom cubic-bezier ease once and reference it by name throughout the tree.
|
|
383
|
+
|
|
384
|
+
```tsx
|
|
385
|
+
<MotionConfig
|
|
386
|
+
transition={{ type: 'spring', stiffness: 300, damping: 25 }}
|
|
387
|
+
reducedMotion="user"
|
|
388
|
+
>
|
|
389
|
+
<App />
|
|
390
|
+
</MotionConfig>
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
With this configuration, every `motion` component that doesn't specify its own `transition` will use the spring default, and the reduced-motion preference is respected automatically.
|
|
394
|
+
|
|
395
|
+
---
|
|
396
|
+
|
|
397
|
+
## 11. Common Pitfalls (from UUPM react.csv data)
|
|
398
|
+
|
|
399
|
+
These are the mistakes that appear most frequently in codebases using Framer Motion:
|
|
400
|
+
|
|
401
|
+
**Missing `initial` with `animate`:** If you add `animate={{ opacity: 1 }}` without `initial={{ opacity: 0 }}`, the element is already at opacity 1 on mount — there's nothing to animate from. Always pair `animate` with `initial` when you want an entrance effect.
|
|
402
|
+
|
|
403
|
+
**Missing `key` props in `AnimatePresence`:** Exit animations will silently not fire if children of `AnimatePresence` don't have `key` props. Framer can't identify which element is leaving without a stable key.
|
|
404
|
+
|
|
405
|
+
**Variant propagation only reaches `motion` children:** Parent variants propagate to child `motion` components, but not to plain HTML children or non-motion React components. If a list item is a plain `<li>` instead of `<motion.li>`, it won't receive the parent's variant orchestration.
|
|
406
|
+
|
|
407
|
+
**`layoutId` conflicts:** If two components with the same `layoutId` are both mounted simultaneously — even briefly during a transition — Framer doesn't know which is the source and which is the target. The result is erratic, broken animation. Ensure mutual exclusivity: when one mounts, the other must have already unmounted.
|
|
408
|
+
|
|
409
|
+
**Unnecessary `AnimatePresence` nesting:** Nesting `AnimatePresence` inside another `AnimatePresence` complicates exit orchestration — inner exits may not complete before outer exits begin. Keep the tree flat; use a single `AnimatePresence` at the appropriate level.
|
|
410
|
+
|
|
411
|
+
**Wrapping everything in `motion.div`:** `motion.div` carries a slightly larger bundle footprint than a plain `div` because it registers the element with Framer's animation engine. Don't wrap static, unanimated elements. Only wrap elements that actually need animation. Reserve `motion.*` for elements where animation provides genuine value.
|