--- name: -interaction-design description: Interaction design for the project. State surfaces (modal vs inline vs drawer vs full-page), motion philosophy, input modes (touch/mouse/keyboard), breakpoints, i18n posture, empty/loading/error/offline state postures, time formatting, keyboard policy, optimistic-update strategy, gesture handling, and focus management. Load and apply whenever building UI behavior — modals, forms, navigation, transitions, gestures, error handling, async states, focus management, or any decision about how the interface responds. Pairs with -design-system. --- # interaction design > **Status: ** > Generated by Composer's `ui-system` phase. Re-running that phase > updates this skill (with confirmation on overwrite). ## How to use this skill When building UI *behavior* — anything beyond static styling — read this skill first. Don't invent new state-surface patterns, motion durations, or empty-state postures. They're declared once here and reused everywhere. For visual tokens (color, type, spacing), see the paired `-design-system` skill. If a screen needs a pattern that isn't declared here, propose it in this skill before writing the code — not the other way around. ## Input modes | Mode | Status | Notes | |---|---|---| | Touch | | <…> | | Mouse | <…> | <…> | | Keyboard | supported (always — a11y baseline) | full keyboard navigation required | | Voice | | — | | Switch / assistive | <…> | — | **Primary**: — design defaults assume this mode. ## State surfaces One pattern per action class. Used everywhere. If a screen needs a deviation, document it inline as an exception with a reason. | Action class | Pattern | Notes | |---|---|---| | Quick edit (single field) | | — | | Multi-field create | | — | | Multi-field edit | | usually same as create | | Confirm destructive | modal | always — non-negotiable | | Settings / configuration | full-page route | — | | Top-level navigation | | — | | Detail-from-list | | — | | Filtering / sorting | | — | | Search |
| — | ## Motion - **Posture**: - **Default duration / easing**: see design-system tokens (`motion.duration.default`, `motion.easing.standard`) ### Animation triggers | Trigger | Animated? | Duration / easing | |---|---|---| | Page / route transitions | | | | List item enter / exit | <…> | | | Modal / drawer open / close | <…> | | | State changes (toggle, expand) | <…> | | | Loading → loaded transitions | <…> | | | Hover / focus state changes | <…> | | ### Reduced motion `prefers-reduced-motion: reduce` is **always honored**. Fallback strategy: - Replace transitions with instant state changes. - Replace fades with instant show/hide. - Replace slides with crossfades or instant. - Keep hover/focus state changes (these are essential signals, not motion). ## Breakpoints | Breakpoint | Range | Purpose | |---|---|---| | Phone | < | <…> | | Tablet | | <…> | | Desktop | ≥ | <…> | | (Large desktop) | ≥ | optional | - **Primary design target**: - **Fluid scale ranges** *(if used)*: <…> - See `tokens.ts` `breakpoint` for px values. ## i18n - **Locales at launch**: - **RTL support**: - **Pluralization**: - **String length budget**: assume +30% over English for de/fr translations - **Date / number formatting**: `Intl.DateTimeFormat` / `Intl.NumberFormat` (locale-aware) - **Locale switching mechanism**: <…> ## State postures One declared posture per state, used everywhere. Per-screen variation is an exception that needs justification, not a default. ### Empty - **Visual**: - **Tone**: - **CTA**: - **Copy length**: keep to 1–2 sentences; the state itself communicates ### Loading - **Default pattern**: - **By action class**: - List / card containers: - Inline buttons: - Page-level: - **Threshold for showing loading at all**: ### Error - **Surface by class**: - Recoverable inline (validation): inline beneath the field - Recoverable async (network): toast with retry - Unrecoverable (system): dialog - **Recovery affordances**: - **Copy tone**: plain language, name what happened, name what to do next - **Copy length**: 1–2 sentences max - **Never** show stack traces, error codes without explanation, or "An error occurred" without specifics ### Offline - **Behavior**: - **Indicator**: - **Sync semantics**: - **Conflict resolution on reconnect**: ## Time formatting - **Relative time** for events within: - Pattern: "<3 hours ago>", "", "" - **Absolute time** otherwise: - Pattern: <`Intl.DateTimeFormat` locale-aware | explicit format> - Example: - **Date-only vs date+time**: show time when it matters (events, logs); date-only for ages, anniversaries, milestones - **Time zones**: - **Tooltip / hover**: relative-time displays should show absolute on hover ## Keyboard - **Global shortcuts**: - **Within-modal**: - `Esc` closes (always) - Focus trapped while open - Focus restored to trigger element on close - **Tab order**: declared per-flow as relevant; focus visible always (per design-system) - **Forms**: - `Enter` submits *(or Cmd+Enter for multi-line forms)* - `Esc` cancels destructive actions only - **Lists / menus**: - Arrow-key navigation: - `Home` / `End`: - Type-ahead select: ## Optimistic updates & error recovery - **Default posture**: - **Optimistic by default**: most actions feel fast; rollback on failure - **Pessimistic by default**: destructive actions, money flows, anything irreversible - **Mixed strategy** *(if applicable)*: - Optimistic for: - Pessimistic for: ### Rollback strategy - **UI on failure**: - **Retry affordance**: - **Stale data detection**: ### Conflict resolution - **Strategy**: - **User-visible signaling**: <…> ## Gestures (touch only) - **Swipe actions on rows**: - **Long-press menu**: - **Pull-to-refresh**: - **Pinch-to-zoom**: - **Edge-swipe back navigation**: ## Focus management - **After modal close**: restore focus to trigger element (always) - **After route change**: - **After form error**: focus first error field (always) - **After successful action that closes UI**: restore to a sensible parent - **On initial page load**: - **Focus visibility**: always visible per design-system tokens; no `outline: none` without a replacement ## Notification patterns - **Toasts**: - Position: - Duration: - Dismissible: yes - Stacking: - **Inline notifications / banners**: - **Dialogs**: - **Badge counts**: ## Selection & multi-select - **Single select**: - **Multi-select**: - **Trigger**: - **Action bar**: - **Bulk action limits**: - **Select-all**: ## Drag & drop - **Use cases**: - **Affordance**: - **Touch support**: - **Live preview**: ## TBD on return -