Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Storybook #65

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions frontend/components/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
# node
node_modules/

*storybook.log
3 changes: 3 additions & 0 deletions frontend/components/.storybook/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
40 changes: 40 additions & 0 deletions frontend/components/.storybook/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import type { StorybookConfig } from "@storybook/react-vite";
import { mergeConfig } from "vite";
import tsConfigPaths from "vite-tsconfig-paths";

import { join, dirname } from "path";

/**
* This function is used to resolve the absolute path of a package.
* It is needed in projects that use Yarn PnP or are set up within a monorepo.
*/
function getAbsolutePath(value: string): any {
return dirname(require.resolve(join(value, "package.json")));
}
const config: StorybookConfig = {
stories: [
"../stories/**/*.mdx",
"../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)",
],
addons: [
getAbsolutePath("@storybook/addon-essentials"),
getAbsolutePath("@storybook/addon-onboarding"),
getAbsolutePath("@chromatic-com/storybook"),
getAbsolutePath("@storybook/experimental-addon-test"),
],
framework: {
name: getAbsolutePath("@storybook/react-vite"),
options: {},
},
viteFinal: async (config) => {
return mergeConfig(config, {
plugins: [tsConfigPaths()],
});
},
typescript: {
reactDocgenTypescriptOptions: {
tsconfigPath: "./tsconfig.json",
},
},
};
export default config;
17 changes: 17 additions & 0 deletions frontend/components/.storybook/preview.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { Preview } from "@storybook/react";
import "./index.css";
import "@styles/colors.css";
import "@styles/main.css";

const preview: Preview = {
parameters: {
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
},
};

export default preview;
9 changes: 9 additions & 0 deletions frontend/components/.storybook/vitest.setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { beforeAll } from 'vitest';
import { setProjectAnnotations } from '@storybook/react';
import * as projectAnnotations from './preview';

// This is an important step to apply the right configuration when testing your stories.
// More info at: https://storybook.js.org/docs/api/portable-stories/portable-stories-vitest#setprojectannotations
const project = setProjectAnnotations([projectAnnotations]);

beforeAll(project.beforeAll);
1 change: 0 additions & 1 deletion frontend/components/base/Buttons/IconButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ export type IconButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> &
iconClassName?: string;
loading?: boolean;
};

