From ad504fa84eb40080862b35e527e1485f5fde3b59 Mon Sep 17 00:00:00 2001 From: akhilmhdh Date: Fri, 20 Jan 2023 23:12:12 +0530 Subject: [PATCH] feat(ui) added select, spinner components --- frontend/.storybook/preview.js | 4 + frontend/package-lock.json | 116 ++++++++++-------- frontend/package.json | 2 +- .../components/v2/Select/Select.stories.tsx | 113 +++++++++++++++++ frontend/src/components/v2/Select/Select.tsx | 96 +++++++++++++++ frontend/src/components/v2/Select/index.tsx | 1 + .../src/components/v2/Spinner/Spinner.tsx | 42 +++++++ frontend/src/components/v2/Spinner/index.tsx | 1 + frontend/src/styles/globals.css | 6 + 9 files changed, 330 insertions(+), 51 deletions(-) create mode 100644 frontend/src/components/v2/Select/Select.stories.tsx create mode 100644 frontend/src/components/v2/Select/Select.tsx create mode 100644 frontend/src/components/v2/Select/index.tsx create mode 100644 frontend/src/components/v2/Spinner/Spinner.tsx create mode 100644 frontend/src/components/v2/Spinner/index.tsx diff --git a/frontend/.storybook/preview.js b/frontend/.storybook/preview.js index 4a19aa4c96..94133eee3d 100644 --- a/frontend/.storybook/preview.js +++ b/frontend/.storybook/preview.js @@ -1,3 +1,4 @@ +import { themes } from '@storybook/theming'; import '../src/styles/globals.css'; export const parameters = { @@ -7,5 +8,8 @@ export const parameters = { color: /(background|color)$/i, date: /Date$/ } + }, + darkMode: { + dark: { ...themes.dark, appContentBg: '#0e1014', appBg: '#0e1014' } } }; diff --git a/frontend/package-lock.json b/frontend/package-lock.json index cff1b80fb0..042c695768 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -28,7 +28,6 @@ "add": "^2.0.6", "axios": "^0.27.2", "axios-auth-refresh": "^3.3.3", - "class-variance-authority": "^0.4.0", "classnames": "^2.3.1", "cookies": "^0.8.0", "cva": "npm:class-variance-authority@^0.4.0", @@ -96,7 +95,7 @@ "prettier": "^2.8.3", "storybook": "^7.0.0-beta.30", "storybook-dark-mode": "^2.0.5", - "tailwindcss": "^3.1.4", + "tailwindcss": "3.2", "typescript": "^4.9.3" } }, @@ -9301,22 +9300,6 @@ "node": ">=0.10.0" } }, - "node_modules/class-variance-authority": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.4.0.tgz", - "integrity": "sha512-74enNN8O9ZNieycac/y8FxqgyzZhZbxmCitAtAeUrLPlxjSd5zA7LfpprmxEcOmQBnaGs5hYhiSGnJ0mqrtBLQ==", - "funding": { - "url": "https://joebell.co.uk" - }, - "peerDependencies": { - "typescript": ">= 4.5.5 < 5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, "node_modules/classnames": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz", @@ -12028,9 +12011,9 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -17203,12 +17186,12 @@ } }, "node_modules/postcss-nested": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-5.0.6.tgz", - "integrity": "sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.0.tgz", + "integrity": "sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==", "dev": true, "dependencies": { - "postcss-selector-parser": "^6.0.6" + "postcss-selector-parser": "^6.0.10" }, "engines": { "node": ">=12.0" @@ -20420,9 +20403,9 @@ "integrity": "sha512-+fflfPxvHFr81hTJpQ3MIwtqgvefHZFUHFiIHpVIRXvG/nX9+gu2P7JNlFu2bfDMJ+uHhi/pUgzaYacMoXv+Ww==" }, "node_modules/tailwindcss": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.1.7.tgz", - "integrity": "sha512-r7mgumZ3k0InfVPpGWcX8X/Ut4xBfv+1O/+C73ar/m01LxGVzWvPxF/w6xIUPEztrCoz7axfx0SMdh8FH8ZvRQ==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.4.tgz", + "integrity": "sha512-AhwtHCKMtR71JgeYDaswmZXhPcW9iuI9Sp2LvZPo9upDZ7231ZJ7eA9RaURbhpXGVlrjX4cFNlB4ieTetEb7hQ==", "dev": true, "dependencies": { "arg": "^5.0.2", @@ -20431,18 +20414,19 @@ "detective": "^5.2.1", "didyoumean": "^1.2.2", "dlv": "^1.1.3", - "fast-glob": "^3.2.11", + "fast-glob": "^3.2.12", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", "lilconfig": "^2.0.6", + "micromatch": "^4.0.5", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", "picocolors": "^1.0.0", - "postcss": "^8.4.14", + "postcss": "^8.4.18", "postcss-import": "^14.1.0", "postcss-js": "^4.0.0", "postcss-load-config": "^3.1.4", - "postcss-nested": "5.0.6", + "postcss-nested": "6.0.0", "postcss-selector-parser": "^6.0.10", "postcss-value-parser": "^4.2.0", "quick-lru": "^5.1.1", @@ -20459,6 +20443,30 @@ "postcss": "^8.0.9" } }, + "node_modules/tailwindcss/node_modules/postcss": { + "version": "8.4.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", + "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], + "dependencies": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -28822,12 +28830,6 @@ } } }, - "class-variance-authority": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.4.0.tgz", - "integrity": "sha512-74enNN8O9ZNieycac/y8FxqgyzZhZbxmCitAtAeUrLPlxjSd5zA7LfpprmxEcOmQBnaGs5hYhiSGnJ0mqrtBLQ==", - "requires": {} - }, "classnames": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz", @@ -30927,9 +30929,9 @@ "dev": true }, "fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", @@ -34637,12 +34639,12 @@ } }, "postcss-nested": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-5.0.6.tgz", - "integrity": "sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.0.tgz", + "integrity": "sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==", "dev": true, "requires": { - "postcss-selector-parser": "^6.0.6" + "postcss-selector-parser": "^6.0.10" } }, "postcss-selector-parser": { @@ -37007,9 +37009,9 @@ "integrity": "sha512-+fflfPxvHFr81hTJpQ3MIwtqgvefHZFUHFiIHpVIRXvG/nX9+gu2P7JNlFu2bfDMJ+uHhi/pUgzaYacMoXv+Ww==" }, "tailwindcss": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.1.7.tgz", - "integrity": "sha512-r7mgumZ3k0InfVPpGWcX8X/Ut4xBfv+1O/+C73ar/m01LxGVzWvPxF/w6xIUPEztrCoz7axfx0SMdh8FH8ZvRQ==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.4.tgz", + "integrity": "sha512-AhwtHCKMtR71JgeYDaswmZXhPcW9iuI9Sp2LvZPo9upDZ7231ZJ7eA9RaURbhpXGVlrjX4cFNlB4ieTetEb7hQ==", "dev": true, "requires": { "arg": "^5.0.2", @@ -37018,22 +37020,36 @@ "detective": "^5.2.1", "didyoumean": "^1.2.2", "dlv": "^1.1.3", - "fast-glob": "^3.2.11", + "fast-glob": "^3.2.12", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", "lilconfig": "^2.0.6", + "micromatch": "^4.0.5", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", "picocolors": "^1.0.0", - "postcss": "^8.4.14", + "postcss": "^8.4.18", "postcss-import": "^14.1.0", "postcss-js": "^4.0.0", "postcss-load-config": "^3.1.4", - "postcss-nested": "5.0.6", + "postcss-nested": "6.0.0", "postcss-selector-parser": "^6.0.10", "postcss-value-parser": "^4.2.0", "quick-lru": "^5.1.1", "resolve": "^1.22.1" + }, + "dependencies": { + "postcss": { + "version": "8.4.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", + "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "dev": true, + "requires": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + } } }, "tapable": { diff --git a/frontend/package.json b/frontend/package.json index 60b8eda85e..43fa01a8bd 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -102,7 +102,7 @@ "prettier": "^2.8.3", "storybook": "^7.0.0-beta.30", "storybook-dark-mode": "^2.0.5", - "tailwindcss": "^3.1.4", + "tailwindcss": "3.2", "typescript": "^4.9.3" } } diff --git a/frontend/src/components/v2/Select/Select.stories.tsx b/frontend/src/components/v2/Select/Select.stories.tsx new file mode 100644 index 0000000000..51f75ae530 --- /dev/null +++ b/frontend/src/components/v2/Select/Select.stories.tsx @@ -0,0 +1,113 @@ +import { useEffect, useState } from 'react'; +import { SelectProps } from '@radix-ui/react-select'; +// eslint-disable-next-line import/no-extraneous-dependencies +import { Meta, StoryObj } from '@storybook/react'; + +import { Select, SelectItem } from './Select'; + +const meta: Meta = { + title: 'Components/Select', + component: Select, + tags: ['v2'], + argTypes: { + placeholder: { + defaultValue: 'Type something...' + } + } +}; + +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => ( +
+ +
+ ) +}; + +const Controlled = (args: SelectProps) => { + const [isOpen, setIsOpen] = useState(false); + const [selected, setSelected] = useState(''); + + return ( +
+ +
+ ); +}; + +export const Control: Story = { + render: (args) => +}; + +export const Disabled: Story = { + render: (args) => ( +
+ +
+ ) +}; + +export const Loading: Story = { + render: (args) => ( +
+ +
+ ) +}; + +const AsyncSelectOptions = () => { + const [isLoading, setIsLoading] = useState(true); + + useEffect(() => { + // eslint-disable-next-line no-new + new Promise((resolve): void => { + setTimeout(() => { + setIsLoading(false); + resolve(); + }, 1000); + }); + }, []); + + return ( +
+ +
+ ); +}; + +export const Async: Story = { + render: (args) => +}; diff --git a/frontend/src/components/v2/Select/Select.tsx b/frontend/src/components/v2/Select/Select.tsx new file mode 100644 index 0000000000..7b45a18481 --- /dev/null +++ b/frontend/src/components/v2/Select/Select.tsx @@ -0,0 +1,96 @@ +import { forwardRef, ReactNode } from 'react'; +import { faCheck, faChevronDown, faChevronUp } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import * as SelectPrimitive from '@radix-ui/react-select'; +import { twMerge } from 'tailwind-merge'; + +import { Spinner } from '../Spinner'; + +type Props = { + children: ReactNode; + placeholder?: string; + className?: string; + isLoading?: boolean; +}; + +type SelectProps = SelectPrimitive.SelectProps & Props; + +export const Select = forwardRef( + ({ children, placeholder, className, isLoading, ...props }, ref): JSX.Element => { + return ( + + + + + + + + + + + + + + {isLoading ? ( +
+ + Loading... +
+ ) : ( + children + )} +
+ + + +
+
+
+ ); + } +); + +Select.displayName = 'Select'; + +type SelectItemProps = Omit & { + isDisabled?: boolean; + isSelected?: boolean; +}; + +export const SelectItem = forwardRef( + ({ children, className, isSelected, isDisabled, ...props }, forwardedRef) => { + return ( + + + + + {children} + + ); + } +); + +SelectItem.displayName = 'SelectItem'; diff --git a/frontend/src/components/v2/Select/index.tsx b/frontend/src/components/v2/Select/index.tsx new file mode 100644 index 0000000000..d42fd8d593 --- /dev/null +++ b/frontend/src/components/v2/Select/index.tsx @@ -0,0 +1 @@ +export {Select} from './Select' \ No newline at end of file diff --git a/frontend/src/components/v2/Spinner/Spinner.tsx b/frontend/src/components/v2/Spinner/Spinner.tsx new file mode 100644 index 0000000000..0fcbf1ce09 --- /dev/null +++ b/frontend/src/components/v2/Spinner/Spinner.tsx @@ -0,0 +1,42 @@ +import { twMerge } from 'tailwind-merge'; + +type SizeOptions = 'xs' | 'sm' | 'md' | 'lg'; + +type Props = { + className?: string; + size?: SizeOptions; +}; + +const sizeChart: Record = { + xs: 'w-4 h-4', + sm: 'w-6 h-6', + md: 'w-8 h-8', + lg: 'w-12 h-12' +}; + +export const Spinner = ({ className, size = 'md' }: Props): JSX.Element => { + return ( +
+ +
+ ); +}; diff --git a/frontend/src/components/v2/Spinner/index.tsx b/frontend/src/components/v2/Spinner/index.tsx new file mode 100644 index 0000000000..1ce6cab2eb --- /dev/null +++ b/frontend/src/components/v2/Spinner/index.tsx @@ -0,0 +1 @@ +export { Spinner } from './Spinner'; diff --git a/frontend/src/styles/globals.css b/frontend/src/styles/globals.css index b5c61c9567..18814e2242 100644 --- a/frontend/src/styles/globals.css +++ b/frontend/src/styles/globals.css @@ -1,3 +1,9 @@ @tailwind base; @tailwind components; @tailwind utilities; + +@layer components { + .select[data-placeholder] { + color: theme("colors.gray.500") + } +}