da64f769da
- Added optional MCP integration settings in project-brief.yaml, allowing for environment-based server configurations. - Introduced conventions for strict package imports to enhance code organization and maintainability. - Updated brief schema to validate new MCP properties and ensure correct usage. - Implemented MCP JSON builder to generate .cursor/mcp.json based on project brief settings. - Enhanced resolver to include MCP configuration in generated files when enabled. This update improves integration capabilities and enforces coding standards across the project.
50 lines
2.4 KiB
Cheetah
50 lines
2.4 KiB
Cheetah
---
|
||
description: "UI/UX standards for {{PROJECT_NAME}}"
|
||
globs: ["lib/**/*.dart", "test/**/*.dart", "integration_test/**/*.dart"]
|
||
alwaysApply: false
|
||
---
|
||
|
||
# UI / UX Standards — {{PROJECT_NAME}}
|
||
|
||
## Theme & design tokens (single source of truth)
|
||
- Define **one** light/dark `ThemeData` (and optional `ThemeExtension`s for brand spacing, radii, semantic colors). Feature code reads `Theme.of(context)` only.
|
||
- **Colors:** `colorScheme` / extensions — never hex/`Color(...)` literals in widgets except inside the theme definition file(s).
|
||
- **Typography:** `textTheme` / `primaryTextTheme` — never raw `TextStyle(fontSize:, fontFamily:)` in feature UI.
|
||
- **Spacing & shapes:** `ThemeExtension` or documented constants consumed consistently — avoid one-off magic numbers for padding/radius.
|
||
|
||
## Loading states
|
||
- Every async operation MUST show a loading skeleton (shimmer), NOT a spinner unless < 300ms
|
||
- Use `shimmer` package with a shimmer that matches the final layout shape
|
||
- Never show a blank screen during loading — skeleton must fill the same space as the content
|
||
|
||
## Empty states
|
||
- Every list/grid MUST have a distinct empty state widget: illustration + headline + CTA
|
||
- Empty state is different from error state — never reuse the same widget for both
|
||
- Empty state copy: positive framing ("No items yet — add your first one")
|
||
|
||
## Error states
|
||
- Every async failure MUST show: error message + retry button
|
||
- Never swallow errors silently
|
||
- Error text: user-friendly, never expose stack traces or raw API messages
|
||
|
||
## Navigation & transitions
|
||
- Use `IndexedStack` for bottom nav tabs — preserves scroll position
|
||
- Named routes only — never `Navigator.push(context, MaterialPageRoute(...))`
|
||
- Page transitions: use `CustomTransitionPage` with `FadeTransition` for modal sheets
|
||
|
||
## Responsive layout
|
||
- Use `LayoutBuilder` or `MediaQuery` for breakpoints, not hardcoded pixel values
|
||
- Minimum touch target: 48×48 logical pixels (Material guideline)
|
||
- Test on 375px (iPhone SE) and 414px (iPhone Pro Max) widths minimum
|
||
|
||
## Haptics
|
||
- Use `HapticFeedback.lightImpact()` on primary CTAs
|
||
- Use `HapticFeedback.selectionClick()` on toggle/checkbox interactions
|
||
- Never add haptics to destructive actions without confirmation
|
||
|
||
## Accessibility
|
||
- All interactive widgets must have a `Semantics` label or `tooltip`
|
||
- Minimum contrast ratio: 4.5:1 (WCAG AA)
|
||
- Test with TalkBack / VoiceOver before each release
|
||
{{HIGH_CONTRAST_UX_LINE}}
|