@valentia-ai-skills/framework 2.0.6 → 2.0.8
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/README.md +157 -13
- package/bin/cli.js +873 -103
- package/package.json +1 -1
- package/skills/global/aisupportapp-project-architecture/SKILL.md +1 -1
- package/skills/global/aisupportapp-project-conventions/SKILL.md +1 -1
- package/skills/global/aisupportapp-project-workflows/SKILL.md +1 -1
- package/skills/global/api-design/SKILL.md +1 -1
- package/skills/global/appointment-oas-app/SKILL.md +1 -1
- package/skills/global/code-quality-auditor/SKILL.md +704 -0
- package/skills/global/code-standards/SKILL.md +1 -1
- package/skills/global/codebase-legacy-intelligence/SKILL.md +1 -1
- package/skills/global/legacy-api-converter/SKILL.md +979 -0
- package/skills/global/legacy-redevelopment-planner/SKILL.md +622 -0
- package/skills/global/observability-integrations/SKILL.md +835 -0
- package/skills/global/project-scanner/SKILL.md +1 -1
- package/skills/global/ui-replication-engine/SKILL.md +591 -0
- package/skills/global/aisupportapp-test-installation/SKILL.md +0 -32
- package/skills/global/viteapp-core-workflows/SKILL.md +0 -32
|
@@ -0,0 +1,591 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ui-replication-engine
|
|
3
|
+
description: Pixel-perfect UI replication skill that takes any design input — Figma exports, screenshots, images, HTML mockups, Google Sites pages, PDFs, wireframes, or any visual reference — and produces an exact React replica using Tailwind CSS for layout/spacing and Mantine UI for all interactive controls. This skill obsesses over visual fidelity: every pixel, every shadow, every border radius, every font weight, every spacing value must match the source. Use this skill whenever someone asks to: replicate a UI, convert a design to React, build a page from a screenshot, turn a Figma design into code, copy a UI from an image, reproduce a layout, clone a website's look, convert HTML to React, rebuild a page from a mockup, match a design exactly, or create a pixel-perfect implementation. Also trigger when someone says things like "make this look exactly like this", "copy this UI", "replicate this screen", "build this from the screenshot", "convert this Figma to React", "match this design precisely", "I need this UI in React", "clone this layout", "rebuild this interface", or "reproduce this page". This skill outputs React components with Tailwind CSS and Mantine UI only — no other UI frameworks, no raw HTML form elements, no CSS-in-JS, no styled-components, no CSS modules
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
scope: global
|
|
6
|
+
last_reviewed: 2026-04-02
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
name: ui-replication-engine
|
|
11
|
+
description: >
|
|
12
|
+
Pixel-perfect UI replication skill that takes any design input — Figma exports, screenshots,
|
|
13
|
+
images, HTML mockups, Google Sites pages, PDFs, wireframes, or any visual reference — and
|
|
14
|
+
produces an exact React replica using Tailwind CSS for layout/spacing and Mantine UI for all
|
|
15
|
+
interactive controls. This skill obsesses over visual fidelity: every pixel, every shadow,
|
|
16
|
+
every border radius, every font weight, every spacing value must match the source. Use this
|
|
17
|
+
skill whenever someone asks to: replicate a UI, convert a design to React, build a page from
|
|
18
|
+
a screenshot, turn a Figma design into code, copy a UI from an image, reproduce a layout,
|
|
19
|
+
clone a website's look, convert HTML to React, rebuild a page from a mockup, match a design
|
|
20
|
+
exactly, or create a pixel-perfect implementation. Also trigger when someone says things like
|
|
21
|
+
"make this look exactly like this", "copy this UI", "replicate this screen", "build this from
|
|
22
|
+
the screenshot", "convert this Figma to React", "match this design precisely", "I need this
|
|
23
|
+
UI in React", "clone this layout", "rebuild this interface", or "reproduce this page".
|
|
24
|
+
This skill outputs React components with Tailwind CSS and Mantine UI only — no other UI
|
|
25
|
+
frameworks, no raw HTML form elements, no CSS-in-JS, no styled-components, no CSS modules.
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
# UI Replication Engine
|
|
29
|
+
|
|
30
|
+
You are a pixel-obsessed frontend engineer. Your single job is to take a visual reference — any format, any source — and produce a React component that is **visually indistinguishable** from the original. Not "similar." Not "inspired by." Identical.
|
|
31
|
+
|
|
32
|
+
## Core Rules — Never Break These
|
|
33
|
+
|
|
34
|
+
1. **Tailwind CSS for ALL layout and spacing**: Flexbox, grid, padding, margin, gap, width, height, positioning, responsive breakpoints, colors, backgrounds, borders, shadows, typography sizing — all Tailwind utility classes. No inline styles for layout. No custom CSS files.
|
|
35
|
+
|
|
36
|
+
2. **Mantine UI for ALL interactive controls**: Buttons, inputs, selects, date pickers, checkboxes, radio buttons, switches, modals, drawers, tabs, accordions, steppers, tooltips, notifications, menus, dropdowns, sliders, file uploads, progress bars — every interactive element MUST be a Mantine component. **Raw HTML form elements (`<input>`, `<select>`, `<button>`, `<textarea>`) are PROHIBITED.** If you see an input in the design, it's a Mantine `TextInput`. If you see a button, it's a Mantine `Button`. No exceptions.
|
|
37
|
+
|
|
38
|
+
3. **Mantine's style props for component-level overrides**: When a Mantine component needs visual tweaks to match the design (specific border radius, custom padding inside a component, color variants), use Mantine's `styles` prop or `classNames` prop with Tailwind classes. Do not fight Mantine — work with its API.
|
|
39
|
+
|
|
40
|
+
4. **Zero visual deviation**: If the design has 16px padding, you use `p-4`. If it has a 1px border with #E5E7EB color, you use `border border-gray-200`. If a shadow is `0 1px 3px rgba(0,0,0,0.1)`, you use `shadow-sm`. Match EVERYTHING.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Step 0: Analyze the Input
|
|
45
|
+
|
|
46
|
+
### Supported Input Formats
|
|
47
|
+
|
|
48
|
+
Accept ANY of these as the design source:
|
|
49
|
+
|
|
50
|
+
**Images**: Screenshots, photos of screens, exported PNGs/JPGs from any tool
|
|
51
|
+
**Figma**: Exported frames, Figma URLs (describe what you see), Figma dev mode exports
|
|
52
|
+
**HTML/CSS**: Raw HTML files, CodePen links, full web pages
|
|
53
|
+
**PDFs**: Design specs, wireframes, mockups exported as PDF
|
|
54
|
+
**Live URLs**: "Make it look like this website" — analyze the visual design
|
|
55
|
+
**Google Sites / Stitch / Webflow**: Screenshots or exported HTML
|
|
56
|
+
**Wireframes**: Balsamiq, Sketch, hand-drawn wireframes (interpret visual intent)
|
|
57
|
+
**Design Systems**: "Use this component library's look" with reference images
|
|
58
|
+
|
|
59
|
+
### Analysis Protocol
|
|
60
|
+
|
|
61
|
+
When you receive the design input:
|
|
62
|
+
|
|
63
|
+
1. **Identify every visual element** — enumerate everything you see: headers, navigation, cards, forms, tables, lists, images, icons, dividers, badges, tooltips, modals, sidebars, footers. Miss nothing.
|
|
64
|
+
|
|
65
|
+
2. **Extract the design tokens**:
|
|
66
|
+
- **Colors**: Every unique color — backgrounds, text, borders, accents, hovers, active states. Map each to the nearest Tailwind color or define as custom if no match.
|
|
67
|
+
- **Typography**: Font family, sizes (map to Tailwind: text-xs through text-9xl), weights (font-light through font-black), line heights, letter spacing.
|
|
68
|
+
- **Spacing**: Padding, margins, gaps — map to Tailwind's spacing scale (1=4px, 2=8px, 3=12px, 4=16px, etc.)
|
|
69
|
+
- **Borders**: Width, style, color, radius (rounded-sm through rounded-full)
|
|
70
|
+
- **Shadows**: Map to Tailwind shadow scale (shadow-sm, shadow, shadow-md, shadow-lg, shadow-xl, shadow-2xl)
|
|
71
|
+
- **Layout**: Flex vs grid, column counts, responsive breakpoints, container widths
|
|
72
|
+
|
|
73
|
+
3. **Identify the page structure**:
|
|
74
|
+
- Is it a full page or a component?
|
|
75
|
+
- What's the layout pattern? (sidebar + content, top nav + body, wizard/stepper, dashboard grid, split panel, single column)
|
|
76
|
+
- What's scrollable vs fixed?
|
|
77
|
+
- What's the responsive behavior?
|
|
78
|
+
|
|
79
|
+
4. **Identify interactive elements**:
|
|
80
|
+
- Every form input → which Mantine component?
|
|
81
|
+
- Every button → Mantine Button with which variant/size/color?
|
|
82
|
+
- Every dropdown → Mantine Select or Menu?
|
|
83
|
+
- Every modal/drawer → Mantine Modal or Drawer?
|
|
84
|
+
- Every tab set → Mantine Tabs?
|
|
85
|
+
- Every table → Mantine Table?
|
|
86
|
+
- Every notification/toast → Mantine Notification?
|
|
87
|
+
|
|
88
|
+
5. **Check for legacy project documentation**:
|
|
89
|
+
- If a legacy intelligence package exists (`.ai-skills/legacy-projects/{project}/` or `./{project}-intelligence/`), READ it before building.
|
|
90
|
+
- Check `DATA_MODELS.md` for the data shapes the UI should render
|
|
91
|
+
- Check `API_REGISTRY.md` for the endpoints the UI should call
|
|
92
|
+
- Check `BUSINESS_RULES.md` for validation rules, field constraints, conditional display logic
|
|
93
|
+
- Check `MASTER_SKILL.md` for architecture context
|
|
94
|
+
- Check module `SKILL.md` files for the specific module being built
|
|
95
|
+
- The legacy docs tell you WHAT data flows through the UI and WHAT rules govern it. The design input tells you HOW it should look. You need both.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Step 1: Plan the Component Architecture
|
|
100
|
+
|
|
101
|
+
Before writing any code, plan the component tree.
|
|
102
|
+
|
|
103
|
+
### Output a Component Map:
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
PageName/
|
|
107
|
+
├── PageName.tsx ← Page-level component (layout, data fetching)
|
|
108
|
+
├── components/
|
|
109
|
+
│ ├── Header.tsx ← Top navigation/header
|
|
110
|
+
│ ├── Sidebar.tsx ← Side navigation (if present)
|
|
111
|
+
│ ├── {FeatureName}Card.tsx ← Repeated card components
|
|
112
|
+
│ ├── {FeatureName}Form.tsx ← Form sections
|
|
113
|
+
│ ├── {FeatureName}Table.tsx ← Table/list sections
|
|
114
|
+
│ └── {FeatureName}Modal.tsx ← Modals/drawers
|
|
115
|
+
├── hooks/
|
|
116
|
+
│ └── use{FeatureName}.ts ← Custom hooks for data/state
|
|
117
|
+
└── types/
|
|
118
|
+
└── index.ts ← TypeScript interfaces
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Component Boundaries:
|
|
122
|
+
- Each visually distinct section = its own component
|
|
123
|
+
- Repeated patterns (cards in a grid, rows in a list) = extracted component
|
|
124
|
+
- Forms with complex state = their own component with internal state management
|
|
125
|
+
- Modals/drawers = always separate components
|
|
126
|
+
- Keep components under 150 lines — if longer, split
|
|
127
|
+
|
|
128
|
+
### Present the plan to the user:
|
|
129
|
+
"Here's how I'll structure this. Does this look right, or should I split/merge anything?"
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Step 2: Extract Design Tokens into Tailwind Config
|
|
134
|
+
|
|
135
|
+
If the design uses colors or spacing not in Tailwind's default palette, extend the config:
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
// tailwind.config.ts
|
|
139
|
+
import type { Config } from 'tailwindcss'
|
|
140
|
+
|
|
141
|
+
const config: Config = {
|
|
142
|
+
content: ['./src/**/*.{ts,tsx}'],
|
|
143
|
+
theme: {
|
|
144
|
+
extend: {
|
|
145
|
+
colors: {
|
|
146
|
+
// Map custom colors from the design
|
|
147
|
+
'brand': {
|
|
148
|
+
50: '#f0f9ff',
|
|
149
|
+
100: '#e0f2fe',
|
|
150
|
+
// ... full scale
|
|
151
|
+
600: '#0284c7', // primary action color from design
|
|
152
|
+
700: '#0369a1', // hover state
|
|
153
|
+
},
|
|
154
|
+
'surface': '#F8F9FA', // card backgrounds
|
|
155
|
+
'border-subtle': '#E9ECEF', // light borders
|
|
156
|
+
},
|
|
157
|
+
spacing: {
|
|
158
|
+
// Only if design uses non-standard spacing
|
|
159
|
+
'18': '4.5rem',
|
|
160
|
+
'88': '22rem',
|
|
161
|
+
},
|
|
162
|
+
borderRadius: {
|
|
163
|
+
// If design uses custom radii
|
|
164
|
+
'card': '12px',
|
|
165
|
+
},
|
|
166
|
+
boxShadow: {
|
|
167
|
+
// If design uses custom shadows
|
|
168
|
+
'card': '0 2px 8px rgba(0, 0, 0, 0.08)',
|
|
169
|
+
'card-hover': '0 4px 16px rgba(0, 0, 0, 0.12)',
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
plugins: [],
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export default config
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Mantine Theme Alignment:
|
|
180
|
+
|
|
181
|
+
Align Mantine's theme with the extracted design tokens so Mantine components match:
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
// theme.ts
|
|
185
|
+
import { createTheme } from '@mantine/core'
|
|
186
|
+
|
|
187
|
+
export const theme = createTheme({
|
|
188
|
+
primaryColor: 'brand', // matches Tailwind brand color
|
|
189
|
+
colors: {
|
|
190
|
+
brand: [
|
|
191
|
+
'#f0f9ff', '#e0f2fe', '#bae6fd', '#7dd3fc', '#38bdf8',
|
|
192
|
+
'#0ea5e9', '#0284c7', '#0369a1', '#075985', '#0c4a6e'
|
|
193
|
+
],
|
|
194
|
+
},
|
|
195
|
+
fontFamily: 'Inter, -apple-system, sans-serif', // match design font
|
|
196
|
+
defaultRadius: 'md', // match design's default border radius
|
|
197
|
+
components: {
|
|
198
|
+
Button: {
|
|
199
|
+
defaultProps: {
|
|
200
|
+
radius: 'md',
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
TextInput: {
|
|
204
|
+
defaultProps: {
|
|
205
|
+
radius: 'md',
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
Select: {
|
|
209
|
+
defaultProps: {
|
|
210
|
+
radius: 'md',
|
|
211
|
+
},
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
})
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Step 3: Build — Pixel by Pixel
|
|
220
|
+
|
|
221
|
+
### The Process:
|
|
222
|
+
|
|
223
|
+
Work top-to-bottom, left-to-right through the design. For each visual section:
|
|
224
|
+
|
|
225
|
+
1. **Layout first**: Build the container, flex/grid structure, spacing — all Tailwind
|
|
226
|
+
2. **Content next**: Text, headings, labels, descriptions — Tailwind typography
|
|
227
|
+
3. **Interactive elements last**: Replace every control with the correct Mantine component
|
|
228
|
+
|
|
229
|
+
### Tailwind Patterns for Common Layouts:
|
|
230
|
+
|
|
231
|
+
**Full-page with sidebar:**
|
|
232
|
+
```tsx
|
|
233
|
+
<div className="flex h-screen">
|
|
234
|
+
<aside className="w-64 shrink-0 border-r border-gray-200 bg-white">
|
|
235
|
+
{/* Sidebar */}
|
|
236
|
+
</aside>
|
|
237
|
+
<main className="flex-1 overflow-auto bg-gray-50">
|
|
238
|
+
{/* Content */}
|
|
239
|
+
</main>
|
|
240
|
+
</div>
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
**Dashboard grid:**
|
|
244
|
+
```tsx
|
|
245
|
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 p-6">
|
|
246
|
+
{/* Cards */}
|
|
247
|
+
</div>
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
**Card component:**
|
|
251
|
+
```tsx
|
|
252
|
+
<div className="rounded-lg border border-gray-200 bg-white p-6 shadow-sm">
|
|
253
|
+
{/* Card content */}
|
|
254
|
+
</div>
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
**Split panel (form left, preview right):**
|
|
258
|
+
```tsx
|
|
259
|
+
<div className="flex gap-6">
|
|
260
|
+
<div className="flex-1">{/* Left panel */}</div>
|
|
261
|
+
<div className="w-96 shrink-0">{/* Right panel */}</div>
|
|
262
|
+
</div>
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
**Sticky header + scrollable content:**
|
|
266
|
+
```tsx
|
|
267
|
+
<div className="flex flex-col h-screen">
|
|
268
|
+
<header className="shrink-0 border-b border-gray-200 bg-white px-6 py-4">
|
|
269
|
+
{/* Header */}
|
|
270
|
+
</header>
|
|
271
|
+
<main className="flex-1 overflow-auto p-6">
|
|
272
|
+
{/* Scrollable content */}
|
|
273
|
+
</main>
|
|
274
|
+
</div>
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Mantine Component Mapping:
|
|
278
|
+
|
|
279
|
+
When you see this in the design → use this Mantine component:
|
|
280
|
+
|
|
281
|
+
| Design Element | Mantine Component | Notes |
|
|
282
|
+
|---------------|-------------------|-------|
|
|
283
|
+
| Text input | `TextInput` | With `label`, `placeholder`, `description`, `error` props |
|
|
284
|
+
| Password field | `PasswordInput` | |
|
|
285
|
+
| Email field | `TextInput` with type="email" | |
|
|
286
|
+
| Phone field | `TextInput` with type="tel" | |
|
|
287
|
+
| Text area | `Textarea` | |
|
|
288
|
+
| Dropdown/select | `Select` | Use `data` prop for options |
|
|
289
|
+
| Multi-select | `MultiSelect` | |
|
|
290
|
+
| Searchable dropdown | `Select` with `searchable` | |
|
|
291
|
+
| Checkbox | `Checkbox` | |
|
|
292
|
+
| Checkbox group | `Checkbox.Group` | |
|
|
293
|
+
| Radio buttons | `Radio.Group` with `Radio` | |
|
|
294
|
+
| Toggle/switch | `Switch` | |
|
|
295
|
+
| Date picker | `DateInput` or `DatePickerInput` | |
|
|
296
|
+
| Time picker | `TimeInput` | |
|
|
297
|
+
| Date range | `DatePickerInput` with `type="range"` | |
|
|
298
|
+
| File upload | `FileInput` or `Dropzone` | |
|
|
299
|
+
| Slider/range | `Slider` or `RangeSlider` | |
|
|
300
|
+
| Number input | `NumberInput` | |
|
|
301
|
+
| Color picker | `ColorInput` or `ColorPicker` | |
|
|
302
|
+
| Rating/stars | `Rating` | |
|
|
303
|
+
| Primary button | `Button` | variant="filled" |
|
|
304
|
+
| Secondary button | `Button` with `variant="outline"` | |
|
|
305
|
+
| Ghost/text button | `Button` with `variant="subtle"` | |
|
|
306
|
+
| Icon button | `ActionIcon` | |
|
|
307
|
+
| Button group | `Button.Group` | |
|
|
308
|
+
| Tabs | `Tabs` with `Tabs.Tab` | |
|
|
309
|
+
| Accordion | `Accordion` with `Accordion.Item` | |
|
|
310
|
+
| Modal/dialog | `Modal` | |
|
|
311
|
+
| Drawer/side panel | `Drawer` | |
|
|
312
|
+
| Tooltip | `Tooltip` | |
|
|
313
|
+
| Popover | `Popover` | |
|
|
314
|
+
| Menu/dropdown menu | `Menu` with `Menu.Item` | |
|
|
315
|
+
| Notification/toast | `Notification` or `notifications.show()` | |
|
|
316
|
+
| Progress bar | `Progress` | |
|
|
317
|
+
| Loading spinner | `Loader` | |
|
|
318
|
+
| Skeleton/placeholder | `Skeleton` | |
|
|
319
|
+
| Badge/tag | `Badge` | |
|
|
320
|
+
| Avatar | `Avatar` or `Avatar.Group` | |
|
|
321
|
+
| Breadcrumbs | `Breadcrumbs` | |
|
|
322
|
+
| Pagination | `Pagination` | |
|
|
323
|
+
| Stepper/wizard | `Stepper` with `Stepper.Step` | |
|
|
324
|
+
| Table | `Table` | Wrap in `Table.ScrollContainer` if wide |
|
|
325
|
+
| Alert/banner | `Alert` | |
|
|
326
|
+
| Chip/tag selector | `Chip` or `Chip.Group` | |
|
|
327
|
+
| Segmented control | `SegmentedControl` | |
|
|
328
|
+
| Navbar links | `NavLink` | |
|
|
329
|
+
| Divider/separator | `Divider` | |
|
|
330
|
+
|
|
331
|
+
### Styling Mantine Components to Match:
|
|
332
|
+
|
|
333
|
+
When a Mantine component doesn't match the design out of the box, override using:
|
|
334
|
+
|
|
335
|
+
**Option 1: Tailwind via `className`** (for outer wrapper):
|
|
336
|
+
```tsx
|
|
337
|
+
<TextInput className="w-full" label="Email" />
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
**Option 2: Mantine `styles` prop** (for internal parts):
|
|
341
|
+
```tsx
|
|
342
|
+
<TextInput
|
|
343
|
+
label="Email"
|
|
344
|
+
styles={{
|
|
345
|
+
input: { borderColor: '#E5E7EB', fontSize: '14px' },
|
|
346
|
+
label: { fontWeight: 600, marginBottom: '4px' },
|
|
347
|
+
}}
|
|
348
|
+
/>
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
**Option 3: Mantine `classNames` prop with Tailwind** (best of both worlds):
|
|
352
|
+
```tsx
|
|
353
|
+
<TextInput
|
|
354
|
+
label="Email"
|
|
355
|
+
classNames={{
|
|
356
|
+
input: 'border-gray-200 text-sm',
|
|
357
|
+
label: 'font-semibold mb-1 text-gray-700',
|
|
358
|
+
}}
|
|
359
|
+
/>
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
Prefer Option 3 when possible — keeps everything in Tailwind's utility system.
|
|
363
|
+
|
|
364
|
+
---
|
|
365
|
+
|
|
366
|
+
## Step 4: Icon Matching
|
|
367
|
+
|
|
368
|
+
### Icon Strategy:
|
|
369
|
+
|
|
370
|
+
1. **Check if Mantine has it**: `@tabler/icons-react` comes with Mantine. Check Tabler Icons first.
|
|
371
|
+
2. **Lucide React**: If Tabler doesn't have the exact icon, use `lucide-react`.
|
|
372
|
+
3. **Heroicons**: For UI icons common in Tailwind ecosystems.
|
|
373
|
+
4. **Custom SVG**: As last resort, extract from the design.
|
|
374
|
+
|
|
375
|
+
```tsx
|
|
376
|
+
// Prefer Tabler (ships with Mantine)
|
|
377
|
+
import { IconSearch, IconUser, IconSettings } from '@tabler/icons-react'
|
|
378
|
+
|
|
379
|
+
// Fallback to Lucide
|
|
380
|
+
import { Search, User, Settings } from 'lucide-react'
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### Icon Sizing:
|
|
384
|
+
Match the design exactly. Tabler icons use `size` prop:
|
|
385
|
+
```tsx
|
|
386
|
+
<IconSearch size={20} className="text-gray-500" />
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
---
|
|
390
|
+
|
|
391
|
+
## Step 5: Responsive Behavior
|
|
392
|
+
|
|
393
|
+
If the design shows multiple breakpoints (desktop + tablet + mobile), implement all of them.
|
|
394
|
+
|
|
395
|
+
If only one breakpoint is shown, implement that as the primary and add sensible responsive behavior:
|
|
396
|
+
|
|
397
|
+
```tsx
|
|
398
|
+
{/* Desktop: 3 columns, Tablet: 2 columns, Mobile: 1 column */}
|
|
399
|
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
400
|
+
|
|
401
|
+
{/* Desktop: side-by-side, Mobile: stacked */}
|
|
402
|
+
<div className="flex flex-col lg:flex-row gap-6">
|
|
403
|
+
|
|
404
|
+
{/* Hide on mobile, show on desktop */}
|
|
405
|
+
<aside className="hidden lg:block w-64">
|
|
406
|
+
|
|
407
|
+
{/* Full width on mobile, constrained on desktop */}
|
|
408
|
+
<div className="w-full max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
### Mantine's responsive props:
|
|
412
|
+
Some Mantine components support responsive props:
|
|
413
|
+
```tsx
|
|
414
|
+
<SimpleGrid cols={{ base: 1, sm: 2, lg: 3 }}>
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
Use Mantine's responsive system for Mantine components, Tailwind's breakpoints for layout.
|
|
418
|
+
|
|
419
|
+
---
|
|
420
|
+
|
|
421
|
+
## Step 6: State & Interactivity
|
|
422
|
+
|
|
423
|
+
### Form State:
|
|
424
|
+
Use Mantine's `useForm` for form management:
|
|
425
|
+
|
|
426
|
+
```tsx
|
|
427
|
+
import { useForm } from '@mantine/form'
|
|
428
|
+
|
|
429
|
+
const form = useForm({
|
|
430
|
+
initialValues: {
|
|
431
|
+
email: '',
|
|
432
|
+
name: '',
|
|
433
|
+
role: '',
|
|
434
|
+
},
|
|
435
|
+
validate: {
|
|
436
|
+
email: (value) => (/^\S+@\S+$/.test(value) ? null : 'Invalid email'),
|
|
437
|
+
name: (value) => (value.length < 2 ? 'Name too short' : null),
|
|
438
|
+
},
|
|
439
|
+
})
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
### Validation Rules from Legacy Docs:
|
|
443
|
+
If legacy project documentation exists, pull validation rules directly from `BUSINESS_RULES.md`:
|
|
444
|
+
|
|
445
|
+
```tsx
|
|
446
|
+
// From BUSINESS_RULES.md Rule booking.003: "Phone must be NZ format"
|
|
447
|
+
validate: {
|
|
448
|
+
phone: (value) => /^(\+64|0)\d{7,10}$/.test(value) ? null : 'Must be valid NZ phone number',
|
|
449
|
+
}
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
### Loading States:
|
|
453
|
+
Every async action needs a loading state:
|
|
454
|
+
```tsx
|
|
455
|
+
<Button loading={isSubmitting} onClick={handleSubmit}>
|
|
456
|
+
Submit
|
|
457
|
+
</Button>
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
### Conditional Rendering from Business Rules:
|
|
461
|
+
If `BUSINESS_RULES.md` says "Show payment section only when total > 0":
|
|
462
|
+
```tsx
|
|
463
|
+
{total > 0 && (
|
|
464
|
+
<div className="mt-6 border-t border-gray-200 pt-6">
|
|
465
|
+
{/* Payment section */}
|
|
466
|
+
</div>
|
|
467
|
+
)}
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
---
|
|
471
|
+
|
|
472
|
+
## Step 7: Quality Gate — The Pixel Test
|
|
473
|
+
|
|
474
|
+
Before delivering, verify every element:
|
|
475
|
+
|
|
476
|
+
### Visual Checklist:
|
|
477
|
+
- [ ] **Colors**: Every background, text, border, icon color matches the design
|
|
478
|
+
- [ ] **Typography**: Every font size, weight, family, line height, letter spacing matches
|
|
479
|
+
- [ ] **Spacing**: Every padding, margin, gap matches (check with Tailwind spacing scale)
|
|
480
|
+
- [ ] **Borders**: Every border width, style, color, radius matches
|
|
481
|
+
- [ ] **Shadows**: Every shadow matches (depth, spread, color, offset)
|
|
482
|
+
- [ ] **Icons**: Every icon matches the design (correct icon, correct size, correct color)
|
|
483
|
+
- [ ] **Images**: Placeholder images or actual images in the correct aspect ratio and position
|
|
484
|
+
- [ ] **Alignment**: Every element is aligned exactly as in the design (left, center, right, baseline)
|
|
485
|
+
- [ ] **Hover states**: If the design shows hover states, they're implemented
|
|
486
|
+
- [ ] **Active/focus states**: Input focus rings, button active states
|
|
487
|
+
- [ ] **Empty states**: If the design shows empty/zero states, they're implemented
|
|
488
|
+
- [ ] **Error states**: If the design shows error states (red borders, error messages), they're implemented
|
|
489
|
+
- [ ] **Loading states**: Skeleton loaders or spinners where data would load
|
|
490
|
+
|
|
491
|
+
### Code Checklist:
|
|
492
|
+
- [ ] **No raw HTML form elements**: Zero `<input>`, `<select>`, `<button>`, `<textarea>` tags — all Mantine
|
|
493
|
+
- [ ] **No inline styles for layout**: All layout via Tailwind classes
|
|
494
|
+
- [ ] **No CSS files**: Everything is Tailwind utilities or Mantine style props
|
|
495
|
+
- [ ] **TypeScript**: All components properly typed, interfaces defined
|
|
496
|
+
- [ ] **Component size**: No component over 150 lines
|
|
497
|
+
- [ ] **Responsive**: Works on mobile, tablet, desktop (or matches design's target viewport)
|
|
498
|
+
|
|
499
|
+
### Comparison Method:
|
|
500
|
+
If working from an image/screenshot, mentally overlay your output on the design:
|
|
501
|
+
- Is anything shifted left/right by even 4px? Fix it.
|
|
502
|
+
- Is any text a shade different? Fix it.
|
|
503
|
+
- Is any spacing off by even one Tailwind unit? Fix it.
|
|
504
|
+
- Is any border radius wrong? Fix it.
|
|
505
|
+
|
|
506
|
+
The standard is not "close enough." The standard is "I cannot tell the difference."
|
|
507
|
+
|
|
508
|
+
---
|
|
509
|
+
|
|
510
|
+
## Step 8: Deliver
|
|
511
|
+
|
|
512
|
+
### Single Component:
|
|
513
|
+
If the design is a single screen, deliver as one file with extracted sub-components.
|
|
514
|
+
|
|
515
|
+
### Multi-Page Application:
|
|
516
|
+
Deliver as a component folder:
|
|
517
|
+
|
|
518
|
+
```
|
|
519
|
+
{FeatureName}/
|
|
520
|
+
├── index.tsx ← Re-exports
|
|
521
|
+
├── {PageName}.tsx ← Page component
|
|
522
|
+
├── components/
|
|
523
|
+
│ ├── {Component}.tsx ← Each visual section
|
|
524
|
+
│ └── ...
|
|
525
|
+
├── hooks/
|
|
526
|
+
│ └── use{Feature}.ts ← Data/state hooks
|
|
527
|
+
└── types/
|
|
528
|
+
└── index.ts ← Interfaces
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
### Always Include:
|
|
532
|
+
1. The component code (React + Tailwind + Mantine)
|
|
533
|
+
2. Any Tailwind config extensions needed
|
|
534
|
+
3. Any Mantine theme customizations needed
|
|
535
|
+
4. A brief note on which Mantine packages need to be installed (`@mantine/core`, `@mantine/form`, `@mantine/dates`, etc.)
|
|
536
|
+
|
|
537
|
+
---
|
|
538
|
+
|
|
539
|
+
## Handling Ambiguity
|
|
540
|
+
|
|
541
|
+
When the design is unclear (blurry screenshot, incomplete mockup, wireframe without colors):
|
|
542
|
+
|
|
543
|
+
1. **Ask first**: "I can see the layout but the colors are unclear. Should I use [your best guess from the design] or do you have a color palette?"
|
|
544
|
+
2. **Use sensible defaults**: If you must guess, use Mantine's default theme colors — they're professional and neutral.
|
|
545
|
+
3. **Flag assumptions**: "I assumed this is a Select dropdown based on the arrow icon. Let me know if it should be something else."
|
|
546
|
+
4. **Never skip elements**: If something is partially visible or unclear, implement your best interpretation and flag it. Do not leave gaps.
|
|
547
|
+
|
|
548
|
+
---
|
|
549
|
+
|
|
550
|
+
## Working with Legacy Documentation
|
|
551
|
+
|
|
552
|
+
When legacy project documentation is available, it supercharges your replication:
|
|
553
|
+
|
|
554
|
+
### What Each Document Gives You:
|
|
555
|
+
|
|
556
|
+
| Document | What You Get For UI |
|
|
557
|
+
|----------|-------------------|
|
|
558
|
+
| `DATA_MODELS.md` | TypeScript interfaces, field names, types for forms and tables |
|
|
559
|
+
| `API_REGISTRY.md` | Endpoint URLs, request/response shapes for data fetching hooks |
|
|
560
|
+
| `BUSINESS_RULES.md` | Validation rules, conditional display logic, field constraints, error messages |
|
|
561
|
+
| `MASTER_SKILL.md` | Architecture context, module relationships, auth patterns |
|
|
562
|
+
| Module `SKILL.md` | Specific module's endpoints, rules, data models — everything for that screen |
|
|
563
|
+
| `GLOSSARY.md` | Domain terms — use correct labels in the UI |
|
|
564
|
+
|
|
565
|
+
### Priority Order:
|
|
566
|
+
1. **The visual design is the PRIMARY source** — match it exactly
|
|
567
|
+
2. **Legacy docs are SUPPLEMENTARY** — they tell you what data to wire up, what rules to enforce, and what labels to use
|
|
568
|
+
3. **If the design contradicts the docs** (e.g., design shows a field that docs say shouldn't exist), follow the design and flag the discrepancy
|
|
569
|
+
|
|
570
|
+
### Example Integration:
|
|
571
|
+
|
|
572
|
+
Design shows a patient form. Legacy `BUSINESS_RULES.md` has:
|
|
573
|
+
```
|
|
574
|
+
Rule patient.003: NHI number must be 3 letters + 4 digits
|
|
575
|
+
Rule patient.007: Date of birth cannot be in the future
|
|
576
|
+
Rule patient.012: Email is required if notification preference is "email"
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
Your implementation:
|
|
580
|
+
```tsx
|
|
581
|
+
const form = useForm({
|
|
582
|
+
validate: {
|
|
583
|
+
nhi: (v) => /^[A-Z]{3}\d{4}$/.test(v) ? null : 'NHI must be 3 letters + 4 digits',
|
|
584
|
+
dateOfBirth: (v) => v > new Date() ? 'Date of birth cannot be in the future' : null,
|
|
585
|
+
email: (v, values) =>
|
|
586
|
+
values.notificationPref === 'email' && !v ? 'Email required for email notifications' : null,
|
|
587
|
+
},
|
|
588
|
+
})
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
The design tells you WHERE the fields go. The rules tell you HOW to validate them.
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: aisupportapp/test-installation
|
|
3
|
-
description: No description
|
|
4
|
-
version: 1.0.0
|
|
5
|
-
scope: project
|
|
6
|
-
last_reviewed: 2026-03-29
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# Skill Name
|
|
10
|
-
|
|
11
|
-
## Overview
|
|
12
|
-
|
|
13
|
-
Describe what this skill covers and when it should be applied.
|
|
14
|
-
|
|
15
|
-
## 1. First Rule
|
|
16
|
-
|
|
17
|
-
- Rule details here
|
|
18
|
-
- Use clear, actionable language
|
|
19
|
-
|
|
20
|
-
```typescript
|
|
21
|
-
// ✅ Good
|
|
22
|
-
const example = 'good pattern'
|
|
23
|
-
|
|
24
|
-
// ❌ Bad
|
|
25
|
-
const example = 'bad pattern'
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
## Checklist
|
|
29
|
-
|
|
30
|
-
- [ ] First check
|
|
31
|
-
- [ ] Second check
|
|
32
|
-
- [ ] Third check
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: viteapp/core-workflows
|
|
3
|
-
description: No description
|
|
4
|
-
version: 1.0.0
|
|
5
|
-
scope: project
|
|
6
|
-
last_reviewed: 2026-03-29
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# Skill Name
|
|
10
|
-
|
|
11
|
-
## Overview
|
|
12
|
-
|
|
13
|
-
Describe what this skill covers and when it should be applied.
|
|
14
|
-
|
|
15
|
-
## 1. First Rule
|
|
16
|
-
|
|
17
|
-
- Rule details here
|
|
18
|
-
- Use clear, actionable language
|
|
19
|
-
|
|
20
|
-
```typescript
|
|
21
|
-
// ✅ Good
|
|
22
|
-
const example = 'good pattern'
|
|
23
|
-
|
|
24
|
-
// ❌ Bad
|
|
25
|
-
const example = 'bad pattern'
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
## Checklist
|
|
29
|
-
|
|
30
|
-
- [ ] First check
|
|
31
|
-
- [ ] Second check
|
|
32
|
-
- [ ] Third check
|