MigsLab UIVue 3 component workshop

Getting Started

Work with AI

Prompts and instructions for using an AI coding assistant (Claude Code, Cursor, Copilot, ChatGPT...) to integrate MigsLab into an existing Vue project.

How it works

  1. Download MigsLab and put the folder at src/MigsLab/shared in your project.
  2. The folder contains AI-INTEGRATION.md: the full rules and component API reference written for AI assistants.
  3. Pick a prompt below, fill in the bracketed parts, and paste it into your assistant.
  4. Review its first report (what it found in your project) before letting it change files.

Prompts

For assistants that can read your files. Each prompt points the assistant at AI-INTEGRATION.md so it uses the real API instead of guessing.

Install MigsLab into the project without touching existing pages.

Integrate the MigsLab Vue component library into this project.

The MigsLab component library is in src/MigsLab/shared. Before doing anything, read src/MigsLab/shared/AI-INTEGRATION.md and follow it exactly; use only the components, props and events it documents.

1. Inspect the project as described in section 1 of AI-INTEGRATION.md and report what you found. Wait for my OK before changing files.
2. Set up the library (sections 2 and 3): check the @ alias, decide whether to import styles/index.css based on our existing CSS, and map our brand color [#hex or "keep default"] to the --ml-* tokens.
3. Add one small demo usage on [page or component path] so I can see it working.
4. Run type-check and build, then report every file you changed.

Full instructions

The contents of MigsLab/shared/AI-INTEGRATION.md. If your assistant cannot read files (for example a chat window), paste this whole text before your request.

# MigsLab Integration Instructions (for AI assistants)

You are integrating **MigsLab Shared**, a copy-in Vue 3 + TypeScript component library, into an existing Vue project. Follow these instructions exactly. Do not invent components, props or events that are not listed here; when unsure, read the component's `.vue` file under `src/MigsLab/shared/components/`.

## 1. Inspect the project first

Before changing anything, report:

- Vue version (MigsLab needs **Vue 3.5+**: it uses `defineModel` and `useId`). If lower, stop and ask.
- Build tool (Vite expected) and whether the `@` alias points to `src` (check `vite.config.*` and `tsconfig*.json`).
- TypeScript or JavaScript. MigsLab files use `<script setup lang="ts">`; Vite compiles them in JS projects too, but `vue-tsc` type-checking only applies to TS projects.
- Existing CSS framework or reset (Tailwind, Bootstrap, Vuetify, PrimeVue, a custom reset).
- Existing UI components that MigsLab could replace.

## 2. Install the library

1. Place the folder at `src/MigsLab/shared` (from the ZIP or by copying it). Keep its internal structure unchanged.
2. If the project has no `@` → `src` alias, either add it (`vite.config`: `resolve.alias['@'] = fileURLToPath(new URL('./src', import.meta.url))`, and `compilerOptions.paths` `"@/*": ["./src/*"]` in the app tsconfig) or import with a relative path to `src/MigsLab/shared`.
3. Do not add npm dependencies. MigsLab only needs `vue`. It needs no icon font.

## 3. Styles

- Components only need the design tokens in `styles/tokens.css`. They load automatically when anything is imported from `@/MigsLab/shared/index.ts`.
- `styles/index.css` adds a CSS reset, the Geist font and **global utility classes** (`.row`, `.col-*`, `.container`, `.p-md`, `.mt-sm`, `.text-sm`, `.font-bold`, `.bg-*`, `.color-*`, `.shadow*`, `.d-flex`, ...).
  - Import it in `main.ts` (`import '@/MigsLab/shared/styles/index.css'`) **only** if the project has no CSS framework or reset.
  - If the project uses Tailwind, Bootstrap or another framework, **do not** import `index.css`; the class names would clash. Tokens alone are enough.
- Theme by overriding `--ml-*` variables in a global stylesheet loaded after MigsLab, e.g. map the project's brand color to `--ml-primary` / `--ml-primary-hover`. Never hard-code colors inside MigsLab files.

## 4. Using components

- Always import from the barrel: `import { ButtonComponent, type SelectOption } from '@/MigsLab/shared'`. Never import a component `.vue` file directly (that skips the tokens).
- Prefer explicit imports. Use the global plugin (`app.use(MigsLabShared, { prefix: 'Ml' })`) only if the user asks for it.
- Template props and events are kebab-case: `:items-per-page`, `@tag-added`.
- Compound components must be nested as shown below; their children throw an error outside their parent.

### API reference

| Component | v-model | Props | Events / slots |
|---|---|---|---|
| `ButtonComponent` | — | `color` 'primary'\|'secondary'\|'danger'\|'ghost', `size` 'sm'\|'md'\|'lg', `type`, `outlined`, `bordered`, `rounded`, `disabled`, `href` | `@click`; default slot |
| `ButtonGroupComponent` | — | — | default slot of `ButtonComponent`s |
| `ButtonMenuContainerComponent` | — | — | default slot (toolbar) |
| `ButtonDropdownComponent` | — | button props + `split-button`, `close-on-select` (true), `menu-align` 'left'\|'right' | `@action` (split mode); slots `#button`, `#menu` |
| `ButtonDropdownItemComponent` | — | `disabled` | `@select`; must be inside `#menu` |
| `AlertComponent` | — | `type` 'info'\|'success'\|'warning'\|'danger', `dismissible` (true), `duration` ms (0 = stay) | `@closed`; default slot |
| `CardComponent` + `CardHeaderComponent` / `CardBodyComponent` / `CardFooterComponent` | — | Card: `border` (true), `shadow` (true), `flat` | default slots |
| `ChipComponent` | — | `label`, `color` 'primary'\|'secondary'\|'success'\|'danger', `closable` | `@remove` |
| `DialogComponent` + `DialogHeaderComponent` / `DialogContentComponent` / `DialogFooterComponent` | `boolean` (open) | `is-persistent`, `show-close` (true), `max-width` ('32rem') | Teleported to body; Escape closes unless persistent |
| `AccordionComponent` > `AccordionItemComponent` > `AccordionTriggerComponent` + `AccordionContentComponent` | `string[]` (optional, open item values) | Accordion: `multiple` (true). Item: `value`, `default-open` | default slots |
| `TabComponent` > `TabListComponent` > `TabTriggerComponent`; `TabContentComponent` | `string` on `TabComponent` only | Trigger: `value`, `disabled`. Content: `value` | — |
| `TableComponent` > `TableHeaderComponent` / `TableBodyComponent` / `TableFooterComponent` | `v-model:selected` `(string\|number)[]` | `border-type` 'rows'\|'all'\|'columns'\|'none', `alternate-row-color`, `outer-border`, `hoverable`, `sticky-header`, `max-height`, `selectable`, `show-checkbox`, `multiple` (true) | slots `#header` (`<th>`s), `#body`, `#footer`; selectable rows use `TableRowComponent :value="id"` instead of `<tr>` |
| `PaginationComponent` | `v-model:page` `number` (1-based) | `total-items`, `items-per-page` | — |
| `InputComponent` | `string \| number` | `type` 'text'\|'numeric'\|'password'\|'email'\|'search'\|'tel'\|'url', `min`, `max` (numeric), `rounded`, `hover-border`; native attrs pass through | — |
| `TextAreaComponent` | `string` | `rows` (3), `rounded` | — |
| `DropdownComponent` | `string \| number` | `options: SelectOption[]`, `placeholder`, `text-only`, `text-size`, `disabled`, `native-breakpoint` (768) | — |
| `CheckboxComponent`, `SwitchToggleComponent` | `boolean` | `disabled` | default slot = label |
| `RadioGroupComponent` | `string \| number` | `options: SelectOption[]`, `direction` 'vertical'\|'horizontal', `name`, `disabled` | — |
| `RadioButtonComponent` | `string \| number` | `value`, `name`, `disabled` | default slot = label |
| `TagInputComponent` | `TagItem[]` | `placeholder`, `allow-duplicates`, `disabled` | `@tag-added`, `@tag-removed` |
| `ColorPickerComponent` | `string` (#rrggbb) | `disabled` | `@copied` |
| `FileUploadComponent` | `File[]` | `accept` ('jpg,png' or 'image/*'), `max-size` bytes, `multiple`, `disabled`, `button-text` | `@file-added`, `@file-removed`, `@file-rejected` |
| `DateTimePickerComponent` | `Date` | `mode` 'date'\|'time'\|'datetime', `format` (tokens yyyy MM dd HH hh mm ss tt), `min-year`, `max-year`, `disabled` | — |
| `IconComponent` | — | `name: IconName` (see `iconNames`), `size` (16), `stroke-width`, `spin` | — |

Types: `SelectOption { label, value, disabled? }`, `TagItem { id, label }`, `OptionValue = string | number`, plus `ButtonColor`, `ButtonSize`, `AlertType`, `ChipColor`, `TableBorderType`, `DateTimeMode`, `InputType`, `IconName`. Composable: `UseClickOutside(refElement, handler)`.

### Example

```vue
<template>
  <CardComponent>
    <CardHeaderComponent>Users</CardHeaderComponent>
    <CardBodyComponent>
      <TableComponent v-model:selected="selectedIds" show-checkbox hoverable>
        <template #header>
          <TableHeaderComponent><th>Name</th></TableHeaderComponent>
        </template>
        <template #body>
          <TableBodyComponent>
            <TableRowComponent v-for="user in users" :key="user.id" :value="user.id">
              <td>{{ user.name }}</td>
            </TableRowComponent>
          </TableBodyComponent>
        </template>
      </TableComponent>
    </CardBodyComponent>
    <CardFooterComponent>
      <ButtonComponent color="danger" rounded :disabled="!selectedIds.length" @click="isDeleteOpen = true">
        Delete
      </ButtonComponent>
    </CardFooterComponent>
  </CardComponent>

  <DialogComponent v-model="isDeleteOpen">
    <DialogHeaderComponent>Delete users?</DialogHeaderComponent>
    <DialogFooterComponent>
      <ButtonComponent color="ghost" @click="isDeleteOpen = false">Cancel</ButtonComponent>
      <ButtonComponent color="danger" @click="DeleteUsers_Click">Delete</ButtonComponent>
    </DialogFooterComponent>
  </DialogComponent>
</template>
```

## 5. Replacing existing components

- Work incrementally: one component type at a time, smallest blast radius first.
- Map each old prop/event to the MigsLab equivalent; keep the page's behavior identical. List anything without an equivalent and ask before dropping it.
- Do not remove the old component library or its dependency until the user confirms every usage is migrated.

## 6. Rules

- **Do not edit files inside `src/MigsLab/shared`** to solve an app-specific need. Wrap or compose components in the app instead. If a library change is truly needed, propose it separately and keep it generic.
- Follow the host project's existing conventions for app code. MigsLab's own code follows its coding standard: `<script setup lang="ts">`, type-based `defineProps`, `defineModel` for v-model, kebab-case events, PascalCase functions (`Save_Click`, `LoadUsersAsync`), scoped styles, `--ml-*` tokens.
- Give every `v-for` a stable `:key`.

## 7. Verify and report

1. Run the project's type-check and build (e.g. `npm run type-check`, `npm run build`) and fix new errors.
2. Start the dev server and open a page that uses MigsLab: components render with styles, interactive parts (dropdowns, dialogs, tabs) work, and the browser console has no errors.
3. Report: files added or changed, whether `styles/index.css` was imported and why, theme overrides, and any follow-ups.

Tips

  • Ask for one change at a time (set-up first, then one page or one component type) and review each diff.
  • If the assistant edits files inside src/MigsLab/shared for an app-specific need, ask it to undo that and wrap the component in the app instead.
  • On projects using Tailwind or Bootstrap, make sure it did not import styles/index.css — utility class names would clash.
  • When you update MigsLab later, replace the whole folder; your app code keeps working as long as it imports from @/MigsLab/shared.