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..474ae7e1 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/'],
+
+ // 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..9f3e0b3a 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "ooni-components",
- "version": "0.6.0-alpha.11",
+ "version": "0.7.0-alpha.6",
"main": "dist/index.cjs.js",
"module": "dist/index.esm.js",
"types": "dist/index.d.ts",
@@ -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/rollup.config.mjs b/rollup.config.mjs
index af279c61..10652abd 100644
--- a/rollup.config.mjs
+++ b/rollup.config.mjs
@@ -53,7 +53,7 @@ const mainBundle = {
copy({
targets: [
{
- src: './src/fonts',
+ src: './src/tailwind.css',
dest: './dist',
},
],
diff --git a/src/__test__/Button.test.tsx b/src/__test__/Button.test.tsx
deleted file mode 100644
index 035f8661..00000000
--- a/src/__test__/Button.test.tsx
+++ /dev/null
@@ -1,39 +0,0 @@
-import React from 'react'
-import { screen } from '@testing-library/react'
-import 'jest-styled-components'
-import renderWithWrapper from './index'
-import { Button } from '..'
-
-describe('Button', () => {
- test('renders Button', () => {
- renderWithWrapper({ component: })
-
- const buttonElement = screen.getByRole('button')
- expect(buttonElement).toBeInTheDocument()
- })
-
- test('renders Button with inverted prop', () => {
- renderWithWrapper({ component: })
-
- const buttonElement = screen.getByRole('button')
- expect(buttonElement).toHaveStyleRule('color', '#0588cb')
- expect(buttonElement).toHaveStyleRule('background-color', '#f8f9fa')
- })
-
- test('renders Button with hollow prop', () => {
- renderWithWrapper({ component: })
-
- const buttonElement = screen.getByRole('button')
- // expect(buttonElement).toHaveStyleRule('color', '#0588cb')
- expect(buttonElement).toHaveStyleRule('background-color', 'transparent')
- })
-
- test('renders Button with rebass props', () => {
- renderWithWrapper({ component: })
-
- const buttonElement = screen.getByRole('button')
- expect(buttonElement).toHaveStyleRule('width', '100%')
- expect(buttonElement).toHaveStyleRule('margin', '8px')
- expect(buttonElement).toHaveStyleRule('font-size', '22px')
- })
-})
diff --git a/src/__test__/Container.test.tsx b/src/__test__/Container.test.tsx
deleted file mode 100644
index ec727ab8..00000000
--- a/src/__test__/Container.test.tsx
+++ /dev/null
@@ -1,34 +0,0 @@
-import React from 'react'
-import { screen } from '@testing-library/react'
-import 'jest-styled-components'
-import renderWithWrapper from './index'
-import { Container } from '..'
-
-describe('Container', () => {
- test('renders Container', () => {
- renderWithWrapper({ component: })
-
- const containerElement = screen.getByTestId('test-div')
- expect(containerElement).toBeInTheDocument()
- })
-
- test('render Container with variant styles', () => {
- renderWithWrapper({ component: })
-
- const containerElement = screen.getByTestId('test-div')
- expect(containerElement).toHaveStyleRule('padding-left', '16px')
- expect(containerElement).toHaveStyleRule('padding-right', '16px')
- expect(containerElement).toHaveStyleRule('margin-left', 'auto')
- expect(containerElement).toHaveStyleRule('margin-left', 'auto')
- expect(containerElement).toHaveStyleRule('max-width', '768px')
- })
-
- test('render Container with rebass props', () => {
- renderWithWrapper({
- component: ,
- })
-
- const containerElement = screen.getByTestId('test-div')
- expect(containerElement).toHaveStyleRule('max-width', '500px')
- })
-})
diff --git a/src/__test__/Heading.test.tsx b/src/__test__/Heading.test.tsx
deleted file mode 100644
index 5dbcf83e..00000000
--- a/src/__test__/Heading.test.tsx
+++ /dev/null
@@ -1,57 +0,0 @@
-import React from 'react'
-import { screen } from '@testing-library/react'
-import 'jest-styled-components'
-import renderWithWrapper from './index'
-import { Heading } from '..'
-
-describe('Heading', () => {
- test('renders Heading', () => {
- renderWithWrapper({ component: })
-
- const headingElement = screen.getByRole('heading')
- expect(headingElement).toBeInTheDocument()
- })
-
- test('render Heading with default h prop', () => {
- renderWithWrapper({ component: })
-
- const headingElement = screen.getByRole('heading', { level: 1 })
- expect(headingElement).toBeInTheDocument()
- })
-
- test('renders Heading with correct h prop', () => {
- renderWithWrapper({ component: })
-
- const headingElement = screen.getByRole('heading', { level: 3 })
- expect(headingElement).toBeInTheDocument()
- })
-
- test('render Heading with text', () => {
- renderWithWrapper({ component: OONI Run! })
-
- const headingElement = screen.getByText(/OONI Run!/i)
- expect(headingElement).toBeVisible()
- })
-
- test('render Heading with variant styles', () => {
- renderWithWrapper({ component: OONI Run! })
-
- const headingElement = screen.getByRole('heading')
- expect(headingElement).toHaveStyleRule('font-size', '36px')
- expect(headingElement).toHaveStyleRule('font-weight', '300')
- expect(headingElement).toHaveStyleRule('letter-spacing', '-1px')
- })
-
- test('render Heading with rebass style props', () => {
- renderWithWrapper({
- component: (
-
- OONI Run!
-
- ),
- })
-
- const headingElement = screen.getByRole('heading')
- expect(headingElement).toHaveStyleRule('color', 'red')
- })
-})
diff --git a/src/__test__/Hero.test.tsx b/src/__test__/Hero.test.tsx
deleted file mode 100644
index 560373b9..00000000
--- a/src/__test__/Hero.test.tsx
+++ /dev/null
@@ -1,34 +0,0 @@
-import React from 'react'
-import { screen } from '@testing-library/react'
-import 'jest-styled-components'
-import renderWithWrapper from './index'
-import { Hero, HeroLead } from '..'
-
-describe('Hero and HeroLead', () => {
- test('renders Hero', () => {
- renderWithWrapper({ component: })
-
- const heroElement = screen.getByTestId('test-hero')
- expect(heroElement).toBeInTheDocument()
- })
-
- test('renders HeroLead', () => {
- renderWithWrapper({
- component: Testing,
- })
-
- const heroLeadElement = screen.getByTestId('test-hero-lead')
- expect(heroLeadElement).toBeInTheDocument()
- expect(heroLeadElement).toHaveTextContent(/Testing/i)
- })
-
- test('renders Hero with variant styles', () => {
- renderWithWrapper({ component: })
-
- const heroElement = screen.getByTestId('test-hero')
- expect(heroElement).toHaveStyleRule('width', '100%')
- expect(heroElement).toHaveStyleRule('text-align', 'center')
- expect(heroElement).toHaveStyleRule('color', '#f8f9fa')
- expect(heroElement).toHaveStyleRule('font-size', '28px')
- })
-})
diff --git a/src/__test__/Icons.test.tsx b/src/__test__/Icons.test.tsx
index b9d0667e..58e0399b 100644
--- a/src/__test__/Icons.test.tsx
+++ b/src/__test__/Icons.test.tsx
@@ -1,6 +1,6 @@
-import React from 'react'
import { render, screen } from '@testing-library/react'
-import Flex from '../components/Flex'
+import React from 'react'
+
import {
CategoryCodeALDR,
CategoryCodeANON,
@@ -106,9 +106,10 @@ describe('Icons', () => {
{Object.keys(icons).map((k, i) => {
const Icon = icons[i]
return (
-
+ // biome-ignore lint/suspicious/noArrayIndexKey:
+
-
+
)
})}
,
diff --git a/src/__test__/InputWithIconButton.test.tsx b/src/__test__/InputWithIconButton.test.tsx
deleted file mode 100644
index 385cad6c..00000000
--- a/src/__test__/InputWithIconButton.test.tsx
+++ /dev/null
@@ -1,50 +0,0 @@
-import React from 'react'
-import { fireEvent, screen } from '@testing-library/react'
-import userEvent from '@testing-library/user-event'
-import { FaAndroid } from 'react-icons/fa'
-import renderWithWrapper from './index'
-import { InputWithIconButton } from '..'
-
-describe('InputWithIconButton', () => {
- test('renders InputWithIconButton', () => {
- renderWithWrapper({ component: })
-
- const element = screen.getByRole('textbox')
- expect(element).toBeInTheDocument()
- })
-
- test('renders InputWithIconButton with icon element', () => {
- renderWithWrapper({
- component: (
- } />
- ),
- })
-
- const element = screen.getByTestId('test-icon')
- expect(element).toBeInTheDocument()
- })
-
- test('should be able to type in Input', async () => {
- renderWithWrapper({ component: })
-
- const inputElement: HTMLInputElement = screen.getByRole('textbox')
- await userEvent.type(inputElement, 'testing input')
- expect(inputElement.value).toBe('testing input')
- })
-
- test('onAction is called on click', () => {
- const onAction = jest.fn()
- renderWithWrapper({
- component: (
- }
- />
- ),
- })
-
- const inputWithButton = screen.getByRole('button')
- fireEvent.click(inputWithButton)
- expect(onAction).toHaveBeenCalled()
- })
-})
diff --git a/src/__test__/Link.test.tsx b/src/__test__/Link.test.tsx
deleted file mode 100644
index 1bac41e7..00000000
--- a/src/__test__/Link.test.tsx
+++ /dev/null
@@ -1,43 +0,0 @@
-import React from 'react'
-import { screen } from '@testing-library/react'
-import 'jest-styled-components'
-import renderWithWrapper from './index'
-import { Link } from '..'
-
-describe('Link', () => {
- test('renders Link', () => {
- renderWithWrapper({
- component: ,
- })
-
- const linkElement = screen.getByTestId('link-test')
- expect(linkElement).toBeInTheDocument()
- })
-
- test('renders Link with color and content', () => {
- renderWithWrapper({
- component: (
-
- OONI Explorer
-
- ),
- })
-
- const linkElement = screen.getByTestId('link-test')
- expect(linkElement).toHaveStyleRule('color', 'red')
- expect(linkElement).toHaveTextContent(/OONI Explorer/i)
- })
-
- test('renders Link with href', () => {
- renderWithWrapper({
- component: (
-
- OONI
-
- ),
- })
-
- const linkElement = screen.getByTestId('link-test')
- expect(linkElement).toHaveAttribute('href', 'https://ooni.org')
- })
-})
diff --git a/src/__test__/ShareButton.test.tsx b/src/__test__/ShareButton.test.tsx
deleted file mode 100644
index 127bafb8..00000000
--- a/src/__test__/ShareButton.test.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import React from 'react'
-import { screen } from '@testing-library/react'
-import renderWithWrapper from './index'
-import { TwitterShareButton, FacebookShareButton } from '..'
-
-describe('Share Buttons', () => {
- test('renders Twitter share button', () => {
- renderWithWrapper({
- component: ,
- })
-
- const element = screen.getByTestId('test-twitter-btn')
- expect(element).toBeInTheDocument()
- })
-
- test('renders Facebook share button', () => {
- renderWithWrapper({
- component: ,
- })
-
- const element = screen.getByTestId('test-facebook-btn')
- expect(element).toBeInTheDocument()
- })
-})
diff --git a/src/__test__/Text.test.tsx b/src/__test__/Text.test.tsx
deleted file mode 100644
index e8ad668d..00000000
--- a/src/__test__/Text.test.tsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import React from 'react'
-import { screen } from '@testing-library/react'
-import 'jest-styled-components'
-import renderWithWrapper from './index'
-import { Text } from '..'
-
-describe('Text', () => {
- test('renders Text', () => {
- renderWithWrapper({ component: })
-
- const textElement = screen.getByTestId('test-text')
- expect(textElement).toBeInTheDocument()
- })
-
- test('renders Text with props', () => {
- renderWithWrapper({
- component: (
-
- ),
- })
-
- const textElement = screen.getByTestId('test-text')
- expect(textElement).toHaveStyleRule('font-size', '18px')
- expect(textElement).toHaveStyleRule('font-weight', '500')
- expect(textElement).toHaveStyleRule('text-align', 'center')
- })
-})
diff --git a/src/__test__/index.tsx b/src/__test__/index.tsx
index fd5d3abf..ecf1f6c9 100644
--- a/src/__test__/index.tsx
+++ b/src/__test__/index.tsx
@@ -1,7 +1,5 @@
import { render } from '@testing-library/react'
import React, { ReactElement } from 'react'
-import { ThemeProvider } from 'styled-components'
-import theme from '../theme'
interface IRenderWithWrapper {
component: ReactElement
@@ -13,9 +11,7 @@ interface IWrapper {
}
function renderWithWrapper({ component, options }: IRenderWithWrapper) {
- const Wrapper = ({ children }: IWrapper) => (
- {children}
- )
+ const Wrapper = ({ children }: IWrapper) => <>{children}>
return render(component, { wrapper: Wrapper, ...options })
}
diff --git a/src/components/Box.tsx b/src/components/Box.tsx
deleted file mode 100644
index add38408..00000000
--- a/src/components/Box.tsx
+++ /dev/null
@@ -1,48 +0,0 @@
-// @ts-nocheck
-import css, { get } from '@styled-system/css'
-import shouldForwardProp from '@styled-system/should-forward-prop'
-import { styled } from 'styled-components'
-import {
- color,
- compose,
- flexbox,
- layout,
- space,
- typography,
-} from 'styled-system'
-import { BoxProps } from 'types'
-
-const sx = (props: any) => css(props?.sx)(props?.theme)
-const base = (props: any) => css(props?.__css)(props?.theme)
-const variant = ({ theme, variant, tx = 'variants' }: any) => {
- let styles = {}
- if (Array.isArray(variant)) {
- variant.forEach((v) => {
- styles = {
- ...styles,
- ...css(get(theme, `${tx}.${v}`, get(theme, v)))(theme),
- }
- })
- } else {
- styles = {
- ...styles,
- ...css(get(theme, `${tx}.${variant}`, get(theme, variant)))(theme),
- }
- }
- return styles
-}
-
-const Box = styled('div').withConfig({ shouldForwardProp })(
- {
- boxSizing: 'border-box',
- margin: 0,
- minWidth: 0,
- },
- base,
- variant,
- sx,
- (props) => props.css,
- compose(space, layout, typography, color, flexbox),
-)
-
-export default Box
diff --git a/src/components/Button.tsx b/src/components/Button.tsx
deleted file mode 100644
index 24ea3ef4..00000000
--- a/src/components/Button.tsx
+++ /dev/null
@@ -1,114 +0,0 @@
-import React, { forwardRef } from 'react'
-import { ButtonProps as BP } from 'types'
-import Box from './Box'
-import Flex from './Flex'
-
-type Size = 'small' | 'medium' | 'large' | 'xLarge' | null
-type Color = 'default' | 'dark'
-type BaseVariants = 'primary' | 'hollow' | 'inverted'
-type AdditionalVariants =
- | 'iconButton'
- | 'link'
- | 'facebookShare'
- | 'twitterShare'
-type Variant =
- | BaseVariants
- | AdditionalVariants
- | Size
- | 'disabled'
- | `${BaseVariants}-disabled`
- | Color
- | `${Color}-hollow`
-export interface ButtonProps extends BP {
- disabled?: boolean
- inverted?: boolean
- hollow?: boolean
- loading?: boolean
- spinner?: React.ReactNode
- variant?: Variant
- color?: Color
- size?: Size
- startIcon?: React.ReactNode
- endIcon?: React.ReactNode
- onClick?: React.MouseEventHandler
-}
-
-const Button = forwardRef(
- (
- {
- hollow = false,
- inverted = false,
- disabled = false,
- variant = 'primary',
- size = 'medium',
- color = 'default',
- type = 'button',
- loading = false,
- spinner,
- children,
- startIcon,
- endIcon,
- ...rest
- }: ButtonProps,
- ref,
- ) => {
- let btnSize = size
- let componentVariant = ['base', variant]
-
- componentVariant.push(size)
- if (disabled) componentVariant.push('disabled')
- if (color) componentVariant.push(`${color}${hollow ? '-hollow' : ''}`)
- if (hollow) componentVariant.push('hollow')
- if (inverted) componentVariant.push('inverted')
-
- if (variant === 'link' || variant === 'iconButton') {
- btnSize = null
- componentVariant = [variant]
- }
-
- return (
-
-
- {startIcon && (
-
- {startIcon}
-
- )}
- {children}
- {endIcon && (
-
- {endIcon}
-
- )}
-
- {loading && spinner}
-
- )
- },
-)
-
-export default Button
diff --git a/src/components/Checkbox.tsx b/src/components/Checkbox.tsx
index d05d0f25..6d5d658c 100644
--- a/src/components/Checkbox.tsx
+++ b/src/components/Checkbox.tsx
@@ -1,85 +1,65 @@
import React, { forwardRef } from 'react'
-import { CheckboxProps as CP } from 'types'
-import { getMarginProps, omitMarginProps } from '../utils'
-import Box from './Box'
-import Flex from './Flex'
+import { twMerge } from 'tailwind-merge'
+import ErrorMessage from './ErrorMessage'
-export interface CheckboxProps extends CP {
- error?: string | undefined
- name: string
+type CheckboxProps = Omit<
+ React.InputHTMLAttributes,
+ 'type'
+> & {
+ error?: string
label: string
- reverse?: boolean
}
-const Checkbox = forwardRef(
- (
- {
- className,
- sx,
- name,
- label,
- variant = 'checkbox',
- reverse = false,
- error,
- ...props
- }: CheckboxProps,
- ref,
- ) => (
-
-
- (
+ ({ name, label, error, disabled = false, className, ...props }, ref) => (
+ <>
+
- {label}
-
-
+
+
+
+
+
+
+
+ {error && {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..032acddc 100644
--- a/src/components/ErrorMessage.tsx
+++ b/src/components/ErrorMessage.tsx
@@ -1,15 +1,14 @@
-import React, { ReactNode } from 'react'
-import Text from './Text'
+import React from 'react'
+import { twMerge } from 'tailwind-merge'
-interface ErrorMessageProps {
- children: ReactNode
-}
-
-const ErrorMessage = ({ children }: ErrorMessageProps) => {
+const ErrorMessage = ({
+ children,
+ className,
+}: React.HTMLAttributes) => {
return (
-
+
{children}
-
+
)
}
diff --git a/src/components/FacebookShareButton.tsx b/src/components/FacebookShareButton.tsx
deleted file mode 100644
index c46ca718..00000000
--- a/src/components/FacebookShareButton.tsx
+++ /dev/null
@@ -1,27 +0,0 @@
-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 {
- url?: string
-}
-
-const FacebookShareButton = ({ url = '', ...rest }: FacebookShareButton) => {
- let href = 'https://www.facebook.com/sharer/sharer.php?'
- href += `&u=${encodeURIComponent(url)}`
-
- return (
-
-
-
- )
-}
-
-export default FacebookShareButton
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..ed41b4d2 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'
-export interface IconButtonProps extends ButtonProps {
+export interface IconButtonProps
+ extends React.HtmlHTMLAttributes {
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..2db9ec88 100644
--- a/src/components/Input.tsx
+++ b/src/components/Input.tsx
@@ -1,45 +1,53 @@
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
+type InputProps = Omit, 'type'> & {
+ error?: string
label?: string
}
-const Input = forwardRef(({ error, name, label, ...rest }: InputProps, ref) => {
- return (
-
- {label && (
-
- {label}
-
- )}
-
- {error && {error}}
-
- )
-})
+const Input = forwardRef(
+ ({ error, name, label, className, ...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
deleted file mode 100644
index 30a4295f..00000000
--- a/src/components/Label.tsx
+++ /dev/null
@@ -1,18 +0,0 @@
-import React, { forwardRef } from 'react'
-import { LabelProps } from 'types'
-import Text from './Flex'
-
-const Label = forwardRef((props: LabelProps, ref) => (
-
-))
-
-export default Label
diff --git a/src/components/Link.tsx b/src/components/Link.tsx
deleted file mode 100644
index 72cfb8fe..00000000
--- a/src/components/Link.tsx
+++ /dev/null
@@ -1,9 +0,0 @@
-import React, { forwardRef } from 'react'
-import { LinkProps } from 'types'
-import Box from './Box'
-
-const Link = forwardRef((props: LinkProps, ref) => (
-
-))
-
-export default Link
diff --git a/src/components/LogoOONIRun.tsx b/src/components/LogoOONIRun.tsx
index c923e866..8e63fadb 100644
--- a/src/components/LogoOONIRun.tsx
+++ b/src/components/LogoOONIRun.tsx
@@ -1,9 +1,13 @@
import React from 'react'
import OONIRunLogo from '../../svgs/logos/Run-HorizontalMonochromeInverted.svg'
-import Image from './Image'
const LogoOONIRun = ({ ...props }) => (
-
+ // biome-ignore lint/a11y/useAltText:
+
)
export default LogoOONIRun
diff --git a/src/components/Modal.tsx b/src/components/Modal.tsx
index 404de6e0..001836de 100644
--- a/src/components/Modal.tsx
+++ b/src/components/Modal.tsx
@@ -1,9 +1,6 @@
import React, { ReactNode } from 'react'
import { MdClose } from 'react-icons/md'
-import { BoxProps } from 'types'
-import Box from './Box'
-import IconButton from './IconButton'
-import Flex from './Flex'
+import { twMerge } from 'tailwind-merge'
interface ModalCloseButtonProps {
icon: ReactNode
@@ -11,79 +8,57 @@ interface ModalCloseButtonProps {
}
const ModalCloseButton = ({ icon, onClick }: ModalCloseButtonProps) => (
-
-
-
+
+
+
)
-export interface ModalProps extends BoxProps {
+export interface ModalProps {
show?: boolean
onHideClick?: () => void
+ children: ReactNode
+ className?: string
}
export const Modal = ({
show = false,
onHideClick,
children,
- sx,
+ className,
...rest
}: ModalProps) => {
return (
-
-
+
} />
{children}
-
+
{show && (
-
)}
-
+
)
}
diff --git a/src/components/MultiSelect.tsx b/src/components/MultiSelect.tsx
index f80adfc6..b22e20a2 100644
--- a/src/components/MultiSelect.tsx
+++ b/src/components/MultiSelect.tsx
@@ -1,74 +1,79 @@
-import React, { forwardRef } from 'react'
+import React from 'react'
import Select from 'react-select'
-import { SelectProps } from 'types'
-import theme from '../theme'
-import { getMarginProps, omitMarginProps } from '../utils'
-import Box from './Box'
-import Text from './Text'
+import { twMerge } from 'tailwind-merge'
+import ErrorMessage from './ErrorMessage'
-export interface MultiSelectProps extends SelectProps {
+export interface MultiSelectProps {
label?: string
options: { label: string; value: string | number }[]
+ name: string
+ className?: string
+ error?: string
}
-const MultiSelect = forwardRef(
- ({ label, name, options, ...rest }: MultiSelectProps, ref) => (
-
- {label && (
-
- {label}
-
- )}
-
- ),
+const MultiSelect = ({
+ label,
+ name,
+ options,
+ className,
+ error,
+ ...props
+}: MultiSelectProps) => (
+
+ {label && (
+
+ )}
+
)
export default MultiSelect
diff --git a/src/components/MultiSelectCreatable.tsx b/src/components/MultiSelectCreatable.tsx
index 9a4dd430..58b0d7e4 100644
--- a/src/components/MultiSelectCreatable.tsx
+++ b/src/components/MultiSelectCreatable.tsx
@@ -1,31 +1,23 @@
-import React, {
- FocusEvent,
- forwardRef,
- KeyboardEventHandler,
- useEffect,
-} from 'react'
+import React, { FocusEvent, KeyboardEventHandler, useEffect } from 'react'
import { MultiValue } from 'react-select'
import CreatableSelect from 'react-select/creatable'
-import { SelectProps as SP } from 'types'
-import theme from '../theme'
-import { getMarginProps, omitMarginProps } from '../utils'
-import Box from './Box'
+import { twMerge } from 'tailwind-merge'
import ErrorMessage from './ErrorMessage'
-import Text from './Text'
interface Option {
readonly label: string
readonly value: string
}
-export interface MultiSelectCreatableProps
- extends Omit {
+export interface MultiSelectCreatableProps {
+ name: string
label?: string
placeholder?: string
value: MultiValue