Initial commit

This commit is contained in:
Zhongwei Li
2025-11-29 17:51:59 +08:00
commit 38e80921c8
89 changed files with 20480 additions and 0 deletions

View File

@@ -0,0 +1,10 @@
{
"projectId": "{{ project_id | default('<PROJECT_ID_PLACEHOLDER>') }}",
"buildScriptName": "build-storybook",
"exitZeroOnChanges": true,
"exitOnceUploaded": true,
"onlyChanged": true,
"externals": ["public/**"],
"skip": "{{ skip_pattern | default('dependabot/**') }}",
"ignoreLastBuildOnBranch": "{{ main_branch | default('main') }}"
}

View File

@@ -0,0 +1,80 @@
name: Visual Regression Tests
on:
push:
branches: {{ branches | default(['main', 'develop']) | tojson }}
pull_request:
branches: ['main']
jobs:
{% if vr_tool == 'chromatic' -%}
chromatic:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Required for Chromatic
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '{{ node_version | default('20') }}'
cache: '{{ package_manager | default('npm') }}'
- name: Install dependencies
run: {{ install_command | default('npm ci') }}
- name: Run Chromatic
uses: chromaui/action@latest
with:
projectToken: {% raw %}${{ secrets.CHROMATIC_PROJECT_TOKEN }}{% endraw %}
exitZeroOnChanges: true
onlyChanged: true
autoAcceptChanges: 'main'
{% elif vr_tool == 'percy' -%}
percy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '{{ node_version | default('20') }}'
cache: '{{ package_manager | default('npm') }}'
- name: Install dependencies
run: {{ install_command | default('npm ci') }}
- name: Build Storybook
run: npm run build-storybook
- name: Run Percy
run: npx percy storybook storybook-static
env:
PERCY_TOKEN: {% raw %}${{ secrets.PERCY_TOKEN }}{% endraw %}
{% elif vr_tool == 'backstopjs' -%}
backstop:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '{{ node_version | default('20') }}'
cache: '{{ package_manager | default('npm') }}'
- name: Install dependencies
run: {{ install_command | default('npm ci') }}
- name: Run BackstopJS
run: npm run backstop:test
- name: Upload test results
if: failure()
uses: actions/upload-artifact@v3
with:
name: backstop-results
path: backstop_data/
{% endif -%}

View File

@@ -0,0 +1,54 @@
# Add to .gitlab-ci.yml
{% if vr_tool == 'chromatic' -%}
chromatic:
stage: test
image: node:{{ node_version | default('20') }}
cache:
paths:
- node_modules/
script:
- {{ install_command | default('npm ci') }}
- npx chromatic --exit-zero-on-changes --only-changed
variables:
CHROMATIC_PROJECT_TOKEN: $CHROMATIC_PROJECT_TOKEN
only:
- main
- develop
- merge_requests
{% elif vr_tool == 'percy' -%}
percy:
stage: test
image: node:{{ node_version | default('20') }}
cache:
paths:
- node_modules/
script:
- {{ install_command | default('npm ci') }}
- npm run build-storybook
- npx percy storybook storybook-static
variables:
PERCY_TOKEN: $PERCY_TOKEN
only:
- main
- develop
- merge_requests
{% elif vr_tool == 'backstopjs' -%}
backstop:
stage: test
image: node:{{ node_version | default('20') }}
cache:
paths:
- node_modules/
script:
- {{ install_command | default('npm ci') }}
- npm run backstop:test
artifacts:
when: on_failure
paths:
- backstop_data/
only:
- main
- develop
- merge_requests
{% endif -%}

View File

@@ -0,0 +1,60 @@
import type { Meta, StoryObj } from '@storybook/react';
import { {{ component_name }} } from './{{ component_name }}';
const meta = {
title: '{{ story_title }}',
component: {{ component_name }},
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
argTypes: {
{% for prop in props -%}
{% if prop.values -%}
{{ prop.name }}: { control: '{{ prop.control }}', options: {{ prop.values | tojson }} },
{% else -%}
{{ prop.name }}: { control: '{{ prop.control }}' },
{% endif -%}
{% endfor %}
},
} satisfies Meta<typeof {{ component_name }}>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Default: Story = {
args: {
{% for prop in props -%}
{% if prop.default is string -%}
{{ prop.name }}: '{{ prop.default }}',
{% elif prop.default is not none -%}
{{ prop.name }}: {{ prop.default | tojson }},
{% endif -%}
{% endfor %}
},
};
{% for variant in variants %}
export const {{ variant.name }}: Story = {
args: {
...Default.args,
{% if variant.value is string -%}
{{ variant.prop_name }}: '{{ variant.value }}',
{% else -%}
{{ variant.prop_name }}: {{ variant.value | tojson }},
{% endif -%}
},
};
{% endfor %}
// Accessibility tests
Default.parameters = {
a11y: {
config: {
rules: [
{ id: 'color-contrast', enabled: true },
{ id: 'label', enabled: true },
],
},
},
};

View File

@@ -0,0 +1,17 @@
module.exports = {
stories: ['../src/**/*.stories.@(js|jsx|ts|tsx)'],
addons: [
'@storybook/addon-links',
'@storybook/addon-essentials',
{% if vr_tool == 'chromatic' -%}
'@chromatic-com/storybook',
{% elif vr_tool == 'percy' -%}
'@percy/storybook',
{% endif -%}
'@storybook/addon-interactions',
],
framework: {
name: '@storybook/{{ framework | default('react') }}-vite',
options: {},
},
};