@kiva/kv-components 8.9.1 → 8.10.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/SKILLS.md +31 -0
- package/dist/index.js +160 -158
- package/dist/utils/pieChartColors.d.ts +4 -0
- package/dist/utils/pieChartColors.js +42 -0
- package/dist/utils/useCountUp.d.ts +5 -0
- package/dist/utils/useCountUp.js +7 -0
- package/dist/vue/KvPieChartV2.css +1 -0
- package/dist/vue/KvPieChartV2.js +143 -0
- package/dist/vue/KvPieChartV2.vue.d.ts +202 -0
- package/dist/vue/KvPieChartV22.js +232 -0
- package/dist/vue/KvProgressCircle.vue.d.ts +1 -1
- package/dist/vue/index.d.ts +1 -0
- package/docs/make-to-vue.md +264 -0
- package/package.json +2 -2
|
@@ -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.
|
|
3
|
+
"version": "8.10.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -125,5 +125,5 @@
|
|
|
125
125
|
"embla-carousel-fade",
|
|
126
126
|
"popper.js"
|
|
127
127
|
],
|
|
128
|
-
"gitHead": "
|
|
128
|
+
"gitHead": "25f78f14c54f336e18ea171c603bd02686785974"
|
|
129
129
|
}
|