const IconButton = ({
icon: Icon,
size,
Expand Down
2 changes: 1 addition & 1 deletion frontend/components/base/Buttons/button.variants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export const iconButtonVariants = tv({
icon: "size-4",
},
xs: {
base: "size-6",
base: "size-5",
icon: "size-[14px]",
},
sm: {
Expand Down
2 changes: 1 addition & 1 deletion frontend/components/base/dialog/alert-dialog-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
import { alertDialog, OpenAlertDialogProps } from "./alert-dialog-store";
import { Spinner } from "../spinner";

type AlertDialogProps = OpenAlertDialogProps & {
export type AlertDialogProps = OpenAlertDialogProps & {
isOpen: boolean;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const GreaterThanOperatorIcon = ({
<svg
height={size}
width={size}
viewBox="0 0 14 14"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const GreaterThanOrEqualOperatorIcon = ({
<svg
height={size}
width={size}
viewBox="0 0 14 14"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
Expand Down
2 changes: 1 addition & 1 deletion frontend/components/base/icons/less-than-operator-icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const LessThanOperatorIcon = ({
<svg
height={size}
width={size}
viewBox="0 0 14 14"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const LessThanOrEqualOperatorIcon = ({
<svg
height={size}
width={size}
viewBox="0 0 14 14"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
import { Input } from "@/components/base/ui/input";
import { QueryInstance } from "@/components/model/query-builder-core";
import { useQueryBuilderDictContext } from "../query-builder-context";
import { useState } from "react";

const formSchema = z.object({
title: z.string(),
Expand All @@ -35,6 +36,7 @@ function QueryBarSaveDialog({
onOpenChange: (open: boolean) => void;
query: QueryInstance;
}) {
const [saving, setSaving] = useState(false);
const dict = useQueryBuilderDictContext();

const form = useForm<z.infer<typeof formSchema>>({
Expand All @@ -45,9 +47,10 @@ function QueryBarSaveDialog({
});

const onSubmit = async (values: z.infer<typeof formSchema>) => {
return Promise.resolve(query.saveAsCustomPill(values.title)).then(() =>
onOpenChange(false)
);
setSaving(true);
return Promise.resolve(query.saveAsCustomPill(values.title))
.then(() => onOpenChange(false))
.finally(() => setSaving(false));
};

return (
Expand Down Expand Up @@ -85,7 +88,7 @@ function QueryBarSaveDialog({
{dict.queryBar.saveDialog.cancel}
</Button>
</DialogClose>
<Button type="submit" variant="primary">
<Button type="submit" variant="primary" loading={saving}>
{dict.queryBar.saveDialog.ok}
</Button>
</DialogFooter>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ function QueryPillCustomEditDialog({
});

const [title, setTitle] = useState(queryPill.title);
const [saving, setSaving] = useState(false);

const coreQuery = customQueryBuilder.getQueries()[0];
const coreSavedFilter = customQueryBuilder.getSelectedSavedFilter();
Expand All @@ -97,17 +98,21 @@ function QueryPillCustomEditDialog({
return;
}

setSaving(true);

if (titleChanged) {
const valid = await customPillConfig?.validateCustomPillTitle(title);

if (valid !== undefined && valid === false) {
setSaving(false);
openCustomPillTitleExistsDialog(dict);
return;
}
}

const associatedSavedFilters =
await customPillConfig?.fetchSavedFiltersByCustomPillId(queryPill.id);
const associatedSavedFilters = await customPillConfig
?.fetchSavedFiltersByCustomPillId(queryPill.id)
.finally(() => setSaving(false));

openCustomPillSaveDialog(dict, title, associatedSavedFilters, async () =>
coreSavedFilter?.save(SavedFilterTypeEnum.Query, {
Expand Down Expand Up @@ -143,7 +148,7 @@ function QueryPillCustomEditDialog({
<div>
<EditableText onChangeText={setTitle}>{title}</EditableText>
</div>
<div data-query-active className="flex group/query">
<div data-query-active className="flex flex-wrap group/query">
<QueryBarContext.Provider value={{ query: coreQuery }}>
<QueryPillBoolean sqon={coreQuery.raw()} />
</QueryBarContext.Provider>
Expand All @@ -157,6 +162,7 @@ function QueryPillCustomEditDialog({
<Button
type="submit"
variant="primary"
loading={saving}
disabled={!hasChanged}
onClick={handleSave}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ function QueryPillValues({ valueFilter }: QueryPillValuesProps) {
))
)}
{canExpand && (
<div className="absolute right-1">
<div className="absolute right-1 hover:cursor-pointer">
{expanded ? (
<ChevronLeft size={16} onClick={() => setExpanded(false)} />
) : (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1164,3 +1164,5 @@ describe("QueryBuilder Core", () => {
expect(qb.isEmpty()).toBeFalsy();
});
});

// TODO test fieldsToIgnore
19 changes: 17 additions & 2 deletions frontend/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,29 @@
"main": "index.js",
"scripts": {
"test": "vite-jest",
"dev": "tailwindcss -i ./style/styles.css -o ./style/dist/styles.css"
"storybook": "THEME=radiant storybook dev -p 6006",
"build-storybook": "storybook build"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"devDependencies": {
"@chromatic-com/storybook": "^3.2.5",
"@storybook/addon-essentials": "^8.6.3",
"@storybook/addon-onboarding": "^8.6.3",
"@storybook/blocks": "^8.6.3",
"@storybook/experimental-addon-test": "^8.6.3",
"@storybook/react": "^8.6.3",
"@storybook/react-vite": "^8.6.3",
"@storybook/test": "^8.6.3",
"@types/lodash": "^4.17.14",
"tailwindcss": "^3.4.16"
"@vitest/browser": "^3.0.7",
"@vitest/coverage-v8": "^3.0.7",
"playwright": "^1.50.1",
"storybook": "^8.6.3",
"tailwindcss": "^3.4.16",
"vitest": "^3.0.7"
},
"dependencies": {
"@dnd-kit/core": "^6.3.1",
Expand All @@ -33,6 +47,7 @@
"@radix-ui/react-tabs": "^1.1.1",
"@radix-ui/react-tooltip": "^1.1.8",
"@tanstack/react-table": "^8.20.6",
"@vitejs/plugin-react": "^4.3.4",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lodash": "^4.17.21",
Expand Down
97 changes: 97 additions & 0 deletions frontend/components/stories/base/buttons/action-button.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import type { Meta, StoryObj } from "@storybook/react";
import { fn } from "@storybook/test";

import ActionButton from "@/components/base/Buttons/ActionButton";

const meta = {
title: "Base/Buttons/Action Button",
component: ActionButton,
tags: ["autodocs"],
args: { onClick: fn(), size: "default", actions: [], onDefaultAction: fn() },
} satisfies Meta<typeof ActionButton>;

export default meta;

type Story = StoryObj<typeof meta>;

export const Default: Story = {
args: {
children: "Button",
variant: "default",
},
};

export const Outline: Story = {
args: {
children: "Button",
variant: "outline",
},
};

export const Primary: Story = {
args: {
children: "Button",
variant: "primary",
},
};

export const Secondary: Story = {
args: {
children: "Button",
variant: "secondary",
},
};

export const Ghost: Story = {
args: {
children: "Button",
variant: "ghost",
},
};

export const Destructive: Story = {
args: {
children: "Button",
variant: "destructive",
},
};

export const Loading: Story = {
args: {
children: "Button",
variant: "primary",
},
};

export const Disabled: Story = {
args: {
children: "Button",
variant: "primary",
disabled: true,
},
};

export const Sizes: Story = {
args: {
children: "Button",
},
render: (args) => (
<div className="flex gap-2">
<ActionButton {...args} size="default" variant="primary">
Default
</ActionButton>
<ActionButton {...args} size="xs" variant="primary">
AButton xs
</ActionButton>
<ActionButton {...args} size="sm" variant="primary">
AButton sm
</ActionButton>
<ActionButton {...args} size="md" variant="primary">
AButton md
</ActionButton>
<ActionButton {...args} size="lg" variant="primary">
AButton lg
</ActionButton>
</div>
),
};
Loading
Loading