From c027bcaac5304c67b5f0f015f6913410e75a9f8f Mon Sep 17 00:00:00 2001 From: majakomel Date: Thu, 22 Feb 2024 15:17:44 +0100 Subject: [PATCH 1/7] Style components with tailwind & update storybook --- .babelrc | 3 +- .storybook/main.ts | 14 +- .storybook/preview.tsx | 11 +- package.json | 63 +- postcss.config.js | 8 + src/__test__/Button.test.tsx | 13 +- src/__test__/Container.test.tsx | 34 - src/__test__/Heading.test.tsx | 57 - src/__test__/Hero.test.tsx | 34 - src/__test__/Icons.test.tsx | 9 +- src/__test__/InputWithIconButton.test.tsx | 50 - src/__test__/Link.test.tsx | 43 - src/__test__/Text.test.tsx | 32 - src/__test__/index.tsx | 6 +- src/components/Box.tsx | 48 - src/components/Button.tsx | 194 +- src/components/Checkbox.tsx | 125 +- src/components/Container.tsx | 7 - src/components/ErrorMessage.tsx | 7 +- src/components/FacebookShareButton.tsx | 17 +- src/components/Flex.tsx | 10 - src/components/Heading.tsx | 32 - src/components/Hero.tsx | 9 - src/components/HeroLead.tsx | 7 - src/components/IconButton.tsx | 10 +- src/components/Image.tsx | 17 - src/components/Input.tsx | 79 +- src/components/InputWithIconButton.tsx | 32 - src/components/Label.tsx | 15 +- src/components/Link.tsx | 9 - src/components/LogoOONIRun.tsx | 8 +- src/components/Modal.tsx | 87 +- src/components/MultiSelect.tsx | 129 +- src/components/MultiSelectCreatable.tsx | 213 +- src/components/RadioButton.tsx | 90 +- src/components/RadioGroup.tsx | 24 +- src/components/Select.tsx | 88 +- src/components/Text.tsx | 9 - src/components/Textarea.tsx | 66 +- src/components/TwitterShareButton.tsx | 21 +- src/index.ts | 36 +- src/tailwind.css | 3 + src/theme/colors.ts | 315 +- src/theme/index.ts | 351 +- src/types/declarations.d.ts | 1 - src/types/index.ts | 118 - stories/Box.stories.tsx | 37 - stories/Button.stories.tsx | 33 +- stories/Checkbox.stories.tsx | 8 +- stories/Colors.mdx | 238 +- stories/Container.stories.tsx | 28 - stories/GettingStarted.mdx | 3 +- stories/Heading.stories.tsx | 39 - stories/Hero.stories.tsx | 26 - stories/InputWithIconButton.stories.tsx | 34 - stories/Link.stories.tsx | 19 - stories/LogoOONIRun.stories.tsx | 7 +- stories/Modal.stories.tsx | 15 +- stories/MultiSelect.stories.tsx | 9 +- stories/MultiSelectCreatable.stories.tsx | 7 +- stories/OONIIcons.stories.tsx | 13 +- stories/RadioGroup.stories.tsx | 18 +- stories/Select.stories.tsx | 6 +- stories/Text.stories.tsx | 26 - stories/Textarea.stories.tsx | 7 +- stories/components/ColorPalette.tsx | 11 +- tailwind.config.js | 7 + vite.config.ts | 7 - yarn.lock | 6649 ++++++++------------- 69 files changed, 3324 insertions(+), 6477 deletions(-) create mode 100644 postcss.config.js delete mode 100644 src/__test__/Container.test.tsx delete mode 100644 src/__test__/Heading.test.tsx delete mode 100644 src/__test__/Hero.test.tsx delete mode 100644 src/__test__/InputWithIconButton.test.tsx delete mode 100644 src/__test__/Link.test.tsx delete mode 100644 src/__test__/Text.test.tsx delete mode 100644 src/components/Box.tsx delete mode 100644 src/components/Container.tsx delete mode 100644 src/components/Flex.tsx delete mode 100644 src/components/Heading.tsx delete mode 100644 src/components/Hero.tsx delete mode 100644 src/components/HeroLead.tsx delete mode 100644 src/components/Image.tsx delete mode 100644 src/components/InputWithIconButton.tsx delete mode 100644 src/components/Link.tsx delete mode 100644 src/components/Text.tsx create mode 100644 src/tailwind.css delete mode 100644 src/types/declarations.d.ts delete mode 100644 src/types/index.ts delete mode 100644 stories/Box.stories.tsx delete mode 100644 stories/Container.stories.tsx delete mode 100644 stories/Heading.stories.tsx delete mode 100644 stories/Hero.stories.tsx delete mode 100644 stories/InputWithIconButton.stories.tsx delete mode 100644 stories/Link.stories.tsx delete mode 100644 stories/Text.stories.tsx create mode 100644 tailwind.config.js delete mode 100644 vite.config.ts diff --git a/.babelrc b/.babelrc index 2c055d07..1f7e3f8b 100644 --- a/.babelrc +++ b/.babelrc @@ -11,6 +11,5 @@ ], "@babel/preset-typescript", "@babel/preset-react" - ], - "plugins": ["babel-plugin-styled-components"] + ] } diff --git a/.storybook/main.ts b/.storybook/main.ts index f5e4f5ff..f2a44679 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -5,20 +5,26 @@ const config: StorybookConfig = { '../stories/**/*.mdx', '../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)', ], + staticDirs: ['../src/fonts/'], + addons: [ '@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-onboarding', '@storybook/addon-interactions', - '@storybook/addon-mdx-gfm', + '@chromatic-com/storybook', ], + framework: { name: '@storybook/react-vite', options: {}, }, - docs: { - autodocs: 'tag', - }, + + docs: {}, + + typescript: { + reactDocgen: 'react-docgen-typescript' + } } export default config diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index 1f3b073e..f4c014ac 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -1,11 +1,10 @@ import type { Preview } from '@storybook/react' import React from 'react' -import { ThemeProvider } from 'styled-components' +import '../src/tailwind.css' import theme from '../src/theme' const preview: Preview = { parameters: { - actions: { argTypesRegex: '^on[A-Z].*' }, controls: { matchers: { color: /(background|color)$/i, @@ -13,13 +12,7 @@ const preview: Preview = { }, }, }, - decorators: [ - (Story) => ( - - - - ), - ], + decorators: [(Story) => ], } export default preview diff --git a/package.json b/package.json index 49d9f519..27b90b8e 100644 --- a/package.json +++ b/package.json @@ -9,10 +9,11 @@ "author": "Arturo Filastò ", "license": "BSD-3-Clause", "dependencies": { - "@styled-system/css": "^5.1.5", - "@styled-system/should-forward-prop": "^5.1.5", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.1", + "mini-svg-data-uri": "^1.4.4", "react-select": "^5.8.0", - "styled-system": "^5.1.5" + "tailwind-merge": "^2.3.0" }, "devDependencies": { "@babel/core": "^7.23.9", @@ -20,23 +21,23 @@ "@babel/preset-react": "^7.23.3", "@babel/preset-typescript": "^7.23.3", "@biomejs/biome": "1.5.3", + "@chromatic-com/storybook": "^1.6.1", "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-terser": "^0.4.4", "@rollup/plugin-typescript": "^11.1.6", "@rollup/plugin-url": "^8.0.2", - "@storybook/addon-essentials": "^7.6.17", - "@storybook/addon-interactions": "^7.6.17", - "@storybook/addon-links": "^7.6.17", - "@storybook/addon-mdx-gfm": "^7.6.17", - "@storybook/addon-onboarding": "^1.0.11", - "@storybook/blocks": "^7.6.17", - "@storybook/react": "^7.6.17", - "@storybook/react-vite": "^7.6.17", - "@storybook/test": "^7.6.17", - "@storybook/testing-library": "^0.2.2", + "@storybook/addon-essentials": "^8.2.1", + "@storybook/addon-interactions": "^8.2.1", + "@storybook/addon-links": "^8.2.1", + "@storybook/addon-onboarding": "^8.2.1", + "@storybook/blocks": "^8.2.1", + "@storybook/react": "^8.2.1", + "@storybook/react-vite": "^8.2.1", + "@storybook/test": "^8.2.1", "@svgr/rollup": "^8.1.0", + "@tailwindcss/forms": "^0.5.7", "@testing-library/dom": "^9.3.4", "@testing-library/jest-dom": "^6.4.2", "@testing-library/react": "^14.2.1", @@ -44,20 +45,17 @@ "@types/jest": "^29.5.12", "@types/react": "^18.2.57", "@types/react-dom": "^18.2.19", - "@types/styled-system": "^5.1.22", - "@types/styled-system__css": "^5.0.21", + "autoprefixer": "^10.4.17", "babel-plugin-inline-react-svg": "^2.0.2", - "babel-plugin-styled-components": "^2.1.4", "cheerio": "^1.0.0-rc.12", "gh-pages": "^6.1.1", "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", - "jest-styled-components": "^7.1.1", "jest-svg-transformer": "^1.0.0", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-icons": "^5.0.1", - "rimraf": "^5.0.1", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-icons": "^5.2.1", + "rimraf": "^5.0.7", "rollup": "^4.12.0", "rollup-plugin-copy": "^3.5.0", "rollup-plugin-delete": "^2.0.0", @@ -66,25 +64,22 @@ "rollup-plugin-peer-deps-external": "^2.2.4", "rollup-plugin-typescript2": "^0.36.0", "rollup-plugin-visualizer": "^5.12.0", - "storybook": "^7.6.17", - "styled-components": "^6.1.8", - "ts-jest": "^29.1.2", - "tslib": "^2.6.2", - "typescript": "^5.3.3", - "vite": "^5.1.3" - }, - "resolutions": { - "serialize-javascript": "^6.0.0", - "node-fetch": "^2.6.7", - "jackspeak": "2.1.1" + "storybook": "^8.2.1", + "tailwindcss": "^3.4.4", + "ts-jest": "^29.1.5", + "tslib": "^2.6.3", + "typescript": "^5.5.3", + "vite": "^5.3.3", + "yalc": "^1.0.0-pre.53" }, "peerDependencies": { "react": ">= 17", "react-icons": ">= 4", - "styled-components": ">= 6" + "tailwindcss": ">=3.0.0" }, "scripts": { "build": "yarn run rollup -c", + "build:tailwind": "tailwindcss -o tailwind/tailwind.css", "create-icons-dir": "rimraf src/components/icons && npx mkdirp src/components/icons", "create-icons": "npm run create-icons-dir && node src/bin/create-icons", "tag": "git tag -s -a v$npm_package_version -m \"ooni-components $npm_package_version\"", @@ -100,5 +95,5 @@ "storybook": "storybook dev -p 6006", "storybook:build": "storybook build" }, - "files": ["dist", "animations", "svgs", "index.d.ts", "icons"] + "files": ["dist", "animations", "svgs", "index.d.ts", "icons", "tailwind"] } diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 00000000..825cb186 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,8 @@ +module.exports = { + plugins: { + 'postcss-import': {}, + 'tailwindcss/nesting': {}, + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/src/__test__/Button.test.tsx b/src/__test__/Button.test.tsx index 035f8661..8ef85a19 100644 --- a/src/__test__/Button.test.tsx +++ b/src/__test__/Button.test.tsx @@ -1,8 +1,8 @@ -import React from 'react' import { screen } from '@testing-library/react' import 'jest-styled-components' -import renderWithWrapper from './index' +import React from 'react' import { Button } from '..' +import renderWithWrapper from './index' describe('Button', () => { test('renders Button', () => { @@ -27,13 +27,4 @@ describe('Button', () => { // expect(buttonElement).toHaveStyleRule('color', '#0588cb') expect(buttonElement).toHaveStyleRule('background-color', 'transparent') }) - - test('renders Button with rebass props', () => { - renderWithWrapper({ component: + ) +} export default Button diff --git a/src/components/Checkbox.tsx b/src/components/Checkbox.tsx index d05d0f25..16ed8ae5 100644 --- a/src/components/Checkbox.tsx +++ b/src/components/Checkbox.tsx @@ -1,85 +1,56 @@ import React, { forwardRef } from 'react' -import { CheckboxProps as CP } from 'types' -import { getMarginProps, omitMarginProps } from '../utils' -import Box from './Box' -import Flex from './Flex' - -export interface CheckboxProps extends CP { - error?: string | undefined +export interface CheckboxProps { + error?: string name: string label: string - reverse?: boolean + disabled?: boolean } -const Checkbox = forwardRef( - ( - { - className, - sx, - name, - label, - variant = 'checkbox', - reverse = false, - error, - ...props - }: CheckboxProps, - ref, - ) => ( - - - - {label} - - +const Checkbox = forwardRef( + ({ name, label, error, disabled = false, ...props }, ref) => ( + <> +
+
+ +
+
+ +
+ {/* {error} */} +
+ ), ) diff --git a/src/components/Container.tsx b/src/components/Container.tsx deleted file mode 100644 index c1fb9967..00000000 --- a/src/components/Container.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from 'react' -import { BoxProps } from 'types' -import Box from './Box' - -const Container = (props: BoxProps) => - -export default Container diff --git a/src/components/ErrorMessage.tsx b/src/components/ErrorMessage.tsx index b423e310..e9547274 100644 --- a/src/components/ErrorMessage.tsx +++ b/src/components/ErrorMessage.tsx @@ -1,16 +1,11 @@ import React, { ReactNode } from 'react' -import Text from './Text' interface ErrorMessageProps { children: ReactNode } const ErrorMessage = ({ children }: ErrorMessageProps) => { - return ( - - {children} - - ) + return

{children}

} export default ErrorMessage diff --git a/src/components/FacebookShareButton.tsx b/src/components/FacebookShareButton.tsx index c46ca718..20de1a37 100644 --- a/src/components/FacebookShareButton.tsx +++ b/src/components/FacebookShareButton.tsx @@ -1,10 +1,7 @@ import React from 'react' import { FaFacebook } from 'react-icons/fa' -import Button, { ButtonProps } from './Button' -import Link from './Link' -import Text from './Text' - -export interface FacebookShareButton extends ButtonProps { +import Button from './Button' +export interface FacebookShareButton { url?: string } @@ -13,14 +10,12 @@ const FacebookShareButton = ({ url = '', ...rest }: FacebookShareButton) => { href += `&u=${encodeURIComponent(url)}` return ( - - - + ) } diff --git a/src/components/Flex.tsx b/src/components/Flex.tsx deleted file mode 100644 index a84aff8a..00000000 --- a/src/components/Flex.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { FlexProps } from 'types' -import React from 'react' -import { styled } from 'styled-components' -import Box from './Box' - -const Flex = styled(Box)({ - display: 'flex', -}) - -export default Flex diff --git a/src/components/Heading.tsx b/src/components/Heading.tsx deleted file mode 100644 index 7ce86f96..00000000 --- a/src/components/Heading.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import React from 'react' -import { TextProps } from 'types' -import Text from './Text' - -export interface HeadingProps extends TextProps { - h?: number -} - -const Heading = ({ h = 1, ...rest }: HeadingProps) => { - const getHeadingElement = () => { - switch (h) { - case 1: - return 'h1' - case 2: - return 'h2' - case 3: - return 'h3' - case 4: - return 'h4' - case 5: - return 'h5' - default: - return 'h3' - } - } - - return ( - - ) -} - -export default Heading diff --git a/src/components/Hero.tsx b/src/components/Hero.tsx deleted file mode 100644 index f8886feb..00000000 --- a/src/components/Hero.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react' -import { BoxProps } from 'types' -import Box from './Box' - -const Hero = (props: BoxProps) => { - return -} - -export default Hero diff --git a/src/components/HeroLead.tsx b/src/components/HeroLead.tsx deleted file mode 100644 index 52625ba7..00000000 --- a/src/components/HeroLead.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from 'react' -import { TextProps } from 'types' -import Text from './Text' - -const HeroLead = (props: TextProps) => - -export default HeroLead diff --git a/src/components/IconButton.tsx b/src/components/IconButton.tsx index 8c45bd9b..d9b491ed 100644 --- a/src/components/IconButton.tsx +++ b/src/components/IconButton.tsx @@ -1,16 +1,12 @@ import React, { ReactNode } from 'react' -import Button, { ButtonProps } from './Button' +import Button from './Button' -export interface IconButtonProps extends ButtonProps { +export interface IconButtonProps { icon: ReactNode } const IconButton = ({ icon, ...rest }: IconButtonProps) => { - return ( - - ) + return } export default IconButton diff --git a/src/components/Image.tsx b/src/components/Image.tsx deleted file mode 100644 index d8099e12..00000000 --- a/src/components/Image.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import React, { forwardRef } from 'react' -import { ImageProps } from 'types' -import Box from './Box' - -const Image = forwardRef((props: ImageProps, ref) => ( - -)) - -export default Image diff --git a/src/components/Input.tsx b/src/components/Input.tsx index ecff186f..15818379 100644 --- a/src/components/Input.tsx +++ b/src/components/Input.tsx @@ -1,45 +1,50 @@ import React, { forwardRef } from 'react' -import { InputProps as IP } from 'types' -import { getMarginProps, omitMarginProps } from '../utils' -import Box from './Box' import ErrorMessage from './ErrorMessage' -import Text from './Text' -export interface InputProps extends IP { - error?: string | undefined +export interface InputProps { + error?: string label?: string + name: string } -const Input = forwardRef(({ error, name, label, ...rest }: InputProps, ref) => { - return ( - - {label && ( - - {label} - - )} - - {error && {error}} - - ) -}) +const Input = forwardRef( + ({ error, name, label, ...props }, ref) => { + return ( +
+ {label && ( + + )} + + {error && {error}} +
+ ) + }, +) export default Input diff --git a/src/components/InputWithIconButton.tsx b/src/components/InputWithIconButton.tsx deleted file mode 100644 index 7ef912cc..00000000 --- a/src/components/InputWithIconButton.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import React, { ReactNode } from 'react' -import { InputProps } from 'types' -import Box from './Box' -import Flex from './Flex' -import IconButton from './IconButton' -import Input from './Input' - -interface InputWithIconButtonProps extends InputProps { - onAction?: () => void - icon?: ReactNode -} - -export const InputWithIconButton = ({ - onAction, - icon, - ...rest -}: InputWithIconButtonProps) => { - return ( - - - - - {icon ? ( - - - - ) : null} - - ) -} - -export default InputWithIconButton diff --git a/src/components/Label.tsx b/src/components/Label.tsx index 30a4295f..5d9ef1d7 100644 --- a/src/components/Label.tsx +++ b/src/components/Label.tsx @@ -1,15 +1,14 @@ import React, { forwardRef } from 'react' -import { LabelProps } from 'types' -import Text from './Flex' -const Label = forwardRef((props: LabelProps, ref) => ( - ((props, ref) => ( + ) }, ) diff --git a/src/components/RadioGroup.tsx b/src/components/RadioGroup.tsx index 7ad3c787..a0fd511f 100644 --- a/src/components/RadioGroup.tsx +++ b/src/components/RadioGroup.tsx @@ -1,12 +1,13 @@ -import React, { ChangeEvent, ReactNode, Children, cloneElement } from 'react' -import { FlexProps } from 'types' -import Flex from './Flex' +import React, { ChangeEvent, Children, ReactNode, cloneElement } from 'react' +import { twMerge } from 'tailwind-merge' -export interface RadioGroupProps extends FlexProps { +export interface RadioGroupProps { children?: ReactNode name?: string value?: string - direction?: 'row' | 'column' + flexDirection?: 'row' | 'column' + className?: string + onChange: (arg: string) => void } const RadioGroup = ({ @@ -14,7 +15,8 @@ const RadioGroup = ({ name, value, onChange, - direction = 'column', + className, + flexDirection = 'column', ...props }: RadioGroupProps) => { const iterateOverChildren = (children: ReactNode) => { @@ -25,16 +27,20 @@ const RadioGroup = ({ ...child.props, checked: child.props.value === value, onChange: (e: ChangeEvent) => - onChange && onChange(e.target.value), + onChange?.(e.target.value), children: iterateOverChildren(child.props.children), }) }) } return ( - +
{iterateOverChildren(children)} - +
) } diff --git a/src/components/Select.tsx b/src/components/Select.tsx index 9be27c82..ceb203e1 100644 --- a/src/components/Select.tsx +++ b/src/components/Select.tsx @@ -1,50 +1,52 @@ import React, { forwardRef } from 'react' -import { SelectProps as SP } from 'types' -import { getMarginProps, omitMarginProps } from '../utils' -import Box from './Box' -import Text from './Text' +import ErrorMessage from './ErrorMessage' -export interface SelectProps extends SP { +export interface SelectProps extends React.HTMLProps { label?: string + error?: string } -const Select = forwardRef(({ label, name, ...rest }: SelectProps, ref) => ( - - {label && ( - - {label} - - )} - - -)) +const Select = forwardRef( + ({ label, name, className, error, ...props }, ref) => ( +
+ {label && ( + + )} + {Object.entries(countries).map(([key, country]) => ( ))} - +
) } diff --git a/stories/Text.stories.tsx b/stories/Text.stories.tsx deleted file mode 100644 index a968cc4c..00000000 --- a/stories/Text.stories.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react' -import Text from '../src/components/Text' - -const meta = { - title: 'Components/Text', - component: Text, - tags: ['autodocs'], - argTypes: { - fontSize: { control: 'number' }, - fontWeight: { control: 'string' }, - color: { control: 'string' }, - }, -} satisfies Meta - -export default meta -type Story = StoryObj - -export const Default: Story = { - args: { - fontSize: 5, - fontWeight: 'bold', - color: 'primary', - children: - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas eu sapien urna. Donec aliquet dictum porta. Sed accumsan dui eu faucibus eleifend. Nunc commodo nibh turpis, quis aliquam erat iaculis et. Cras et interdum eros, sed euismod dolor. In ac nulla mollis, scelerisque ante et, faucibus urna. Etiam sit amet neque aliquet, molestie orci ac, porta sem. Curabitur iaculis porta massa, sed bibendum lectus suscipit sed. Nullam nisi eros, cursus non mi vitae, facilisis tempus dui.', - }, -} diff --git a/stories/Textarea.stories.tsx b/stories/Textarea.stories.tsx index 75b5cd47..66aee24c 100644 --- a/stories/Textarea.stories.tsx +++ b/stories/Textarea.stories.tsx @@ -16,7 +16,12 @@ type Story = StoryObj export const Default: Story = { render: (args) => ( -