diff --git a/apps/frontend/.storybook/preview.ts b/apps/frontend/.storybook/preview.ts index ff58bbd..0832f89 100644 --- a/apps/frontend/.storybook/preview.ts +++ b/apps/frontend/.storybook/preview.ts @@ -1,8 +1,9 @@ -import type { Preview } from "@storybook/react"; +import type { Preview } from '@storybook/react'; +import '../src/App.scss'; const preview: Preview = { parameters: { - actions: { argTypesRegex: "^on[A-Z].*" }, + actions: { argTypesRegex: '^on[A-Z].*' }, controls: { matchers: { color: /(background|color)$/i, diff --git a/apps/frontend/src/App.scss b/apps/frontend/src/App.scss index 4f61b80..c719760 100644 --- a/apps/frontend/src/App.scss +++ b/apps/frontend/src/App.scss @@ -42,8 +42,8 @@ } // Fonts -$gellix-font-family: "Gellix"; -$gellix-fonts-path: "./stories/assets/fonts/"; +$gellix-font-family: 'Gellix'; +$gellix-fonts-path: './stories/assets/fonts/'; $font-weight-thin: 100; $font-weight-light: 300; $font-weight-regular: 400; @@ -54,20 +54,32 @@ $font-weight-black: 900; @font-face { font-family: $gellix-font-family; - src: url("./stories/assets/fonts/Gellix-Light_R.woff2") format("woff2"); + src: url('./stories/assets/fonts/Gellix-Light_R.woff2') format('woff2'); font-weight: $font-weight-light; } @font-face { font-family: $gellix-font-family; - src: url("./stories/assets/fonts/Gellix-Regular_R.woff2") format("woff2"); + src: url('./stories/assets/fonts/Gellix-Regular_R.woff2') format('woff2'); font-weight: $font-weight-regular; font-style: normal; } @font-face { font-family: $gellix-font-family; - src: url("./stories/assets/fonts/Gellix-SemiBold_R.woff2") format("woff2"); + src: url('./stories/assets/fonts/Gellix-SemiBold_R.woff2') format('woff2'); font-weight: $font-weight-semibold; font-style: normal; } + +// BUTTON STYLES +.btn-secondary { + &:hover { + svg path { + fill: theme('colors.midnight-blue'); + } + } + svg path { + fill: theme('colors.link-blue'); + } +} diff --git a/apps/frontend/src/assets/icons/arrow-right-bold.svg b/apps/frontend/src/assets/icons/arrow-right-bold.svg new file mode 100644 index 0000000..bcf5411 --- /dev/null +++ b/apps/frontend/src/assets/icons/arrow-right-bold.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/frontend/src/components/Button.stories.ts b/apps/frontend/src/components/Button.stories.ts deleted file mode 100644 index e640f2a..0000000 --- a/apps/frontend/src/components/Button.stories.ts +++ /dev/null @@ -1,44 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; - -import { Button } from './Button'; - -const meta = { - title: 'Example/Button', - component: Button, - parameters: { - layout: 'centered', - }, - // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs - tags: ['autodocs'], -} satisfies Meta; - -export default meta; -type Story = StoryObj; - -// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args -export const Primary: Story = { - args: { - label: 'Button', - size: 'default', - }, -}; - -export const Secondary: Story = { - args: { - label: 'Button', - }, -}; - -export const Large: Story = { - args: { - size: 'large', - label: 'Button', - }, -}; - -export const Small: Story = { - args: { - size: 'small', - label: 'Button', - }, -}; diff --git a/apps/frontend/src/components/Button.tsx b/apps/frontend/src/components/Button.tsx index 09b9631..3799a12 100644 --- a/apps/frontend/src/components/Button.tsx +++ b/apps/frontend/src/components/Button.tsx @@ -1,9 +1,82 @@ +import clsx from 'clsx'; + +type Icon = React.FunctionComponent< + React.SVGProps & { + title?: string | undefined; + } +>; + export interface ButtonProps extends React.ButtonHTMLAttributes { variant?: 'primary' | 'secondary' | 'link'; size?: 'default' | 'small' | 'large' | 'tiny'; label: string; + /** + * import { ReactComponent as YourIcon } from '/assets/icons/...svg + */ + IconLeft?: Icon; + /** + * import { ReactComponent as YourIcon } from '/assets/icons/...svg + */ + IconRight?: Icon; } -export const Button = ({ variant = 'primary', size = 'default', onClick, label, ...props }: ButtonProps) => { - return ; +const common = 'btn font-gellix flex items-center gap-5px rounded-full font-semibold disabled:opacity-25'; +const defaultSize = 'text-xl leading-5 py-15px px-25px'; +const small = 'leading-4 px-5 py-3'; +const large = 'text-25px leading-25px px-31.25px py-18.75px'; +const tiny = 'text-xs leading-3 px-15px py-9px'; + +const primary = + 'bg-dark-teal text-midnight-blue hover:bg-medium-teal active:bg-light-teal focus:outline focus:outline-2 focus:outline-offset-1 focus:outline-link-blue'; +const secondary = + 'btn-secondary border-2 border-link-blue border-solid text-link-blue hover:text-midnight-blue hover:border-midnight-blue focus:outline focus:outline-2 focus:outline-offset-1 focus:outline-link-blue'; +const link = `${secondary} !p-0 !border-none focus:!outline-none`; + +export const Button = ({ + variant = 'primary', + size = 'default', + onClick, + label, + IconRight, + IconLeft, + disabled, + ...props +}: ButtonProps) => { + return ( + + ); }; diff --git a/apps/frontend/src/stories/Button.stories.ts b/apps/frontend/src/stories/Button.stories.ts new file mode 100644 index 0000000..e482901 --- /dev/null +++ b/apps/frontend/src/stories/Button.stories.ts @@ -0,0 +1,108 @@ +import type { Meta, StoryObj } from '@storybook/react'; + +import { Button } from '../components/Button'; + +const meta = { + title: 'Button', + component: Button, + parameters: { + layout: 'centered', + }, + tags: ['autodocs'], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +// --- PRIMARY --- +export const PrimaryDefault: Story = { + args: { + label: 'Button', + variant: 'primary', + }, +}; + +export const PrimaryLarge: Story = { + args: { + label: 'Button', + size: 'large', + }, +}; + +export const PrimarySmall: Story = { + args: { + label: 'Button', + size: 'small', + }, +}; + +export const PrimaryTiny: Story = { + args: { + label: 'Button', + size: 'tiny', + }, +}; + +// --- SECONDARY --- +export const SecondaryDefault: Story = { + args: { + label: 'Button', + variant: 'secondary', + }, +}; + +export const SecondaryLarge: Story = { + args: { + label: 'Button', + variant: 'secondary', + size: 'large', + }, +}; + +export const SecondarySmall: Story = { + args: { + label: 'Button', + variant: 'secondary', + size: 'small', + }, +}; + +export const SecondaryTiny: Story = { + args: { + label: 'Button', + variant: 'secondary', + size: 'tiny', + }, +}; + +// --- LINK --- +export const LinkDefault: Story = { + args: { + label: 'Button', + variant: 'link', + }, +}; + +export const LinkLarge: Story = { + args: { + label: 'Button', + variant: 'link', + size: 'large', + }, +}; + +export const LinkSmall: Story = { + args: { + label: 'Button', + variant: 'link', + size: 'small', + }, +}; + +export const LinkTiny: Story = { + args: { + label: 'Button', + variant: 'link', + size: 'tiny', + }, +}; diff --git a/apps/frontend/src/stories/button.css b/apps/frontend/src/stories/button.css deleted file mode 100644 index dc91dc7..0000000 --- a/apps/frontend/src/stories/button.css +++ /dev/null @@ -1,30 +0,0 @@ -.storybook-button { - font-family: 'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; - font-weight: 700; - border: 0; - border-radius: 3em; - cursor: pointer; - display: inline-block; - line-height: 1; -} -.storybook-button--primary { - color: white; - background-color: #1ea7fd; -} -.storybook-button--secondary { - color: #333; - background-color: transparent; - box-shadow: rgba(0, 0, 0, 0.15) 0px 0px 0px 1px inset; -} -.storybook-button--small { - font-size: 12px; - padding: 10px 16px; -} -.storybook-button--medium { - font-size: 14px; - padding: 11px 20px; -} -.storybook-button--large { - font-size: 16px; - padding: 12px 24px; -} diff --git a/apps/frontend/tailwind.config.js b/apps/frontend/tailwind.config.js index 11f14f2..1ab8f1a 100644 --- a/apps/frontend/tailwind.config.js +++ b/apps/frontend/tailwind.config.js @@ -4,7 +4,22 @@ const colors = require('tailwindcss/colors'); module.exports = { content: ['./src/**/*.{html,js,jsx,ts,tsx}'], theme: { - extend: {}, + extend: { + spacing: { + '5px': '5px', + '15px': '15px', + '9px': '9px', + '25px': '25px', + '31.25px': '31.25px', + '18.75px': '18.75px', + }, + lineHeight: { + '25px': '25px', + }, + fontSize: { + '25px': '25px', + }, + }, colors: { black: colors.black, white: colors.white, @@ -13,10 +28,11 @@ module.exports = { waterspout: '#A8F9F6', 'midnight-blue': '#000048', 'dark-teal': '#11C7CC', - 'medium-teal': '#26EFE9', - 'light-teal': 'C9FBFA', + 'medium-teal': '#29EEE9', + 'light-teal': '#A8F9F6', + 'lightest-teal': '#C9FBFA', 'disabled-teal': '#26EFE9', - 'medium-blue': '#2F78C4', + 'link-blue': '#2F78C4', }, fontFamily: { gellix: ['Gellix', 'sans-serif'],