docs: note about Storybook
This commit is contained in:
parent
c2d8759812
commit
bd7cc6ac38
6 changed files with 90 additions and 47 deletions
|
@ -203,6 +203,90 @@ niraxは、Misskeyで使用しているオリジナルのフロントエンド
|
||||||
vue-routerとの最大の違いは、niraxは複数のルーターが存在することを許可している点です。
|
vue-routerとの最大の違いは、niraxは複数のルーターが存在することを許可している点です。
|
||||||
これにより、アプリ内ウィンドウでブラウザとは個別にルーティングすることなどが可能になります。
|
これにより、アプリ内ウィンドウでブラウザとは個別にルーティングすることなどが可能になります。
|
||||||
|
|
||||||
|
## Storybook
|
||||||
|
|
||||||
|
Misskey uses [Storybook](https://storybook.js.org/) for UI development.
|
||||||
|
|
||||||
|
### Setup
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd path/to/packages/frontend
|
||||||
|
pnpm tsc -p .storybook && (node .storybook/generate.js & node .storybook/preload-locale.js & node .storybook/preload-theme.js)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Run
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd path/to/packages/frontend
|
||||||
|
pnpm storybook dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
When you create a new component (in this example, `MyComponent.vue`), the story file (`MyComponent.stories.ts`) will be automatically generated by the `.storybook/generate.js` script.
|
||||||
|
You can override the default story by creating a impl story file (`MyComponent.stories.impl.ts`).
|
||||||
|
|
||||||
|
```ts
|
||||||
|
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
||||||
|
/* eslint-disable import/no-duplicates */
|
||||||
|
import { StoryObj } from '@storybook/vue3';
|
||||||
|
import MyComponent from './MyComponent.vue';
|
||||||
|
export const Default = {
|
||||||
|
render(args) {
|
||||||
|
return {
|
||||||
|
components: {
|
||||||
|
MyComponent,
|
||||||
|
},
|
||||||
|
setup() {
|
||||||
|
return {
|
||||||
|
args,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
props() {
|
||||||
|
return {
|
||||||
|
...args,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
template: '<MyComponent v-bind="props" />',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
args: {
|
||||||
|
foo: 'bar',
|
||||||
|
},
|
||||||
|
parameters: {
|
||||||
|
layout: 'centered',
|
||||||
|
},
|
||||||
|
} satisfies StoryObj<typeof MkAvatar>;
|
||||||
|
```
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import MyComponent from './MyComponent.vue';
|
||||||
|
void MyComponent;
|
||||||
|
```
|
||||||
|
|
||||||
|
You can use msw to mock API requests in the storybook. Creating a `MyComponent.stories.msw.ts` file and add the following line to the file.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { rest } from 'msw';
|
||||||
|
export const handlers = [
|
||||||
|
rest.post('/api/notes/timeline', (req, res, ctx) => {
|
||||||
|
return res(
|
||||||
|
ctx.json({
|
||||||
|
notes: [],
|
||||||
|
users: [],
|
||||||
|
hasNext: false,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
```
|
||||||
|
|
||||||
|
Don't forget to re-run the `.storybook/generate.js` script after adding, editing, or removing the above files.
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
### How to resolve conflictions occurred at pnpm-lock.yaml?
|
### How to resolve conflictions occurred at pnpm-lock.yaml?
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { resolve } from 'node:path';
|
import { resolve } from 'node:path';
|
||||||
import type { StorybookConfig } from '@storybook/vue3-vite';
|
import type { StorybookConfig } from '@storybook/vue3-vite';
|
||||||
import { mergeConfig } from 'vite';
|
import { mergeConfig } from 'vite';
|
||||||
import { getConfig } from '../vite.config';
|
|
||||||
const config = {
|
const config = {
|
||||||
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
|
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
|
||||||
addons: [
|
addons: [
|
||||||
|
@ -22,18 +21,9 @@ const config = {
|
||||||
disableTelemetry: true,
|
disableTelemetry: true,
|
||||||
},
|
},
|
||||||
async viteFinal(config, options) {
|
async viteFinal(config, options) {
|
||||||
const { plugins, build: { rollupOptions, ...build }, ...original } = getConfig();
|
return mergeConfig(config, {
|
||||||
console.dir(config, {depth:Infinity});
|
|
||||||
console.dir(original, {depth:Infinity});
|
|
||||||
const x = mergeConfig(config, {
|
|
||||||
...original,
|
|
||||||
build,
|
|
||||||
assetsInclude: [resolve(__dirname, '../node_modules/@tabler/icons-webfont/**/*.{css,eot,ttf,woff,woff2}')],
|
assetsInclude: [resolve(__dirname, '../node_modules/@tabler/icons-webfont/**/*.{css,eot,ttf,woff,woff2}')],
|
||||||
server: {
|
|
||||||
hmr: false,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
return x;
|
|
||||||
},
|
},
|
||||||
} satisfies StorybookConfig;
|
} satisfies StorybookConfig;
|
||||||
export default config;
|
export default config;
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
import MkCaptcha from './MkCaptcha.vue';
|
||||||
|
void MkCaptcha;
|
|
@ -1,34 +1,10 @@
|
||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
||||||
/* eslint-disable import/no-default-export */
|
/* eslint-disable import/no-default-export */
|
||||||
import { Meta, StoryObj } from '@storybook/vue3';
|
import { Meta } from '@storybook/vue3';
|
||||||
import MkCaptcha from './MkCaptcha.vue';
|
|
||||||
const meta = {
|
const meta = {
|
||||||
title: 'components/MkCaptcha',
|
title: 'components/MkCaptcha',
|
||||||
component: MkCaptcha,
|
component: MkCaptcha,
|
||||||
} satisfies Meta<typeof MkCaptcha>;
|
} satisfies Meta<typeof MkCaptcha>;
|
||||||
export const Default = {
|
|
||||||
render(args) {
|
|
||||||
return {
|
|
||||||
components: {
|
|
||||||
MkCaptcha,
|
|
||||||
},
|
|
||||||
setup() {
|
|
||||||
return {
|
|
||||||
args,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
props() {
|
|
||||||
return {
|
|
||||||
...args,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
},
|
|
||||||
template: '<MkCaptcha v-bind="props" />',
|
|
||||||
};
|
|
||||||
},
|
|
||||||
parameters: {
|
|
||||||
layout: 'centered',
|
|
||||||
},
|
|
||||||
} satisfies StoryObj<typeof MkCaptcha>;
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
import MkCaptcha from './MkCaptcha.vue';
|
||||||
|
void MkCaptcha;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
||||||
/* eslint-disable import/no-default-export */
|
|
||||||
/* eslint-disable import/no-duplicates */
|
/* eslint-disable import/no-duplicates */
|
||||||
import { StoryObj } from '@storybook/vue3';
|
import { StoryObj } from '@storybook/vue3';
|
||||||
import MkAvatar from './MkAvatar.vue';
|
import MkAvatar from './MkAvatar.vue';
|
||||||
|
|
|
@ -7,7 +7,6 @@ const meta = {
|
||||||
} satisfies Meta<typeof MkAvatar>;
|
} satisfies Meta<typeof MkAvatar>;
|
||||||
export default meta;
|
export default meta;
|
||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
||||||
/* eslint-disable import/no-default-export */
|
|
||||||
/* eslint-disable import/no-duplicates */
|
/* eslint-disable import/no-duplicates */
|
||||||
import { StoryObj } from '@storybook/vue3';
|
import { StoryObj } from '@storybook/vue3';
|
||||||
import MkAvatar from './MkAvatar.vue';
|
import MkAvatar from './MkAvatar.vue';
|
||||||
|
@ -68,13 +67,6 @@ export const ProfilePageCat = {
|
||||||
user: {
|
user: {
|
||||||
...ProfilePage.args.user,
|
...ProfilePage.args.user,
|
||||||
isCat: true,
|
isCat: true,
|
||||||
// avatarUrl: 'https://millionlive-theaterdays.idolmaster-official.jp/assets/data/webp/common/footer/icon_app.png.webp',
|
|
||||||
// avatarUrl: 'https://cdn.imastodon.net/accounts/avatars/000/144/021/original/8137afa4114ab85f.png',
|
|
||||||
// avatarUrl: 'https://avatars.githubusercontent.com/u/4439005?v=4',
|
|
||||||
// avatarUrl: 'https://avatars.githubusercontent.com/u/7973572?v=4',
|
|
||||||
// avatarUrl: 'https://avatars.githubusercontent.com/u/6533808?v=4',
|
|
||||||
// avatarUrl: 'https://avatars.githubusercontent.com/u/7106976?v=4',
|
|
||||||
avatarUrl: 'https://avatars.githubusercontent.com/u/3396686?v=4',
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue