From 2c18f8bc41fd1bc28501ad2d929952f578fbf1bf Mon Sep 17 00:00:00 2001 From: majakomel Date: Wed, 28 Feb 2024 21:43:52 +0100 Subject: [PATCH] Implement button with vanilla-extract --- package.json | 1 + src/components/ButtonVE.css.ts | 142 ++++++++++++++++++++++++ src/components/ButtonVE.tsx | 56 ++++++++++ src/components/ButtonVESprinkles.css.ts | 17 +++ stories/ButtonVE.stories.tsx | 51 +++++++++ vite.config.ts | 8 +- yarn.lock | 5 + 7 files changed, 276 insertions(+), 4 deletions(-) create mode 100644 src/components/ButtonVE.css.ts create mode 100644 src/components/ButtonVE.tsx create mode 100644 src/components/ButtonVESprinkles.css.ts create mode 100644 stories/ButtonVE.stories.tsx diff --git a/package.json b/package.json index b655631..a4fdbc5 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "@styled-system/should-forward-prop": "^5.1.5", "@vanilla-extract/css": "^1.14.1", "@vanilla-extract/recipes": "^0.5.1", + "@vanilla-extract/sprinkles": "^1.6.1", "react-select": "^5.8.0", "styled-system": "^5.1.5" }, diff --git a/src/components/ButtonVE.css.ts b/src/components/ButtonVE.css.ts new file mode 100644 index 0000000..0779631 --- /dev/null +++ b/src/components/ButtonVE.css.ts @@ -0,0 +1,142 @@ +import { createGlobalTheme } from '@vanilla-extract/css' +import { recipe } from '@vanilla-extract/recipes' +import { sprinkles } from './ButtonVESprinkles.css' + +export const vars = createGlobalTheme(':root', { + color: { + blue: { + '100': '#c9e8ff', + '200': '#8dd5f8', + '300': '#5db8fe', + '400': '#37a6ed', + '500': '#0588cb', + '600': '#0f77b8', + '700': '#056aa6', + '800': '#005f9c', + '900': '#005a99', + }, + }, + fontSize: { + sm: { fontSize: '0.875rem', lineHeight: '1.25rem' }, + }, + space: { + sm: '0.5rem', + }, +}) + +export const button = recipe({ + base: { + display: 'flex', + justifyItems: 'center', + alignItems: 'center', + borderRadius: 999, + cursor: 'pointer', + fontFamily: 'inherit', + // display: 'inline-block', + textTransform: 'capitalize', + // textAlign: 'center', + letterSpacing: '0.5px', + // verticalAlign: 'middle', + // Gets rid of tap active state + WebkitTapHighlightColor: 'transparent', + transition: '.2s ease-out', + outline: 0, + borderWidth: '2px', + borderStyle: 'solid', + ':focus-visible': { + transition: 'none', + outline: '2px solid', + outlineColor: vars.color.blue[500], + outlineOffset: '1px', + }, + }, + variants: { + variant: { + primary: { + background: vars.color.blue[500], + color: 'white', + borderColor: vars.color.blue[500], + ':hover': { + background: vars.color.blue[900], + borderColor: vars.color.blue[900], + }, + }, + dark: { + background: 'black', + borderColor: 'black', + color: 'white', + ':hover': { + background: 'black', + borderColor: 'black', + }, + }, + }, + size: { + s: [{ padding: '0.25rem 1rem' }, sprinkles({ textStyle: 'sm' })], + m: [{ padding: '0.5rem 1.5rem' }, sprinkles({ textStyle: 'md' })], + l: [{ padding: '0.5rem 2rem' }, sprinkles({ textStyle: 'xxl' })], + xl: [{ padding: '0.875rem 4rem' }, sprinkles({ textStyle: 'xxl' })], + }, + hollow: { + true: { background: 'transparent' }, + }, + }, + defaultVariants: { + size: 'm', + hollow: false, + variant: 'primary', + }, + compoundVariants: [ + { + variants: { + variant: 'primary', + hollow: true, + }, + style: { + background: 'transparent', + color: vars.color.blue[500], + ':hover': { + background: 'transparent', + borderColor: vars.color.blue[900], + color: vars.color.blue[900], + }, + }, + }, + ], +}) + +// export const storybookButton = style({ +// fontFamily: 'Nunito Sans , Helvetica Neue , Helvetica , Arial , sans-serif', +// fontWeight: '700', +// border: '0', +// borderRadius: '3em', +// cursor: 'pointer', +// display: 'inline-block', +// lineHeight: '1', +// }); + +// export const storybookButtonLarge = style({ +// fontSize: '16px', +// padding: '12px 24px', +// }); + +// export const storybookButtonMedium = style({ +// fontSize: '14px', +// padding: '11px 20px', +// }); + +// export const storybookButtonPrimary = style({ +// color: 'white', +// backgroundColor: '#1ea7fd', +// }); + +// export const storybookButtonSecondary = style({ +// color: '#333', +// backgroundColor: 'transparent', +// boxShadow: 'rgba(0,0,0,0.15) 0px 0px 0px 1px inset', +// }); + +// export const storybookButtonSmall = style({ +// fontSize: '12px', +// padding: '10px 16px', +// }); diff --git a/src/components/ButtonVE.tsx b/src/components/ButtonVE.tsx new file mode 100644 index 0000000..6356ad7 --- /dev/null +++ b/src/components/ButtonVE.tsx @@ -0,0 +1,56 @@ +import React, { forwardRef } from 'react' +import { button } from './ButtonVE.css' +import { sprinkles } from './ButtonVESprinkles.css' + +type Size = 's' | 'm' | 'l' | 'xl' +type Variant = 'primary' | 'dark' + +console.log(' sprinkles', sprinkles({ textStyle: 'sm' })) + +export interface ButtonProps + extends React.ButtonHTMLAttributes { + disabled?: boolean + inverted?: boolean + hollow?: boolean + variant?: Variant + size?: Size + startIcon?: React.ReactNode + endIcon?: React.ReactNode +} + +const Button = forwardRef( + ( + { + hollow = false, + inverted = false, + disabled = false, + variant = 'primary', + size = 'm', + type = 'button', + children, + startIcon, + endIcon, + ...rest + }: ButtonProps, + ref, + ) => { + return ( + + ) + }, +) + +export default Button diff --git a/src/components/ButtonVESprinkles.css.ts b/src/components/ButtonVESprinkles.css.ts new file mode 100644 index 0000000..c0554ba --- /dev/null +++ b/src/components/ButtonVESprinkles.css.ts @@ -0,0 +1,17 @@ +import { createSprinkles, defineProperties } from '@vanilla-extract/sprinkles' + +const properties = defineProperties({ + properties: { + textStyle: { + sm: { fontSize: '0.875rem', lineHeight: '1.25rem' }, + md: { fontSize: '1rem', lineHeight: '1.5rem' }, + lg: { fontSize: '1.125rem', lineHeight: '1.75rem' }, + xl: { fontSize: '1.25rem', lineHeight: '1.75rem' }, + xxl: { fontSize: '1.5rem', lineHeight: '2rem' }, + }, + }, +}) + +export const sprinkles = createSprinkles(properties) + +export type Sprinkles = Parameters[0] diff --git a/stories/ButtonVE.stories.tsx b/stories/ButtonVE.stories.tsx new file mode 100644 index 0000000..7964547 --- /dev/null +++ b/stories/ButtonVE.stories.tsx @@ -0,0 +1,51 @@ +import { Meta, StoryObj } from '@storybook/react' +import React from 'react' +import { BsTwitter } from 'react-icons/bs' +import Box from '../src/components/Box' +import Button from '../src/components/ButtonVE' + +const meta = { + title: 'Components/ButtonVE', + component: Button, + tags: ['autodocs'], + argTypes: { + onClick: { action: 'clicked' }, + hollow: { control: 'boolean' }, + disabled: { control: 'boolean' }, + inverted: { control: 'boolean' }, + }, +} satisfies Meta + +export default meta +type Story = StoryObj + +export const Primary: Story = { + args: { + children: 'Button', + }, +} + +export const ColorVariant: Story = { + args: { + variant: 'dark', + children: 'Button', + size: 's', + endIcon: , + }, +} + +export const Hollow: Story = { + args: { + hollow: true, + size: 'l', + children: 'Button', + }, +} + +export const LongButton = () => { + return ( + + + + ) +} diff --git a/vite.config.ts b/vite.config.ts index 3af5aa7..f88d398 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,8 +1,8 @@ -import { vanillaExtractPlugin } from '@vanilla-extract/vite-plugin'; -import react from '@vitejs/plugin-react'; -import { defineConfig } from 'vite'; +import { vanillaExtractPlugin } from '@vanilla-extract/vite-plugin' +import react from '@vitejs/plugin-react' +import { defineConfig } from 'vite' // https://vitejs.dev/config/ export default defineConfig({ plugins: [react(), vanillaExtractPlugin()], -}); \ No newline at end of file +}) diff --git a/yarn.lock b/yarn.lock index 382ebee..2016b05 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3811,6 +3811,11 @@ resolved "https://registry.yarnpkg.com/@vanilla-extract/recipes/-/recipes-0.5.1.tgz#617d1a0375af60835341770397810317d2f61998" integrity sha512-7dCuBgPQQ/89siQ0w2lkfjgkmToPUUDzFlHf5DRmt9ykiiycfA52tmPJ2RI/mr7jXi7U/vEN2aGP9QJSXEpGlA== +"@vanilla-extract/sprinkles@^1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@vanilla-extract/sprinkles/-/sprinkles-1.6.1.tgz#2c8a832757a0d8104dc6bd5d961db2c70d1dbdcb" + integrity sha512-N/RGKwGAAidBupZ436RpuweRQHEFGU+mvAqBo8PRMAjJEmHoPDttV8RObaMLrJHWLqvX+XUMinHUnD0hFRQISw== + "@vanilla-extract/vite-plugin@^4.0.4": version "4.0.4" resolved "https://registry.yarnpkg.com/@vanilla-extract/vite-plugin/-/vite-plugin-4.0.4.tgz#8975d1e584e7bb8bbc241d31d49db3b134328627"