フロントエンドの実装・レビューを行う人向け。
Misskey uses Vue(v3) as its front-end framework.
- Use TypeScript.
- When creating a new component, please use the Composition API (with
<script setup>,ref, andcomputed) instead of the Options API.- Some of the existing components are implemented in the Options API, but it is an old implementation. Refactors that migrate those components to the Composition API are also welcome.
アイコンは、Production Build時に使用されていないものが削除されるようになっています。
アイコンを動的に設定する際には、 ti-${someVal} のような、アイコン名のみを動的に変化させる実装を行わないでください。
必ず ti-xxx のような完全なクラス名を含めるようにしてください。
niraxは、Misskeyで使用しているオリジナルのフロントエンドルーティングシステムです。 vue-routerから影響を多大に受けているので、まずはvue-routerについて学ぶことをお勧めします。
ルート定義は、以下の形式のオブジェクトの配列です。
{
name?: string;
path: string;
component: Component;
query?: Record<string, string>;
loginRequired?: boolean;
hash?: string;
children?: RouteDef[];
}Warning
現状、ルートは定義された順に評価されます。
たとえば、/foo/:idルート定義の次に/foo/barルート定義がされていた場合、後者がマッチすることはありません。
vue-routerとの最大の違いは、niraxは複数のルーターが存在することを許可している点です。 これにより、アプリ内ウィンドウでブラウザとは個別にルーティングすることなどが可能になります。
Misskey uses Storybook for UI development.
pnpm --filter misskey-js buildpnpm --filter frontend storybook-devFor components matched by the glob allowlist in packages/frontend/.storybook/generate.tsx, the story file (for example, MyComponent.stories.ts for MyComponent.vue) will be automatically generated by the compiled .storybook/generate.js script.
If your new component is not matched by the allowlist, add it to the components list in generate.tsx. Creating a .stories.impl.ts file alone does not add a component to the generation targets.
You can override the default story by creating a impl story file (MyComponent.stories.impl.ts).
/* eslint-disable @typescript-eslint/explicit-function-return-type */
import { StoryObj } from '@storybook/vue3';
import MyComponent from './MyComponent.vue';
export const Default = {
render(args) {
return {
components: {
MyComponent,
},
setup() {
return {
args,
};
},
computed: {
props() {
return {
...this.args,
};
},
},
template: '<MyComponent v-bind="props" />',
};
},
args: {
foo: 'bar',
},
parameters: {
layout: 'centered',
},
} satisfies StoryObj<typeof MyComponent>;If you want to opt-out from the automatic generation, create a MyComponent.stories.impl.ts file and add the following line to the file.
import MyComponent from './MyComponent.vue';
void MyComponent;You can override the component meta by creating a meta story file (MyComponent.stories.meta.ts).
export const argTypes = {
scale: {
control: {
type: 'range',
min: 1,
max: 4,
},
},
};Also, you can use msw to mock API requests in the storybook. Creating a MyComponent.stories.msw.ts file to define the mock handlers.
import { HttpResponse, http } from 'msw';
export const handlers = [
http.post('/api/notes/timeline', ({ request }) => {
return HttpResponse.json([]);
}),
];After changing the allowlist or adding, editing, or removing the above files, run pnpm --filter frontend build-storybook-pre from the repository root to compile and run the generator again.
Vueのコンポーネントのdataオプションとしてmisskey.jsのコネクションを設定するとき、必ずmarkRawでラップしてください。インスタンスが不必要にリアクティブ化されることで、misskey.js内の処理で不具合が発生するとともに、パフォーマンス上の問題にも繋がる。なお、Composition APIを使う場合はこの限りではない(リアクティブ化はマニュアルなため)。
コンポーネント自身がmarginを設定するのは問題の元となることはよく知られている marginはそのコンポーネントを使う側が設定する
広告ブロッカーで誤ってブロックされる
color: hsl(from var(--MI_THEME-accent) h s calc(l + 10));color: hsl(from var(--MI_THEME-accent) h s calc(l - 10));color: color(from var(--MI_THEME-accent) srgb r g b / 0.5);