Skip to content

Commit

Permalink
icon button, starButton, testToggle button
Browse files Browse the repository at this point in the history
  • Loading branch information
mewdev committed Nov 4, 2024
1 parent 9de51a0 commit 42a735b
Show file tree
Hide file tree
Showing 13 changed files with 540 additions and 3 deletions.
28 changes: 28 additions & 0 deletions apps/design-system/stories/iconButton.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { IconButton } from "@repo/design-system/iconButton";
import { StarIcon } from "@repo/design-system/starIcon";
import { Meta, StoryObj } from "@storybook/react";

export default {
title: "Components/IconButton",
component: IconButton,
argTypes: {
size: {
control: { type: "select", options: ["small", "default", "large"] },
},
iconSize: {
control: { type: "select", options: ["small", "default", "large"] },
},
},
tags: ["autodocs"],
} as Meta;

type Story = StoryObj<typeof IconButton>;

export const Default: Story = {
args: {
size: "default",
iconSize: "default",
icon: StarIcon,
children: "Icon button",
},
};
16 changes: 16 additions & 0 deletions apps/design-system/stories/starIconButton.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { StarIconButton } from "@repo/design-system/starIconButton";
import { Meta, StoryObj } from "@storybook/react";

export default {
title: "Components/StarIconButton",
component: StarIconButton,
tags: ["autodocs"],
} as Meta;

type Story = StoryObj<typeof StarIconButton>;

export const Default: Story = {
args: {
pressed: true

Check warning on line 14 in apps/design-system/stories/starIconButton.stories.tsx

View workflow job for this annotation

GitHub Actions / Build & lint

Insert `,`
}

Check warning on line 15 in apps/design-system/stories/starIconButton.stories.tsx

View workflow job for this annotation

GitHub Actions / Build & lint

Insert `,`
};
66 changes: 66 additions & 0 deletions apps/design-system/stories/toggleButton.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { Meta, StoryObj } from "@storybook/react";
import { ToggleButton } from "@repo/design-system/toggleButton";
import { YesIcon } from "@repo/design-system/yesIcon";
import { Button } from "@repo/design-system/button";

export default {
title: "Components/ToggleButton",
component: ToggleButton,
argTypes: {},
tags: ["autodocs"],
} as Meta;

type Story = StoryObj<typeof ToggleButton>;

export const AnswerInFavour: Story = {
render: () => (
<ToggleButton>
<Button
answerType="In favour"
hasIcon
icon={YesIcon}
iconPosition="left"
color="primary"
kind="inverse"
size="default"
wider
fitContent
compactable
>
Jsem pro
</Button>
</ToggleButton>
),
};

export const AnswerAgainst: Story = {
args: {
answerType: "Against",
children: "Jsem proti",
hasIcon: true,
icon: YesIcon,
iconPosition: "left",
color: "secondary",
kind: "inverse",
size: "default",
wider: true,
fitContent: true,
compactable: true,
},
};

export const AnswerNeutral: Story = {
args: {
answerType: "Neutral",
children: "Přeskočit",
hasIcon: true,
icon: YesIcon,
iconPosition: "left",
color: "neutral",
kind: "inverse",
size: "default",
wider: true,
fitContent: true,
compactable: true,
},
};
19 changes: 19 additions & 0 deletions apps/design-system/stories/toggleIconButton.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Meta, StoryObj } from "@storybook/react";
import { ToggleIconButton } from "@repo/design-system/toggleIconButton";

export default {
title: "Components/ToggleIconButton",
component: ToggleIconButton,
argTypes: {},
tags: ["autodocs"],
} as Meta;

type Story = StoryObj<typeof ToggleIconButton>;

