feat(ui): introduces storybook
- adds the necessary dependencies and configuration for Storybook. - refactors the `Button` component and adds some stories for it.
This commit is contained in:
32
pkgs/clan-app/ui/.storybook/main.ts
Normal file
32
pkgs/clan-app/ui/.storybook/main.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { createRequire } from "module";
|
||||
import { dirname, join } from "path";
|
||||
import { mergeConfig } from "vite";
|
||||
import type { StorybookConfig } from "@kachurun/storybook-solid-vite";
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
const getAbsolutePath = (pkg: string) =>
|
||||
dirname(require.resolve(join(pkg, "package.json")));
|
||||
|
||||
const config: StorybookConfig = {
|
||||
stories: ["../src/components/**/*.mdx", "../src/components/**/*.stories.tsx"],
|
||||
addons: [
|
||||
getAbsolutePath("@storybook/addon-links"),
|
||||
getAbsolutePath("@storybook/addon-essentials"),
|
||||
getAbsolutePath("@chromatic-com/storybook"),
|
||||
getAbsolutePath("@storybook/addon-interactions"),
|
||||
],
|
||||
framework: {
|
||||
name: "@kachurun/storybook-solid-vite",
|
||||
options: {},
|
||||
},
|
||||
async viteFinal(config) {
|
||||
return mergeConfig(config, {
|
||||
define: { "process.env": {} },
|
||||
});
|
||||
},
|
||||
docs: {
|
||||
autodocs: "tag",
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
25
pkgs/clan-app/ui/.storybook/preview.ts
Normal file
25
pkgs/clan-app/ui/.storybook/preview.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import type { Preview } from "@kachurun/storybook-solid";
|
||||
|
||||
export const preview: Preview = {
|
||||
tags: ["autodocs"],
|
||||
parameters: {
|
||||
docs: { toc: true },
|
||||
backgrounds: {
|
||||
values: [
|
||||
{ name: "Dark", value: "#333" },
|
||||
{ name: "Light", value: "#F7F9F2" },
|
||||
],
|
||||
default: "Light",
|
||||
},
|
||||
// automatically create action args for all props that start with "on"
|
||||
actions: { argTypesRegex: "^on.*" },
|
||||
controls: {
|
||||
matchers: {
|
||||
color: /(background|color)$/i,
|
||||
date: /Date$/,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default preview;
|
||||
@@ -31,6 +31,12 @@ Solid in production mode and optimizes the build for the best performance.
|
||||
The build is minified and the filenames include the hashes.<br> Your app is
|
||||
ready to be deployed!
|
||||
|
||||
### `npm run storybook`
|
||||
|
||||
Starts an instance of [storybook](https://storybook.js.org/).
|
||||
|
||||
For more info on how to write stories, please [see here](https://storybook.js.org/docs).
|
||||
|
||||
## Deployment
|
||||
|
||||
You can deploy the `dist` folder to any static host provider (netlify, surge,
|
||||
|
||||
6654
pkgs/clan-app/ui/package-lock.json
generated
6654
pkgs/clan-app/ui/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -10,12 +10,22 @@
|
||||
"convert-html": "node gtk.webview.js",
|
||||
"serve": "vite preview",
|
||||
"check": "tsc --noEmit --skipLibCheck && eslint ./src",
|
||||
"test": "vitest run --typecheck"
|
||||
"test": "vitest run --typecheck",
|
||||
"storybook": "storybook dev -p 6006"
|
||||
},
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@babel/plugin-syntax-import-attributes": "^7.27.1",
|
||||
"@chromatic-com/storybook": "^3.2.6",
|
||||
"@eslint/js": "^9.3.0",
|
||||
"@kachurun/storybook-solid": "^8.6.7",
|
||||
"@kachurun/storybook-solid-vite": "^8.6.7",
|
||||
"@storybook/addon-essentials": "^8.6.14",
|
||||
"@storybook/addon-interactions": "^8.6.14",
|
||||
"@storybook/addon-links": "^8.6.14",
|
||||
"@storybook/addon-viewport": "^8.6.14",
|
||||
"@storybook/builder-vite": "^8.6.14",
|
||||
"@storybook/test-runner": "^0.22.0",
|
||||
"@tailwindcss/typography": "^0.5.13",
|
||||
"@types/json-schema": "^7.0.15",
|
||||
"@types/node": "^22.15.19",
|
||||
@@ -30,6 +40,7 @@
|
||||
"postcss-url": "^10.1.3",
|
||||
"prettier": "^3.2.5",
|
||||
"solid-devtools": "^0.34.0",
|
||||
"storybook": "^8.6.14",
|
||||
"tailwindcss": "^3.4.3",
|
||||
"typescript": "^5.4.5",
|
||||
"typescript-eslint": "^8.32.1",
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
import { Portal } from "solid-js/web";
|
||||
import { useFloating } from "../base";
|
||||
import { autoUpdate, flip, hide, offset, shift, size } from "@floating-ui/dom";
|
||||
import { Button } from "@/src/components/button";
|
||||
import { Button } from "../../components/Button/Button";
|
||||
import {
|
||||
InputBase,
|
||||
InputError,
|
||||
|
||||
@@ -20,7 +20,7 @@ import { createEffect, For, JSX, Match, Show, Switch } from "solid-js";
|
||||
import cx from "classnames";
|
||||
import { Label } from "../base/label";
|
||||
import { SelectInput } from "../fields/Select";
|
||||
import { Button } from "@/src/components/button";
|
||||
import { Button } from "../../components/Button/Button";
|
||||
import Icon from "@/src/components/icon";
|
||||
|
||||
function generateDefaults(schema: JSONSchema7): unknown {
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
SubmitHandler,
|
||||
} from "@modular-forms/solid";
|
||||
import { TextInput } from "@/src/Form/fields/TextInput";
|
||||
import { Button } from "./components/button";
|
||||
import { Button } from "./components/Button/Button";
|
||||
import { callApi } from "./api";
|
||||
import { API } from "@/api/API";
|
||||
import { createSignal, Match, Switch } from "solid-js";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useNavigate } from "@solidjs/router";
|
||||
import { Button } from "./button";
|
||||
import { Button } from "./Button/Button";
|
||||
import Icon from "./icon";
|
||||
|
||||
export const BackButton = () => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
@import "./button-light.css";
|
||||
@import "./button-dark.css";
|
||||
@import "./button-ghost.css";
|
||||
@import "Button-Light.css";
|
||||
@import "Button-Dark.css";
|
||||
@import "Button-Ghost.css";
|
||||
|
||||
.button {
|
||||
@apply inline-flex items-center flex-shrink gap-1 justify-center p-4 font-semibold;
|
||||
43
pkgs/clan-app/ui/src/components/Button/Button.stories.tsx
Normal file
43
pkgs/clan-app/ui/src/components/Button/Button.stories.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import type { Meta, StoryObj } from "@kachurun/storybook-solid";
|
||||
import { Button, ButtonProps } from "./Button";
|
||||
import FlashIcon from "@/icons/flash.svg";
|
||||
|
||||
const meta: Meta<ButtonProps> = {
|
||||
title: "Components/Button",
|
||||
component: Button,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<ButtonProps>;
|
||||
|
||||
const children = "click me";
|
||||
const startIcon = <FlashIcon width={16} height={16} viewBox="0 0 48 48" />;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
children,
|
||||
startIcon,
|
||||
},
|
||||
};
|
||||
|
||||
export const Small: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
size: "s",
|
||||
},
|
||||
};
|
||||
|
||||
export const Light: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
variant: "light",
|
||||
},
|
||||
};
|
||||
|
||||
export const Ghost: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
variant: "ghost",
|
||||
},
|
||||
};
|
||||
@@ -1,8 +1,8 @@
|
||||
import { splitProps, type JSX } from "solid-js";
|
||||
import cx from "classnames";
|
||||
import { Typography } from "../Typography";
|
||||
//import './css/index.css'
|
||||
import "./css/index.css";
|
||||
|
||||
import "./Button-Base.css";
|
||||
|
||||
type Variants = "dark" | "light" | "ghost";
|
||||
type Size = "default" | "s";
|
||||
@@ -42,7 +42,8 @@ const sizeFont: Record<Size, string> = {
|
||||
s: cx("text-[0.75rem]"),
|
||||
};
|
||||
|
||||
interface ButtonProps extends JSX.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
export interface ButtonProps
|
||||
extends JSX.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
variant?: Variants;
|
||||
size?: Size;
|
||||
children?: JSX.Element;
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
shift,
|
||||
} from "@floating-ui/dom";
|
||||
import cx from "classnames";
|
||||
import { Button } from "./button";
|
||||
import { Button } from "./Button/Button";
|
||||
|
||||
interface MenuProps {
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createSignal, JSX, Show } from "solid-js";
|
||||
import Icon from "../icon";
|
||||
import { Button } from "../button";
|
||||
import { Button } from "../Button/Button";
|
||||
import cx from "classnames";
|
||||
import "./accordion.css";
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
import { Button } from ".";
|
||||
import FlashIcon from "@/icons/flash.svg";
|
||||
|
||||
export const Test = () => {
|
||||
<div class="p-8">
|
||||
<Button>Label</Button>
|
||||
<Button
|
||||
startIcon={<FlashIcon width={16} height={16} viewBox="0 0 48 48" />}
|
||||
>
|
||||
Label
|
||||
</Button>
|
||||
<Button
|
||||
variant="light"
|
||||
endIcon={<FlashIcon width={16} height={16} viewBox="0 0 48 48" />}
|
||||
>
|
||||
Label
|
||||
</Button>
|
||||
<Button size="s">Label</Button>
|
||||
<Button
|
||||
variant="light"
|
||||
size="s"
|
||||
endIcon={<FlashIcon width={13} height={13} viewBox="0 0 48 48" />}
|
||||
>
|
||||
Label
|
||||
</Button>
|
||||
</div>;
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
import Dialog from "corvu/dialog";
|
||||
import { createSignal, JSX } from "solid-js";
|
||||
import { Button } from "../button";
|
||||
import { Button } from "../Button/Button";
|
||||
import Icon from "../icon";
|
||||
import cx from "classnames";
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
import toast from "solid-toast";
|
||||
import { TextInput } from "@/src/Form/fields/TextInput";
|
||||
import { useNavigate } from "@solidjs/router";
|
||||
import { Button } from "@/src/components/button";
|
||||
import { Button } from "../../components/Button/Button";
|
||||
import Icon from "@/src/components/icon";
|
||||
import { useClanContext } from "@/src/contexts/clan";
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
} from "@modular-forms/solid";
|
||||
import { TextInput } from "@/src/Form/fields/TextInput";
|
||||
import toast from "solid-toast";
|
||||
import { Button } from "@/src/components/button";
|
||||
import { Button } from "../../components/Button/Button";
|
||||
import Icon from "@/src/components/icon";
|
||||
import { Header } from "@/src/layout/header";
|
||||
import { clanMetaQuery } from "@/src/queries/clan-meta";
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useFloating } from "@/src/floating";
|
||||
import { autoUpdate, flip, hide, offset, shift } from "@floating-ui/dom";
|
||||
import { A, useNavigate } from "@solidjs/router";
|
||||
import { registerClan } from "@/src/hooks";
|
||||
import { Button } from "@/src/components/button";
|
||||
import { Button } from "../../components/Button/Button";
|
||||
import Icon from "@/src/components/icon";
|
||||
import { useClanContext } from "@/src/contexts/clan";
|
||||
import { clanURIs, setActiveClanURI } from "@/src/stores/clan";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Button } from "@/src/components/button";
|
||||
import { Button } from "../../components/Button/Button";
|
||||
import { InputBase, InputLabel } from "@/src/components/inputBase";
|
||||
import { TextInput } from "@/src/Form/fields";
|
||||
import { Header } from "@/src/layout/header";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { callApi } from "@/src/api";
|
||||
import { Button } from "@/src/components/button";
|
||||
import { Button } from "../../components/Button/Button";
|
||||
// Icon is used in CustomFileField, ensure it's available or remove if not needed there
|
||||
import Icon from "@/src/components/icon";
|
||||
import { Typography } from "@/src/components/Typography";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { type Component, createSignal, For, Show } from "solid-js";
|
||||
import { OperationResponse, callApi } from "@/src/api";
|
||||
import { Button } from "@/src/components/button";
|
||||
import { Button } from "../../components/Button/Button";
|
||||
import Icon from "@/src/components/icon";
|
||||
|
||||
type ServiceModel = Extract<
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { callApi, OperationArgs } from "@/src/api";
|
||||
import { Button } from "@/src/components/button";
|
||||
import { Button } from "../../components/Button/Button";
|
||||
import Icon from "@/src/components/icon";
|
||||
import { TextInput } from "@/src/Form/fields/TextInput";
|
||||
import { Header } from "@/src/layout/header";
|
||||
|
||||
@@ -10,7 +10,7 @@ import { useNavigate, useParams, useSearchParams } from "@solidjs/router";
|
||||
import { createQuery, useQuery, useQueryClient } from "@tanstack/solid-query";
|
||||
import { createEffect, createSignal, For, Match, Show, Switch } from "solid-js";
|
||||
|
||||
import { Button } from "@/src/components/button";
|
||||
import { Button } from "../../components/Button/Button";
|
||||
import Icon from "@/src/components/icon";
|
||||
import { TextInput } from "@/src/Form/fields/TextInput";
|
||||
import Accordion from "@/src/components/accordion";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { callApi } from "@/src/api";
|
||||
import { Button } from "@/src/components/button";
|
||||
import { Button } from "../../../components/Button/Button";
|
||||
import Icon from "@/src/components/icon";
|
||||
import { InputError, InputLabel } from "@/src/components/inputBase";
|
||||
import { FieldLayout } from "@/src/Form/fields/layout";
|
||||
|
||||
@@ -14,7 +14,7 @@ import toast from "solid-toast";
|
||||
import { useNavigate, useParams, useSearchParams } from "@solidjs/router";
|
||||
import { StepProps } from "./hardware-step";
|
||||
import { BackButton } from "@/src/components/BackButton";
|
||||
import { Button } from "@/src/components/button";
|
||||
import { Button } from "../../../components/Button/Button";
|
||||
import { useClanContext } from "@/src/contexts/clan";
|
||||
|
||||
export type VarsValues = FieldValues & Record<string, Record<string, string>>;
|
||||
|
||||
@@ -3,7 +3,7 @@ import { callApi, OperationResponse } from "@/src/api";
|
||||
import { MachineListItem } from "@/src/components/machine-list-item";
|
||||
import { useQuery, useQueryClient } from "@tanstack/solid-query";
|
||||
import { useNavigate } from "@solidjs/router";
|
||||
import { Button } from "@/src/components/button";
|
||||
import { Button } from "../../components/Button/Button";
|
||||
import Icon from "@/src/components/icon";
|
||||
import { Header } from "@/src/layout/header";
|
||||
import { makePersisted } from "@solid-primitives/storage";
|
||||
|
||||
@@ -7,7 +7,7 @@ import { createQuery } from "@tanstack/solid-query";
|
||||
import { JSONSchema7 } from "json-schema";
|
||||
import { SubmitHandler } from "@modular-forms/solid";
|
||||
import { DynForm } from "@/src/Form/form";
|
||||
import { Button } from "@/src/components/button";
|
||||
import { Button } from "../../components/Button/Button";
|
||||
import Icon from "@/src/components/icon";
|
||||
import { useClanContext } from "@/src/contexts/clan";
|
||||
import { activeClanURI } from "@/src/stores/clan";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { SuccessData } from "@/src/api";
|
||||
import { Button } from "@/src/components/button";
|
||||
import { Button } from "../../components/Button/Button";
|
||||
import { Header } from "@/src/layout/header";
|
||||
import { createModulesQuery } from "@/src/queries";
|
||||
import { A, useNavigate } from "@solidjs/router";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Button } from "@/src/components/button";
|
||||
import { Button } from "../../components/Button/Button";
|
||||
import { registerClan } from "@/src/hooks";
|
||||
import { useNavigate } from "@solidjs/router";
|
||||
import { useClanContext } from "@/src/contexts/clan";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createEffect, createSignal, onCleanup, onMount, Show } from "solid-js";
|
||||
import * as THREE from "three";
|
||||
import { Button } from "./components/button";
|
||||
import { Button } from "./components/Button/Button";
|
||||
import Icon from "./components/icon";
|
||||
|
||||
function addCubesSpiral({
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
{
|
||||
"exclude": [
|
||||
// ignore storybook stories
|
||||
"**/*.stories.tsx"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"target": "ESNext",
|
||||
|
||||
Reference in New Issue
Block a user