@peerbots/core 0.2.6 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.changeset/config.json +1 -1
- package/.github/workflows/storybook.yml +9 -1
- package/CHANGELOG.md +94 -0
- package/dist/index.d.mts +643 -131
- package/dist/index.d.ts +643 -131
- package/dist/index.js +7 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +7 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -3
- package/src/charts/DistributionBarChart.tsx +10 -4
- package/src/charts/DistributionHistogram.tsx +13 -5
- package/src/charts/LineGraph.stories.tsx +60 -0
- package/src/charts/LineGraph.tsx +216 -0
- package/src/charts/index.ts +2 -0
- package/src/docs/DesignSystem.mdx +241 -25
- package/src/styles/theme.css +8 -0
- package/src/ui/feedback/Alert.stories.tsx +56 -0
- package/src/ui/feedback/Alert.tsx +168 -0
- package/src/ui/{Dialog.stories.tsx → feedback/Dialog.stories.tsx} +2 -2
- package/src/ui/{Dialog.tsx → feedback/Dialog.tsx} +2 -2
- package/src/ui/feedback/EmptyState.stories.tsx +57 -0
- package/src/ui/feedback/EmptyState.tsx +123 -0
- package/src/ui/feedback/Popover.stories.tsx +130 -0
- package/src/ui/feedback/Popover.tsx +135 -0
- package/src/ui/feedback/Skeleton.stories.tsx +88 -0
- package/src/ui/{Skeleton.tsx → feedback/Skeleton.tsx} +2 -2
- package/src/ui/feedback/Spinner.stories.tsx +77 -0
- package/src/ui/feedback/Spinner.tsx +62 -0
- package/src/ui/{Tooltip.stories.tsx → feedback/Tooltip.stories.tsx} +3 -3
- package/src/ui/{Tooltip.tsx → feedback/Tooltip.tsx} +2 -2
- package/src/ui/feedback/index.ts +7 -0
- package/src/ui/forms/Button.stories.tsx +181 -0
- package/src/ui/forms/Button.tsx +323 -0
- package/src/ui/{Checkbox.stories.tsx → forms/Checkbox.stories.tsx} +2 -2
- package/src/ui/{Checkbox.tsx → forms/Checkbox.tsx} +2 -2
- package/src/ui/forms/ChipGroup.stories.tsx +118 -0
- package/src/ui/forms/ChipGroup.tsx +239 -0
- package/src/ui/{Dropdown.tsx → forms/Dropdown.tsx} +1 -1
- package/src/ui/{Field.stories.tsx → forms/Field.stories.tsx} +3 -3
- package/src/ui/{Field.tsx → forms/Field.tsx} +1 -1
- package/src/ui/{Input.stories.tsx → forms/Input.stories.tsx} +6 -6
- package/src/ui/{Input.tsx → forms/Input.tsx} +1 -1
- package/src/ui/{Label.stories.tsx → forms/Label.stories.tsx} +2 -2
- package/src/ui/{Label.tsx → forms/Label.tsx} +2 -2
- package/src/ui/{NumberField.stories.tsx → forms/NumberField.stories.tsx} +2 -2
- package/src/ui/{NumberField.tsx → forms/NumberField.tsx} +8 -9
- package/src/ui/forms/PeerbotsColorSelector.stories.tsx +49 -0
- package/src/ui/forms/PeerbotsColorSelector.tsx +100 -0
- package/src/ui/{Select.stories.tsx → forms/Select.stories.tsx} +2 -2
- package/src/ui/{Select.tsx → forms/Select.tsx} +5 -3
- package/src/ui/{Slider.stories.tsx → forms/Slider.stories.tsx} +6 -4
- package/src/ui/{Slider.tsx → forms/Slider.tsx} +7 -3
- package/src/ui/forms/SliderWithNumberField.stories.tsx +136 -0
- package/src/ui/{SliderWithNumberField.tsx → forms/SliderWithNumberField.tsx} +19 -7
- package/src/ui/{Switch.stories.tsx → forms/Switch.stories.tsx} +2 -2
- package/src/ui/{Switch.tsx → forms/Switch.tsx} +1 -1
- package/src/ui/{TabRadio.stories.tsx → forms/TabRadio.stories.tsx} +3 -3
- package/src/ui/{TabRadio.tsx → forms/TabRadio.tsx} +1 -1
- package/src/ui/{TextArea.stories.tsx → forms/TextArea.stories.tsx} +5 -3
- package/src/ui/{TextArea.tsx → forms/TextArea.tsx} +1 -1
- package/src/ui/forms/index.ts +15 -0
- package/src/ui/foundations/Anchor.stories.tsx +39 -0
- package/src/ui/foundations/Anchor.tsx +96 -0
- package/src/ui/foundations/CodeBlock.stories.tsx +86 -0
- package/src/ui/foundations/CodeBlock.tsx +148 -0
- package/src/ui/foundations/Colors.stories.tsx +80 -0
- package/src/ui/{Icon.stories.tsx → foundations/Icon.stories.tsx} +1 -1
- package/src/ui/{Icon.tsx → foundations/Icon.tsx} +1 -1
- package/src/ui/{IconRegistry.tsx → foundations/IconRegistry.tsx} +261 -57
- package/src/ui/foundations/SocialLinks.stories.tsx +38 -0
- package/src/ui/foundations/SocialLinks.tsx +117 -0
- package/src/ui/foundations/Typography.stories.tsx +58 -0
- package/src/ui/foundations/Typography.tsx +163 -0
- package/src/ui/foundations/index.ts +6 -0
- package/src/ui/index.ts +7 -27
- package/src/ui/layout/Accordion.stories.tsx +86 -0
- package/src/ui/layout/Accordion.tsx +205 -0
- package/src/ui/layout/Card.stories.tsx +151 -0
- package/src/ui/layout/Card.tsx +124 -0
- package/src/ui/layout/Collapsible.stories.tsx +54 -0
- package/src/ui/layout/Collapsible.tsx +54 -0
- package/src/ui/{Separator.stories.tsx → layout/Separator.stories.tsx} +2 -2
- package/src/ui/{Separator.tsx → layout/Separator.tsx} +1 -1
- package/src/ui/{SettingsPanel.stories.tsx → layout/SettingsPanel.stories.tsx} +5 -5
- package/src/ui/{SettingsPanel.tsx → layout/SettingsPanel.tsx} +33 -29
- package/src/ui/layout/index.ts +5 -0
- package/src/ui/media/Avatar.stories.tsx +89 -0
- package/src/ui/media/Avatar.tsx +122 -0
- package/src/ui/media/Dropzone.stories.tsx +95 -0
- package/src/ui/media/Dropzone.tsx +328 -0
- package/src/ui/media/FileUpload.stories.tsx +62 -0
- package/src/ui/media/FileUpload.tsx +175 -0
- package/src/ui/media/index.ts +3 -0
- package/src/ui/{AuthFormUI.stories.tsx → patterns/AuthFormUI.stories.tsx} +1 -1
- package/src/ui/{AuthFormUI.tsx → patterns/AuthFormUI.tsx} +24 -23
- package/src/ui/patterns/CopyButton.stories.tsx +77 -0
- package/src/ui/patterns/CopyButton.tsx +93 -0
- package/src/ui/patterns/SearchInput.stories.tsx +51 -0
- package/src/ui/patterns/SearchInput.tsx +93 -0
- package/src/ui/patterns/Stepper.stories.tsx +129 -0
- package/src/ui/patterns/Stepper.tsx +295 -0
- package/src/ui/{TabSelection.stories.tsx → patterns/TabSelection.stories.tsx} +1 -1
- package/src/ui/{TabSelection.tsx → patterns/TabSelection.tsx} +2 -2
- package/src/ui/patterns/index.ts +6 -0
- package/src/ui/patterns/useClipboard.ts +75 -0
- package/src/ui/types.ts +48 -0
- package/src/ui/Alert.stories.tsx +0 -41
- package/src/ui/Alert.tsx +0 -72
- package/src/ui/Anchor.stories.tsx +0 -25
- package/src/ui/Anchor.tsx +0 -32
- package/src/ui/Button.stories.tsx +0 -108
- package/src/ui/Button.tsx +0 -121
- package/src/ui/Collapsible.stories.tsx +0 -91
- package/src/ui/Collapsible.tsx +0 -52
- package/src/ui/Colors.stories.tsx +0 -67
- package/src/ui/Popover.tsx +0 -42
- package/src/ui/Skeleton.stories.tsx +0 -43
- package/src/ui/SliderWithNumberField.stories.tsx +0 -101
- package/src/ui/Typography.stories.tsx +0 -87
- package/src/ui/Typography.tsx +0 -80
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
-
import { Anchor } from "./Anchor";
|
|
3
|
-
|
|
4
|
-
const meta = {
|
|
5
|
-
title: "UI/Anchor",
|
|
6
|
-
component: Anchor,
|
|
7
|
-
parameters: {
|
|
8
|
-
layout: "centered",
|
|
9
|
-
},
|
|
10
|
-
tags: ["autodocs"],
|
|
11
|
-
argTypes: {
|
|
12
|
-
href: { control: "text" },
|
|
13
|
-
children: { control: "text" },
|
|
14
|
-
},
|
|
15
|
-
} satisfies Meta<typeof Anchor>;
|
|
16
|
-
|
|
17
|
-
export default meta;
|
|
18
|
-
type Story = StoryObj<typeof meta>;
|
|
19
|
-
|
|
20
|
-
export const Default: Story = {
|
|
21
|
-
args: {
|
|
22
|
-
href: "https://peerbots.org",
|
|
23
|
-
children: "Visit Peerbots",
|
|
24
|
-
},
|
|
25
|
-
};
|
package/src/ui/Anchor.tsx
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import { Link } from "react-router-dom";
|
|
3
|
-
import { cn } from "./utils";
|
|
4
|
-
|
|
5
|
-
export type AnchorProps = React.AnchorHTMLAttributes<HTMLAnchorElement>;
|
|
6
|
-
|
|
7
|
-
const Anchor = React.forwardRef<HTMLAnchorElement, AnchorProps>(
|
|
8
|
-
({ className, href, target, ...props }, ref) => {
|
|
9
|
-
const isInternal = href && !href.startsWith("http") && !target;
|
|
10
|
-
const commonClass = cn(
|
|
11
|
-
"pb:font-medium pb:text-teal-700 pb:underline pb:underline-offset-4 pb:hover:text-teal-900 pb:cursor-pointer",
|
|
12
|
-
className,
|
|
13
|
-
);
|
|
14
|
-
|
|
15
|
-
if (isInternal) {
|
|
16
|
-
return <Link to={href} ref={ref} className={commonClass} {...props} />;
|
|
17
|
-
} else {
|
|
18
|
-
return (
|
|
19
|
-
<a
|
|
20
|
-
href={href}
|
|
21
|
-
target={target}
|
|
22
|
-
ref={ref}
|
|
23
|
-
className={commonClass}
|
|
24
|
-
{...props}
|
|
25
|
-
/>
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
);
|
|
30
|
-
Anchor.displayName = "Anchor";
|
|
31
|
-
|
|
32
|
-
export { Anchor };
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
-
import { Button } from "./Button";
|
|
3
|
-
import { Icon } from "./Icon";
|
|
4
|
-
import { Heading } from "./Typography";
|
|
5
|
-
|
|
6
|
-
const meta: Meta<typeof Button> = {
|
|
7
|
-
title: "UI/Button",
|
|
8
|
-
component: Button,
|
|
9
|
-
parameters: {
|
|
10
|
-
layout: "centered",
|
|
11
|
-
},
|
|
12
|
-
tags: ["autodocs"],
|
|
13
|
-
argTypes: {
|
|
14
|
-
variant: {
|
|
15
|
-
control: "select",
|
|
16
|
-
options: ["primary", "secondary", "danger", "ghost", "ghostly-danger"],
|
|
17
|
-
},
|
|
18
|
-
size: {
|
|
19
|
-
control: "select",
|
|
20
|
-
options: ["sm", "md", "lg"],
|
|
21
|
-
},
|
|
22
|
-
disabled: { control: "boolean" },
|
|
23
|
-
isLoading: { control: "boolean" },
|
|
24
|
-
onClick: { action: "clicked" },
|
|
25
|
-
},
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export default meta;
|
|
29
|
-
type Story = StoryObj<typeof Button>;
|
|
30
|
-
|
|
31
|
-
export const Default: Story = {
|
|
32
|
-
args: {
|
|
33
|
-
children: "Button",
|
|
34
|
-
variant: "primary",
|
|
35
|
-
},
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
export const Variations: Story = {
|
|
39
|
-
render: () => (
|
|
40
|
-
<div className="pb:flex pb:flex-col pb:gap-8">
|
|
41
|
-
<div className="pb:space-y-4">
|
|
42
|
-
<Heading level={4} className="pb:text-sm pb:font-medium pb:text-black pb:italic">
|
|
43
|
-
Variants
|
|
44
|
-
</Heading>
|
|
45
|
-
<div className="pb:flex pb:flex-wrap pb:gap-4 pb:items-center">
|
|
46
|
-
<Button variant="primary">Primary</Button>
|
|
47
|
-
<Button variant="secondary">Secondary</Button>
|
|
48
|
-
<Button variant="danger">Danger</Button>
|
|
49
|
-
<Button variant="ghost">Ghost</Button>
|
|
50
|
-
<Button variant="ghostly-danger">Ghostly Danger</Button>
|
|
51
|
-
</div>
|
|
52
|
-
</div>
|
|
53
|
-
|
|
54
|
-
<div className="pb:space-y-4">
|
|
55
|
-
<Heading level={4} className="pb:text-sm pb:font-medium pb:text-black pb:italic">
|
|
56
|
-
Sizes
|
|
57
|
-
</Heading>
|
|
58
|
-
<div className="pb:flex pb:flex-wrap pb:gap-4 pb:items-end">
|
|
59
|
-
<Button size="sm">Small</Button>
|
|
60
|
-
<Button size="md">Medium</Button>
|
|
61
|
-
<Button size="lg">Large</Button>
|
|
62
|
-
</div>
|
|
63
|
-
</div>
|
|
64
|
-
|
|
65
|
-
<div className="pb:space-y-4">
|
|
66
|
-
<Heading level={4} className="pb:text-sm pb:font-medium pb:text-black pb:italic">
|
|
67
|
-
States
|
|
68
|
-
</Heading>
|
|
69
|
-
<div className="pb:flex pb:flex-wrap pb:gap-4 pb:items-center">
|
|
70
|
-
<Button isLoading>Loading</Button>
|
|
71
|
-
<Button disabled>Disabled</Button>
|
|
72
|
-
</div>
|
|
73
|
-
</div>
|
|
74
|
-
|
|
75
|
-
<div className="pb:space-y-4">
|
|
76
|
-
<Heading level={4} className="pb:text-sm pb:font-medium pb:text-black pb:italic">
|
|
77
|
-
With Icons
|
|
78
|
-
</Heading>
|
|
79
|
-
<div className="pb:flex pb:flex-wrap pb:gap-4 pb:items-center">
|
|
80
|
-
<Button leftIcon={<Icon name="cloudArrowUp" />}>Upload</Button>
|
|
81
|
-
<Button variant="secondary" rightIcon={<Icon name="chevronRight" />}>
|
|
82
|
-
Next
|
|
83
|
-
</Button>
|
|
84
|
-
</div>
|
|
85
|
-
</div>
|
|
86
|
-
|
|
87
|
-
<div className="pb:space-y-4">
|
|
88
|
-
<Heading level={4} className="pb:text-sm pb:font-medium pb:text-black pb:italic">
|
|
89
|
-
Icon Only
|
|
90
|
-
</Heading>
|
|
91
|
-
<div className="pb:flex pb:flex-wrap pb:gap-4 pb:items-center">
|
|
92
|
-
<Button size="sm">
|
|
93
|
-
<Icon name="plus" />
|
|
94
|
-
</Button>
|
|
95
|
-
<Button size="md">
|
|
96
|
-
<Icon name="plus" />
|
|
97
|
-
</Button>
|
|
98
|
-
<Button size="lg">
|
|
99
|
-
<Icon name="plus" />
|
|
100
|
-
</Button>
|
|
101
|
-
<Button variant="ghost" size="sm" aria-label="Close">
|
|
102
|
-
<Icon name="close" />
|
|
103
|
-
</Button>
|
|
104
|
-
</div>
|
|
105
|
-
</div>
|
|
106
|
-
</div>
|
|
107
|
-
),
|
|
108
|
-
};
|
package/src/ui/Button.tsx
DELETED
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import { Button as BaseButton } from "@base-ui/react";
|
|
2
|
-
import React from "react";
|
|
3
|
-
import { cn } from "./utils";
|
|
4
|
-
|
|
5
|
-
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
6
|
-
variant?: "primary" | "secondary" | "danger" | "ghost" | "ghostly-danger";
|
|
7
|
-
size?: "sm" | "md" | "lg";
|
|
8
|
-
isLoading?: boolean;
|
|
9
|
-
leftIcon?: React.ReactNode;
|
|
10
|
-
rightIcon?: React.ReactNode;
|
|
11
|
-
render?: BaseButton.Props["render"];
|
|
12
|
-
nativeButton?: boolean;
|
|
13
|
-
isIconOnly?: boolean;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|
17
|
-
(
|
|
18
|
-
{
|
|
19
|
-
className,
|
|
20
|
-
variant = "primary",
|
|
21
|
-
size = "md",
|
|
22
|
-
isLoading = false,
|
|
23
|
-
leftIcon,
|
|
24
|
-
rightIcon,
|
|
25
|
-
children,
|
|
26
|
-
disabled,
|
|
27
|
-
render,
|
|
28
|
-
nativeButton,
|
|
29
|
-
isIconOnly,
|
|
30
|
-
...props
|
|
31
|
-
},
|
|
32
|
-
ref,
|
|
33
|
-
) => {
|
|
34
|
-
const isActuallyIconOnly =
|
|
35
|
-
isIconOnly || (!children && (!!leftIcon || !!rightIcon));
|
|
36
|
-
|
|
37
|
-
const variants = {
|
|
38
|
-
primary:
|
|
39
|
-
"pb:bg-primary pb:hover:bg-dark-primary pb:text-gray-900 pb:shadow-sm pb:border pb:border-transparent pb:font-bold pb:disabled:bg-gray-400 pb:disabled:hover:bg-gray-300",
|
|
40
|
-
secondary:
|
|
41
|
-
"pb:bg-gray-100 pb:hover:bg-gray-200 pb:text-gray-800 pb:border pb:border-gray-200 pb:border pb:font-normal pb:disabled:bg-gray-400 pb:disabled:hover:bg-gray-300",
|
|
42
|
-
danger:
|
|
43
|
-
"pb:bg-danger pb:hover:opacity-80 pb:text-gray-900 pb:shadow-sm pb:border pb:border-transparent pb:font-bold pb:disabled:bg-gray-400 pb:disabled:hover:bg-gray-300",
|
|
44
|
-
ghost:
|
|
45
|
-
"pb:bg-transparent pb:hover:bg-gray-100 pb:text-gray-700 pb:hover:text-gray-900 pb:font-medium",
|
|
46
|
-
"ghostly-danger":
|
|
47
|
-
"pb:bg-transparent pb:hover:bg-danger/10 pb:text-red-700 pb:border pb:border-red-700 pb:font-medium pb:disabled:border-gray-400 pb:disabled:text-gray-400",
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const sizes = {
|
|
51
|
-
sm: isActuallyIconOnly ? "pb:p-1 pb:text-xs" : "pb:px-2 pb:py-1 pb:text-xs",
|
|
52
|
-
md: isActuallyIconOnly ? "pb:p-2 pb:text-sm" : "pb:px-4 pb:py-2 pb:text-sm",
|
|
53
|
-
lg: isActuallyIconOnly ? "pb:p-3 pb:text-base" : "pb:px-6 pb:py-3 pb:text-base",
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
return (
|
|
57
|
-
<BaseButton
|
|
58
|
-
ref={ref}
|
|
59
|
-
render={render}
|
|
60
|
-
nativeButton={nativeButton}
|
|
61
|
-
className={cn(
|
|
62
|
-
"pb:inline-flex pb:items-center pb:justify-center pb:rounded-md pb:transition-colors pb:focus:outline-none pb:focus:ring-2 pb:focus:ring-primary pb:focus:ring-offset-2 pb:disabled:cursor-not-allowed pb:cursor-pointer",
|
|
63
|
-
variants[variant],
|
|
64
|
-
sizes[size],
|
|
65
|
-
className,
|
|
66
|
-
)}
|
|
67
|
-
disabled={disabled || isLoading}
|
|
68
|
-
{...props}
|
|
69
|
-
>
|
|
70
|
-
{isLoading && (
|
|
71
|
-
<svg
|
|
72
|
-
className={cn(
|
|
73
|
-
"pb:animate-spin pb:h-4 pb:w-4",
|
|
74
|
-
!isActuallyIconOnly && "pb:mr-2 pb:-ml-1",
|
|
75
|
-
)}
|
|
76
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
77
|
-
fill="none"
|
|
78
|
-
viewBox="0 0 24 24"
|
|
79
|
-
>
|
|
80
|
-
<circle
|
|
81
|
-
className="pb:opacity-25"
|
|
82
|
-
cx="12"
|
|
83
|
-
cy="12"
|
|
84
|
-
r="10"
|
|
85
|
-
stroke="currentColor"
|
|
86
|
-
strokeWidth="4"
|
|
87
|
-
></circle>
|
|
88
|
-
<path
|
|
89
|
-
className="pb:opacity-75"
|
|
90
|
-
fill="currentColor"
|
|
91
|
-
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
92
|
-
></path>
|
|
93
|
-
</svg>
|
|
94
|
-
)}
|
|
95
|
-
{!isLoading && leftIcon && (
|
|
96
|
-
<span
|
|
97
|
-
className={cn(
|
|
98
|
-
"pb:inline-flex pb:items-center pb:justify-center",
|
|
99
|
-
!isActuallyIconOnly && "pb:mr-2 pb:-ml-1",
|
|
100
|
-
)}
|
|
101
|
-
>
|
|
102
|
-
{leftIcon}
|
|
103
|
-
</span>
|
|
104
|
-
)}
|
|
105
|
-
{children}
|
|
106
|
-
{!isLoading && rightIcon && (
|
|
107
|
-
<span
|
|
108
|
-
className={cn(
|
|
109
|
-
"pb:inline-flex pb:items-center pb:justify-center",
|
|
110
|
-
!isActuallyIconOnly && "pb:ml-2 pb:-mr-1",
|
|
111
|
-
)}
|
|
112
|
-
>
|
|
113
|
-
{rightIcon}
|
|
114
|
-
</span>
|
|
115
|
-
)}
|
|
116
|
-
</BaseButton>
|
|
117
|
-
);
|
|
118
|
-
},
|
|
119
|
-
);
|
|
120
|
-
|
|
121
|
-
Button.displayName = "Button";
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
-
import { Collapsible } from "./Collapsible";
|
|
3
|
-
import { Heading } from "./Typography";
|
|
4
|
-
import React from "react";
|
|
5
|
-
|
|
6
|
-
const meta: Meta<typeof Collapsible> = {
|
|
7
|
-
title: "UI/Collapsible",
|
|
8
|
-
component: Collapsible,
|
|
9
|
-
tags: ["autodocs"],
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export default meta;
|
|
13
|
-
type Story = StoryObj<typeof Collapsible>;
|
|
14
|
-
|
|
15
|
-
export const Default: Story = {
|
|
16
|
-
args: {
|
|
17
|
-
title: "Click to expand",
|
|
18
|
-
children: (
|
|
19
|
-
<div className="pb:p-4 pb:bg-gray-50 pb:rounded-md">
|
|
20
|
-
This is the collapsible content. It can contain any elements.
|
|
21
|
-
</div>
|
|
22
|
-
),
|
|
23
|
-
},
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export const Variations: Story = {
|
|
27
|
-
render: () => (
|
|
28
|
-
<div className="pb:flex pb:flex-col pb:gap-8 pb:p-4">
|
|
29
|
-
<div className="pb:space-y-4">
|
|
30
|
-
<Heading level={4} className="pb:text-sm pb:font-medium pb:text-black pb:uppercase">
|
|
31
|
-
States & Styling
|
|
32
|
-
</Heading>
|
|
33
|
-
<div className="pb:space-y-4">
|
|
34
|
-
<Collapsible title="Initially Open" defaultOpen={true}>
|
|
35
|
-
<div className="pb:p-4 pb:bg-gray-50 pb:rounded-md">
|
|
36
|
-
This content is visible by default.
|
|
37
|
-
</div>
|
|
38
|
-
</Collapsible>
|
|
39
|
-
<Collapsible
|
|
40
|
-
title={<span className="pb:font-bold pb:text-primary">Styled Title</span>}
|
|
41
|
-
className="pb:border pb:border-gray-200 pb:rounded-lg pb:overflow-hidden"
|
|
42
|
-
>
|
|
43
|
-
<div className="pb:p-4">Custom styled wrapper and title.</div>
|
|
44
|
-
</Collapsible>
|
|
45
|
-
</div>
|
|
46
|
-
</div>
|
|
47
|
-
|
|
48
|
-
<div className="pb:space-y-4">
|
|
49
|
-
<Heading level={4} className="pb:text-sm pb:font-medium pb:text-black pb:uppercase">
|
|
50
|
-
Variants
|
|
51
|
-
</Heading>
|
|
52
|
-
<div className="pb:space-y-4">
|
|
53
|
-
<Collapsible title="Secondary (Default)" variant="secondary">
|
|
54
|
-
<div className="pb:p-4 pb:bg-gray-50 pb:rounded-md">
|
|
55
|
-
Secondary variant content.
|
|
56
|
-
</div>
|
|
57
|
-
</Collapsible>
|
|
58
|
-
<Collapsible title="Ghost" variant="ghost">
|
|
59
|
-
<div className="pb:p-4 pb:bg-gray-50 pb:rounded-md">
|
|
60
|
-
Ghost variant content.
|
|
61
|
-
</div>
|
|
62
|
-
</Collapsible>
|
|
63
|
-
<Collapsible title="Primary" variant="primary">
|
|
64
|
-
<div className="pb:p-4 pb:bg-gray-50 pb:rounded-md">
|
|
65
|
-
Primary variant content.
|
|
66
|
-
</div>
|
|
67
|
-
</Collapsible>
|
|
68
|
-
</div>
|
|
69
|
-
</div>
|
|
70
|
-
|
|
71
|
-
<div className="pb:space-y-4">
|
|
72
|
-
<Heading level={4} className="pb:text-sm pb:font-medium pb:text-black pb:uppercase">
|
|
73
|
-
Sizes
|
|
74
|
-
</Heading>
|
|
75
|
-
<div className="pb:space-y-4">
|
|
76
|
-
<Collapsible title="Small" size="sm">
|
|
77
|
-
<div className="pb:p-4 pb:bg-gray-50 pb:rounded-md">Small size content.</div>
|
|
78
|
-
</Collapsible>
|
|
79
|
-
<Collapsible title="Medium (Default)" size="md">
|
|
80
|
-
<div className="pb:p-4 pb:bg-gray-50 pb:rounded-md">
|
|
81
|
-
Medium size content.
|
|
82
|
-
</div>
|
|
83
|
-
</Collapsible>
|
|
84
|
-
<Collapsible title="Large" size="lg">
|
|
85
|
-
<div className="pb:p-4 pb:bg-gray-50 pb:rounded-md">Large size content.</div>
|
|
86
|
-
</Collapsible>
|
|
87
|
-
</div>
|
|
88
|
-
</div>
|
|
89
|
-
</div>
|
|
90
|
-
),
|
|
91
|
-
};
|
package/src/ui/Collapsible.tsx
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import React, { useState } from "react";
|
|
2
|
-
import { cn } from "./utils";
|
|
3
|
-
import { Button, ButtonProps } from "./Button";
|
|
4
|
-
import { Icon } from "./Icon";
|
|
5
|
-
|
|
6
|
-
export interface CollapsibleProps {
|
|
7
|
-
title: React.ReactNode;
|
|
8
|
-
children: React.ReactNode;
|
|
9
|
-
/** The variant of the trigger button */
|
|
10
|
-
variant?: ButtonProps["variant"];
|
|
11
|
-
/** The size of the trigger button */
|
|
12
|
-
size?: ButtonProps["size"];
|
|
13
|
-
defaultOpen?: boolean;
|
|
14
|
-
className?: string;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function Collapsible({
|
|
18
|
-
title,
|
|
19
|
-
children,
|
|
20
|
-
variant = "secondary",
|
|
21
|
-
size = "md",
|
|
22
|
-
defaultOpen = false,
|
|
23
|
-
className,
|
|
24
|
-
}: CollapsibleProps) {
|
|
25
|
-
const [isOpen, setIsOpen] = useState(defaultOpen);
|
|
26
|
-
|
|
27
|
-
return (
|
|
28
|
-
<div className={cn("w-full", className)}>
|
|
29
|
-
<Button
|
|
30
|
-
variant={variant}
|
|
31
|
-
size={size}
|
|
32
|
-
className="pb:w-full pb:justify-between pb:font-medium"
|
|
33
|
-
onClick={() => setIsOpen(!isOpen)}
|
|
34
|
-
aria-expanded={isOpen}
|
|
35
|
-
rightIcon={
|
|
36
|
-
<Icon className="pb:h-5 pb:w-5 pb:text-gray-600" strokeWidth="2.5">
|
|
37
|
-
{isOpen ? (
|
|
38
|
-
<path d="M4.5 15.75l7.5-7.5 7.5 7.5" />
|
|
39
|
-
) : (
|
|
40
|
-
<path d="M19.5 8.25l-7.5 7.5-7.5-7.5" />
|
|
41
|
-
)}
|
|
42
|
-
</Icon>
|
|
43
|
-
}
|
|
44
|
-
>
|
|
45
|
-
<span>{title}</span>
|
|
46
|
-
</Button>
|
|
47
|
-
{isOpen && (
|
|
48
|
-
<div className="pb:px-4 pb:pt-4 pb:pb-2 pb:text-sm pb:text-gray-500">{children}</div>
|
|
49
|
-
)}
|
|
50
|
-
</div>
|
|
51
|
-
);
|
|
52
|
-
}
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
-
|
|
3
|
-
const meta: Meta = {
|
|
4
|
-
title: "UI/Colors",
|
|
5
|
-
tags: ["autodocs"],
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
export default meta;
|
|
9
|
-
|
|
10
|
-
export const Variations: StoryObj = {
|
|
11
|
-
render: () => (
|
|
12
|
-
<div className="pb:flex pb:flex-col pb:gap-8 pb:p-4 pb:bg-white">
|
|
13
|
-
<div>
|
|
14
|
-
<h3 className="pb:text-sm pb:font-medium pb:text-black pb:uppercase pb:tracking-wider pb:border-b pb:pb-1 pb:mb-4">
|
|
15
|
-
Theme Colors
|
|
16
|
-
</h3>
|
|
17
|
-
<div className="pb:grid pb:grid-cols-2 pb:md:grid-cols-3 pb:lg:grid-cols-5 pb:gap-4">
|
|
18
|
-
<ColorItem name="Primary" variable="var(--pb-color-primary)" />
|
|
19
|
-
<ColorItem name="Secondary" variable="var(--pb-color-secondary)" />
|
|
20
|
-
<ColorItem name="Accent" variable="var(--pb-color-accent)" />
|
|
21
|
-
<ColorItem name="Danger" variable="var(--pb-color-danger)" />
|
|
22
|
-
<ColorItem name="Light BG" variable="var(--pb-color-light-bg)" />
|
|
23
|
-
</div>
|
|
24
|
-
</div>
|
|
25
|
-
|
|
26
|
-
<div>
|
|
27
|
-
<h3 className="pb:text-sm pb:font-medium pb:text-black pb:uppercase pb:tracking-wider pb:border-b pb:pb-1 pb:mb-4">
|
|
28
|
-
Extended Accent Colors
|
|
29
|
-
</h3>
|
|
30
|
-
<div className="pb:grid pb:grid-cols-2 pb:md:grid-cols-3 pb:lg:grid-cols-4 pb:gap-4">
|
|
31
|
-
<ColorItem name="Accent HC" variable="var(--pb-color-accent-hc)" />
|
|
32
|
-
<ColorItem name="Accent Two" variable="var(--pb-color-accent-two)" />
|
|
33
|
-
<ColorItem
|
|
34
|
-
name="Accent Two HC"
|
|
35
|
-
variable="var(--pb-color-accent-two-hc)"
|
|
36
|
-
/>
|
|
37
|
-
<ColorItem name="Accent Three" variable="var(--pb-color-accent-three)" />
|
|
38
|
-
</div>
|
|
39
|
-
</div>
|
|
40
|
-
|
|
41
|
-
<div>
|
|
42
|
-
<h3 className="pb:text-sm pb:font-medium pb:text-black pb:uppercase pb:tracking-wider pb:border-b pb:pb-1 pb:mb-4">
|
|
43
|
-
UI Elements
|
|
44
|
-
</h3>
|
|
45
|
-
<div className="pb:grid pb:grid-cols-2 pb:md:grid-cols-3 pb:lg:grid-cols-4 pb:gap-4">
|
|
46
|
-
<ColorItem name="Sidebar BG" variable="var(--pb-sidebar-bg)" />
|
|
47
|
-
<ColorItem name="Dark Primary" variable="var(--pb-color-dark-primary)" />
|
|
48
|
-
</div>
|
|
49
|
-
</div>
|
|
50
|
-
</div>
|
|
51
|
-
),
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
function ColorItem({ name, variable }: { name: string; variable: string }) {
|
|
55
|
-
return (
|
|
56
|
-
<div className="pb:flex pb:flex-col pb:gap-2">
|
|
57
|
-
<div
|
|
58
|
-
className="pb:h-20 pb:w-full pb:rounded-md pb:shadow-inner pb:border pb:border-gray-100"
|
|
59
|
-
style={{ backgroundColor: variable }}
|
|
60
|
-
/>
|
|
61
|
-
<div className="pb:flex pb:flex-col">
|
|
62
|
-
<span className="pb:text-sm pb:font-bold pb:text-gray-900">{name}</span>
|
|
63
|
-
<code className="pb:text-xs pb:text-gray-500">{variable}</code>
|
|
64
|
-
</div>
|
|
65
|
-
</div>
|
|
66
|
-
);
|
|
67
|
-
}
|
package/src/ui/Popover.tsx
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { Popover as BasePopover } from "@base-ui/react";
|
|
3
|
-
import { cn } from "./utils";
|
|
4
|
-
|
|
5
|
-
export interface PopoverProps {
|
|
6
|
-
trigger: React.ReactNode;
|
|
7
|
-
children: React.ReactNode;
|
|
8
|
-
side?: "top" | "right" | "bottom" | "left";
|
|
9
|
-
align?: "start" | "center" | "end";
|
|
10
|
-
className?: string;
|
|
11
|
-
open?: boolean;
|
|
12
|
-
onOpenChange?: (open: boolean) => void;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function Popover({
|
|
16
|
-
trigger,
|
|
17
|
-
children,
|
|
18
|
-
side = "bottom",
|
|
19
|
-
align = "center",
|
|
20
|
-
className,
|
|
21
|
-
open,
|
|
22
|
-
onOpenChange,
|
|
23
|
-
}: PopoverProps) {
|
|
24
|
-
return (
|
|
25
|
-
<BasePopover.Root open={open} onOpenChange={onOpenChange}>
|
|
26
|
-
<BasePopover.Trigger>{trigger}</BasePopover.Trigger>
|
|
27
|
-
<BasePopover.Portal>
|
|
28
|
-
<BasePopover.Positioner side={side} align={align} sideOffset={5}>
|
|
29
|
-
<BasePopover.Popup
|
|
30
|
-
className={cn(
|
|
31
|
-
"pb:z-50 pb:w-72 pb:rounded-md pb:border pb:bg-white pb:p-4 pb:shadow-md pb:outline-none pb:data-[state=open]:animate-in pb:data-[state=closed]:animate-out pb:data-[state=closed]:fade-out-0 pb:data-[state=open]:fade-in-0 pb:data-[state=closed]:zoom-out-95 pb:data-[state=open]:zoom-in-95",
|
|
32
|
-
className,
|
|
33
|
-
)}
|
|
34
|
-
>
|
|
35
|
-
{children}
|
|
36
|
-
<BasePopover.Arrow className="pb:fill-white pb:stroke-gray-200" />
|
|
37
|
-
</BasePopover.Popup>
|
|
38
|
-
</BasePopover.Positioner>
|
|
39
|
-
</BasePopover.Portal>
|
|
40
|
-
</BasePopover.Root>
|
|
41
|
-
);
|
|
42
|
-
}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { Meta, StoryObj } from "@storybook/react";
|
|
2
|
-
import { Skeleton } from "./Skeleton";
|
|
3
|
-
|
|
4
|
-
const meta: Meta<typeof Skeleton> = {
|
|
5
|
-
title: "UI/Skeleton",
|
|
6
|
-
component: Skeleton,
|
|
7
|
-
tags: ["autodocs"],
|
|
8
|
-
parameters: {
|
|
9
|
-
layout: "centered",
|
|
10
|
-
},
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export default meta;
|
|
14
|
-
type Story = StoryObj<typeof Skeleton>;
|
|
15
|
-
|
|
16
|
-
export const Default: Story = {
|
|
17
|
-
args: {
|
|
18
|
-
className: "w-[250px] h-4",
|
|
19
|
-
},
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export const Variations: Story = {
|
|
23
|
-
render: () => (
|
|
24
|
-
<div className="pb:flex pb:flex-col pb:space-y-3">
|
|
25
|
-
{/* Circle Skeleton */}
|
|
26
|
-
<Skeleton className="pb:h-12 pb:w-12 pb:rounded-full" />
|
|
27
|
-
|
|
28
|
-
{/* Rectangular Skeletons */}
|
|
29
|
-
<div className="pb:space-y-2">
|
|
30
|
-
<Skeleton className="pb:h-4 pb:w-[250px]" />
|
|
31
|
-
<Skeleton className="pb:h-4 pb:w-[200px]" />
|
|
32
|
-
</div>
|
|
33
|
-
|
|
34
|
-
<div className="pb:flex pb:items-center pb:space-x-4 pb:mt-6">
|
|
35
|
-
<Skeleton className="pb:h-12 pb:w-12 pb:rounded-full" />
|
|
36
|
-
<div className="pb:space-y-2">
|
|
37
|
-
<Skeleton className="pb:h-4 pb:w-[250px]" />
|
|
38
|
-
<Skeleton className="pb:h-4 pb:w-[200px]" />
|
|
39
|
-
</div>
|
|
40
|
-
</div>
|
|
41
|
-
</div>
|
|
42
|
-
),
|
|
43
|
-
};
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
-
import SliderWithNumberField from "./SliderWithNumberField";
|
|
3
|
-
import React, { useState } from "react";
|
|
4
|
-
import { Heading, Text } from "./Typography";
|
|
5
|
-
|
|
6
|
-
const meta: Meta<typeof SliderWithNumberField> = {
|
|
7
|
-
title: "UI/SliderWithNumberField",
|
|
8
|
-
component: SliderWithNumberField,
|
|
9
|
-
argTypes: {
|
|
10
|
-
onChange: { action: "changed" },
|
|
11
|
-
min: { control: { type: "number" } },
|
|
12
|
-
max: { control: { type: "number" } },
|
|
13
|
-
step: { control: { type: "number" } },
|
|
14
|
-
disabled: { control: "boolean" },
|
|
15
|
-
},
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export default meta;
|
|
19
|
-
type Story = StoryObj<typeof SliderWithNumberField>;
|
|
20
|
-
|
|
21
|
-
const InteractiveSliderWithNumberField = (
|
|
22
|
-
props: React.ComponentProps<typeof SliderWithNumberField>,
|
|
23
|
-
) => {
|
|
24
|
-
const [value, setValue] = useState(props.value || props.defaultValue || 0);
|
|
25
|
-
return (
|
|
26
|
-
<SliderWithNumberField
|
|
27
|
-
{...props}
|
|
28
|
-
value={value}
|
|
29
|
-
onChange={(v) => {
|
|
30
|
-
setValue(v);
|
|
31
|
-
props.onChange?.(v as number, new Event("change")); // Match signature
|
|
32
|
-
}}
|
|
33
|
-
/>
|
|
34
|
-
);
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export const Default: Story = {
|
|
38
|
-
args: {
|
|
39
|
-
min: 0,
|
|
40
|
-
max: 100,
|
|
41
|
-
defaultValue: 50,
|
|
42
|
-
},
|
|
43
|
-
render: (args) => (
|
|
44
|
-
<div className="pb:w-80 pb:p-4">
|
|
45
|
-
<InteractiveSliderWithNumberField
|
|
46
|
-
{...(args as React.ComponentProps<typeof SliderWithNumberField>)}
|
|
47
|
-
/>
|
|
48
|
-
</div>
|
|
49
|
-
),
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
export const Variations: Story = {
|
|
53
|
-
render: () => (
|
|
54
|
-
<div className="pb:flex pb:flex-col pb:gap-12 pb:p-4">
|
|
55
|
-
<div className="pb:space-y-4">
|
|
56
|
-
<Heading level={4} className="pb:text-sm pb:font-medium pb:text-black pb:uppercase">
|
|
57
|
-
Responsive Layouts
|
|
58
|
-
</Heading>
|
|
59
|
-
<div className="pb:space-y-8 pb:max-w-lg">
|
|
60
|
-
<div className="pb:space-y-2">
|
|
61
|
-
<Text variant="small" className="pb:font-bold pb:underline">
|
|
62
|
-
Flexible (Full width of container)
|
|
63
|
-
</Text>
|
|
64
|
-
<InteractiveSliderWithNumberField defaultValue={50} />
|
|
65
|
-
</div>
|
|
66
|
-
|
|
67
|
-
<div className="pb:space-y-2 pb:w-64 pb:border-l pb:border-r pb:border-dotted pb:px-2 pb:bg-gray-50 pb:py-4">
|
|
68
|
-
<Text variant="small" className="pb:font-bold pb:underline">
|
|
69
|
-
Narrow Container (w-64)
|
|
70
|
-
</Text>
|
|
71
|
-
<InteractiveSliderWithNumberField defaultValue={50} />
|
|
72
|
-
</div>
|
|
73
|
-
|
|
74
|
-
<div className="pb:space-y-2 pb:w-48 pb:border-l pb:border-r pb:border-dotted pb:px-2 pb:bg-gray-50 pb:py-4">
|
|
75
|
-
<Text variant="small" className="pb:font-bold pb:underline">
|
|
76
|
-
Very Narrow (w-48) - Wraps
|
|
77
|
-
</Text>
|
|
78
|
-
<InteractiveSliderWithNumberField defaultValue={50} />
|
|
79
|
-
</div>
|
|
80
|
-
</div>
|
|
81
|
-
</div>
|
|
82
|
-
|
|
83
|
-
<div className="pb:space-y-4">
|
|
84
|
-
<Heading level={4} className="pb:text-sm pb:font-medium pb:text-black pb:uppercase">
|
|
85
|
-
Configuration
|
|
86
|
-
</Heading>
|
|
87
|
-
<div className="pb:space-y-4 pb:max-w-sm">
|
|
88
|
-
<div className="pb:space-y-1">
|
|
89
|
-
<Text variant="small">Custom Step (0.5)</Text>
|
|
90
|
-
<InteractiveSliderWithNumberField
|
|
91
|
-
step={0.5}
|
|
92
|
-
defaultValue={2.5}
|
|
93
|
-
min={0}
|
|
94
|
-
max={10}
|
|
95
|
-
/>
|
|
96
|
-
</div>
|
|
97
|
-
</div>
|
|
98
|
-
</div>
|
|
99
|
-
</div>
|
|
100
|
-
),
|
|
101
|
-
};
|