* chore(#10336): register snippets
* test(#10336): add `components/Mk[A-B].*` stories
* build: desynced lockfile
* ci(#10336): preload assets
* ci(#10336): use pull_request
* build: update lockfile
* fix: reactivity transform
* chore: track upstream changes
* refactor: avoid temporary previous tapping declarations
* revert: avoid temporary previous tapping declarations
This reverts commit e649b1b1e6.
* test: flaky snapshots
* style: import
			
			
This commit is contained in:
		 Acid Chicken (硫酸鶏)
					Acid Chicken (硫酸鶏)
				
			
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			 GitHub
						GitHub
					
				
			
						parent
						
							2a7ba37996
						
					
				
				
					commit
					9bb6c536c0
				
			| @@ -0,0 +1,49 @@ | ||||
| /* eslint-disable @typescript-eslint/explicit-function-return-type */ | ||||
| import { action } from '@storybook/addon-actions'; | ||||
| import { StoryObj } from '@storybook/vue3'; | ||||
| import { rest } from 'msw'; | ||||
| import { abuseUserReport } from '../../.storybook/fakes'; | ||||
| import { commonHandlers } from '../../.storybook/mocks'; | ||||
| import MkAbuseReport from './MkAbuseReport.vue'; | ||||
| export const Default = { | ||||
| 	render(args) { | ||||
| 		return { | ||||
| 			components: { | ||||
| 				MkAbuseReport, | ||||
| 			}, | ||||
| 			setup() { | ||||
| 				return { | ||||
| 					args, | ||||
| 				}; | ||||
| 			}, | ||||
| 			computed: { | ||||
| 				props() { | ||||
| 					return { | ||||
| 						...this.args, | ||||
| 					}; | ||||
| 				}, | ||||
| 				events() { | ||||
| 					return { | ||||
| 						resolved: action('resolved'), | ||||
| 					}; | ||||
| 				}, | ||||
| 			}, | ||||
| 			template: '<MkAbuseReport v-bind="props" v-on="events" />', | ||||
| 		}; | ||||
| 	}, | ||||
| 	args: { | ||||
| 		report: abuseUserReport(), | ||||
| 	}, | ||||
| 	parameters: { | ||||
| 		layout: 'fullscreen', | ||||
| 		msw: { | ||||
| 			handlers: [ | ||||
| 				...commonHandlers, | ||||
| 				rest.post('/api/admin/resolve-abuse-user-report', async (req, res, ctx) => { | ||||
| 					action('POST /api/admin/resolve-abuse-user-report')(await req.json()); | ||||
| 					return res(ctx.json({})); | ||||
| 				}), | ||||
| 			], | ||||
| 		}, | ||||
| 	}, | ||||
| } satisfies StoryObj<typeof MkAbuseReport>; | ||||
| @@ -0,0 +1,49 @@ | ||||
| /* eslint-disable @typescript-eslint/explicit-function-return-type */ | ||||
| import { action } from '@storybook/addon-actions'; | ||||
| import { StoryObj } from '@storybook/vue3'; | ||||
| import { rest } from 'msw'; | ||||
| import { userDetailed } from '../../.storybook/fakes'; | ||||
| import { commonHandlers } from '../../.storybook/mocks'; | ||||
| import MkAbuseReportWindow from './MkAbuseReportWindow.vue'; | ||||
| export const Default = { | ||||
| 	render(args) { | ||||
| 		return { | ||||
| 			components: { | ||||
| 				MkAbuseReportWindow, | ||||
| 			}, | ||||
| 			setup() { | ||||
| 				return { | ||||
| 					args, | ||||
| 				}; | ||||
| 			}, | ||||
| 			computed: { | ||||
| 				props() { | ||||
| 					return { | ||||
| 						...this.args, | ||||
| 					}; | ||||
| 				}, | ||||
| 				events() { | ||||
| 					return { | ||||
| 						'closed': action('closed'), | ||||
| 					}; | ||||
| 				}, | ||||
| 			}, | ||||
| 			template: '<MkAbuseReportWindow v-bind="props" v-on="events" />', | ||||
| 		}; | ||||
| 	}, | ||||
| 	args: { | ||||
| 		user: userDetailed(), | ||||
| 	}, | ||||
| 	parameters: { | ||||
| 		layout: 'centered', | ||||
| 		msw: { | ||||
| 			handlers: [ | ||||
| 				...commonHandlers, | ||||
| 				rest.post('/api/users/report-abuse', async (req, res, ctx) => { | ||||
| 					action('POST /api/users/report-abuse')(await req.json()); | ||||
| 					return res(ctx.json({})); | ||||
| 				}), | ||||
| 			], | ||||
| 		}, | ||||
| 	}, | ||||
| } satisfies StoryObj<typeof MkAbuseReportWindow>; | ||||
| @@ -0,0 +1,33 @@ | ||||
| /* eslint-disable @typescript-eslint/explicit-function-return-type */ | ||||
| import { StoryObj } from '@storybook/vue3'; | ||||
| import { userDetailed } from '../../.storybook/fakes'; | ||||
| import MkAccountMoved from './MkAccountMoved.vue'; | ||||
| export const Default = { | ||||
| 	render(args) { | ||||
| 		return { | ||||
| 			components: { | ||||
| 				MkAccountMoved, | ||||
| 			}, | ||||
| 			setup() { | ||||
| 				return { | ||||
| 					args, | ||||
| 				}; | ||||
| 			}, | ||||
| 			computed: { | ||||
| 				props() { | ||||
| 					return { | ||||
| 						...this.args, | ||||
| 					}; | ||||
| 				}, | ||||
| 			}, | ||||
| 			template: '<MkAccountMoved v-bind="props" />', | ||||
| 		}; | ||||
| 	}, | ||||
| 	args: { | ||||
| 		username: userDetailed().username, | ||||
| 		host: userDetailed().host, | ||||
| 	}, | ||||
| 	parameters: { | ||||
| 		layout: 'centered', | ||||
| 	}, | ||||
| } satisfies StoryObj<typeof MkAccountMoved>; | ||||
| @@ -2,7 +2,7 @@ | ||||
| <div :class="$style.root"> | ||||
| 	<i class="ti ti-plane-departure" style="margin-right: 8px;"></i> | ||||
| 	{{ i18n.ts.accountMoved }} | ||||
| 	<MkMention :class="$style.link" :username="acct" :host="host ?? localHost"/> | ||||
| 	<MkMention :class="$style.link" :username="username" :host="host ?? localHost"/> | ||||
| </div> | ||||
| </template> | ||||
|  | ||||
| @@ -12,7 +12,7 @@ import { i18n } from '@/i18n'; | ||||
| import { host as localHost } from '@/config'; | ||||
|  | ||||
| defineProps<{ | ||||
| 	acct: string; | ||||
| 	username: string; | ||||
| 	host: string; | ||||
| }>(); | ||||
| </script> | ||||
|   | ||||
| @@ -0,0 +1,56 @@ | ||||
| /* eslint-disable @typescript-eslint/explicit-function-return-type */ | ||||
| import { StoryObj } from '@storybook/vue3'; | ||||
| import { rest } from 'msw'; | ||||
| import { userDetailed } from '../../.storybook/fakes'; | ||||
| import { commonHandlers } from '../../.storybook/mocks'; | ||||
| import MkAchievements from './MkAchievements.vue'; | ||||
| import { ACHIEVEMENT_TYPES } from '@/scripts/achievements'; | ||||
| export const Empty = { | ||||
| 	render(args) { | ||||
| 		return { | ||||
| 			components: { | ||||
| 				MkAchievements, | ||||
| 			}, | ||||
| 			setup() { | ||||
| 				return { | ||||
| 					args, | ||||
| 				}; | ||||
| 			}, | ||||
| 			computed: { | ||||
| 				props() { | ||||
| 					return { | ||||
| 						...this.args, | ||||
| 					}; | ||||
| 				}, | ||||
| 			}, | ||||
| 			template: '<MkAchievements v-bind="props" />', | ||||
| 		}; | ||||
| 	}, | ||||
| 	args: { | ||||
| 		user: userDetailed(), | ||||
| 	}, | ||||
| 	parameters: { | ||||
| 		layout: 'fullscreen', | ||||
| 		msw: { | ||||
| 			handlers: [ | ||||
| 				...commonHandlers, | ||||
| 				rest.post('/api/users/achievements', (req, res, ctx) => { | ||||
| 					return res(ctx.json([])); | ||||
| 				}), | ||||
| 			], | ||||
| 		}, | ||||
| 	}, | ||||
| } satisfies StoryObj<typeof MkAchievements>; | ||||
| export const All = { | ||||
| 	...Empty, | ||||
| 	parameters: { | ||||
| 		msw: { | ||||
| 			handlers: [ | ||||
| 				...commonHandlers, | ||||
| 				rest.post('/api/users/achievements', (req, res, ctx) => { | ||||
| 					return res(ctx.json(ACHIEVEMENT_TYPES.map((name) => ({ name, unlockedAt: 0 })))); | ||||
| 				}), | ||||
| 			], | ||||
| 		}, | ||||
| 	}, | ||||
| } satisfies StoryObj<typeof MkAchievements>; | ||||
| @@ -1,6 +1,7 @@ | ||||
| /* eslint-disable @typescript-eslint/explicit-function-return-type */ | ||||
| import { StoryObj } from '@storybook/vue3'; | ||||
| import MkAnalogClock from './MkAnalogClock.vue'; | ||||
| import isChromatic from 'chromatic'; | ||||
| export const Default = { | ||||
| 	render(args) { | ||||
| 		return { | ||||
| @@ -22,6 +23,14 @@ export const Default = { | ||||
| 			template: '<MkAnalogClock v-bind="props" />', | ||||
| 		}; | ||||
| 	}, | ||||
| 	args: { | ||||
| 		now: isChromatic() ? () => new Date('2023-01-01T10:10:30') : undefined, | ||||
| 	}, | ||||
| 	decorators: [ | ||||
| 		() => ({ | ||||
| 			template: '<div style="container-type:inline-size;height:100%"><div style="height:100cqmin;margin:auto;width:100cqmin"><story/></div></div>', | ||||
| 		}), | ||||
| 	], | ||||
| 	parameters: { | ||||
| 		layout: 'fullscreen', | ||||
| 	}, | ||||
|   | ||||
| @@ -99,6 +99,7 @@ const props = withDefaults(defineProps<{ | ||||
| 	graduations?: 'none' | 'dots' | 'numbers'; | ||||
| 	fadeGraduations?: boolean; | ||||
| 	sAnimation?: 'none' | 'elastic' | 'easeOut'; | ||||
| 	now?: () => Date; | ||||
| }>(), { | ||||
| 	numbers: false, | ||||
| 	thickness: 0.1, | ||||
| @@ -107,6 +108,7 @@ const props = withDefaults(defineProps<{ | ||||
| 	graduations: 'dots', | ||||
| 	fadeGraduations: true, | ||||
| 	sAnimation: 'elastic', | ||||
| 	now: () => new Date(), | ||||
| }); | ||||
|  | ||||
| const graduationsMajor = computed(() => { | ||||
| @@ -145,11 +147,17 @@ let disableSAnimate = $ref(false); | ||||
| let sOneRound = false; | ||||
|  | ||||
| function tick() { | ||||
| 	const now = new Date(); | ||||
| 	now.setMinutes(now.getMinutes() + (new Date().getTimezoneOffset() + props.offset)); | ||||
| 	const now = props.now(); | ||||
| 	now.setMinutes(now.getMinutes() + now.getTimezoneOffset() + props.offset); | ||||
| 	const previousS = s; | ||||
| 	const previousM = m; | ||||
| 	const previousH = h; | ||||
| 	s = now.getSeconds(); | ||||
| 	m = now.getMinutes(); | ||||
| 	h = now.getHours(); | ||||
| 	if (previousS === s && previousM === m && previousH === h) { | ||||
| 		return; | ||||
| 	} | ||||
| 	hAngle = Math.PI * (h % (props.twentyfour ? 24 : 12) + (m + s / 60) / 60) / (props.twentyfour ? 12 : 6); | ||||
| 	mAngle = Math.PI * (m + s / 60) / 30; | ||||
| 	if (sOneRound) { // 秒針が一周した際のアニメーションをよしなに処理する(これが無いと秒が59->0になったときに期待したアニメーションにならない) | ||||
|   | ||||
							
								
								
									
										2
									
								
								packages/frontend/src/components/MkAsUi.stories.impl.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								packages/frontend/src/components/MkAsUi.stories.impl.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| import MkAsUi from './MkAsUi.vue'; | ||||
| void MkAsUi; | ||||
							
								
								
									
										176
									
								
								packages/frontend/src/components/MkAutocomplete.stories.impl.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										176
									
								
								packages/frontend/src/components/MkAutocomplete.stories.impl.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,176 @@ | ||||
| /* eslint-disable @typescript-eslint/explicit-function-return-type */ | ||||
| import { action } from '@storybook/addon-actions'; | ||||
| import { expect } from '@storybook/jest'; | ||||
| import { userEvent, waitFor, within } from '@storybook/testing-library'; | ||||
| import { StoryObj } from '@storybook/vue3'; | ||||
| import { rest } from 'msw'; | ||||
| import { userDetailed } from '../../.storybook/fakes'; | ||||
| import { commonHandlers } from '../../.storybook/mocks'; | ||||
| import MkAutocomplete from './MkAutocomplete.vue'; | ||||
| import MkInput from './MkInput.vue'; | ||||
| import { tick } from '@/scripts/test-utils'; | ||||
| const common = { | ||||
| 	render(args) { | ||||
| 		return { | ||||
| 			components: { | ||||
| 				MkAutocomplete, | ||||
| 			}, | ||||
| 			setup() { | ||||
| 				return { | ||||
| 					args, | ||||
| 				}; | ||||
| 			}, | ||||
| 			computed: { | ||||
| 				props() { | ||||
| 					return { | ||||
| 						...this.args, | ||||
| 					}; | ||||
| 				}, | ||||
| 				events() { | ||||
| 					return { | ||||
| 						open: action('open'), | ||||
| 						closed: action('closed'), | ||||
| 					}; | ||||
| 				}, | ||||
| 			}, | ||||
| 			template: '<MkAutocomplete v-bind="props" v-on="events" :textarea="textarea" />', | ||||
| 		}; | ||||
| 	}, | ||||
| 	args: { | ||||
| 		close: action('close'), | ||||
| 		x: 0, | ||||
| 		y: 0, | ||||
| 	}, | ||||
| 	decorators: [ | ||||
| 		(_, context) => ({ | ||||
| 			components: { | ||||
| 				MkInput, | ||||
| 			}, | ||||
| 			data() { | ||||
| 				return { | ||||
| 					q: context.args.q, | ||||
| 					textarea: null, | ||||
| 				}; | ||||
| 			}, | ||||
| 			methods: { | ||||
| 				inputMounted() { | ||||
| 					this.textarea = this.$refs.input.$refs.inputEl; | ||||
| 				}, | ||||
| 			}, | ||||
| 			template: '<MkInput v-model="q" ref="input" @vue:mounted="inputMounted"/><story v-if="textarea" :q="q" :textarea="textarea"/>', | ||||
| 		}), | ||||
| 	], | ||||
| 	parameters: { | ||||
| 		controls: { | ||||
| 			exclude: ['textarea'], | ||||
| 		}, | ||||
| 		layout: 'centered', | ||||
| 		chromatic: { | ||||
| 			// FIXME: flaky | ||||
| 			disableSnapshot: true, | ||||
| 		}, | ||||
| 	}, | ||||
| } satisfies StoryObj<typeof MkAutocomplete>; | ||||
| export const User = { | ||||
| 	...common, | ||||
| 	args: { | ||||
| 		...common.args, | ||||
| 		type: 'user', | ||||
| 	}, | ||||
| 	async play({ canvasElement }) { | ||||
| 		const canvas = within(canvasElement); | ||||
| 		const input = canvas.getByRole('combobox'); | ||||
| 		await waitFor(() => userEvent.hover(input)); | ||||
| 		await waitFor(() => userEvent.click(input)); | ||||
| 		await waitFor(() => userEvent.type(input, 'm')); | ||||
| 		await waitFor(async () => { | ||||
| 			await userEvent.type(input, ' ', { delay: 256 }); | ||||
| 			await tick(); | ||||
| 			return await expect(canvas.getByRole('list')).toBeInTheDocument(); | ||||
| 		}, { timeout: 16384 }); | ||||
| 	}, | ||||
| 	parameters: { | ||||
| 		...common.parameters, | ||||
| 		msw: { | ||||
| 			handlers: [ | ||||
| 				...commonHandlers, | ||||
| 				rest.post('/api/users/search-by-username-and-host', (req, res, ctx) => { | ||||
| 					return res(ctx.json([ | ||||
| 						userDetailed('44', 'mizuki', 'misskey-hub.net', 'Mizuki'), | ||||
| 						userDetailed('49', 'momoko', 'misskey-hub.net', 'Momoko'), | ||||
| 					])); | ||||
| 				}), | ||||
| 			], | ||||
| 		}, | ||||
| 	}, | ||||
| }; | ||||
| export const Hashtag = { | ||||
| 	...common, | ||||
| 	args: { | ||||
| 		...common.args, | ||||
| 		type: 'hashtag', | ||||
| 	}, | ||||
| 	async play({ canvasElement }) { | ||||
| 		const canvas = within(canvasElement); | ||||
| 		const input = canvas.getByRole('combobox'); | ||||
| 		await waitFor(() => userEvent.hover(input)); | ||||
| 		await waitFor(() => userEvent.click(input)); | ||||
| 		await waitFor(() => userEvent.type(input, '気象')); | ||||
| 		await waitFor(async () => { | ||||
| 			await userEvent.type(input, ' ', { delay: 256 }); | ||||
| 			await tick(); | ||||
| 			return await expect(canvas.getByRole('list')).toBeInTheDocument(); | ||||
| 		}, { interval: 256, timeout: 16384 }); | ||||
| 	}, | ||||
| 	parameters: { | ||||
| 		...common.parameters, | ||||
| 		msw: { | ||||
| 			handlers: [ | ||||
| 				...commonHandlers, | ||||
| 				rest.post('/api/hashtags/search', (req, res, ctx) => { | ||||
| 					return res(ctx.json([ | ||||
| 						'気象警報注意報', | ||||
| 						'気象警報', | ||||
| 						'気象情報', | ||||
| 					])); | ||||
| 				}), | ||||
| 			], | ||||
| 		}, | ||||
| 	}, | ||||
| }; | ||||
| export const Emoji = { | ||||
| 	...common, | ||||
| 	args: { | ||||
| 		...common.args, | ||||
| 		type: 'emoji', | ||||
| 	}, | ||||
| 	async play({ canvasElement }) { | ||||
| 		const canvas = within(canvasElement); | ||||
| 		const input = canvas.getByRole('combobox'); | ||||
| 		await waitFor(() => userEvent.hover(input)); | ||||
| 		await waitFor(() => userEvent.click(input)); | ||||
| 		await waitFor(() => userEvent.type(input, 'smile')); | ||||
| 		await waitFor(async () => { | ||||
| 			await userEvent.type(input, ' ', { delay: 256 }); | ||||
| 			await tick(); | ||||
| 			return await expect(canvas.getByRole('list')).toBeInTheDocument(); | ||||
| 		}, { interval: 256, timeout: 16384 }); | ||||
| 	}, | ||||
| } satisfies StoryObj<typeof MkAutocomplete>; | ||||
| export const MfmTag = { | ||||
| 	...common, | ||||
| 	args: { | ||||
| 		...common.args, | ||||
| 		type: 'mfmTag', | ||||
| 	}, | ||||
| 	async play({ canvasElement }) { | ||||
| 		const canvas = within(canvasElement); | ||||
| 		const input = canvas.getByRole('combobox'); | ||||
| 		await waitFor(() => userEvent.hover(input)); | ||||
| 		await waitFor(() => userEvent.click(input)); | ||||
| 		await waitFor(async () => { | ||||
| 			await tick(); | ||||
| 			return await expect(canvas.getByRole('list')).toBeInTheDocument(); | ||||
| 		}, { interval: 256, timeout: 16384 }); | ||||
| 	}, | ||||
| } satisfies StoryObj<typeof MkAutocomplete>; | ||||
							
								
								
									
										46
									
								
								packages/frontend/src/components/MkAvatars.stories.impl.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								packages/frontend/src/components/MkAvatars.stories.impl.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| /* eslint-disable @typescript-eslint/explicit-function-return-type */ | ||||
| import { StoryObj } from '@storybook/vue3'; | ||||
| import { rest } from 'msw'; | ||||
| import { userDetailed } from '../../.storybook/fakes'; | ||||
| import { commonHandlers } from '../../.storybook/mocks'; | ||||
| import MkAvatars from './MkAvatars.vue'; | ||||
| export const Default = { | ||||
| 	render(args) { | ||||
| 		return { | ||||
| 			components: { | ||||
| 				MkAvatars, | ||||
| 			}, | ||||
| 			setup() { | ||||
| 				return { | ||||
| 					args, | ||||
| 				}; | ||||
| 			}, | ||||
| 			computed: { | ||||
| 				props() { | ||||
| 					return { | ||||
| 						...this.args, | ||||
| 					}; | ||||
| 				}, | ||||
| 			}, | ||||
| 			template: '<MkAvatars v-bind="props" />', | ||||
| 		}; | ||||
| 	}, | ||||
| 	args: { | ||||
| 		userIds: ['17', '20', '18'], | ||||
| 	}, | ||||
| 	parameters: { | ||||
| 		layout: 'centered', | ||||
| 		msw: { | ||||
| 			handlers: [ | ||||
| 				...commonHandlers, | ||||
| 				rest.post('/api/users/show', (req, res, ctx) => { | ||||
| 					return res(ctx.json([ | ||||
| 						userDetailed('17'), | ||||
| 						userDetailed('20'), | ||||
| 						userDetailed('18'), | ||||
| 					])); | ||||
| 				}), | ||||
| 			], | ||||
| 		}, | ||||
| 	}, | ||||
| } satisfies StoryObj<typeof MkAvatars>; | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* eslint-disable @typescript-eslint/explicit-function-return-type */ | ||||
| /* eslint-disable import/no-default-export */ | ||||
| /* eslint-disable import/no-duplicates */ | ||||
| import { action } from '@storybook/addon-actions'; | ||||
| import { StoryObj } from '@storybook/vue3'; | ||||
| import MkButton from './MkButton.vue'; | ||||
| export const Default = { | ||||
| @@ -20,11 +20,60 @@ export const Default = { | ||||
| 						...this.args, | ||||
| 					}; | ||||
| 				}, | ||||
| 				events() { | ||||
| 					return { | ||||
| 						click: action('click'), | ||||
| 					}; | ||||
| 				}, | ||||
| 			}, | ||||
| 			template: '<MkButton v-bind="props">Text</MkButton>', | ||||
| 			template: '<MkButton v-bind="props" v-on="events">Text</MkButton>', | ||||
| 		}; | ||||
| 	}, | ||||
| 	args: { | ||||
| 	}, | ||||
| 	parameters: { | ||||
| 		layout: 'centered', | ||||
| 	}, | ||||
| } satisfies StoryObj<typeof MkButton>; | ||||
| export const Primary = { | ||||
| 	...Default, | ||||
| 	args: { | ||||
| 		...Default.args, | ||||
| 		primary: true, | ||||
| 	}, | ||||
| } satisfies StoryObj<typeof MkButton>; | ||||
| export const Gradate = { | ||||
| 	...Default, | ||||
| 	args: { | ||||
| 		...Default.args, | ||||
| 		gradate: true, | ||||
| 	}, | ||||
| } satisfies StoryObj<typeof MkButton>; | ||||
| export const Rounded = { | ||||
| 	...Default, | ||||
| 	args: { | ||||
| 		...Default.args, | ||||
| 		rounded: true, | ||||
| 	}, | ||||
| } satisfies StoryObj<typeof MkButton>; | ||||
| export const Danger = { | ||||
| 	...Default, | ||||
| 	args: { | ||||
| 		...Default.args, | ||||
| 		danger: true, | ||||
| 	}, | ||||
| } satisfies StoryObj<typeof MkButton>; | ||||
| export const Small = { | ||||
| 	...Default, | ||||
| 	args: { | ||||
| 		...Default.args, | ||||
| 		small: true, | ||||
| 	}, | ||||
| } satisfies StoryObj<typeof MkButton>; | ||||
| export const Large = { | ||||
| 	...Default, | ||||
| 	args: { | ||||
| 		...Default.args, | ||||
| 		large: true, | ||||
| 	}, | ||||
| } satisfies StoryObj<typeof MkButton>; | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| /* eslint-disable @typescript-eslint/explicit-function-return-type */ | ||||
| import { action } from '@storybook/addon-actions'; | ||||
| import { expect } from '@storybook/jest'; | ||||
| import { waitFor } from '@storybook/testing-library'; | ||||
| import { StoryObj } from '@storybook/vue3'; | ||||
| @@ -20,14 +21,21 @@ export const Default = { | ||||
| 						...this.args, | ||||
| 					}; | ||||
| 				}, | ||||
| 				events() { | ||||
| 					return { | ||||
| 						retry: action('retry'), | ||||
| 					}; | ||||
| 				}, | ||||
| 			}, | ||||
| 			template: '<MkError v-bind="props" />', | ||||
| 			template: '<MkError v-bind="props" v-on="events" />', | ||||
| 		}; | ||||
| 	}, | ||||
| 	async play({ canvasElement }) { | ||||
| 		await expect(canvasElement.firstElementChild).not.toBeNull(); | ||||
| 		await waitFor(async () => expect(canvasElement.firstElementChild?.classList).not.toContain('_transition_zoom-enter-active')); | ||||
| 	}, | ||||
| 	args: { | ||||
| 	}, | ||||
| 	parameters: { | ||||
| 		layout: 'centered', | ||||
| 	}, | ||||
|   | ||||
| @@ -8,6 +8,7 @@ | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup> | ||||
| import isChromatic from 'chromatic/isChromatic'; | ||||
| import { onUnmounted } from 'vue'; | ||||
| import { i18n } from '@/i18n'; | ||||
| import { dateTimeFormat } from '@/scripts/intl-const'; | ||||
| @@ -17,7 +18,7 @@ const props = withDefaults(defineProps<{ | ||||
| 	origin?: Date | null; | ||||
| 	mode?: 'relative' | 'absolute' | 'detail'; | ||||
| }>(), { | ||||
| 	origin: null, | ||||
| 	origin: isChromatic() ? new Date('2023-04-01T00:00:00Z') : null, | ||||
| 	mode: 'relative', | ||||
| }); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user