export const Default: Story = {
args: {
iconDefault: () => <svg />,
iconPressed: () => <svg />,
children: "Click me",
},
};
12 changes: 9 additions & 3 deletions packages/design-system/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,17 @@
"./tailwind": "./tailwind.config.ts",
"./demo": "./src/index.ts",
"./progressBar": "./src/progressBar.tsx",
"./arrowIcon": "./src/arrowIcon.tsx",
"./iconButton": "./src/iconButton.tsx",
"./starIconButton": "./src/starIconButton.tsx",
"./starIcon": "./src/starIcon.tsx",
"./starIconFilled": "./src/starIconFilled.tsx",
"./toggleIconButton": "./src/toggleIconButton.tsx",
"./toggleButton": "./src/toggleButton.tsx",
"./yesIcon": "./src/yesIcon.tsx",
"./noIcon": "./src/noIcon.tsx",
"./neutralIcon": "./src/neutralIcon.tsx"
"./button": "./src/button.tsx",
"./buttonInFavour": "./src/buttonInFavour.tsx",
"./buttonAgainst": "./src/buttonAgainst.tsx",
"./buttonNeutral": "./src/buttonNeutral.tsx"
},
"scripts": {
"build": "npm run fonts && npm run tailwind",
Expand Down
160 changes: 160 additions & 0 deletions packages/design-system/src/button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import React from "react";
import { Button as HeadlessUIButton } from "@headlessui/react";
import { cva, VariantProps } from "class-variance-authority";

const buttonVariants = cva(
[
"k1-inline-flex k1-items-center k1-min-w-fit",
"data-[hover]:k1-cursor-pointer k1-text-nowrap data-[disabled]:k1-pointer-events-none",
"k1-uppercase k1-font-bold",
"k1-rounded-l-[16px] k1-rounded-br-[16px]",
"k1-select-none",
"k1-gap-2",
],
{
variants: {
kind: {
filled:
"k1-p-4 data-[active]:k1-bg-primary-strong-active data-[disabled]:k1-bg-neutral-disaled",
inverse: "k1-border-2 k1-bg-transparent k1-p-4 k1-gap-4",
outline: "k1-border-2 k1-bg-transparent k1-p-4",
link: [
"k1-bg-transparent k1-text-neutral k1-p-0 k1-gap-2",
"k1-border-0",
"data-[hover]:k1-text-neutral-hover",
"data-[active]:k1-text-neutral-active",
"data-[disabled]:k1-text-neutral-disabled",
],
},
hasIcon: {
true: "k1-justify-between",
false: "k1-justify-center",
},
iconPosition: {
left: "k1-flex-row",
right: "k1-flex-row-reverse",
},
color: {
primary: [
"k1-bg-primary-strong",
"data-[hover]:k1-bg-primary-strong-hover data-[hover]-k1-text-white",
],
secondary: [
"k1-bg-secondary-strong",
"data-[hover]:k1-bg-secondary-strong-hover",
"data-[disabled]:k1-bg-neutral-disaled",
],
neutral: [
"k1-border-2 k1-text-neutral k1-border-neutral-strong",
"data-[hover]:k1-bg-neutral-backdrop-hover data-[hover]:k1-border-neutral-strong",
"data-[active]:k1-bg-neutral-backdrop-active data-[active]:k1-text-neutral-active",
"data-[disabled]:k1-border-neutral-disabled data-[disabled]:k1-text-neutral-disabled",
],
},
size: {
default: "k1-h-14 k1-text-sm k1-tracking-wider k1-leading-6",
small: "k1-h-10 k1-text-xs k1-tracking-wider k1-leading-4",
},
wider: {
true: "k1-px-6",
},
fitContent: {
true: "k1-w-fit",
false: "k1-w-full",
},
},

defaultVariants: {
kind: "filled",
size: "default",
fitContent: false,
},

compoundVariants: [
{
kind: "inverse",
color: "primary",
className: [
"k1-border-primary-strong k1-text-primary",
"data-[hover]:k1-border-primary-strong-hover data-[hover]:k1-text-neutral-inverse data-[hover]:k1-bg-primary-strong-hover",
"data-[active]:k1-bg-primary-strong data-[active]:k1-text-neutral-inverse data-[active]:k1-border-primary-strong-active",
"data-[pressed]:k1-bg-primary-strong data-[pressed]:k1-text-neutral-inverse",
],
},
{
kind: "inverse",
color: "secondary",
className: [
"k1-border-secondary-strong k1-text-secondary",
"data-[hover]:k1-border-secondary-strong-hover data-[hover]:k1-text-neutral-inverse data-[hover]:k1-bg-secondary-strong-hover",
"data-[active]:k1-bg-secondary-strong data-[active]:k1-text-neutral-inverse data-[active]:k1-border-secondary-strong-active",
"data-[pressed]:k1-bg-secondary-strong data-[pressed]:k1-text-neutral-inverse",
],
},
{
kind: "inverse",
color: "neutral",
className: [
"k1-border-neutral-strong k1-text-neutral k1-gap-4",
"data-[hover]:k1-border-neutral-strong-hover data-[hover]:k1-text-neutral-inverse data-[hover]:k1-bg-neutral-strong-hover",
"data-[active]:k1-bg-neutral-strong-active data-[active]:k1-text-neutral-inverse data-[active]:k1-border-neutral-active",
"data-[pressed]:k1-bg-neutral-strong-active data-[pressed]:k1-text-neutral-inverse",
],
},
],
},
);

type Props = React.ButtonHTMLAttributes<HTMLButtonElement> &
VariantProps<typeof buttonVariants> & {
pressed?: boolean;
answerType?: string;
children: React.ReactNode;
compactable?: boolean;
icon?: React.ComponentType<React.SVGProps<SVGSVGElement>>;
};

const Button = React.forwardRef<HTMLButtonElement, Props>(
(
{
children,
kind,
color,
iconPosition,
size,
wider,
fitContent,
compactable,
pressed,
answerType,
...props
},
ref,
) => {
const Icon = props.icon;
const hasIcon = !!Icon;

return (
<HeadlessUIButton
className={`${buttonVariants({ kind, size, wider, fitContent, hasIcon, iconPosition, color })}`}
ref={ref}
aria-pressed={pressed ? true : false}
data-pressed={pressed ? true : null}
aria-label={
pressed
? `Button ${answerType} pressed`
: `Press ${answerType} button`
}
{...props}
>
{hasIcon ? <Icon className="k1-w-6 k1-h-6" /> : null}
<div className={compactable ? "k1-hidden md:k1-block" : "k1-block"}>
{children}
</div>
</HeadlessUIButton>
);
},
);
Button.displayName = "Button";

export { Button, buttonVariants };
66 changes: 66 additions & 0 deletions packages/design-system/src/iconButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React from "react";
import { Button, ButtonProps } from "@headlessui/react";
import { cva, VariantProps } from "class-variance-authority";

const IconButtonVariants = cva(
["k1-inline-flex k1-gap-2 k1-items-center k1-w-auto k1-select-none"],

{
variants: {
size: {
small: "k1-w-8 k1-h-8",
default: "k1-w-10 k1-h-10",
large: "k1-w-14 k1-h-14",
},
},
},
);

const IconVariants = cva(
[
"k1-flex k1-justify-center k1-items-center k1-rounded-full hover:k1-bg-neutral-backdrop-hover active:k1-bg-neutral-backdrop-active",
],
{
variants: {
iconWrapper: {
small: "k1-h-8 k1-w-8",
default: "k1-h-10 k1-w-10",
large: "k1-h-14 k1-w-14",
},
iconSize: {
small: "k1-h-4 k1-w-4",
default: "k1-h-6 k1-w-6",
large: "k1-h-10 k1-w-10",
},
},
},
);

type Props = {
pressed?: boolean;
children?: React.ReactNode;
icon: React.ComponentType<React.SVGProps<SVGSVGElement>>;
"aria-label"?: string;
} & VariantProps<typeof IconButtonVariants> &
VariantProps<typeof IconVariants> &
ButtonProps;

const IconButton = React.forwardRef<HTMLButtonElement, Props>(
({ icon: Icon, size, iconWrapper, iconSize, children, ...props }, ref) => {
return (
<Button ref={ref} className={IconButtonVariants({ size })} {...props}>
<div className={IconVariants({ iconWrapper })}>
<Icon className={IconVariants({ iconSize })} />
</div>

<div className="k1-hidden md:k1-block">{children}</div>
</Button>
);
},
);

export { IconButton, IconButtonVariants, IconVariants };

//TODO:
// 1. fix wrapper/icon hover bug
// 2. iconWrapper hover on button hover
Loading

0 comments on commit 42a735b

Please sign in to comment.