--- name: add-mk-component description: Misskey フロントエンドの新規 Vue 3 コンポーネントを追加する。Mk* 命名 / SPDX (HTML コメント) / ``` ### 規約ポイント | 項目 | 規約 | |---|---| | ` ``` ### `os` の主なヘルパー (詳細は [os.ts](../../../packages/frontend/src/os.ts)) | 関数 | 用途 | |---|---| | `os.alert({ type, title?, text })` | 単方向アラート | | `os.confirm({ type, title, text })` | yes/no 確認 (`{ canceled }` を返す) | | `os.toast(message)` | 一時通知 | | `os.popup(component, props, handlers)` | 任意コンポーネントの非同期ポップアップ | | `os.popupMenu(items, anchor?)` | コンテキストメニュー | | `os.form(title, fields)` | フォームダイアログ | | `os.apiWithDialog(endpoint, data)` | API 呼出し + エラー時ダイアログ表示 | ## ステップ 5: Storybook ストーリー併設 [MkButton.stories.impl.ts](../../../packages/frontend/src/components/MkButton.stories.impl.ts) を雛形として参考にする。`.stories.impl.ts` も `packages/frontend/src/` 配下の `.ts` ファイルなので [AGENTS.md §1 SPDX ヘッダー必須](../../../AGENTS.md#1-spdx-ヘッダー必須) の対象であり、冒頭に SPDX ヘッダーを必ず付ける (HTML コメント形式ではなく `/* */` 形式)。形式 (以下の `MkXxx` は実際のコンポーネント名に置換する): ```ts /* * SPDX-FileCopyrightText: syuilo and misskey-project * SPDX-License-Identifier: AGPL-3.0-only */ /* eslint-disable @typescript-eslint/explicit-function-return-type */ /* eslint-disable import/no-default-export */ import type { StoryObj } from '@storybook/vue3'; import MkXxx from './MkXxx.vue'; export const Default = { render(args) { return { components: { MkXxx }, setup() { return { args }; }, template: 'slot content', }; }, args: { variant: 'primary', }, parameters: { layout: 'centered', }, } satisfies StoryObj; ``` `Vue` SFC は default export なので、`import MkXxx from './MkXxx.vue';` のように名前付き import ではなく default import で書く。実行確認は `pnpm --filter frontend storybook-dev`。 ## ステップ 6: Lint と typecheck ```bash pnpm --filter frontend lint ``` (typecheck = vue-tsc 等、ESLint = `@misskey-dev/eslint-plugin` 含む) ESLint --fix をピンポイントで: ```bash pnpm exec eslint --fix packages/frontend/src/components/Mk.vue ``` ## ステップ 7: 既存コンポーネントとの整合性確認 - 似た用途の既存 `Mk*` コンポーネントを参考に、スタイルやプロップ命名を揃える。 - `_button` / `_panel` / `_selectable` などの **共通 utility class** (グローバルスタイルにある) を活用できるか確認する。 - 大きな機能なら、Storybook stories で各バリエーションを網羅する。 ## 参照ファイル - [MkInfo.vue (シンプル例)](../../../packages/frontend/src/components/MkInfo.vue) - [MkButton.vue (汎用ボタン例)](../../../packages/frontend/src/components/MkButton.vue) - [MkInput.vue (generics + 多機能例)](../../../packages/frontend/src/components/MkInput.vue) - [MkButton.stories.impl.ts (Storybook 雛形)](../../../packages/frontend/src/components/MkButton.stories.impl.ts) - [packages/frontend/src/os.ts](../../../packages/frontend/src/os.ts) - [packages/frontend/src/i18n.ts](../../../packages/frontend/src/i18n.ts)