diff --git a/packages/ui/src/v2/Button/Button.stories.tsx b/packages/ui/src/v2/Button/Button.stories.tsx new file mode 100644 index 000000000..c64b28391 --- /dev/null +++ b/packages/ui/src/v2/Button/Button.stories.tsx @@ -0,0 +1,130 @@ +// Copyright (c) 2026 Probo Inc . +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +import { ArrowRightIcon, BookmarkSimpleIcon } from "@phosphor-icons/react"; +import type { Meta, StoryObj } from "@storybook/react"; + +import { Button } from "./Button"; +import { ButtonSkeleton } from "./ButtonSkeleton"; + +const sizes = [1, 2, 3, 4] as const; +const variants = ["classic", "solid", "soft", "surface", "outline", "ghost"] as const; +const colors = ["neutral", "gold", "red", "green", "amber", "sky"] as const; + +export default { + title: "v2/Button", + component: Button, + args: { + children: "Edit profile", + size: 2, + variant: "solid", + color: "gold", + highContrast: false, + loading: false, + disabled: false, + }, +} satisfies Meta; + +type Story = StoryObj; + +export const Playground: Story = {}; + +export const Sizes: Story = { + render: () => ( +
+ {sizes.map(size => ( + + ))} +
+ ), +}; + +export const Variants: Story = { + render: () => ( +
+ {variants.map(variant => ( + + ))} +
+ ), +}; + +export const Colors: Story = { + render: () => ( +
+ {variants.map(variant => ( +
+ {colors.map(color => ( + + ))} +
+ ))} +
+ ), +}; + +export const HighContrast: Story = { + render: () => ( +
+ {colors.map(color => ( + + ))} +
+ ), +}; + +export const WithIcons: Story = { + render: () => ( +
+ + +
+ ), +}; + +export const Loading: Story = { + render: () => ( +
+ + +
+ ), +}; + +export const Disabled: Story = { + render: () => ( +
+ + + +
+ ), +}; + +export const Skeleton: Story = { + render: () => ( +
+ + +
+ ), +}; diff --git a/packages/ui/src/v2/Button/Button.tsx b/packages/ui/src/v2/Button/Button.tsx new file mode 100644 index 000000000..bba2ce54b --- /dev/null +++ b/packages/ui/src/v2/Button/Button.tsx @@ -0,0 +1,58 @@ +// Copyright (c) 2026 Probo Inc . +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +import { SpinnerGapIcon } from "@phosphor-icons/react"; +import type { ComponentProps, ReactNode } from "react"; +import type { VariantProps } from "tailwind-variants/lite"; + +import { button } from "./variants"; + +export type ButtonProps + = Omit, "color"> + & VariantProps + & { + iconStart?: ReactNode; + iconEnd?: ReactNode; + // Shows a spinner in place of the leading icon and disables the button. + loading?: boolean; + }; + +// Clickable action (Radix "Button"). Renders a + ); +} diff --git a/packages/ui/src/v2/Button/ButtonSkeleton.tsx b/packages/ui/src/v2/Button/ButtonSkeleton.tsx new file mode 100644 index 000000000..35446477d --- /dev/null +++ b/packages/ui/src/v2/Button/ButtonSkeleton.tsx @@ -0,0 +1,28 @@ +// Copyright (c) 2026 Probo Inc . +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +import type { ComponentProps } from "react"; +import type { VariantProps } from "tailwind-variants/lite"; + +import { buttonSkeleton } from "./variants"; + +export type ButtonSkeletonProps = Omit, "children"> & VariantProps; + +// Loading placeholder paired with Button: a pulse block matching its size and +// radius. +export function ButtonSkeleton(props: ButtonSkeletonProps) { + const { size, className, ...rest } = props; + + return ; +} diff --git a/packages/ui/src/v2/Button/variants.ts b/packages/ui/src/v2/Button/variants.ts new file mode 100644 index 000000000..4cb77f456 --- /dev/null +++ b/packages/ui/src/v2/Button/variants.ts @@ -0,0 +1,136 @@ +// Copyright (c) 2026 Probo Inc . +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +import { tv } from "tailwind-variants/lite"; + +// Button (Radix "Button"). A