Skip to content

Commit 6027a9c

Browse files
authored
Add storybook for component development (#7162)
Signed-off-by: Nicholas Gates <nick@nickgates.com>
1 parent b9132aa commit 6027a9c

10 files changed

Lines changed: 1456 additions & 94 deletions

File tree

.github/workflows/web.yml

Lines changed: 6 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ jobs:
3737
- ".github/workflows/web.yml"
3838
3939
build:
40-
name: Build
40+
name: Build & Check
41+
needs: [changes]
42+
if: needs.changes.outputs.web == 'true'
4143
runs-on: ubuntu-latest
4244
timeout-minutes: 30
4345
steps:
@@ -55,68 +57,7 @@ jobs:
5557
cache: "npm"
5658
cache-dependency-path: vortex-web/package-lock.json
5759
- run: npm ci
58-
- run: npm run build
60+
- run: npm run wasm
5961
- run: npm run lint
60-
- uses: actions/upload-artifact@v4
61-
with:
62-
name: vortex-web-dist
63-
path: vortex-web/dist
64-
retention-days: 7
65-
66-
preview:
67-
name: Deploy Preview
68-
needs: [build, changes]
69-
if: needs.changes.outputs.web == 'true'
70-
runs-on: ubuntu-latest
71-
timeout-minutes: 10
72-
permissions:
73-
contents: read
74-
pull-requests: write
75-
deployments: write
76-
environment:
77-
name: preview
78-
url: ${{ steps.deploy.outputs.deployment-url }}
79-
steps:
80-
- uses: actions/download-artifact@v4
81-
with:
82-
name: vortex-web-dist
83-
path: dist
84-
- name: Deploy to Cloudflare Pages
85-
id: deploy
86-
uses: cloudflare/wrangler-action@v3
87-
with:
88-
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
89-
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
90-
command: >-
91-
pages deploy dist/
92-
--project-name=vortex-web
93-
--branch=${{ github.head_ref || github.ref_name }}
94-
- name: Comment preview URL on PR
95-
if: github.event_name == 'pull_request'
96-
uses: actions/github-script@v7
97-
with:
98-
script: |
99-
const body = `**Vortex Web Preview:** ${{ steps.deploy.outputs.deployment-url }}`;
100-
const { data: comments } = await github.rest.issues.listComments({
101-
owner: context.repo.owner,
102-
repo: context.repo.repo,
103-
issue_number: context.issue.number,
104-
});
105-
const existing = comments.find(c =>
106-
c.body?.startsWith('**Vortex Web Preview:**')
107-
);
108-
if (existing) {
109-
await github.rest.issues.updateComment({
110-
owner: context.repo.owner,
111-
repo: context.repo.repo,
112-
comment_id: existing.id,
113-
body,
114-
});
115-
} else {
116-
await github.rest.issues.createComment({
117-
owner: context.repo.owner,
118-
repo: context.repo.repo,
119-
issue_number: context.issue.number,
120-
body,
121-
});
122-
}
62+
- run: npm run typecheck
63+
- run: npm run build-storybook

.idea/copyright/profiles_settings.xml

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/scopes/web_files.xml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vortex-web/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
node_modules
22
dist
3+
storybook-static
34
src/wasm/pkg
45
*.local

vortex-web/.storybook/main.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3+
4+
import type { StorybookConfig } from '@storybook/react-vite';
5+
6+
const config: StorybookConfig = {
7+
"stories": [
8+
"../src/**/*.mdx",
9+
"../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"
10+
],
11+
"addons": [
12+
"@storybook/addon-docs",
13+
],
14+
"framework": "@storybook/react-vite"
15+
};
16+
export default config;

vortex-web/.storybook/preview.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3+
4+
import type { Preview } from '@storybook/react-vite'
5+
import '../src/index.css'
6+
7+
const preview: Preview = {
8+
parameters: {
9+
controls: {
10+
matchers: {
11+
color: /(background|color)$/i,
12+
date: /Date$/i,
13+
},
14+
},
15+
},
16+
};
17+
18+
export default preview;

vortex-web/README.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Vortex Web
2+
3+
A web UI for exploring Vortex data files, built with React, TypeScript, Tailwind CSS, and Rust/WASM.
4+
5+
## Prerequisites
6+
7+
- Node.js 22+
8+
- [wasm-pack](https://rustwasm.github.io/wasm-pack/installer/) (for full app development)
9+
- Rust toolchain (for full app development)
10+
11+
## Getting Started
12+
13+
```bash
14+
npm install
15+
```
16+
17+
### Full App (requires Rust + wasm-pack)
18+
19+
```bash
20+
# Start dev server (builds WASM in debug mode, then starts Vite)
21+
npm run dev
22+
```
23+
24+
### Storybook (no Rust/WASM required)
25+
26+
Storybook lets you develop and preview UI components in isolation:
27+
28+
```bash
29+
npm run storybook
30+
```
31+
32+
This starts a dev server at http://localhost:6006.
33+
34+
## Scripts
35+
36+
| Command | Description |
37+
|---------------------------|--------------------------------------------|
38+
| `npm run dev` | Build WASM (debug) + start Vite dev server |
39+
| `npm run build` | Production build (WASM release + Vite) |
40+
| `npm run storybook` | Start Storybook dev server on port 6006 |
41+
| `npm run build-storybook` | Build static Storybook site |
42+
| `npm run lint` | Run ESLint |
43+
| `npm run lint:fix` | Run ESLint with auto-fix |
44+
| `npm run typecheck` | Run TypeScript type checking |
45+
| `npm run check` | Build WASM + lint + typecheck |
46+
47+
## Writing Stories
48+
49+
Add story files alongside your components as `*.stories.tsx`:
50+
51+
```tsx
52+
import type {Meta, StoryObj} from '@storybook/react-vite';
53+
import {MyComponent} from './MyComponent';
54+
55+
const meta: Meta<typeof MyComponent> = {
56+
component: MyComponent,
57+
};
58+
export default meta;
59+
60+
type Story = StoryObj<typeof MyComponent>;
61+
62+
export const Default: Story = {
63+
args: {},
64+
};
65+
```
66+
67+
## Project Structure
68+
69+
```
70+
vortex-web/
71+
crate/ # Rust WASM crate (vortex bindings)
72+
src/ # React/TypeScript frontend
73+
wasm/pkg/ # Generated WASM bindings (not checked in)
74+
.storybook/ # Storybook configuration
75+
public/ # Static assets
76+
```

vortex-web/eslint.config.ts

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,25 @@ import js from "@eslint/js";
55
import globals from "globals";
66
import reactHooks from "eslint-plugin-react-hooks";
77
import reactRefresh from "eslint-plugin-react-refresh";
8+
import storybook from "eslint-plugin-storybook";
89
import tseslint from "typescript-eslint";
910

10-
export default tseslint.config(
11-
{ ignores: ["dist"] },
12-
{
13-
extends: [js.configs.recommended, ...tseslint.configs.recommended],
14-
files: ["**/*.{ts,tsx}"],
15-
languageOptions: {
16-
ecmaVersion: 2020,
17-
globals: globals.browser,
18-
},
19-
plugins: {
20-
"react-hooks": reactHooks,
21-
"react-refresh": reactRefresh,
22-
},
23-
rules: {
24-
...reactHooks.configs.recommended.rules,
25-
"react-refresh/only-export-components": [
26-
"warn",
27-
{ allowConstantExport: true },
28-
],
29-
},
11+
export default tseslint.config({ ignores: ["dist"] }, {
12+
extends: [js.configs.recommended, ...tseslint.configs.recommended],
13+
files: ["**/*.{ts,tsx}"],
14+
languageOptions: {
15+
ecmaVersion: 2020,
16+
globals: globals.browser,
3017
},
31-
);
18+
plugins: {
19+
"react-hooks": reactHooks,
20+
"react-refresh": reactRefresh,
21+
},
22+
rules: {
23+
...reactHooks.configs.recommended.rules,
24+
"react-refresh/only-export-components": [
25+
"warn",
26+
{ allowConstantExport: true },
27+
],
28+
},
29+
}, storybook.configs["flat/recommended"]);

0 commit comments

Comments
 (0)