@kiva/kv-components 8.9.1 → 8.11.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.
@@ -0,0 +1,264 @@
1
+ ---
2
+ name: make-to-vue
3
+ description: Use when porting a Figma Make (or other React) component into a Vue 3 component for @kiva/kv-components — typically triggered by a request like "port this to Vue", "convert this React component", or when the user shares Figma Make code, a Figma Make URL, or a Figma file link.
4
+ ---
5
+
6
+ # Figma Make to Vue Component Porting Guide
7
+
8
+ A repeatable process for converting Figma Make-generated React components into Vue 3 components for `@kiva/kv-components`.
9
+
10
+ ## How to Use This Skill
11
+
12
+ **Announce at start:** "I'm using the make-to-vue skill to port `<ComponentName>` into kv-components."
13
+
14
+ Then walk the [Procedure](#procedure) below in order. Each phase has explicit verification steps; do not move to the next phase until the current one passes. If any **Stop-and-ask** condition fires, pause and check with the user before continuing.
15
+
16
+ ### Inputs You Need Before Starting
17
+
18
+ Before Phase 1, confirm you have at least one of the following. If none are present, **stop and ask the user** which they can provide:
19
+
20
+ - React/TSX source code for the component (pasted, attached, or saved into the repo — `/source-files/` at the repo root is a suggested location but not required)
21
+ - A Figma Make URL (so the source can be inspected/exported)
22
+ - A Figma file or frame link for the target design (for visual reference, color, and spacing verification)
23
+
24
+ Screenshots help but are not a substitute for source code or a Figma link.
25
+
26
+ ### Stop-and-Ask Conditions
27
+
28
+ Pause and ask the user rather than guessing when:
29
+
30
+ - No source code or Figma Make URL is available — porting from a screenshot alone will produce drift.
31
+ - The component overlaps an existing kv-components component (see Phase 1.2). Confirm whether to extend the existing one, create a `V2`, or build a new component.
32
+ - Hardcoded colors don't map cleanly to a design token. Confirm the intended token rather than inventing a new hex.
33
+ - The source uses an animation library (`motion/react`, `framer-motion`, etc.) and the equivalent CSS transition would visibly differ. Confirm whether to match exactly or adapt.
34
+ - Accessibility behavior is unclear (e.g., what should screen readers announce, what should keyboard interactions trigger).
35
+
36
+ ## Procedure
37
+
38
+ The [Quick Reference: Porting Checklist](#quick-reference-porting-checklist) at the end of this doc is the spine — work through it top-to-bottom. The phases below elaborate each step. After every phase, run the listed verification before moving on.
39
+
40
+ ### Verification Gates
41
+
42
+ | After Phase | Verify |
43
+ |-------------|--------|
44
+ | 1 (Analysis) | You can name the props, state, sub-components, animations, and existing equivalents. If not, re-read the source. |
45
+ | 2 (Translation) | Component renders in Storybook with representative data and no console errors. |
46
+ | 3 (Structure) | Component is exported in `src/vue/index.ts` and visible in Storybook sidebar under the correct folder prefix. |
47
+ | 4 (Design system) | No raw hex colors or pixel spacing remain unless the user explicitly approved them. |
48
+ | 5 (Testing) | `npm run test` passes (lint + jest), including `jest-axe` accessibility check. |
49
+ | 6 (Storybook) | Default + edge-case stories render correctly under visual review. |
50
+
51
+ If a verification fails, fix the underlying issue before continuing — do not paper over it to keep moving.
52
+
53
+ ## Prerequisites
54
+
55
+ - Source React code available (see [Inputs You Need Before Starting](#inputs-you-need-before-starting))
56
+ - Familiarity with the target component's Figma design (request links/screenshots if needed)
57
+ - Read `@kiva/kv-components/AGENTS.md` for component development patterns
58
+
59
+ ## Phase 1: Analysis
60
+
61
+ ### 1.1 Read the React Source
62
+
63
+ Read the source file and identify:
64
+
65
+ - **Props and data model** — What data does the component accept? Is it hardcoded or dynamic?
66
+ - **State management** — React hooks (`useState`, `useEffect`, `useRef`) that need Vue equivalents
67
+ - **Sub-components** — Internal components that may become part of the Vue file or separate utils
68
+ - **External dependencies** — Libraries used (e.g., `motion/react`, `framer-motion`)
69
+ - **Styling approach** — Tailwind classes, inline styles, CSS modules
70
+
71
+ ### 1.2 Check for Existing Equivalents
72
+
73
+ ```
74
+ # Check if a similar component already exists
75
+ Glob: @kiva/kv-components/src/vue/Kv*<ComponentName>*.vue
76
+
77
+ # Check for reusable utils
78
+ Glob: @kiva/kv-components/src/utils/**/*
79
+ ```
80
+
81
+ Decide: new component, v2 of existing, or enhancement to existing.
82
+
83
+ ### 1.3 Identify What Changes
84
+
85
+ Figma Make output is presentational/demo code. Determine what needs to change:
86
+
87
+ - **Hardcoded data** -> Dynamic props
88
+ - **Hardcoded colors** -> Design system tokens from `@kiva/kv-tokens/primitives.js`
89
+ - **Fixed dimensions** -> Container-responsive sizing
90
+ - **Presentational strings** -> Configurable via props/slots
91
+ - **React animation libraries** -> CSS transitions or Vue composables (prefer no extra deps)
92
+
93
+ ## Phase 2: Translation Patterns
94
+
95
+ ### 2.1 React Hooks to Vue Composition API
96
+
97
+ | React | Vue 3 |
98
+ |-------|-------|
99
+ | `useState(value)` | `ref(value)` |
100
+ | `useEffect(() => {}, [deps])` | `watch(deps, () => {})` or `onMounted(() => {})` |
101
+ | `useRef(null)` | `ref(null)` or `templateRef` |
102
+ | `useMemo(() => {}, [deps])` | `computed(() => {})` |
103
+ | `useCallback(() => {}, [deps])` | Plain function (no memoization needed in Vue) |
104
+ | Custom hooks | Composables in `src/utils/use*.ts` |
105
+
106
+ ### 2.2 JSX to Vue Template
107
+
108
+ | React JSX | Vue Template |
109
+ |-----------|-------------|
110
+ | `{condition && <div>}` | `<div v-if="condition">` |
111
+ | `{items.map(item => <X key={item.id} />)}` | `<X v-for="item in items" :key="item.id" />` |
112
+ | `className="..."` | `class="..."` |
113
+ | `style={{ color: 'red' }}` | `:style="{ color: 'red' }"` |
114
+ | `onClick={handler}` | `@click="handler"` |
115
+ | `{children}` | `<slot />` |
116
+ | `<motion.div animate={...}>` | CSS transitions or Vue transition components |
117
+
118
+ ### 2.3 Styling Translation
119
+
120
+ Figma Make outputs raw Tailwind classes. Convert to kv-components patterns:
121
+
122
+ - **Add `tw-` prefix** to all Tailwind utility classes
123
+ - **Replace hardcoded font families** with design system fonts (`tw-font-sans`, `tw-font-serif`)
124
+ - **Replace hardcoded colors** with token references where possible
125
+ - **Replace pixel values** in Tailwind classes with spacing scale values (8px increments)
126
+ - **Use design tokens** from `@kiva/kv-tokens/primitives.js` for colors, spacing, typography
127
+
128
+ ### 2.4 Animation Translation
129
+
130
+ Prefer CSS transitions over JavaScript animation libraries:
131
+
132
+ | Figma Make / React | Vue Equivalent |
133
+ |--------------------|----------------|
134
+ | `motion/react` animate prop | CSS `transition` property |
135
+ | `transition={{ duration: 0.5 }}` | `transition: property 500ms ease-in-out` |
136
+ | Staggered animations | Computed `transition-delay` per item index |
137
+ | Spring animations | CSS `cubic-bezier()` or `ease-in-out` |
138
+ | `requestAnimationFrame` hooks | Vue composable with `onMounted`/`onUnmounted` lifecycle |
139
+ | Opacity/transform tweens | CSS transitions on those properties |
140
+
141
+ For complex numeric animations (count-up, interpolation), create a composable in `src/utils/`:
142
+
143
+ ```ts
144
+ // src/utils/useCountUp.ts
145
+ import { ref, watch, onUnmounted } from 'vue';
146
+
147
+ export function useCountUp(target: Ref<number>, active: Ref<boolean>, duration = 500) {
148
+ // requestAnimationFrame-based tween with easing
149
+ // Returns reactive ref with current display value
150
+ }
151
+ ```
152
+
153
+ ## Phase 3: Component Structure
154
+
155
+ ### 3.1 File Creation Checklist
156
+
157
+ 1. `src/vue/Kv<Name>.vue` — Main component
158
+ 2. `src/utils/<utilName>.ts` — Extracted logic (composables, helpers)
159
+ 3. `src/vue/stories/Kv<Name>.stories.ts` — Storybook stories (create EARLY)
160
+ 4. `tests/unit/specs/components/Kv<Name>.spec.ts` — Component tests
161
+ 5. `tests/unit/specs/utils/<utilName>.spec.ts` — Utility tests
162
+ 6. Export in `src/vue/index.ts`
163
+
164
+ ### 3.2 Component Patterns
165
+
166
+ Follow these kv-components conventions:
167
+
168
+ - **Script**: `<script lang="ts">` with `export default { setup() {} }` or `<script setup lang="ts">`
169
+ - **Styling**: `<style lang="postcss" scoped>` for component-specific styles
170
+ - **Props**: TypeScript typed with JSDoc for Storybook auto-docs
171
+ - **Naming**: `Kv` prefix, PascalCase (e.g., `KvPieChartV2`)
172
+ - **Accessibility**: ARIA attributes, semantic HTML, keyboard support
173
+ - **No references to the source framework**: The shipped Vue component is the source of truth — code, comments, and JSDoc must not mention "React", "Figma Make", "the React source", etc. Strip these as you translate, and double-check before committing.
174
+
175
+ ### 3.3 When to Extract Utils
176
+
177
+ Extract into `src/utils/` when:
178
+ - Logic involves lifecycle management (rAF, timers, observers)
179
+ - Logic is reusable across components
180
+ - Logic is complex enough to benefit from independent unit testing
181
+ - The main component file would exceed ~300 lines without extraction
182
+
183
+ ## Phase 4: Design System Integration
184
+
185
+ ### 4.1 Colors
186
+
187
+ Always check `@kiva/kv-tokens/primitives.js` for existing color tokens before using hardcoded hex values. Map Figma Make colors to the closest token:
188
+
189
+ ```js
190
+ import kvTokensPrimitives from '@kiva/kv-tokens';
191
+ const { colors } = kvTokensPrimitives;
192
+ // colors['eco-green'].DEFAULT, colors.marigold['3'], etc.
193
+ ```
194
+
195
+ ### 4.2 Typography
196
+
197
+ Map Figma Make font references:
198
+ - `Kiva Post Grot:Book` -> `font-weight: 300` (light/book)
199
+ - `Kiva Post Grot:Medium` -> `font-weight: 500` (medium)
200
+ - Font family -> `tw-font-sans` (PostGrotesk)
201
+
202
+ ### 4.3 Spacing
203
+
204
+ Convert pixel values to the 8px spacing scale:
205
+ - `4px` -> `tw-p-0.5`
206
+ - `8px` -> `tw-p-1`
207
+ - `16px` -> `tw-p-2`
208
+ - etc.
209
+
210
+ ## Phase 5: Testing
211
+
212
+ ### 5.1 Test Requirements
213
+
214
+ Every ported component must have:
215
+
216
+ 1. **Accessibility test** — jest-axe `toHaveNoViolations()`
217
+ 2. **Rendering tests** — correct output for various prop combinations
218
+ 3. **Interaction tests** — click/hover/keyboard behaviors
219
+ 4. **Edge cases** — empty data, single item, maximum items
220
+ 5. **Utility tests** — independent tests for extracted composables/helpers
221
+
222
+ ### 5.2 Test Structure
223
+
224
+ ```ts
225
+ import { render } from '@testing-library/vue';
226
+ import { axe } from 'jest-axe';
227
+ import KvComponentName from '#components/KvComponentName.vue';
228
+
229
+ describe('KvComponentName', () => {
230
+ it('should have no automated accessibility violations', async () => {
231
+ const { container } = render(KvComponentName, { props: { /* ... */ } });
232
+ const results = await axe(container);
233
+ expect(results).toHaveNoViolations();
234
+ });
235
+
236
+ // ... rendering, interaction, edge case tests
237
+ });
238
+ ```
239
+
240
+ ## Phase 6: Storybook
241
+
242
+ Create stories early in the process for visual review:
243
+
244
+ 1. **Default story** with representative data
245
+ 2. **Loading/skeleton state**
246
+ 3. **Edge cases** (empty, single item, many items)
247
+ 4. **Prop variations** (different modes, sizes, configurations)
248
+ 5. **Interactive controls** via argTypes
249
+
250
+ ## Quick Reference: Porting Checklist
251
+
252
+ - [ ] Read React source, identify hooks/state/deps/sub-components
253
+ - [ ] Check for existing kv-components equivalents
254
+ - [ ] Map hardcoded values to design system tokens
255
+ - [ ] Create Storybook story early for visual review
256
+ - [ ] Translate React hooks to Vue Composition API
257
+ - [ ] Convert JSX to Vue template with `tw-` prefix classes
258
+ - [ ] Replace animation libraries with CSS transitions
259
+ - [ ] Extract complex logic into `src/utils/` composables
260
+ - [ ] Export component in `src/vue/index.ts`
261
+ - [ ] Write component tests with jest-axe accessibility check
262
+ - [ ] Write utility tests for extracted logic
263
+ - [ ] Review in Storybook across stories
264
+ - [ ] Run `npm run test` (lint + jest)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kiva/kv-components",
3
- "version": "8.9.1",
3
+ "version": "8.11.0",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -34,7 +34,7 @@
34
34
  "@babel/preset-env": "^7.24.8",
35
35
  "@babel/preset-react": "^7.24.7",
36
36
  "@babel/preset-typescript": "^7.24.7",
37
- "@kiva/kv-tokens": "^3.7.6",
37
+ "@kiva/kv-tokens": "^4.0.0",
38
38
  "@kiva/vite-plugin-vue-lib-css": "^2.0.0",
39
39
  "@laynezh/vite-plugin-lib-assets": "^0.6.1",
40
40
  "@mdi/js": "^7.4.47",
@@ -101,7 +101,7 @@
101
101
  "lint": "eslint --ext .ts,.vue ./",
102
102
  "test": "npm run lint && jest",
103
103
  "prebuild": "node build/copyFlags.js",
104
- "build": "vite build",
104
+ "build": "rimraf dist && vite build",
105
105
  "postbuild": "mkdir -p ../../dist/kvui && mv -v dist/kvui/* ../../dist/kvui/"
106
106
  },
107
107
  "peerDependencies": {
@@ -125,5 +125,5 @@
125
125
  "embla-carousel-fade",
126
126
  "popper.js"
127
127
  ],
128
- "gitHead": "ff3cad55e305990584c6d393f118b979987720ba"
128
+ "gitHead": "adc213db33b85ed8e36aff18b14bff6db7093fdd"
129
129
  }