Merge pull request #6 from codex-storage/add-events-to-storybook
Add events to be tracked by the Storybook while interacting with the …
This commit is contained in:
commit
b4d2072d49
|
@ -23,6 +23,10 @@ type Props = {
|
|||
|
||||
onClick?: () => unknown | Promise<unknown>;
|
||||
|
||||
onMouseEnter?: () => unknown | Promise<unknown>;
|
||||
|
||||
onMouseLeave?: () => unknown | Promise<unknown>;
|
||||
|
||||
label: string;
|
||||
|
||||
/**
|
||||
|
@ -67,6 +71,8 @@ export function Button({
|
|||
label,
|
||||
className = "",
|
||||
Icon,
|
||||
onMouseEnter,
|
||||
onMouseLeave,
|
||||
fetching = false,
|
||||
disabled = false,
|
||||
style,
|
||||
|
@ -76,6 +82,8 @@ export function Button({
|
|||
return (
|
||||
<button
|
||||
onClick={onClick}
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
style={style}
|
||||
className={`button ${className} button--${variant}`}
|
||||
{...attributes({
|
||||
|
|
|
@ -15,6 +15,10 @@ type Props = {
|
|||
|
||||
onClick?: () => void;
|
||||
|
||||
onMouseEnter?: () => unknown | Promise<unknown>;
|
||||
|
||||
onMouseLeave?: () => unknown | Promise<unknown>;
|
||||
|
||||
disabled?: boolean;
|
||||
|
||||
/**
|
||||
|
@ -32,12 +36,16 @@ export function ButtonIcon({
|
|||
Icon,
|
||||
onClick,
|
||||
style,
|
||||
onMouseEnter,
|
||||
onMouseLeave,
|
||||
disabled = false,
|
||||
variant = "big",
|
||||
}: Props) {
|
||||
return (
|
||||
<button
|
||||
className={`buttonIcon buttonIcon--${variant}`}
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
onClick={onClick}
|
||||
style={style}
|
||||
{...attributes({ disabled: disabled, "aria-disabled": disabled })}
|
||||
|
|
|
@ -52,6 +52,14 @@ type Props = {
|
|||
*/
|
||||
onSelected?: (o: DropdownOption) => void;
|
||||
|
||||
onBlur?: () => void;
|
||||
|
||||
onFocus?: () => void;
|
||||
|
||||
onMouseEnter?: () => void;
|
||||
|
||||
onMouseLeave?: () => void;
|
||||
|
||||
/**
|
||||
* Apply custom css variables.
|
||||
* --codex-dropdown-panel-background
|
||||
|
@ -65,6 +73,10 @@ export function Dropdown({
|
|||
placeholder,
|
||||
style,
|
||||
options,
|
||||
onMouseEnter,
|
||||
onMouseLeave,
|
||||
onFocus,
|
||||
onBlur,
|
||||
onChange,
|
||||
onSelected,
|
||||
value = "",
|
||||
|
@ -78,11 +90,17 @@ export function Dropdown({
|
|||
);
|
||||
const [focused, setFocused] = useState(false);
|
||||
|
||||
const onFocus = () => setFocused(true);
|
||||
const onInternalFocus = () => {
|
||||
setFocused(true);
|
||||
onFocus?.();
|
||||
};
|
||||
|
||||
const onBlur = () => () => window.setTimeout(() => setFocused(false), 150);
|
||||
const onInternalBlur = () => {
|
||||
onBlur?.();
|
||||
window.setTimeout(() => setFocused(false), 150);
|
||||
};
|
||||
|
||||
const onClick = (o: DropdownOption) => {
|
||||
const onSelect = (o: DropdownOption) => {
|
||||
onSelected?.(o);
|
||||
setFocused(false);
|
||||
};
|
||||
|
@ -98,12 +116,14 @@ export function Dropdown({
|
|||
<Input
|
||||
className="dropdown-input"
|
||||
onChange={onChange}
|
||||
onFocus={onFocus}
|
||||
onBlur={onBlur}
|
||||
onFocus={onInternalFocus}
|
||||
onBlur={onInternalBlur}
|
||||
placeholder={placeholder}
|
||||
value={value}
|
||||
label={""}
|
||||
id={""}
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
/>
|
||||
|
||||
<div className="dropdown-panel" {...attr}>
|
||||
|
@ -111,7 +131,7 @@ export function Dropdown({
|
|||
filtered.map((o) => (
|
||||
<div
|
||||
className="dropdown-option"
|
||||
onClick={() => onClick(o)}
|
||||
onClick={() => onSelect(o)}
|
||||
key={o.title}
|
||||
>
|
||||
{o.Icon && <o.Icon />}
|
||||
|
|
|
@ -27,6 +27,12 @@ type Props = {
|
|||
|
||||
onBlur?: () => unknown | Promise<unknown>;
|
||||
|
||||
onClick?: (() => void) | undefined;
|
||||
|
||||
onMouseEnter?: () => void;
|
||||
|
||||
onMouseLeave?: () => void;
|
||||
|
||||
placeholder?: string;
|
||||
|
||||
value?: string;
|
||||
|
@ -74,6 +80,9 @@ export function Input({
|
|||
onFocus,
|
||||
placeholder,
|
||||
onChange,
|
||||
onMouseEnter,
|
||||
onMouseLeave,
|
||||
onClick,
|
||||
className,
|
||||
style,
|
||||
Icon,
|
||||
|
@ -95,6 +104,9 @@ export function Input({
|
|||
</div>
|
||||
)}
|
||||
<input
|
||||
onClick={onClick}
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
className={classnames(
|
||||
["input"],
|
||||
["input-icon-input", !!Icon],
|
||||
|
|
|
@ -43,6 +43,14 @@ type Props = {
|
|||
*/
|
||||
onGroupChange?: (e: ChangeEvent<HTMLSelectElement>) => void;
|
||||
|
||||
onBlur?: () => void;
|
||||
|
||||
onFocus?: () => void;
|
||||
|
||||
onMouseEnter?: () => void;
|
||||
|
||||
onMouseLeave?: () => void;
|
||||
|
||||
id: string;
|
||||
|
||||
step?: string;
|
||||
|
@ -63,9 +71,13 @@ export function InputGroup({
|
|||
className,
|
||||
onChange,
|
||||
onGroupChange,
|
||||
onMouseEnter,
|
||||
onMouseLeave,
|
||||
onFocus,
|
||||
onBlur,
|
||||
id,
|
||||
step,
|
||||
value = "",
|
||||
value = undefined,
|
||||
groupValue = "",
|
||||
}: Props) {
|
||||
return (
|
||||
|
@ -81,6 +93,10 @@ export function InputGroup({
|
|||
type={type}
|
||||
value={value}
|
||||
step={step}
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
onFocus={onFocus}
|
||||
onBlur={onBlur}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ select.inputGroup-select {
|
|||
border-top-right-radius: var(--codex-border-radius);
|
||||
border-bottom-right-radius: var(--codex-border-radius);
|
||||
background-color: var(--codex-border-color);
|
||||
padding: 0.75rem;
|
||||
padding: calc(0.5rem + 0.5px);
|
||||
}
|
||||
|
||||
.inputGroup-inputContainer {
|
||||
|
|
|
@ -24,6 +24,14 @@ type Props = {
|
|||
*/
|
||||
onChange?: (e: ChangeEvent<HTMLSelectElement>) => void | Promise<void>;
|
||||
|
||||
onFocus?: () => void | Promise<void>;
|
||||
|
||||
onBlur?: () => unknown | Promise<unknown>;
|
||||
|
||||
onMouseEnter?: () => void;
|
||||
|
||||
onMouseLeave?: () => void;
|
||||
|
||||
/**
|
||||
* Apply custom css variables.
|
||||
*/
|
||||
|
@ -39,6 +47,10 @@ export function Select({
|
|||
id,
|
||||
options,
|
||||
onChange,
|
||||
onBlur,
|
||||
onFocus,
|
||||
onMouseEnter,
|
||||
onMouseLeave,
|
||||
style,
|
||||
className,
|
||||
defaultValue,
|
||||
|
@ -53,6 +65,10 @@ export function Select({
|
|||
id={id}
|
||||
className={`select ${className}`}
|
||||
onChange={onChange}
|
||||
onBlur={onBlur}
|
||||
onFocus={onFocus}
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
style={style}
|
||||
defaultValue={defaultValue}
|
||||
>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { ReactNode } from "react";
|
||||
import "./Table.css";
|
||||
import { CellRender } from "./CellRender";
|
||||
|
||||
|
|
|
@ -32,12 +32,23 @@ type Props = {
|
|||
*/
|
||||
onSuccess?: (cid: string) => void;
|
||||
|
||||
/*
|
||||
* Event triggered when the user selected files to upload.
|
||||
*/
|
||||
onFileChange?: (e: ChangeEvent<HTMLInputElement>) => void;
|
||||
|
||||
/**
|
||||
* Event triggered when a file is deleted.
|
||||
* The id is generated after the file are selected by the user.
|
||||
*/
|
||||
onDeleteItem?: (id: string) => void;
|
||||
|
||||
onClick?: (() => void) | undefined;
|
||||
|
||||
onMouseEnter?: () => void;
|
||||
|
||||
onMouseLeave?: () => void;
|
||||
|
||||
/**
|
||||
* Allow to override the previous file(s).
|
||||
* If false, the user cannot upload a new file(s) until he deletes the previous file(s).
|
||||
|
@ -86,6 +97,10 @@ const defaultProvider = () =>
|
|||
);
|
||||
|
||||
export function Upload({
|
||||
onMouseEnter,
|
||||
onMouseLeave,
|
||||
onClick,
|
||||
onFileChange,
|
||||
multiple = true,
|
||||
editable = true,
|
||||
onDeleteItem,
|
||||
|
@ -109,7 +124,7 @@ export function Upload({
|
|||
uploadFiles(e.dataTransfer.files);
|
||||
};
|
||||
|
||||
const onFileChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
const onInternalFileChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
if (e.target.files) {
|
||||
uploadFiles(e.target.files);
|
||||
}
|
||||
|
@ -117,6 +132,8 @@ export function Upload({
|
|||
if (input.current) {
|
||||
input.current.value = "";
|
||||
}
|
||||
|
||||
onFileChange?.(e);
|
||||
};
|
||||
|
||||
const onClose = (id: string) => {
|
||||
|
@ -124,17 +141,22 @@ export function Upload({
|
|||
onDeleteItem?.(id);
|
||||
};
|
||||
|
||||
const onClick = () => input.current?.click();
|
||||
const onInternalClick = () => {
|
||||
onClick?.();
|
||||
input.current?.click();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className={classnames(["upload"], ["upload-warning", !!warning])}
|
||||
tabIndex={1}
|
||||
onClick={onClick}
|
||||
onClick={onInternalClick}
|
||||
onDragOver={onDragPrevents}
|
||||
onDragEnter={onDragPrevents}
|
||||
onDrop={onDrop}
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
>
|
||||
<ButtonIcon Icon={multiple ? FileStack : UploadIcon}></ButtonIcon>
|
||||
<div className="upload-text">
|
||||
|
@ -152,7 +174,7 @@ export function Upload({
|
|||
type="file"
|
||||
hidden
|
||||
ref={input}
|
||||
onChange={onFileChange}
|
||||
onChange={onInternalFileChange}
|
||||
{...attributes({ multiple: multiple })}
|
||||
/>
|
||||
|
||||
|
|
|
@ -20,7 +20,11 @@ const meta = {
|
|||
},
|
||||
},
|
||||
// Use `fn` to spy on the onClick arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#action-args
|
||||
args: { onClick: fn() },
|
||||
args: {
|
||||
onClick: fn(),
|
||||
onMouseEnter: fn(),
|
||||
onMouseLeave: fn(),
|
||||
},
|
||||
} satisfies Meta<typeof Button>;
|
||||
|
||||
export default meta;
|
||||
|
|
|
@ -15,7 +15,7 @@ const meta = {
|
|||
control: { type: "select" },
|
||||
},
|
||||
},
|
||||
args: { onClick: fn() },
|
||||
args: { onClick: fn(), onMouseEnter: fn(), onMouseLeave: fn() },
|
||||
} satisfies Meta<typeof ButtonIcon>;
|
||||
|
||||
export default meta;
|
||||
|
|
|
@ -3,6 +3,7 @@ import { Dropdown, DropdownOption } from "../src/components/Dropdown/Dropdown";
|
|||
import { PdfIcon } from "../src/components/WebFileIcon/PdfIcon";
|
||||
import { ImageIcon } from "../src/components/WebFileIcon/ImageIcon";
|
||||
import { ChangeEvent, useState } from "react";
|
||||
import { fn } from "@storybook/test";
|
||||
|
||||
const meta = {
|
||||
title: "Forms/Dropdown",
|
||||
|
@ -12,20 +13,46 @@ const meta = {
|
|||
},
|
||||
tags: ["autodocs"],
|
||||
argTypes: {},
|
||||
args: {
|
||||
onChange: fn(),
|
||||
onSelected: fn(),
|
||||
onFocus: fn(),
|
||||
onBlur: fn(),
|
||||
onMouseEnter: fn(),
|
||||
onMouseLeave: fn(),
|
||||
},
|
||||
} satisfies Meta<typeof Dropdown>;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
const Template = () => {
|
||||
const [value, setValue] = useState<string>("");
|
||||
const onChange = (e: ChangeEvent<HTMLInputElement>) =>
|
||||
setValue(e.currentTarget.value);
|
||||
type Props = {
|
||||
onChange: (e: ChangeEvent<HTMLInputElement>) => void;
|
||||
|
||||
const onSelected = (o: DropdownOption) => setValue(o.title);
|
||||
onSelected?: (o: DropdownOption) => void;
|
||||
|
||||
onClick?: () => void;
|
||||
|
||||
onMouseEnter?: () => void;
|
||||
|
||||
onBlur?: () => void;
|
||||
};
|
||||
|
||||
const Template = (p: Props) => {
|
||||
const [value, setValue] = useState<string>("");
|
||||
const onChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
p.onChange(e);
|
||||
setValue(e.currentTarget.value);
|
||||
};
|
||||
|
||||
const onSelected = (o: DropdownOption) => {
|
||||
setValue(o.title);
|
||||
p.onSelected?.(o);
|
||||
};
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
{...p}
|
||||
placeholder="Select your file"
|
||||
onChange={onChange}
|
||||
onSelected={onSelected}
|
||||
|
@ -46,7 +73,7 @@ const Template = () => {
|
|||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
export const Default = Template;
|
||||
|
||||
export const CustomStyle: Story = {
|
||||
args: {
|
||||
|
@ -54,6 +81,5 @@ export const CustomStyle: Story = {
|
|||
options: [],
|
||||
style: { "--codex-input-border": "1px solid red" },
|
||||
value: "",
|
||||
onChange: () => "",
|
||||
},
|
||||
};
|
||||
|
|
|
@ -11,7 +11,13 @@ const meta = {
|
|||
},
|
||||
tags: ["autodocs"],
|
||||
argTypes: {},
|
||||
args: { onChange: fn() },
|
||||
args: {
|
||||
onFocus: fn(),
|
||||
onBlur: fn(),
|
||||
onMouseEnter: fn(),
|
||||
onMouseLeave: fn(),
|
||||
onChange: fn(),
|
||||
},
|
||||
} satisfies Meta<typeof Input>;
|
||||
|
||||
export default meta;
|
||||
|
|
|
@ -10,7 +10,14 @@ const meta = {
|
|||
},
|
||||
tags: ["autodocs"],
|
||||
argTypes: {},
|
||||
args: { onChange: fn() },
|
||||
args: {
|
||||
onGroupChange: fn(),
|
||||
onChange: fn(),
|
||||
onFocus: fn(),
|
||||
onBlur: fn(),
|
||||
onMouseEnter: fn(),
|
||||
onMouseLeave: fn(),
|
||||
},
|
||||
} satisfies Meta<typeof InputGroup>;
|
||||
|
||||
export default meta;
|
||||
|
|
|
@ -10,7 +10,13 @@ const meta = {
|
|||
},
|
||||
tags: ["autodocs"],
|
||||
argTypes: {},
|
||||
args: { onChange: fn() },
|
||||
args: {
|
||||
onFocus: fn(),
|
||||
onBlur: fn(),
|
||||
onMouseEnter: fn(),
|
||||
onMouseLeave: fn(),
|
||||
onChange: fn(),
|
||||
},
|
||||
} satisfies Meta<typeof Select>;
|
||||
|
||||
export default meta;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
import { Stepper } from "../src/components/Stepper/Stepper";
|
||||
import React, { useState } from "react";
|
||||
import { fn } from "@storybook/test";
|
||||
|
||||
const meta = {
|
||||
title: "Advanced/Stepper",
|
||||
|
@ -10,13 +11,16 @@ const meta = {
|
|||
},
|
||||
tags: ["autodocs"],
|
||||
argTypes: {},
|
||||
// args: { onClick: fn() },
|
||||
args: { onChangeStep: fn() },
|
||||
} satisfies Meta<typeof Stepper>;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
const Template = () => {
|
||||
type Props = {
|
||||
onChangeStep: (s: number, state: "before" | "end") => void | Promise<void>;
|
||||
};
|
||||
|
||||
const Template = (p: Props) => {
|
||||
const [step, setStep] = useState(0);
|
||||
const [progress, setProgress] = useState(false);
|
||||
|
||||
|
@ -24,6 +28,8 @@ const Template = () => {
|
|||
const title = titles[step];
|
||||
|
||||
const onChangeStep = (newStep: number, event: "before" | "end") => {
|
||||
p.onChangeStep(newStep, event);
|
||||
|
||||
if (event === "before") {
|
||||
setProgress(true);
|
||||
return;
|
||||
|
|
|
@ -2,6 +2,7 @@ import type { Meta } from "@storybook/react";
|
|||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { UploadResponse } from "@codex/sdk-js";
|
||||
import { Upload } from "../src/components/Upload/Upload";
|
||||
import { fn } from "@storybook/test";
|
||||
|
||||
const meta = {
|
||||
title: "Advanced/Upload",
|
||||
|
@ -11,16 +12,36 @@ const meta = {
|
|||
},
|
||||
tags: ["autodocs"],
|
||||
argTypes: {},
|
||||
args: {
|
||||
onMouseEnter: fn(),
|
||||
onMouseLeave: fn(),
|
||||
onClick: fn(),
|
||||
onSuccess: fn(),
|
||||
onDeleteItem: fn(),
|
||||
onFileChange: fn(),
|
||||
},
|
||||
} satisfies Meta<typeof Upload>;
|
||||
|
||||
export default meta;
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
const Template = () => {
|
||||
type Props = {
|
||||
onClick?: () => void;
|
||||
|
||||
onMouseEnter?: () => void;
|
||||
|
||||
onMouseLeave?: () => void;
|
||||
|
||||
onSuccess?: () => void;
|
||||
|
||||
onDeletedItem?: () => void;
|
||||
};
|
||||
|
||||
const Template = (p: Props) => {
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
{<Upload useWorker={false} multiple />}
|
||||
{<Upload useWorker={false} multiple {...p} />}
|
||||
</QueryClientProvider>
|
||||
);
|
||||
};
|
||||
|
@ -59,11 +80,11 @@ const slowProvider = () =>
|
|||
}
|
||||
);
|
||||
|
||||
const SlowTemplate = () => {
|
||||
const SlowTemplate = (p: Props) => {
|
||||
return (
|
||||
<div className="demo">
|
||||
<QueryClientProvider client={queryClient}>
|
||||
{<Upload useWorker={false} multiple provider={slowProvider} />}
|
||||
{<Upload useWorker={false} multiple provider={slowProvider} {...p} />}
|
||||
</QueryClientProvider>
|
||||
</div>
|
||||
);
|
||||
|
@ -71,7 +92,7 @@ const SlowTemplate = () => {
|
|||
|
||||
export const Slow = SlowTemplate.bind({});
|
||||
|
||||
const SingleTemplate = () => {
|
||||
const SingleTemplate = (p: Props) => {
|
||||
return (
|
||||
<div className="demo">
|
||||
<QueryClientProvider client={queryClient}>
|
||||
|
@ -81,6 +102,7 @@ const SingleTemplate = () => {
|
|||
multiple={false}
|
||||
editable={false}
|
||||
provider={slowProvider}
|
||||
{...p}
|
||||
/>
|
||||
}
|
||||
</QueryClientProvider>
|
||||
|
|
Loading…
Reference in New Issue