From 9f4bc05c23d1c7a8b5b96ed6d0676ecb4dde6445 Mon Sep 17 00:00:00 2001 From: SySagar Date: Sat, 11 Jan 2025 21:07:52 +0530 Subject: [PATCH 1/6] chore: component stories directory change --- apps/ui/.eslintrc.cjs | 1 + apps/ui/.storybook/main.ts | 88 +++--- apps/ui/__test__/Button.spec.js | 41 --- apps/ui/__test__/Textfield.spec.js | 92 ------ apps/ui/__test__/Typography.spec.js | 41 --- .../Accordion/Accordion.stories.tsx | 49 +++ .../lib/components/Avatar/Avatar.stories.tsx | 94 ++++++ .../lib/components/Button/Button.stories.tsx | 75 +++++ apps/ui/lib/components/Chip/Chip.stories.tsx | 99 ++++++ .../ui/lib/components/Label/Label.stories.tsx | 31 ++ .../Navigation-menu/Navigation.stories.tsx | 114 +++++++ .../components/Progress/Progress.stories.tsx | 32 ++ .../lib/components/Select/Select.stories.tsx | 78 +++++ .../lib/components/Switch/Switch.stories.tsx | 27 ++ .../Textfield/Textfield.stories.tsx | 175 +++++++++++ .../ui/lib/components/Toast/Toast.stories.tsx | 89 ++++++ .../Typography/Typography.stories.tsx | 295 +++++++++++++++++ apps/ui/stories/Accordion.stories.tsx | 52 --- apps/ui/stories/Avatar.stories.tsx | 95 ------ apps/ui/stories/Button.stories.tsx | 77 ----- apps/ui/stories/Chip.stories.tsx | 100 ------ apps/ui/stories/Label.stories.tsx | 32 -- apps/ui/stories/Navigation.stories.tsx | 118 ------- apps/ui/stories/Progress.stories.tsx | 34 -- apps/ui/stories/Select.stories.tsx | 84 ----- apps/ui/stories/Switch.stories.tsx | 29 -- apps/ui/stories/Textfield.stories.tsx | 177 ----------- apps/ui/stories/Toast.stories.tsx | 91 ------ apps/ui/stories/Typography.stories.tsx | 296 ------------------ 29 files changed, 1203 insertions(+), 1403 deletions(-) delete mode 100644 apps/ui/__test__/Button.spec.js delete mode 100644 apps/ui/__test__/Textfield.spec.js delete mode 100644 apps/ui/__test__/Typography.spec.js create mode 100644 apps/ui/lib/components/Accordion/Accordion.stories.tsx create mode 100644 apps/ui/lib/components/Avatar/Avatar.stories.tsx create mode 100644 apps/ui/lib/components/Button/Button.stories.tsx create mode 100644 apps/ui/lib/components/Chip/Chip.stories.tsx create mode 100644 apps/ui/lib/components/Label/Label.stories.tsx create mode 100644 apps/ui/lib/components/Navigation-menu/Navigation.stories.tsx create mode 100644 apps/ui/lib/components/Progress/Progress.stories.tsx create mode 100644 apps/ui/lib/components/Select/Select.stories.tsx create mode 100644 apps/ui/lib/components/Switch/Switch.stories.tsx create mode 100644 apps/ui/lib/components/Textfield/Textfield.stories.tsx create mode 100644 apps/ui/lib/components/Toast/Toast.stories.tsx create mode 100644 apps/ui/lib/components/Typography/Typography.stories.tsx delete mode 100644 apps/ui/stories/Accordion.stories.tsx delete mode 100644 apps/ui/stories/Avatar.stories.tsx delete mode 100644 apps/ui/stories/Button.stories.tsx delete mode 100644 apps/ui/stories/Chip.stories.tsx delete mode 100644 apps/ui/stories/Label.stories.tsx delete mode 100644 apps/ui/stories/Navigation.stories.tsx delete mode 100644 apps/ui/stories/Progress.stories.tsx delete mode 100644 apps/ui/stories/Select.stories.tsx delete mode 100644 apps/ui/stories/Switch.stories.tsx delete mode 100644 apps/ui/stories/Textfield.stories.tsx delete mode 100644 apps/ui/stories/Toast.stories.tsx delete mode 100644 apps/ui/stories/Typography.stories.tsx diff --git a/apps/ui/.eslintrc.cjs b/apps/ui/.eslintrc.cjs index 6716988..d542efb 100644 --- a/apps/ui/.eslintrc.cjs +++ b/apps/ui/.eslintrc.cjs @@ -14,6 +14,7 @@ module.exports = { 'react/prop-types': 'off', 'react/react-in-jsx-scope': 'off', 'react/no-children-prop': 'off', + '@typescript-eslint/no-explicit-any': 'off', }, parserOptions: { project: true, diff --git a/apps/ui/.storybook/main.ts b/apps/ui/.storybook/main.ts index 2e7bd1d..55a16aa 100644 --- a/apps/ui/.storybook/main.ts +++ b/apps/ui/.storybook/main.ts @@ -4,55 +4,55 @@ import { defineConfig } from 'vite'; const tsconfigPaths = require('vite-tsconfig-paths').default; module.exports = { - stories: ['../stories/**/*.stories.@(ts|tsx|js|jsx)'], + stories: ['../lib/**/*.stories.@(ts|tsx|js|jsx)'], - viteFinal: async (config) => { - return mergeConfig(config, { - plugins: [tsconfigPaths()], - }); - }, - - viteConfig: defineConfig({ - resolve: { - alias: { - '@': '/src', - '@utils': '/utils', - }, + viteFinal: async (config) => { + return mergeConfig(config, { + plugins: [tsconfigPaths()], + }); }, - }), - addons: [ - '@storybook/addon-links', - '@storybook/addon-essentials', - '@storybook/addon-controls', - '@storybook/addon-themes', - 'storybook-css-modules', - { - name: '@storybook/addon-postcss', - options: { - postcssLoaderOptions: { - implementation: require('postcss'), + viteConfig: defineConfig({ + resolve: { + alias: { + '@': '/src', + '@utils': '/utils', + }, }, - }, - }, - ], + }), - // https://storybook.js.org/docs/react/configure/typescript#mainjs-configuration - typescript: { - check: true, // type-check stories during Storybook build - }, + addons: [ + '@storybook/addon-links', + '@storybook/addon-essentials', + '@storybook/addon-controls', + '@storybook/addon-themes', + 'storybook-css-modules', + { + name: '@storybook/addon-postcss', + options: { + postcssLoaderOptions: { + implementation: require('postcss'), + }, + }, + }, + ], - framework: { - name: '@storybook/react-vite', - // options: { - // legacyRootApi: true, - // builder: { - // viteConfigPath: './vite.config.ts', - // }, - // }, - }, + // https://storybook.js.org/docs/react/configure/typescript#mainjs-configuration + typescript: { + check: true, // type-check stories during Storybook build + }, - docs: { - autodocs: true, - }, + framework: { + name: '@storybook/react-vite', + // options: { + // legacyRootApi: true, + // builder: { + // viteConfigPath: './vite.config.ts', + // }, + // }, + }, + + docs: { + autodocs: true, + }, }; diff --git a/apps/ui/__test__/Button.spec.js b/apps/ui/__test__/Button.spec.js deleted file mode 100644 index 0d15fcd..0000000 --- a/apps/ui/__test__/Button.spec.js +++ /dev/null @@ -1,41 +0,0 @@ -import React from 'react'; -import { render, screen } from '@testing-library/react'; -import { Button } from '../lib/components/Button/index'; -import { Variants, Sizes } from '../stories/Button.stories'; -import '@testing-library/jest-dom'; - -const argsColor = { - variant: 'default', - size: 'md', -}; - -const args = { - variant: 'default', - size: 'md', -}; - -describe('Button Component', () => { - test('renders without crashing', () => { - render( + +
+ +
+
+ +
+
+ +
+
+ +
+ +); + +export const tailwindButton = () => { + return ; +}; + +export const tailwindButtonWithOverridingVariant = () => { + return ( + + ); +}; + +export const Sizes = () => ( +
+
+ +
+
+ +
+
+ +
+
+); + +Sizes.args = { + variant: 'filled', + color: 'primary', +}; diff --git a/apps/ui/lib/components/Chip/Chip.stories.tsx b/apps/ui/lib/components/Chip/Chip.stories.tsx new file mode 100644 index 0000000..8763e7b --- /dev/null +++ b/apps/ui/lib/components/Chip/Chip.stories.tsx @@ -0,0 +1,99 @@ +import { Story } from '@storybook/react'; +import { withGlobalStyles } from '../../../.storybook/decorator'; + +import { Chip, ChipProps } from '../..'; +import { Avatar, AvatarImage, AvatarFallback } from '../..'; +import { Star, Mail } from 'lucide-react'; + +const ChipExample = (props: ChipProps) => ( +
+ Default +
+); + +const ChipVariants = () => ( +
+ Filled + Outlined +
+); + +const ChipSizes = () => ( +
+ Small + Medium + Large +
+); + +const ChipInteractions = () => ( +
+ alert('Clicked!')}> + Clickable + + alert('Delete clicked!')}>Deletable + + Link + +
+); + +const ChipWithIcons = () => ( +
+ + + AB + + } + > + User Chip + + } + > + Starred + + } + afterChildren={ + + 99+ + + } + > + Inbox + +
+); + +export default { + title: 'components/Chip', + component: ChipExample, + decorators: [withGlobalStyles], +}; + +export const Default: Story = (args) => ; +Default.args = { + children: 'Default Chip', + variant: 'filled', + size: 'md', +}; + +export const Variants = () => ; +export const Sizes = () => ; +export const Interactions = () => ; +export const WithIcons = () => ; + +export const CustomStyles = () => ( +
+ + Custom Styled Chip + +
+); diff --git a/apps/ui/lib/components/Label/Label.stories.tsx b/apps/ui/lib/components/Label/Label.stories.tsx new file mode 100644 index 0000000..f12764c --- /dev/null +++ b/apps/ui/lib/components/Label/Label.stories.tsx @@ -0,0 +1,31 @@ +import { StoryObj } from '@storybook/react'; +import { Label } from '../..'; +import { withGlobalStyles } from '../../../.storybook/decorator'; + +type LabelComponentStory = StoryObj; + +export default { + title: 'Components/Label', + component: Label, + tags: ['autodocs'], + decorators: [withGlobalStyles], + argTypes: { + htmlFor: { control: 'text' }, + children: { control: 'text' }, + }, +}; + +export const BasicLabelComponent: LabelComponentStory = { + args: { + htmlFor: 'firstName', + children: 'First Name:', + }, +}; + +export const LabelWithTailwind = () => { + return ( + + ); +}; diff --git a/apps/ui/lib/components/Navigation-menu/Navigation.stories.tsx b/apps/ui/lib/components/Navigation-menu/Navigation.stories.tsx new file mode 100644 index 0000000..0a6b726 --- /dev/null +++ b/apps/ui/lib/components/Navigation-menu/Navigation.stories.tsx @@ -0,0 +1,114 @@ +import { + NavigationMenu, + NavigationMenuList, + NavigationMenuItem, + NavigationMenuTrigger, + NavigationMenuContent, + NavigationMenuLink, + ListItem, +} from '../..'; + +const components: { title: string; href: string; description: string }[] = [ + { + title: 'Alert Dialog', + href: '/docs/primitives/alert-dialog', + description: + 'A modal dialog that interrupts the user with important content and expects a response.', + }, + { + title: 'Hover Card', + href: '/docs/primitives/hover-card', + description: + 'For sighted users to preview content available behind a link.', + }, + { + title: 'Progress', + href: '/docs/primitives/progress', + description: + 'Displays an indicator showing the completion progress of a task, typically displayed as a progress bar.', + }, + { + title: 'Scroll-area', + href: '/docs/primitives/scroll-area', + description: 'Visually or semantically separates content.', + }, + { + title: 'Tabs', + href: '/docs/primitives/tabs', + description: + 'A set of layered sections of content—known as tab panels—that are displayed one at a time.', + }, + { + title: 'Tooltip', + href: '/docs/primitives/tooltip', + description: + 'A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it.', + }, +]; + +const Test = () => ( + + + + Getting started + + + + + + Components + +
    + {components.map((component) => ( + + {component.description} + + ))} +
+
+
+ + + Documentation + + +
+
+); + +export default { + title: 'components/Navigation', + component: Test, +}; + +export const Default = () => { + return ; +}; diff --git a/apps/ui/lib/components/Progress/Progress.stories.tsx b/apps/ui/lib/components/Progress/Progress.stories.tsx new file mode 100644 index 0000000..e55f6c6 --- /dev/null +++ b/apps/ui/lib/components/Progress/Progress.stories.tsx @@ -0,0 +1,32 @@ +import { withGlobalStyles } from '../../../.storybook/decorator'; +import { Progress, Text } from '../..'; + +const DefaultTemplate = ({ value = 40 }) => { + return ( +
+ + {value}% complete + + +
+ ); +}; + +export default { + title: 'components/Progress', + component: DefaultTemplate, + decorators: [withGlobalStyles], +}; + +export const Default = () => { + return ; +}; diff --git a/apps/ui/lib/components/Select/Select.stories.tsx b/apps/ui/lib/components/Select/Select.stories.tsx new file mode 100644 index 0000000..2bbea3d --- /dev/null +++ b/apps/ui/lib/components/Select/Select.stories.tsx @@ -0,0 +1,78 @@ +// SelectDemo.stories.js +import { + ChevronDownIcon, + ChevronUpIcon, +} from '@radix-ui/react-icons'; +import { + Select, + SelectContent, + SelectGroup, + SelectItem, + SelectLabel, + SelectScrollDownButton, + SelectScrollUpButton, + SelectTrigger, + SelectValue, +} from '../..'; // Import your custom Select component +import { SelectIcon } from '@radix-ui/react-select'; + +// type SelectComponentStory = StoryObj; + +const options = [ + { value: 'broccoli', label: 'Broccoli' }, + { value: 'carrot', label: 'Carrot' }, + { value: 'lettuce', label: 'Lettuce' }, + { value: 'corn', label: 'Corn' }, + { value: 'cucumber', label: 'Cucumber' }, + { value: 'spinach', label: 'Spinach' }, + { value: 'peas', label: 'Peas' }, + { value: 'cabbage', label: 'Cabbage' }, +]; + +const BasicSelect = () => ( +
+ +
+); + +export default { + title: 'Components/Select', + component: BasicSelect, +}; + +export const Default = () => ; diff --git a/apps/ui/lib/components/Switch/Switch.stories.tsx b/apps/ui/lib/components/Switch/Switch.stories.tsx new file mode 100644 index 0000000..810439b --- /dev/null +++ b/apps/ui/lib/components/Switch/Switch.stories.tsx @@ -0,0 +1,27 @@ +import { withGlobalStyles } from '../../../.storybook/decorator'; +import { Label, Switch } from '../..'; + +const DefaultTemplate = () => { + return ( +
+ + +
+ ); +}; + +export default { + title: 'components/Switch', + component: DefaultTemplate, + decorators: [withGlobalStyles], +}; + +export const Default = () => { + return ; +}; diff --git a/apps/ui/lib/components/Textfield/Textfield.stories.tsx b/apps/ui/lib/components/Textfield/Textfield.stories.tsx new file mode 100644 index 0000000..595eae6 --- /dev/null +++ b/apps/ui/lib/components/Textfield/Textfield.stories.tsx @@ -0,0 +1,175 @@ +import { TextField } from '../..'; + +export default { + title: 'Components/TextField', + component: TextField, + argTypes: { + variant: { + options: ['filled', 'outlined', 'standard'], + control: { type: 'radio' }, + }, + size: { + options: ['sm', 'md', 'lg'], + control: { type: 'radio' }, + }, + type: { + options: ['password', 'number', 'email', 'text'], + control: { type: 'radio' }, + }, + color: { + options: ['primary', 'secondary'], + control: { type: 'radio' }, + }, + placeholder: { + control: { type: 'text' }, + }, + disabled: { + control: { type: 'boolean' }, + }, + required: { + control: { type: 'boolean' }, + }, + readOnly: { + control: { type: 'boolean' }, + }, + fullWidth: { + control: { type: 'boolean' }, + }, + multiline: { + control: { type: 'boolean' }, + }, + rows: { + control: { type: 'number' }, + }, + rowsMax: { + control: { type: 'number' }, + }, + startIcon: { + control: { type: 'text' }, + }, + endIcon: { + control: { type: 'text' }, + }, + onChange: { + control: { type: 'text' }, + }, + onClick: { + control: { type: 'text' }, + }, + onFocus: { + control: { type: 'text' }, + }, + onBlur: { + control: { type: 'text' }, + }, + onKeyPress: { + control: { type: 'text' }, + }, + onKeyUp: { + control: { type: 'text' }, + }, + onKeyDown: { + control: { type: 'text' }, + }, + }, +}; + +export const Default = (args: any) => ; + +Default.args = { + label: 'Label', + placeholder: 'Placeholder', + startIcon: '👋', + endIcon: '👋', +}; + +export const Colors = (args: any) => ( +
+
+ +
+
+ +
+
+); + +Colors.args = { + variant: 'filled', +}; + +export const Variants = (args: any) => ( +
+
+ +
+
+ +
+
+); + +Variants.args = { + color: 'primary', +}; + +export const Sizes = (args: any) => ( +
+
+ +
+
+ +
+
+ +
+
+); + +Sizes.args = { + color: 'primary', +}; + +export const Multiline = (args: any) => ( +
+
+ +
+
+ +
+
+); diff --git a/apps/ui/lib/components/Toast/Toast.stories.tsx b/apps/ui/lib/components/Toast/Toast.stories.tsx new file mode 100644 index 0000000..7c51597 --- /dev/null +++ b/apps/ui/lib/components/Toast/Toast.stories.tsx @@ -0,0 +1,89 @@ +import { withGlobalStyles } from '../../../.storybook/decorator'; +import { useToast, Button, Toaster, ToastAction } from '../..'; + +export const Default = () => { + const { toast } = useToast(); + return ( +
+ + +
+ ); +}; + +export default { + title: 'components/Toast', + component: Default, + decorators: [withGlobalStyles], +}; + +export const Destructive = () => { + const { toast } = useToast(); + return ( +
+ + +
+ ); +}; + +export const DestructiveWithActionButton = () => { + const { toast } = useToast(); + return ( +
+ + +
+ ); +}; diff --git a/apps/ui/lib/components/Typography/Typography.stories.tsx b/apps/ui/lib/components/Typography/Typography.stories.tsx new file mode 100644 index 0000000..2a6688a --- /dev/null +++ b/apps/ui/lib/components/Typography/Typography.stories.tsx @@ -0,0 +1,295 @@ +import { Text } from '../..'; + +export default { + title: 'Components/Text', + component: Text, + parameters: { + layout: 'centered', + }, + tags: ['autodocs'], + argTypes: { + variant: { + control: { + type: 'select', + options: [ + 'body-1', + 'body-2', + 'body-3', + 'button-1', + 'button-2', + 'button-3', + 'heading-1', + 'heading-2', + 'heading-3', + 'heading-4', + 'heading-5', + 'heading-6', + 'label-1', + 'label-2', + 'label-2-strong', + 'label-3', + 'subtitle-1', + 'subtitle-2', + 'subtitle-3', + ], + }, + defaultValue: 'body-1', + description: 'The variant of the Text component.', + }, + alignment: { + control: { + type: 'select', + options: ['left', 'right', 'center', 'justify'], + }, + defaultValue: 'left', + description: 'The text alignment of the Text component.', + }, + color: { + control: 'color', + defaultValue: '#2A2C35', + description: 'The color of the text in the Text component.', + }, + asChild: { + control: 'text', + description: + 'The type of child element to render within the Text component.', + }, + children: { + control: 'text', + description: 'The text content of the Text component.', + }, + }, +}; + +// Create a template for your Text component +const Template = (args: any) => ; + +export const Default = Template.bind({}); +Default.args = { + variant: 'heading-1', + alignment: 'left', + color: '#2A2C35', + children: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', +}; + +// Combined Story +export const AllVariants = () => { + return ( + <> + {/* Body-1 */} +
+ + body-1 + +
+ + {/* Body-2 */} +
+ + body-2 + +
+ + {/* Body-3 */} +
+ + body-3 + +
+ + {/* Button-1 */} +
+ + Button-1 + +
+ + {/* Button-2 */} +
+ + Button-2 + +
+ + {/* Heading-1 */} +
+ + Heading-1 + +
+ + {/* Heading-2 */} +
+ + Heading-2 + +
+ + {/* Heading-3 */} +
+ + Heading-3 + +
+ + {/* Heading-4 */} +
+ + Heading-4 + +
+ + {/* Heading-5 */} +
+ + Heading-5 + +
+ + {/* Heading-6 */} +
+ + Heading-6 + +
+ + {/* Label-1 */} +
+ + label-1 + +
+ + {/* Label-2 */} +
+ + label-2 + +
+ + {/* Subtitle-1 */} +
+ + subtitle-1 + +
+ + {/* Subtitle-2*/} +
+ + subtitle-2 + +
+ + {/* Subtitle-3 */} +
+ + subtitle-3 + +
+ + ); +}; + +export const ColorStory = Template.bind({}); +ColorStory.args = { + variant: 'body-1', + alignment: 'center', + color: '#2a52be', + children: + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.', +}; + +export const withTailwind = () => { + return ( +
+ + With extensible tailwind classes + +
+ ); +}; + +export const withTailwindAndVariant = () => { + return ( +
+ + with tailwind classes and variant + +
+ ); +}; + +export const withTailwindAndVariant2 = () => { + return ( +
+ + with tailwind classes and variant + +
+ ); +}; + +// Alignment Center +export const AlignmentCenterStory = Template.bind({}); +AlignmentCenterStory.args = { + variant: 'body-1', + alignment: 'center', + color: '#2A2C35', + children: + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.', +}; + +// Alignment Left +export const AlignmentLeftStory = Template.bind({}); +AlignmentLeftStory.args = { + variant: 'body-1', + alignment: 'left', + color: '#2A2C35', + children: + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi.', +}; + +// Alignment Right +export const AlignmentRightStory = Template.bind({}); +AlignmentRightStory.args = { + variant: 'body-1', + alignment: 'right', + color: '#2A2C35', + children: + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi.', +}; + +// Alignment Justify +export const AlignmentJustifyStory = Template.bind({}); +AlignmentJustifyStory.args = { + variant: 'body-1', + alignment: 'justify', + color: '#2A2C35', + children: + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi.', +}; + +// story for maxLines +export const Body2MaxLinesEllipsis = Template.bind({}); +Body2MaxLinesEllipsis.args = { + variant: 'body-2', + alignment: 'left', + color: '#2A2C35', + width: 400, + children: + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi.', + maxLines: 2, // Limit the maximum lines +}; + +export const asChild = Template.bind({}); +asChild.args = { + variant: 'body-1', + asChild: true, + alignment: 'center', + color: '#2A2C35', + children:

This is heading 1

, +}; diff --git a/apps/ui/stories/Accordion.stories.tsx b/apps/ui/stories/Accordion.stories.tsx deleted file mode 100644 index a667ddd..0000000 --- a/apps/ui/stories/Accordion.stories.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import React from 'react'; -import { Meta, Story } from '@storybook/react'; -import { withGlobalStyles } from '../.storybook/decorator'; - -import { - Accordion, - AccordionContent, - AccordionItem, - AccordionTrigger, -} from '../lib'; -import exp from 'constants'; - -const Test = () => ( -
- - - Accordion 1 - Content 1 - - - Accordion 2 - Content 2 - - - Accordion 3 - Content 3 - - -
-); - -const withTailwind = ()=>{ - return ( -
- - - Accordion 1 - Content 1 - - -
- ); -} - -export default { - title: 'components/Accordion', - component: Test, - decorators: [withGlobalStyles], -} as Meta; - -export const Default = () => ; -export const WithTailwind = () => withTailwind(); diff --git a/apps/ui/stories/Avatar.stories.tsx b/apps/ui/stories/Avatar.stories.tsx deleted file mode 100644 index aab125b..0000000 --- a/apps/ui/stories/Avatar.stories.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import React from 'react'; -import { Meta, Story } from '@storybook/react'; -import { Avatar, AvatarImage, AvatarContent, AvatarFallback } from '../lib'; -import { Search, File } from 'lucide-react'; - -export default { - title: 'Components/Avatar', - component: Avatar, - subcomponents: { AvatarImage, AvatarContent, AvatarFallback }, - argTypes: { - className: { control: 'text' }, - }, -} as Meta; - -const Template: Story = (args) => ( - - - AB - -); - -export const Default = Template.bind({}); -Default.args = { - className: '', -}; - -export const WithContentImage: Story = (args) => ( - - - Avatar Content Image - - -); - -export const WithContentIcon: Story = (args) => ( -
- - - - - - - - - - -
-); - -export const WithFallback: Story = (args) => ( - - AB - -); - -export const allSizes: Story = (args) => ( -
- - - Avatar Content Image - - - - - - Avatar Content Image - - - - - - Avatar Content Image - - -
-); diff --git a/apps/ui/stories/Button.stories.tsx b/apps/ui/stories/Button.stories.tsx deleted file mode 100644 index 9c42ea5..0000000 --- a/apps/ui/stories/Button.stories.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import React from 'react'; -import { Meta } from '@storybook/react'; -import { Button } from '../lib'; -import { withGlobalStyles } from '../.storybook/decorator'; - -export default { - title: 'Components/Button', - component: Button, - decorators: [withGlobalStyles], -} as Meta; - -export const Variants = () => ( -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-); - -export const tailwindButton = () => { - return ; -}; - -export const tailwindButtonWithOverridingVariant = () => { - return ( - - ); -}; - -export const Sizes = () => ( -
-
- -
-
- -
-
- -
-
-); - -Sizes.args = { - variant: 'filled', - color: 'primary', -}; diff --git a/apps/ui/stories/Chip.stories.tsx b/apps/ui/stories/Chip.stories.tsx deleted file mode 100644 index 0148df7..0000000 --- a/apps/ui/stories/Chip.stories.tsx +++ /dev/null @@ -1,100 +0,0 @@ -import React from 'react'; -import { Meta, Story } from '@storybook/react'; -import { withGlobalStyles } from '../.storybook/decorator'; - -import { Chip, ChipProps } from '../lib'; -import { Avatar, AvatarImage, AvatarFallback } from '../lib'; -import { Star, Mail } from 'lucide-react'; - -const ChipExample = (props: ChipProps) => ( -
- Default -
-); - -const ChipVariants = () => ( -
- Filled - Outlined -
-); - -const ChipSizes = () => ( -
- Small - Medium - Large -
-); - -const ChipInteractions = () => ( -
- alert('Clicked!')}> - Clickable - - alert('Delete clicked!')}>Deletable - - Link - -
-); - -const ChipWithIcons = () => ( -
- - - AB - - } - > - User Chip - - } - > - Starred - - } - afterChildren={ - - 99+ - - } - > - Inbox - -
-); - -export default { - title: 'components/Chip', - component: ChipExample, - decorators: [withGlobalStyles], -} as Meta; - -export const Default: Story = (args) => ; -Default.args = { - children: 'Default Chip', - variant: 'filled', - size: 'md', -}; - -export const Variants = () => ; -export const Sizes = () => ; -export const Interactions = () => ; -export const WithIcons = () => ; - -export const CustomStyles = () => ( -
- - Custom Styled Chip - -
-); diff --git a/apps/ui/stories/Label.stories.tsx b/apps/ui/stories/Label.stories.tsx deleted file mode 100644 index 10e27e6..0000000 --- a/apps/ui/stories/Label.stories.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import React from 'react'; -import { Meta, StoryObj } from '@storybook/react'; -import { Label } from '../lib'; -import { withGlobalStyles } from '../.storybook/decorator'; - -type LabelComponentStory = StoryObj; - -export default { - title: 'Components/Label', - component: Label, - tags: ['autodocs'], - decorators: [withGlobalStyles], - argTypes: { - htmlFor: { control: 'text' }, - children: { control: 'text' }, - }, -} as Meta; - -export const BasicLabelComponent: LabelComponentStory = { - args: { - htmlFor: 'firstName', - children: 'First Name:', - }, -}; - -export const LabelWithTailwind = () => { - return ( - - ); -}; diff --git a/apps/ui/stories/Navigation.stories.tsx b/apps/ui/stories/Navigation.stories.tsx deleted file mode 100644 index df0a9a6..0000000 --- a/apps/ui/stories/Navigation.stories.tsx +++ /dev/null @@ -1,118 +0,0 @@ -import React from 'react'; -import { Meta, Story } from '@storybook/react'; - -import { - NavigationMenu, - NavigationMenuList, - NavigationMenuItem, - NavigationMenuTrigger, - NavigationMenuContent, - NavigationMenuIndicator, - NavigationMenuLink, - ListItem, -} from '../lib'; - -const components: { title: string; href: string; description: string }[] = [ - { - title: 'Alert Dialog', - href: '/docs/primitives/alert-dialog', - description: - 'A modal dialog that interrupts the user with important content and expects a response.', - }, - { - title: 'Hover Card', - href: '/docs/primitives/hover-card', - description: - 'For sighted users to preview content available behind a link.', - }, - { - title: 'Progress', - href: '/docs/primitives/progress', - description: - 'Displays an indicator showing the completion progress of a task, typically displayed as a progress bar.', - }, - { - title: 'Scroll-area', - href: '/docs/primitives/scroll-area', - description: 'Visually or semantically separates content.', - }, - { - title: 'Tabs', - href: '/docs/primitives/tabs', - description: - 'A set of layered sections of content—known as tab panels—that are displayed one at a time.', - }, - { - title: 'Tooltip', - href: '/docs/primitives/tooltip', - description: - 'A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it.', - }, -]; - -const Test = () => ( - - - - Getting started - - - - - - Components - -
    - {components.map((component) => ( - - {component.description} - - ))} -
-
-
- - - Documentation - - -
-
-); - -export default { - title: 'components/Navigation', - component: Test, -} as Meta; - -export const Default = () => { - return ; -}; diff --git a/apps/ui/stories/Progress.stories.tsx b/apps/ui/stories/Progress.stories.tsx deleted file mode 100644 index 6313e01..0000000 --- a/apps/ui/stories/Progress.stories.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import React from 'react'; -import { Meta, Story } from '@storybook/react'; -import { withGlobalStyles } from '../.storybook/decorator'; -import { Progress, Text } from '../lib'; - -const DefaultTemplate = ({ value = 40 }) => { - return ( -
- - {value}% complete - - -
- ); -}; - -export default { - title: 'components/Progress', - component: DefaultTemplate, - decorators: [withGlobalStyles], -} as Meta; - -export const Default = () => { - return ; -}; diff --git a/apps/ui/stories/Select.stories.tsx b/apps/ui/stories/Select.stories.tsx deleted file mode 100644 index 8315d5f..0000000 --- a/apps/ui/stories/Select.stories.tsx +++ /dev/null @@ -1,84 +0,0 @@ -// SelectDemo.stories.js - -import React from 'react'; -import { - CheckIcon, - ChevronDownIcon, - ChevronUpIcon, -} from '@radix-ui/react-icons'; -import { Check } from 'lucide-react'; -import { Meta, StoryObj } from '@storybook/react'; -import { - Select, - SelectContent, - SelectGroup, - SelectItem, - SelectLabel, - SelectScrollDownButton, - SelectScrollUpButton, - SelectSeparator, - SelectTrigger, - SelectValue, -} from '../lib'; // Import your custom Select component -import { SelectIcon } from '@radix-ui/react-select'; - -// type SelectComponentStory = StoryObj; - -const options = [ - { value: 'broccoli', label: 'Broccoli' }, - { value: 'carrot', label: 'Carrot' }, - { value: 'lettuce', label: 'Lettuce' }, - { value: 'corn', label: 'Corn' }, - { value: 'cucumber', label: 'Cucumber' }, - { value: 'spinach', label: 'Spinach' }, - { value: 'peas', label: 'Peas' }, - { value: 'cabbage', label: 'Cabbage' }, -]; - -const Test = () => ( -
- -
-); - -export default { - title: 'Components/Select', - component: Test, -} as Meta; - -export const Default = () => ; diff --git a/apps/ui/stories/Switch.stories.tsx b/apps/ui/stories/Switch.stories.tsx deleted file mode 100644 index ba89aad..0000000 --- a/apps/ui/stories/Switch.stories.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from 'react'; -import { Meta, Story } from '@storybook/react'; -import { withGlobalStyles } from '../.storybook/decorator'; -import { Label, Switch } from '../lib'; - -const DefaultTemplate = () => { - return ( -
- - -
- ); -}; - -export default { - title: 'components/Switch', - component: DefaultTemplate, - decorators: [withGlobalStyles], -} as Meta; - -export const Default = () => { - return ; -}; diff --git a/apps/ui/stories/Textfield.stories.tsx b/apps/ui/stories/Textfield.stories.tsx deleted file mode 100644 index e932747..0000000 --- a/apps/ui/stories/Textfield.stories.tsx +++ /dev/null @@ -1,177 +0,0 @@ -import React from 'react'; -import { Meta } from '@storybook/react'; -import { TextField } from '../lib'; - -export default { - title: 'Components/TextField', - component: TextField, - argTypes: { - variant: { - options: ['filled', 'outlined', 'standard'], - control: { type: 'radio' }, - }, - size: { - options: ['sm', 'md', 'lg'], - control: { type: 'radio' }, - }, - type: { - options: ['password', 'number', 'email', 'text'], - control: { type: 'radio' }, - }, - color: { - options: ['primary', 'secondary'], - control: { type: 'radio' }, - }, - placeholder: { - control: { type: 'text' }, - }, - disabled: { - control: { type: 'boolean' }, - }, - required: { - control: { type: 'boolean' }, - }, - readOnly: { - control: { type: 'boolean' }, - }, - fullWidth: { - control: { type: 'boolean' }, - }, - multiline: { - control: { type: 'boolean' }, - }, - rows: { - control: { type: 'number' }, - }, - rowsMax: { - control: { type: 'number' }, - }, - startIcon: { - control: { type: 'text' }, - }, - endIcon: { - control: { type: 'text' }, - }, - onChange: { - control: { type: 'text' }, - }, - onClick: { - control: { type: 'text' }, - }, - onFocus: { - control: { type: 'text' }, - }, - onBlur: { - control: { type: 'text' }, - }, - onKeyPress: { - control: { type: 'text' }, - }, - onKeyUp: { - control: { type: 'text' }, - }, - onKeyDown: { - control: { type: 'text' }, - }, - }, -} as Meta; - -export const Default = (args: any) => ; - -Default.args = { - label: 'Label', - placeholder: 'Placeholder', - startIcon: '👋', - endIcon: '👋', -}; - -export const Colors = (args: any) => ( -
-
- -
-
- -
-
-); - -Colors.args = { - variant: 'filled', -}; - -export const Variants = (args: any) => ( -
-
- -
-
- -
-
-); - -Variants.args = { - color: 'primary', -}; - -export const Sizes = (args: any) => ( -
-
- -
-
- -
-
- -
-
-); - -Sizes.args = { - color: 'primary', -}; - -export const Multiline = (args: any) => ( -
-
- -
-
- -
-
-); diff --git a/apps/ui/stories/Toast.stories.tsx b/apps/ui/stories/Toast.stories.tsx deleted file mode 100644 index 4902fa5..0000000 --- a/apps/ui/stories/Toast.stories.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import React from 'react'; -import { Meta, Story } from '@storybook/react'; -import { withGlobalStyles } from '../.storybook/decorator'; -import { useToast, Button, Toaster, ToastAction } from '../lib'; - -export const Default = () => { - const { toast } = useToast(); - return ( -
- - -
- ); -}; - -export default { - title: 'components/Toast', - component: Default, - decorators: [withGlobalStyles], -} as Meta; - -export const Destructive = () => { - const { toast } = useToast(); - return ( -
- - -
- ); -}; - -export const DestructiveWithActionButton = () => { - const { toast } = useToast(); - return ( -
- - -
- ); -}; diff --git a/apps/ui/stories/Typography.stories.tsx b/apps/ui/stories/Typography.stories.tsx deleted file mode 100644 index 551e1e9..0000000 --- a/apps/ui/stories/Typography.stories.tsx +++ /dev/null @@ -1,296 +0,0 @@ -import React from 'react'; -import { Text, TextProps } from '../lib'; - -export default { - title: 'Components/Text', - component: Text, - parameters: { - layout: 'centered', - }, - tags: ['autodocs'], - argTypes: { - variant: { - control: { - type: 'select', - options: [ - 'body-1', - 'body-2', - 'body-3', - 'button-1', - 'button-2', - 'button-3', - 'heading-1', - 'heading-2', - 'heading-3', - 'heading-4', - 'heading-5', - 'heading-6', - 'label-1', - 'label-2', - 'label-2-strong', - 'label-3', - 'subtitle-1', - 'subtitle-2', - 'subtitle-3', - ], - }, - defaultValue: 'body-1', - description: 'The variant of the Text component.', - }, - alignment: { - control: { - type: 'select', - options: ['left', 'right', 'center', 'justify'], - }, - defaultValue: 'left', - description: 'The text alignment of the Text component.', - }, - color: { - control: 'color', - defaultValue: '#2A2C35', - description: 'The color of the text in the Text component.', - }, - asChild: { - control: 'text', - description: - 'The type of child element to render within the Text component.', - }, - children: { - control: 'text', - description: 'The text content of the Text component.', - }, - }, -}; - -// Create a template for your Text component -const Template = (args) => ; - -export const Default = Template.bind({}); -Default.args = { - variant: 'heading-1', - alignment: 'left', - color: '#2A2C35', - children: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', -}; - -// Combined Story -export const AllVariants = () => { - return ( - <> - {/* Body-1 */} -
- - body-1 - -
- - {/* Body-2 */} -
- - body-2 - -
- - {/* Body-3 */} -
- - body-3 - -
- - {/* Button-1 */} -
- - Button-1 - -
- - {/* Button-2 */} -
- - Button-2 - -
- - {/* Heading-1 */} -
- - Heading-1 - -
- - {/* Heading-2 */} -
- - Heading-2 - -
- - {/* Heading-3 */} -
- - Heading-3 - -
- - {/* Heading-4 */} -
- - Heading-4 - -
- - {/* Heading-5 */} -
- - Heading-5 - -
- - {/* Heading-6 */} -
- - Heading-6 - -
- - {/* Label-1 */} -
- - label-1 - -
- - {/* Label-2 */} -
- - label-2 - -
- - {/* Subtitle-1 */} -
- - subtitle-1 - -
- - {/* Subtitle-2*/} -
- - subtitle-2 - -
- - {/* Subtitle-3 */} -
- - subtitle-3 - -
- - ); -}; - -export const ColorStory = Template.bind({}); -ColorStory.args = { - variant: 'body-1', - alignment: 'center', - color: '#2a52be', - children: - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.', -}; - -export const withTailwind = () => { - return ( -
- - With extensible tailwind classes - -
- ); -}; - -export const withTailwindAndVariant = () => { - return ( -
- - with tailwind classes and variant - -
- ); -}; - -export const withTailwindAndVariant2 = () => { - return ( -
- - with tailwind classes and variant - -
- ); -}; - -// Alignment Center -export const AlignmentCenterStory = Template.bind({}); -AlignmentCenterStory.args = { - variant: 'body-1', - alignment: 'center', - color: '#2A2C35', - children: - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.', -}; - -// Alignment Left -export const AlignmentLeftStory = Template.bind({}); -AlignmentLeftStory.args = { - variant: 'body-1', - alignment: 'left', - color: '#2A2C35', - children: - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi.', -}; - -// Alignment Right -export const AlignmentRightStory = Template.bind({}); -AlignmentRightStory.args = { - variant: 'body-1', - alignment: 'right', - color: '#2A2C35', - children: - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi.', -}; - -// Alignment Justify -export const AlignmentJustifyStory = Template.bind({}); -AlignmentJustifyStory.args = { - variant: 'body-1', - alignment: 'justify', - color: '#2A2C35', - children: - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi.', -}; - -// story for maxLines -export const Body2MaxLinesEllipsis = Template.bind({}); -Body2MaxLinesEllipsis.args = { - variant: 'body-2', - alignment: 'left', - color: '#2A2C35', - width: 400, - children: - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi.', - maxLines: 2, // Limit the maximum lines -}; - -export const asChild = Template.bind({}); -asChild.args = { - variant: 'body-1', - asChild: true, - alignment: 'center', - color: '#2A2C35', - children:

This is heading 1

, -}; From 74d42c76f46436218541a1b65ac77a690c5fa856 Mon Sep 17 00:00:00 2001 From: SySagar Date: Sun, 12 Jan 2025 00:15:41 +0530 Subject: [PATCH 2/6] chore: typography and button story update --- apps/ui/.storybook/preview.tsx | 100 ++++++------ apps/ui/.storybook/theme.ts | 40 ++--- .../lib/components/Button/Button.stories.tsx | 9 +- apps/ui/lib/components/Button/index.tsx | 78 +++++----- apps/ui/lib/components/Typography/Text.tsx | 60 ++++---- .../Typography/Typography.stories.tsx | 2 +- apps/ui/tailwind.config.ts | 142 +++++++++--------- apps/ui/utils/utils.ts | 2 +- 8 files changed, 216 insertions(+), 217 deletions(-) diff --git a/apps/ui/.storybook/preview.tsx b/apps/ui/.storybook/preview.tsx index 82e2219..3a12059 100644 --- a/apps/ui/.storybook/preview.tsx +++ b/apps/ui/.storybook/preview.tsx @@ -1,69 +1,69 @@ // https://storybook.js.org/docs/react/writing-stories/parameters#global-parameters import '../lib/tailwind.css'; import '../lib/color-scheme.css'; -import { withGlobalStyles } from './decorator'; +import '@groovy-box/tokens/src/fonts.css'; const customViewports = { - xs: { - name: 'XS', - styles: { - width: '350px', - height: '963px', + xs: { + name: 'XS', + styles: { + width: '350px', + height: '963px', + }, }, - }, - sm: { - name: 'SM', - styles: { - width: '600px', - height: '801px', + sm: { + name: 'SM', + styles: { + width: '600px', + height: '801px', + }, }, - }, - md: { - name: 'MD', - styles: { - width: '900px', - height: '801px', + md: { + name: 'MD', + styles: { + width: '900px', + height: '801px', + }, }, - }, - lg: { - name: 'LG', - styles: { - width: '1200px', - height: '801px', + lg: { + name: 'LG', + styles: { + width: '1200px', + height: '801px', + }, }, - }, - xl: { - name: 'XL', - styles: { - width: '1536px', - height: '801px', + xl: { + name: 'XL', + styles: { + width: '1536px', + height: '801px', + }, }, - }, }; export const parameters = { - // https://storybook.js.org/docs/react/essentials/actions#automatically-matching-args - actions: { argTypesRegex: '^on.*' }, - controls: { - matchers: { - color: /(background|color)$/i, - date: /Date$/, + // https://storybook.js.org/docs/react/essentials/actions#automatically-matching-args + actions: { argTypesRegex: '^on.*' }, + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/, + }, + }, + visualViewport: { + customViewports, }, - }, - visualViewport: { - customViewports, - }, }; export const globalTypes = { - scheme: { - name: 'Scheme', - description: 'Select light or dark', - defaultValue: 'light', - toolbar: { - icon: 'mirror', - items: ['light', 'dark'], - dynamicTitle: true, + scheme: { + name: 'Scheme', + description: 'Select light or dark', + defaultValue: 'light', + toolbar: { + icon: 'mirror', + items: ['light', 'dark'], + dynamicTitle: true, + }, }, - }, }; diff --git a/apps/ui/.storybook/theme.ts b/apps/ui/.storybook/theme.ts index c68890d..a867536 100644 --- a/apps/ui/.storybook/theme.ts +++ b/apps/ui/.storybook/theme.ts @@ -1,28 +1,28 @@ import { create } from '@storybook/theming/create'; export default create({ - base: 'light', - brandTitle: 'Groovy-Box', - brandUrl: 'https://ui.soumyasagar.in/', - brandImage: - 'https://raw.githubusercontent.com/EnigmaVSSUT/Enigma-UI-Kit/main/assets/logo.png', - brandTarget: '_self', - //fonts - fontBase: '"Inter", sans-serif', - fontCode: 'monospace', + base: 'light', + brandTitle: 'Groovy-Box', + brandUrl: 'https://ui.soumyasagar.in/', + brandImage: + 'https://raw.githubusercontent.com/EnigmaVSSUT/Enigma-UI-Kit/main/assets/logo.png', + brandTarget: '_self', + //fonts + fontBase: '"Inter", sans-serif', + fontCode: 'monospace', - //UI - appBg: '#E9EFE7', + //UI + appBg: '#E9EFE7', - // Text colors - textColor: '#454A44', - textInverseColor: '#10162F', + // Text colors + textColor: '#454A44', + textInverseColor: '#10162F', - // Toolbar default and active colors - barTextColor: '#9E9E9E', - barBg: '#ffffff', + // Toolbar default and active colors + barTextColor: '#9E9E9E', + barBg: '#ffffff', - // Form colors - inputBg: '#ffffff', - inputTextColor: '#10162F', + // Form colors + inputBg: '#ffffff', + inputTextColor: '#10162F', }); diff --git a/apps/ui/lib/components/Button/Button.stories.tsx b/apps/ui/lib/components/Button/Button.stories.tsx index bc6eb72..57d0368 100644 --- a/apps/ui/lib/components/Button/Button.stories.tsx +++ b/apps/ui/lib/components/Button/Button.stories.tsx @@ -36,16 +36,9 @@ export const Variants = () => ( ); export const tailwindButton = () => { - return ; + return ; }; -export const tailwindButtonWithOverridingVariant = () => { - return ( - - ); -}; export const Sizes = () => (
, + extends React.ButtonHTMLAttributes, VariantProps { - asChild?: boolean; + asChild?: boolean; } const Button = React.forwardRef( - ({ className, variant, size, asChild = false, ...props }, ref) => { - const Comp = asChild ? Slot : 'button'; - return ( - - ); - } + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : 'button'; + + console.log('cn', cn(buttonVariants({ variant, size, className }))); + return ( + + ); + } ); Button.displayName = 'Button'; diff --git a/apps/ui/lib/components/Typography/Text.tsx b/apps/ui/lib/components/Typography/Text.tsx index fab6b84..e9943d4 100644 --- a/apps/ui/lib/components/Typography/Text.tsx +++ b/apps/ui/lib/components/Typography/Text.tsx @@ -1,44 +1,40 @@ import React from 'react'; import { VARIANT_MAPPINGS } from './constants'; import { Slot } from './Slot'; -import style from './text.module.css'; import { cn } from '@utils/utils'; export interface TextProps extends React.HTMLAttributes { - variant?: keyof typeof VARIANT_MAPPINGS; - alignment?: 'left' | 'right' | 'center' | 'justify'; - maxLines?: number; - asChild?: boolean; - children: React.ReactNode; + variant?: keyof typeof VARIANT_MAPPINGS; + alignment?: 'left' | 'right' | 'center' | 'justify'; + maxLines?: number; + asChild?: boolean; + children: React.ReactNode; } export const Text: React.FC = ({ - variant, - alignment, - maxLines, - asChild = false, - children, - ...props + variant, + alignment, + maxLines, + asChild = false, + children, + ...props }) => { - const textStyle = { - textAlign: alignment || 'center', - margin: '0 0 0 0', - padding: '0 0 0 0', - display: asChild ? 'inline-block' : 'block', - textOverflow: 'ellipsis', - overflow: 'hidden', - WebkitLineClamp: maxLines || 'inherit', - }; + const textStyle = { + textAlign: alignment || 'center', + display: asChild ? 'inline-block' : 'block', + textOverflow: 'ellipsis', + overflow: 'hidden', + WebkitLineClamp: maxLines || 'inherit', + }; - const Comp = asChild ? Slot : 'p'; - const classNames = VARIANT_MAPPINGS[variant as keyof typeof VARIANT_MAPPINGS]; - const mergedClasses = cn(style.text, classNames?.slice(1), props.className); + const Comp = asChild ? Slot : 'p'; + const classNames = VARIANT_MAPPINGS[variant as keyof typeof VARIANT_MAPPINGS]; - return ( - - ); + return ( + + ); }; diff --git a/apps/ui/lib/components/Typography/Typography.stories.tsx b/apps/ui/lib/components/Typography/Typography.stories.tsx index 2a6688a..aeaa662 100644 --- a/apps/ui/lib/components/Typography/Typography.stories.tsx +++ b/apps/ui/lib/components/Typography/Typography.stories.tsx @@ -213,7 +213,7 @@ export const withTailwind = () => { export const withTailwindAndVariant = () => { return (
- + with tailwind classes and variant
diff --git a/apps/ui/tailwind.config.ts b/apps/ui/tailwind.config.ts index 53c64cb..e5e28b5 100644 --- a/apps/ui/tailwind.config.ts +++ b/apps/ui/tailwind.config.ts @@ -1,78 +1,86 @@ import plugin from 'tailwindcss/plugin'; import type { Config } from 'tailwindcss'; import { - scopedPreflightStyles, - isolateInsideOfContainer, + scopedPreflightStyles, + isolateInsideOfContainer, } from 'tailwindcss-scoped-preflight'; import { customTypographyClasses, groovyFontFamily } from '@groovy-box/tokens'; /** @type {import('tailwindcss').Config} */ module.exports = { - prefix: 'grv-', - important: true, - darkMode: ['class', '[data-mode="dark"]'], - content: [ - './lib/**/*.{html,ts,tsx,js,jsx}', - './stories/**/*.{ts,tsx,js,jsx}', - ], - theme: { - extend: { - fontFamily: groovyFontFamily, + prefix: 'grv-', + important: true, + darkMode: ['class', '[data-mode="dark"]'], + content: [ + './lib/**/*.{html,ts,tsx,js,jsx}', + './stories/**/*.{ts,tsx,js,jsx}', + ], + theme: { + extend: { + fontFamily: groovyFontFamily, + }, + colors: { + primary: { + 100: 'rgb(var(--primary-100))', + 300: 'rgb(var(--primary-300))', + 500: 'rgb(var(--primary-500))', + 700: 'rgb(var(--primary-700))', + 900: 'rgb(var(--primary-900))', + }, + secondary: { + 100: 'rgb(var(--secondary-100))', + 300: 'rgb(var(--secondary-300))', + 500: 'rgb(var(--secondary-500))', + 700: 'rgb(var(--secondary-700))', + 900: 'rgb(var(--secondary-900))', + }, + success: { + 100: 'rgb(var(--success-100))', + 300: 'rgb(var(--success-300))', + 500: 'rgb(var(--success-500))', + 700: 'rgb(var(--success-700))', + 900: 'rgb(var(--success-900))', + }, + error: { + 100: 'rgb(var(--error-100))', + 300: 'rgb(var(--error-300))', + 500: 'rgb(var(--error-500))', + 700: 'rgb(var(--error-700))', + 900: 'rgb(var(--error-900))', + }, + warning: { + 100: 'rgb(var(--warning-100))', + 300: 'rgb(var(--warning-300))', + 500: 'rgb(var(--warning-500))', + 700: 'rgb(var(--warning-700))', + 900: 'rgb(var(--warning-900))', + }, + text: { + primary: 'rgb(var(--text-primary))', + secondary: 'rgb(var(--text-secondary))', + }, + accent: 'rgb(var(--accent))', + backgroundPaper: 'rgb(var(--background-paper))', + bgopacity: 'rgb(var( --background-opacity))', + }, + fontWeight: { + thin: '100', + light: '300', + regular: '400', + medium: '500', + semibold: '600', + bold: '700', + }, }, - colors: { - primary: { - 100: 'rgb(var(--primary-100))', - 300: 'rgb(var(--primary-300))', - 500: 'rgb(var(--primary-500))', - 700: 'rgb(var(--primary-700))', - 900: 'rgb(var(--primary-900))', - }, - secondary: { - 100: 'rgb(var(--secondary-100))', - 300: 'rgb(var(--secondary-300))', - 500: 'rgb(var(--secondary-500))', - 700: 'rgb(var(--secondary-700))', - 900: 'rgb(var(--secondary-900))', - }, - success: { - 100: 'rgb(var(--success-100))', - 300: 'rgb(var(--success-300))', - 500: 'rgb(var(--success-500))', - 700: 'rgb(var(--success-700))', - 900: 'rgb(var(--success-900))', - }, - error: { - 100: 'rgb(var(--error-100))', - 300: 'rgb(var(--error-300))', - 500: 'rgb(var(--error-500))', - 700: 'rgb(var(--error-700))', - 900: 'rgb(var(--error-900))', - }, - warning: { - 100: 'rgb(var(--warning-100))', - 300: 'rgb(var(--warning-300))', - 500: 'rgb(var(--warning-500))', - 700: 'rgb(var(--warning-700))', - 900: 'rgb(var(--warning-900))', - }, - text: { - primary: 'rgb(var(--text-primary))', - secondary: 'rgb(var(--text-secondary))', - }, - accent: 'rgb(var(--accent))', - backgroundPaper: 'rgb(var(--background-paper))', - bgopacity: 'rgb(var( --background-opacity))', + plugins: [ + plugin(({ addUtilities }) => { + addUtilities(customTypographyClasses, { respectPrefix: false }); + }), + scopedPreflightStyles({ + isolationStrategy: isolateInsideOfContainer('.ui', {}), + }), + ], + corePlugins: { + preflight: false, // <== disable this! }, - }, - plugins: [ - plugin(({ addUtilities }) => { - addUtilities(customTypographyClasses, { respectPrefix: false }); - }), - scopedPreflightStyles({ - isolationStrategy: isolateInsideOfContainer('.ui', {}), - }), - ], - corePlugins: { - preflight: false, // <== disable this! - }, } satisfies Config; diff --git a/apps/ui/utils/utils.ts b/apps/ui/utils/utils.ts index 1a860ee..c1d3862 100644 --- a/apps/ui/utils/utils.ts +++ b/apps/ui/utils/utils.ts @@ -2,5 +2,5 @@ import { type ClassValue, clsx } from "clsx" import { twMerge } from "tailwind-merge" export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)) + return twMerge(clsx(inputs)) } \ No newline at end of file From 3cf0fdb5bdf6a5c5ac2ec7d335e4e4dda5e13008 Mon Sep 17 00:00:00 2001 From: SySagar Date: Sun, 12 Jan 2025 21:18:26 +0530 Subject: [PATCH 3/6] feat: modal component --- .../Accordion/Accordion.stories.tsx | 68 +-- .../lib/components/Avatar/Avatar.stories.tsx | 134 +++--- .../lib/components/Button/Button.stories.tsx | 101 ++-- apps/ui/lib/components/Button/index.tsx | 78 ++-- apps/ui/lib/components/Chip/Chip.stories.tsx | 126 ++--- .../ui/lib/components/Label/Label.stories.tsx | 34 +- .../ui/lib/components/Modal/Modal.stories.tsx | 149 ++++++ apps/ui/lib/components/Modal/Modal.tsx | 168 +++++++ apps/ui/lib/components/Modal/index.tsx | 1 + .../Navigation-menu/Navigation.stories.tsx | 198 ++++---- .../components/Progress/Progress.stories.tsx | 42 +- .../lib/components/Select/Select.stories.tsx | 117 ++--- .../lib/components/Switch/Switch.stories.tsx | 32 +- .../Textfield/Textfield.stories.tsx | 280 +++++------ .../ui/lib/components/Toast/Toast.stories.tsx | 150 +++--- apps/ui/lib/components/Typography/Text.tsx | 56 +-- .../Typography/Typography.stories.tsx | 442 +++++++++--------- apps/ui/lib/index.tsx | 3 +- apps/ui/lib/tailwind.css | 6 +- apps/ui/package.json | 3 +- apps/ui/tailwind.config.ts | 21 + package-lock.json | 304 ++++++++++++ 22 files changed, 1582 insertions(+), 931 deletions(-) create mode 100644 apps/ui/lib/components/Modal/Modal.stories.tsx create mode 100644 apps/ui/lib/components/Modal/Modal.tsx create mode 100644 apps/ui/lib/components/Modal/index.tsx diff --git a/apps/ui/lib/components/Accordion/Accordion.stories.tsx b/apps/ui/lib/components/Accordion/Accordion.stories.tsx index 3f752c5..bdf9591 100644 --- a/apps/ui/lib/components/Accordion/Accordion.stories.tsx +++ b/apps/ui/lib/components/Accordion/Accordion.stories.tsx @@ -1,48 +1,48 @@ import { withGlobalStyles } from '../../../.storybook/decorator'; import { - Accordion, - AccordionContent, - AccordionItem, - AccordionTrigger, + Accordion, + AccordionContent, + AccordionItem, + AccordionTrigger, } from '../..'; const Test = () => ( -
- - - Accordion 1 - Content 1 - - - Accordion 2 - Content 2 - - - Accordion 3 - Content 3 - - -
+
+ + + Accordion 1 + Content 1 + + + Accordion 2 + Content 2 + + + Accordion 3 + Content 3 + + +
); const withTailwind = () => { - return ( -
- - - Accordion 1 - Content 1 - - -
- ); -} + return ( +
+ + + Accordion 1 + Content 1 + + +
+ ); +}; export default { - title: 'components/Accordion', - component: Test, - decorators: [withGlobalStyles], + title: 'components/Accordion', + component: Test, + decorators: [withGlobalStyles], }; export const Default = () => ; diff --git a/apps/ui/lib/components/Avatar/Avatar.stories.tsx b/apps/ui/lib/components/Avatar/Avatar.stories.tsx index 9a26cf4..e779dfa 100644 --- a/apps/ui/lib/components/Avatar/Avatar.stories.tsx +++ b/apps/ui/lib/components/Avatar/Avatar.stories.tsx @@ -3,92 +3,92 @@ import { Avatar, AvatarImage, AvatarContent, AvatarFallback } from './Avatar'; import { Search, File } from 'lucide-react'; export default { - title: 'Components/Avatar', - component: Avatar, - subcomponents: { AvatarImage, AvatarContent, AvatarFallback }, - argTypes: { - className: { control: 'text' }, - }, + title: 'Components/Avatar', + component: Avatar, + subcomponents: { AvatarImage, AvatarContent, AvatarFallback }, + argTypes: { + className: { control: 'text' }, + }, }; const Template: Story = (args) => ( - - - AB - + + + AB + ); export const Default = Template.bind({}); Default.args = { - className: '', + className: '', }; export const WithContentImage: Story = (args) => ( - - - Avatar Content Image - - + + + Avatar Content Image + + ); export const WithContentIcon: Story = (args) => ( -
- - - - - - - - - - -
+
+ + + + + + + + + + +
); export const WithFallback: Story = () => ( - - AB - + + AB + ); export const allSizes: Story = () => ( -
- - - Avatar Content Image - - +
+ + + Avatar Content Image + + - - - Avatar Content Image - - + + + Avatar Content Image + + - - - Avatar Content Image - - -
+ + + Avatar Content Image + + +
); diff --git a/apps/ui/lib/components/Button/Button.stories.tsx b/apps/ui/lib/components/Button/Button.stories.tsx index 57d0368..0681225 100644 --- a/apps/ui/lib/components/Button/Button.stories.tsx +++ b/apps/ui/lib/components/Button/Button.stories.tsx @@ -2,67 +2,70 @@ import { Button } from './index'; import { withGlobalStyles } from '../../../.storybook/decorator'; export default { - title: 'Components/Button', - component: Button, - decorators: [withGlobalStyles], + title: 'Components/Button', + component: Button, + decorators: [withGlobalStyles], }; export const Variants = () => ( -
-
- -
-
- -
-
- -
-
- -
-
- -
+
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
); export const tailwindButton = () => { - return ; + return ( + + ); }; - export const Sizes = () => ( -
-
- -
-
- -
-
- -
+
+
+ +
+
+ +
+
+
+
); Sizes.args = { - variant: 'filled', - color: 'primary', + variant: 'filled', + color: 'primary', }; diff --git a/apps/ui/lib/components/Button/index.tsx b/apps/ui/lib/components/Button/index.tsx index 232d521..4ffb8bc 100644 --- a/apps/ui/lib/components/Button/index.tsx +++ b/apps/ui/lib/components/Button/index.tsx @@ -5,53 +5,53 @@ import { cva, type VariantProps } from 'class-variance-authority'; import { cn } from '@utils/utils'; const buttonVariants = cva( - 'grv-inline-flex grv-items-center grv-justify-center grv-whitespace-nowrap grv-rounded-md grv-text-sm grv-font-medium grv-ring-offset-background grv-transition-colors focus-visible:grv-outline-none focus-visible:grv-ring-2 focus-visible:grv-ring-ring focus-visible:grv-ring-offset-2 disabled:grv-pointer-events-none disabled:grv-opacity-50', - { - variants: { - variant: { - default: - 'grv-bg-primary-700 grv-text-text-primary hover:grv-bg-primary-500 grv-border-none', - destructive: - 'grv-bg-error-900 grv-text-text-primary hover:grv-bg-error-700 grv-border-none grv-outline-0 grv-shadow-none', - outline: - ' grv-border-none hover:grv-bg-bgopacity grv-text-accent grv-bg-primary-100/0 grv-outline grv-font-medium grv-outline-2 grv-outline-primary-500 grv-shadow-none', - secondary: - 'grv-bg-secondary-700 grv-text-text-primary hover:grv-bg-secondary-500 grv-border-none grv-outline-0 grv-shadow-none', - link: 'grv-text-accent grv-underline-offset-4 hover:grv-underline grv-bg-primary-100/0 grv-font-medium grv-border-none hover:grv-cursor-pointer p-0 m-0', - }, - size: { - default: 'grv-h-10 grv-px-4 grv-py-2', - sm: 'grv-h-9 grv-rounded-md grv-px-3', - lg: 'grv-h-11 grv-rounded-md grv-px-8', - icon: 'grv-h-10 grv-w-10', - }, - }, - defaultVariants: { - variant: 'default', - size: 'default', - }, - } + 'grv-inline-flex grv-items-center grv-justify-center grv-whitespace-nowrap grv-rounded-md grv-text-sm grv-font-medium grv-ring-offset-background grv-transition-colors focus-visible:grv-outline-none focus-visible:grv-ring-2 focus-visible:grv-ring-ring focus-visible:grv-ring-offset-2 disabled:grv-pointer-events-none disabled:grv-opacity-50', + { + variants: { + variant: { + default: + 'grv-bg-primary-700 grv-text-text-primary hover:grv-bg-primary-500 grv-border-none', + destructive: + 'grv-bg-error-900 grv-text-text-primary hover:grv-bg-error-700 grv-border-none grv-outline-0 grv-shadow-none', + outline: + ' grv-border-none hover:grv-bg-bgopacity grv-text-accent grv-bg-primary-100/0 grv-outline grv-font-medium grv-outline-2 grv-outline-primary-500 grv-shadow-none', + secondary: + 'grv-bg-secondary-700 grv-text-text-primary hover:grv-bg-secondary-500 grv-border-none grv-outline-0 grv-shadow-none', + link: 'grv-text-accent grv-underline-offset-4 hover:grv-underline grv-bg-primary-100/0 grv-font-medium grv-border-none hover:grv-cursor-pointer p-0 m-0', + }, + size: { + default: 'grv-h-10 grv-px-4 grv-py-2', + sm: 'grv-h-9 grv-rounded-md grv-px-3', + lg: 'grv-h-11 grv-rounded-md grv-px-8', + icon: 'grv-h-10 grv-w-10', + }, + }, + defaultVariants: { + variant: 'default', + size: 'default', + }, + } ); export interface ButtonProps - extends React.ButtonHTMLAttributes, + extends React.ButtonHTMLAttributes, VariantProps { - asChild?: boolean; + asChild?: boolean; } const Button = React.forwardRef( - ({ className, variant, size, asChild = false, ...props }, ref) => { - const Comp = asChild ? Slot : 'button'; + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : 'button'; - console.log('cn', cn(buttonVariants({ variant, size, className }))); - return ( - - ); - } + console.log('cn', cn(buttonVariants({ variant, size, className }))); + return ( + + ); + } ); Button.displayName = 'Button'; diff --git a/apps/ui/lib/components/Chip/Chip.stories.tsx b/apps/ui/lib/components/Chip/Chip.stories.tsx index 8763e7b..2d2adce 100644 --- a/apps/ui/lib/components/Chip/Chip.stories.tsx +++ b/apps/ui/lib/components/Chip/Chip.stories.tsx @@ -6,83 +6,83 @@ import { Avatar, AvatarImage, AvatarFallback } from '../..'; import { Star, Mail } from 'lucide-react'; const ChipExample = (props: ChipProps) => ( -
- Default -
+
+ Default +
); const ChipVariants = () => ( -
- Filled - Outlined -
+
+ Filled + Outlined +
); const ChipSizes = () => ( -
- Small - Medium - Large -
+
+ Small + Medium + Large +
); const ChipInteractions = () => ( -
- alert('Clicked!')}> - Clickable - - alert('Delete clicked!')}>Deletable - - Link - -
+
+ alert('Clicked!')}> + Clickable + + alert('Delete clicked!')}>Deletable + + Link + +
); const ChipWithIcons = () => ( -
- - - AB - - } - > - User Chip - - } - > - Starred - - } - afterChildren={ - - 99+ - - } - > - Inbox - -
+
+ + + AB + + } + > + User Chip + + } + > + Starred + + } + afterChildren={ + + 99+ + + } + > + Inbox + +
); export default { - title: 'components/Chip', - component: ChipExample, - decorators: [withGlobalStyles], + title: 'components/Chip', + component: ChipExample, + decorators: [withGlobalStyles], }; export const Default: Story = (args) => ; Default.args = { - children: 'Default Chip', - variant: 'filled', - size: 'md', + children: 'Default Chip', + variant: 'filled', + size: 'md', }; export const Variants = () => ; @@ -91,9 +91,9 @@ export const Interactions = () => ; export const WithIcons = () => ; export const CustomStyles = () => ( -
- - Custom Styled Chip - -
+
+ + Custom Styled Chip + +
); diff --git a/apps/ui/lib/components/Label/Label.stories.tsx b/apps/ui/lib/components/Label/Label.stories.tsx index f12764c..b97d93c 100644 --- a/apps/ui/lib/components/Label/Label.stories.tsx +++ b/apps/ui/lib/components/Label/Label.stories.tsx @@ -5,27 +5,27 @@ import { withGlobalStyles } from '../../../.storybook/decorator'; type LabelComponentStory = StoryObj; export default { - title: 'Components/Label', - component: Label, - tags: ['autodocs'], - decorators: [withGlobalStyles], - argTypes: { - htmlFor: { control: 'text' }, - children: { control: 'text' }, - }, + title: 'Components/Label', + component: Label, + tags: ['autodocs'], + decorators: [withGlobalStyles], + argTypes: { + htmlFor: { control: 'text' }, + children: { control: 'text' }, + }, }; export const BasicLabelComponent: LabelComponentStory = { - args: { - htmlFor: 'firstName', - children: 'First Name:', - }, + args: { + htmlFor: 'firstName', + children: 'First Name:', + }, }; export const LabelWithTailwind = () => { - return ( - - ); + return ( + + ); }; diff --git a/apps/ui/lib/components/Modal/Modal.stories.tsx b/apps/ui/lib/components/Modal/Modal.stories.tsx new file mode 100644 index 0000000..0bf282d --- /dev/null +++ b/apps/ui/lib/components/Modal/Modal.stories.tsx @@ -0,0 +1,149 @@ +import { + Dialog, + DialogTrigger, + DialogContent, + DialogHeader, + DialogFooter, + DialogTitle, + DialogDescription, + DialogClose, +} from './Modal'; +import { Text } from '../Typography'; +import { Button } from '../Button'; +import { Label } from '../Label'; +import { TextField } from '../Textfield'; +import { withGlobalStyles } from '../../../.storybook/decorator'; + +export default { + title: 'Components/Modal', + component: Dialog, + decorators: [withGlobalStyles], +}; + +const BasicDialog = () => ( + + + + + + + + + Dialog Title + + This is a description for the dialog content. + + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar + risus non rikus. + + + +); + +export const Basic = () => ; + +const ModalWithFooter = () => ( + + + + + + + + + Dialog Title + + This is a description for the dialog content. + + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar + risus non rikus. + + + + + + + +); + +export const WithFooter = () => ; + +const ModalWithImage = () => ( + + + + + + + + Hello 2025 + + + + Random Image + + + Wish you a very happy new year. May this year bring you joy and + happiness. + + + +); + +export const WithImage = () => ; + +const LoginModal = () => ( + + + + + + + + Login + + Please enter your credentials to login. + + +
+
+ + +
+
+ + +
+ +
+
+
+); + +export const Login = () => ; diff --git a/apps/ui/lib/components/Modal/Modal.tsx b/apps/ui/lib/components/Modal/Modal.tsx new file mode 100644 index 0000000..9a1393d --- /dev/null +++ b/apps/ui/lib/components/Modal/Modal.tsx @@ -0,0 +1,168 @@ +import * as React from 'react'; +import * as DialogPrimitive from '@radix-ui/react-dialog'; +import { motion, AnimatePresence } from 'framer-motion'; +import { X } from 'lucide-react'; + +import { cn } from '@utils/utils'; + +const Dialog = DialogPrimitive.Root; + +const DialogTrigger = DialogPrimitive.Trigger; + +const DialogPortal = DialogPrimitive.Portal; + +const DialogClose = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className }, ref) => ( + + + + + +)); + +DialogClose.displayName = DialogPrimitive.Close.displayName; + +const DialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)); +DialogOverlay.displayName = DialogPrimitive.Overlay.displayName; + +const DialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + {children} + + + + +)); +DialogContent.displayName = DialogPrimitive.Content.displayName; + +const DialogHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+); +DialogHeader.displayName = 'DialogHeader'; + +const DialogFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+); +DialogFooter.displayName = 'DialogFooter'; + +const DialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DialogTitle.displayName = DialogPrimitive.Title.displayName; + +const DialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DialogDescription.displayName = DialogPrimitive.Description.displayName; + +export { + Dialog, + DialogPortal, + DialogOverlay, + DialogClose, + DialogTrigger, + DialogContent, + DialogHeader, + DialogFooter, + DialogTitle, + DialogDescription, +}; diff --git a/apps/ui/lib/components/Modal/index.tsx b/apps/ui/lib/components/Modal/index.tsx new file mode 100644 index 0000000..cb89ee1 --- /dev/null +++ b/apps/ui/lib/components/Modal/index.tsx @@ -0,0 +1 @@ +export * from './Modal'; diff --git a/apps/ui/lib/components/Navigation-menu/Navigation.stories.tsx b/apps/ui/lib/components/Navigation-menu/Navigation.stories.tsx index 0a6b726..071bcea 100644 --- a/apps/ui/lib/components/Navigation-menu/Navigation.stories.tsx +++ b/apps/ui/lib/components/Navigation-menu/Navigation.stories.tsx @@ -1,114 +1,114 @@ import { - NavigationMenu, - NavigationMenuList, - NavigationMenuItem, - NavigationMenuTrigger, - NavigationMenuContent, - NavigationMenuLink, - ListItem, + NavigationMenu, + NavigationMenuList, + NavigationMenuItem, + NavigationMenuTrigger, + NavigationMenuContent, + NavigationMenuLink, + ListItem, } from '../..'; const components: { title: string; href: string; description: string }[] = [ - { - title: 'Alert Dialog', - href: '/docs/primitives/alert-dialog', - description: - 'A modal dialog that interrupts the user with important content and expects a response.', - }, - { - title: 'Hover Card', - href: '/docs/primitives/hover-card', - description: - 'For sighted users to preview content available behind a link.', - }, - { - title: 'Progress', - href: '/docs/primitives/progress', - description: - 'Displays an indicator showing the completion progress of a task, typically displayed as a progress bar.', - }, - { - title: 'Scroll-area', - href: '/docs/primitives/scroll-area', - description: 'Visually or semantically separates content.', - }, - { - title: 'Tabs', - href: '/docs/primitives/tabs', - description: - 'A set of layered sections of content—known as tab panels—that are displayed one at a time.', - }, - { - title: 'Tooltip', - href: '/docs/primitives/tooltip', - description: - 'A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it.', - }, + { + title: 'Alert Dialog', + href: '/docs/primitives/alert-dialog', + description: + 'A modal dialog that interrupts the user with important content and expects a response.', + }, + { + title: 'Hover Card', + href: '/docs/primitives/hover-card', + description: + 'For sighted users to preview content available behind a link.', + }, + { + title: 'Progress', + href: '/docs/primitives/progress', + description: + 'Displays an indicator showing the completion progress of a task, typically displayed as a progress bar.', + }, + { + title: 'Scroll-area', + href: '/docs/primitives/scroll-area', + description: 'Visually or semantically separates content.', + }, + { + title: 'Tabs', + href: '/docs/primitives/tabs', + description: + 'A set of layered sections of content—known as tab panels—that are displayed one at a time.', + }, + { + title: 'Tooltip', + href: '/docs/primitives/tooltip', + description: + 'A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it.', + }, ]; const Test = () => ( - - - - Getting started - - - - - - Components - -
    - {components.map((component) => ( - - {component.description} - - ))} -
-
-
- - - Documentation + + + + Getting started + + + + + + Components + +
    + {components.map((component) => ( + + {component.description} + + ))} +
+
+
+ + + Documentation + + +
+
); export default { - title: 'components/Navigation', - component: Test, + title: 'components/Navigation', + component: Test, }; export const Default = () => { - return ; + return ; }; diff --git a/apps/ui/lib/components/Progress/Progress.stories.tsx b/apps/ui/lib/components/Progress/Progress.stories.tsx index e55f6c6..75a388a 100644 --- a/apps/ui/lib/components/Progress/Progress.stories.tsx +++ b/apps/ui/lib/components/Progress/Progress.stories.tsx @@ -2,31 +2,31 @@ import { withGlobalStyles } from '../../../.storybook/decorator'; import { Progress, Text } from '../..'; const DefaultTemplate = ({ value = 40 }) => { - return ( -
- - {value}% complete - - -
- ); + return ( +
+ + {value}% complete + + +
+ ); }; export default { - title: 'components/Progress', - component: DefaultTemplate, - decorators: [withGlobalStyles], + title: 'components/Progress', + component: DefaultTemplate, + decorators: [withGlobalStyles], }; export const Default = () => { - return ; + return ; }; diff --git a/apps/ui/lib/components/Select/Select.stories.tsx b/apps/ui/lib/components/Select/Select.stories.tsx index 2bbea3d..f3980c6 100644 --- a/apps/ui/lib/components/Select/Select.stories.tsx +++ b/apps/ui/lib/components/Select/Select.stories.tsx @@ -1,78 +1,79 @@ // SelectDemo.stories.js +import { ChevronDownIcon, ChevronUpIcon } from '@radix-ui/react-icons'; import { - ChevronDownIcon, - ChevronUpIcon, -} from '@radix-ui/react-icons'; -import { - Select, - SelectContent, - SelectGroup, - SelectItem, - SelectLabel, - SelectScrollDownButton, - SelectScrollUpButton, - SelectTrigger, - SelectValue, + Select, + SelectContent, + SelectGroup, + SelectItem, + SelectLabel, + SelectScrollDownButton, + SelectScrollUpButton, + SelectTrigger, + SelectValue, } from '../..'; // Import your custom Select component import { SelectIcon } from '@radix-ui/react-select'; // type SelectComponentStory = StoryObj; const options = [ - { value: 'broccoli', label: 'Broccoli' }, - { value: 'carrot', label: 'Carrot' }, - { value: 'lettuce', label: 'Lettuce' }, - { value: 'corn', label: 'Corn' }, - { value: 'cucumber', label: 'Cucumber' }, - { value: 'spinach', label: 'Spinach' }, - { value: 'peas', label: 'Peas' }, - { value: 'cabbage', label: 'Cabbage' }, + { value: 'broccoli', label: 'Broccoli' }, + { value: 'carrot', label: 'Carrot' }, + { value: 'lettuce', label: 'Lettuce' }, + { value: 'corn', label: 'Corn' }, + { value: 'cucumber', label: 'Cucumber' }, + { value: 'spinach', label: 'Spinach' }, + { value: 'peas', label: 'Peas' }, + { value: 'cabbage', label: 'Cabbage' }, ]; const BasicSelect = () => ( -
- + + + + + + - - {/* */} + + {/* */} - - - - - - Vegetables - - {options.map((option: any, index: number) => ( - - {option.label} - - ))} - + + + + + + Vegetables + + {options.map((option: any, index: number) => ( + + {option.label} + + ))} + - - - - - -
+ + + + + +
); export default { - title: 'Components/Select', - component: BasicSelect, + title: 'Components/Select', + component: BasicSelect, }; export const Default = () => ; diff --git a/apps/ui/lib/components/Switch/Switch.stories.tsx b/apps/ui/lib/components/Switch/Switch.stories.tsx index 810439b..133ecb9 100644 --- a/apps/ui/lib/components/Switch/Switch.stories.tsx +++ b/apps/ui/lib/components/Switch/Switch.stories.tsx @@ -2,26 +2,26 @@ import { withGlobalStyles } from '../../../.storybook/decorator'; import { Label, Switch } from '../..'; const DefaultTemplate = () => { - return ( -
- - -
- ); + return ( +
+ + +
+ ); }; export default { - title: 'components/Switch', - component: DefaultTemplate, - decorators: [withGlobalStyles], + title: 'components/Switch', + component: DefaultTemplate, + decorators: [withGlobalStyles], }; export const Default = () => { - return ; + return ; }; diff --git a/apps/ui/lib/components/Textfield/Textfield.stories.tsx b/apps/ui/lib/components/Textfield/Textfield.stories.tsx index 595eae6..95f2676 100644 --- a/apps/ui/lib/components/Textfield/Textfield.stories.tsx +++ b/apps/ui/lib/components/Textfield/Textfield.stories.tsx @@ -1,175 +1,175 @@ import { TextField } from '../..'; export default { - title: 'Components/TextField', - component: TextField, - argTypes: { - variant: { - options: ['filled', 'outlined', 'standard'], - control: { type: 'radio' }, - }, - size: { - options: ['sm', 'md', 'lg'], - control: { type: 'radio' }, - }, - type: { - options: ['password', 'number', 'email', 'text'], - control: { type: 'radio' }, - }, - color: { - options: ['primary', 'secondary'], - control: { type: 'radio' }, - }, - placeholder: { - control: { type: 'text' }, - }, - disabled: { - control: { type: 'boolean' }, - }, - required: { - control: { type: 'boolean' }, - }, - readOnly: { - control: { type: 'boolean' }, - }, - fullWidth: { - control: { type: 'boolean' }, - }, - multiline: { - control: { type: 'boolean' }, - }, - rows: { - control: { type: 'number' }, - }, - rowsMax: { - control: { type: 'number' }, - }, - startIcon: { - control: { type: 'text' }, - }, - endIcon: { - control: { type: 'text' }, - }, - onChange: { - control: { type: 'text' }, - }, - onClick: { - control: { type: 'text' }, - }, - onFocus: { - control: { type: 'text' }, - }, - onBlur: { - control: { type: 'text' }, - }, - onKeyPress: { - control: { type: 'text' }, - }, - onKeyUp: { - control: { type: 'text' }, - }, - onKeyDown: { - control: { type: 'text' }, - }, + title: 'Components/TextField', + component: TextField, + argTypes: { + variant: { + options: ['filled', 'outlined', 'standard'], + control: { type: 'radio' }, }, + size: { + options: ['sm', 'md', 'lg'], + control: { type: 'radio' }, + }, + type: { + options: ['password', 'number', 'email', 'text'], + control: { type: 'radio' }, + }, + color: { + options: ['primary', 'secondary'], + control: { type: 'radio' }, + }, + placeholder: { + control: { type: 'text' }, + }, + disabled: { + control: { type: 'boolean' }, + }, + required: { + control: { type: 'boolean' }, + }, + readOnly: { + control: { type: 'boolean' }, + }, + fullWidth: { + control: { type: 'boolean' }, + }, + multiline: { + control: { type: 'boolean' }, + }, + rows: { + control: { type: 'number' }, + }, + rowsMax: { + control: { type: 'number' }, + }, + startIcon: { + control: { type: 'text' }, + }, + endIcon: { + control: { type: 'text' }, + }, + onChange: { + control: { type: 'text' }, + }, + onClick: { + control: { type: 'text' }, + }, + onFocus: { + control: { type: 'text' }, + }, + onBlur: { + control: { type: 'text' }, + }, + onKeyPress: { + control: { type: 'text' }, + }, + onKeyUp: { + control: { type: 'text' }, + }, + onKeyDown: { + control: { type: 'text' }, + }, + }, }; export const Default = (args: any) => ; Default.args = { - label: 'Label', - placeholder: 'Placeholder', - startIcon: '👋', - endIcon: '👋', + label: 'Label', + placeholder: 'Placeholder', + startIcon: '👋', + endIcon: '👋', }; export const Colors = (args: any) => ( -
-
- -
-
- -
+
+
+ +
+
+
+
); Colors.args = { - variant: 'filled', + variant: 'filled', }; export const Variants = (args: any) => ( -
-
- -
-
- -
+
+
+ +
+
+
+
); Variants.args = { - color: 'primary', + color: 'primary', }; export const Sizes = (args: any) => ( -
-
- -
-
- -
-
- -
+
+
+
+
+ +
+
+ +
+
); Sizes.args = { - color: 'primary', + color: 'primary', }; export const Multiline = (args: any) => ( -
-
- -
-
- -
+
+
+ +
+
+
+
); diff --git a/apps/ui/lib/components/Toast/Toast.stories.tsx b/apps/ui/lib/components/Toast/Toast.stories.tsx index 7c51597..0f9599e 100644 --- a/apps/ui/lib/components/Toast/Toast.stories.tsx +++ b/apps/ui/lib/components/Toast/Toast.stories.tsx @@ -2,88 +2,88 @@ import { withGlobalStyles } from '../../../.storybook/decorator'; import { useToast, Button, Toaster, ToastAction } from '../..'; export const Default = () => { - const { toast } = useToast(); - return ( -
- - -
- ); + const { toast } = useToast(); + return ( +
+ + +
+ ); }; export default { - title: 'components/Toast', - component: Default, - decorators: [withGlobalStyles], + title: 'components/Toast', + component: Default, + decorators: [withGlobalStyles], }; export const Destructive = () => { - const { toast } = useToast(); - return ( -
- - -
- ); + const { toast } = useToast(); + return ( +
+ + +
+ ); }; export const DestructiveWithActionButton = () => { - const { toast } = useToast(); - return ( -
- - -
- ); + const { toast } = useToast(); + return ( +
+ + +
+ ); }; diff --git a/apps/ui/lib/components/Typography/Text.tsx b/apps/ui/lib/components/Typography/Text.tsx index e9943d4..fb52618 100644 --- a/apps/ui/lib/components/Typography/Text.tsx +++ b/apps/ui/lib/components/Typography/Text.tsx @@ -3,38 +3,38 @@ import { VARIANT_MAPPINGS } from './constants'; import { Slot } from './Slot'; import { cn } from '@utils/utils'; export interface TextProps extends React.HTMLAttributes { - variant?: keyof typeof VARIANT_MAPPINGS; - alignment?: 'left' | 'right' | 'center' | 'justify'; - maxLines?: number; - asChild?: boolean; - children: React.ReactNode; + variant?: keyof typeof VARIANT_MAPPINGS; + alignment?: 'left' | 'right' | 'center' | 'justify'; + maxLines?: number; + asChild?: boolean; + children: React.ReactNode; } export const Text: React.FC = ({ - variant, - alignment, - maxLines, - asChild = false, - children, - ...props + variant, + alignment, + maxLines, + asChild = false, + children, + ...props }) => { - const textStyle = { - textAlign: alignment || 'center', - display: asChild ? 'inline-block' : 'block', - textOverflow: 'ellipsis', - overflow: 'hidden', - WebkitLineClamp: maxLines || 'inherit', - }; + const textStyle = { + textAlign: alignment || 'center', + display: asChild ? 'inline-block' : 'block', + textOverflow: 'ellipsis', + overflow: 'hidden', + WebkitLineClamp: maxLines || 'inherit', + }; - const Comp = asChild ? Slot : 'p'; - const classNames = VARIANT_MAPPINGS[variant as keyof typeof VARIANT_MAPPINGS]; + const Comp = asChild ? Slot : 'p'; + const classNames = VARIANT_MAPPINGS[variant as keyof typeof VARIANT_MAPPINGS]; - return ( - - ); + return ( + + ); }; diff --git a/apps/ui/lib/components/Typography/Typography.stories.tsx b/apps/ui/lib/components/Typography/Typography.stories.tsx index aeaa662..923f67c 100644 --- a/apps/ui/lib/components/Typography/Typography.stories.tsx +++ b/apps/ui/lib/components/Typography/Typography.stories.tsx @@ -1,64 +1,64 @@ import { Text } from '../..'; export default { - title: 'Components/Text', - component: Text, - parameters: { - layout: 'centered', + title: 'Components/Text', + component: Text, + parameters: { + layout: 'centered', + }, + tags: ['autodocs'], + argTypes: { + variant: { + control: { + type: 'select', + options: [ + 'body-1', + 'body-2', + 'body-3', + 'button-1', + 'button-2', + 'button-3', + 'heading-1', + 'heading-2', + 'heading-3', + 'heading-4', + 'heading-5', + 'heading-6', + 'label-1', + 'label-2', + 'label-2-strong', + 'label-3', + 'subtitle-1', + 'subtitle-2', + 'subtitle-3', + ], + }, + defaultValue: 'body-1', + description: 'The variant of the Text component.', }, - tags: ['autodocs'], - argTypes: { - variant: { - control: { - type: 'select', - options: [ - 'body-1', - 'body-2', - 'body-3', - 'button-1', - 'button-2', - 'button-3', - 'heading-1', - 'heading-2', - 'heading-3', - 'heading-4', - 'heading-5', - 'heading-6', - 'label-1', - 'label-2', - 'label-2-strong', - 'label-3', - 'subtitle-1', - 'subtitle-2', - 'subtitle-3', - ], - }, - defaultValue: 'body-1', - description: 'The variant of the Text component.', - }, - alignment: { - control: { - type: 'select', - options: ['left', 'right', 'center', 'justify'], - }, - defaultValue: 'left', - description: 'The text alignment of the Text component.', - }, - color: { - control: 'color', - defaultValue: '#2A2C35', - description: 'The color of the text in the Text component.', - }, - asChild: { - control: 'text', - description: - 'The type of child element to render within the Text component.', - }, - children: { - control: 'text', - description: 'The text content of the Text component.', - }, + alignment: { + control: { + type: 'select', + options: ['left', 'right', 'center', 'justify'], + }, + defaultValue: 'left', + description: 'The text alignment of the Text component.', }, + color: { + control: 'color', + defaultValue: '#2A2C35', + description: 'The color of the text in the Text component.', + }, + asChild: { + control: 'text', + description: + 'The type of child element to render within the Text component.', + }, + children: { + control: 'text', + description: 'The text content of the Text component.', + }, + }, }; // Create a template for your Text component @@ -66,230 +66,230 @@ const Template = (args: any) => ; export const Default = Template.bind({}); Default.args = { - variant: 'heading-1', - alignment: 'left', - color: '#2A2C35', - children: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', + variant: 'heading-1', + alignment: 'left', + color: '#2A2C35', + children: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', }; // Combined Story export const AllVariants = () => { - return ( - <> - {/* Body-1 */} -
- - body-1 - -
+ return ( + <> + {/* Body-1 */} +
+ + body-1 + +
- {/* Body-2 */} -
- - body-2 - -
+ {/* Body-2 */} +
+ + body-2 + +
- {/* Body-3 */} -
- - body-3 - -
+ {/* Body-3 */} +
+ + body-3 + +
- {/* Button-1 */} -
- - Button-1 - -
+ {/* Button-1 */} +
+ + Button-1 + +
- {/* Button-2 */} -
- - Button-2 - -
+ {/* Button-2 */} +
+ + Button-2 + +
- {/* Heading-1 */} -
- - Heading-1 - -
+ {/* Heading-1 */} +
+ + Heading-1 + +
- {/* Heading-2 */} -
- - Heading-2 - -
+ {/* Heading-2 */} +
+ + Heading-2 + +
- {/* Heading-3 */} -
- - Heading-3 - -
+ {/* Heading-3 */} +
+ + Heading-3 + +
- {/* Heading-4 */} -
- - Heading-4 - -
+ {/* Heading-4 */} +
+ + Heading-4 + +
- {/* Heading-5 */} -
- - Heading-5 - -
+ {/* Heading-5 */} +
+ + Heading-5 + +
- {/* Heading-6 */} -
- - Heading-6 - -
+ {/* Heading-6 */} +
+ + Heading-6 + +
- {/* Label-1 */} -
- - label-1 - -
+ {/* Label-1 */} +
+ + label-1 + +
- {/* Label-2 */} -
- - label-2 - -
+ {/* Label-2 */} +
+ + label-2 + +
- {/* Subtitle-1 */} -
- - subtitle-1 - -
+ {/* Subtitle-1 */} +
+ + subtitle-1 + +
- {/* Subtitle-2*/} -
- - subtitle-2 - -
+ {/* Subtitle-2*/} +
+ + subtitle-2 + +
- {/* Subtitle-3 */} -
- - subtitle-3 - -
- - ); + {/* Subtitle-3 */} +
+ + subtitle-3 + +
+ + ); }; export const ColorStory = Template.bind({}); ColorStory.args = { - variant: 'body-1', - alignment: 'center', - color: '#2a52be', - children: - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.', + variant: 'body-1', + alignment: 'center', + color: '#2a52be', + children: + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.', }; export const withTailwind = () => { - return ( -
- - With extensible tailwind classes - -
- ); + return ( +
+ + With extensible tailwind classes + +
+ ); }; export const withTailwindAndVariant = () => { - return ( -
- - with tailwind classes and variant - -
- ); + return ( +
+ + with tailwind classes and variant + +
+ ); }; export const withTailwindAndVariant2 = () => { - return ( -
- - with tailwind classes and variant - -
- ); + return ( +
+ + with tailwind classes and variant + +
+ ); }; // Alignment Center export const AlignmentCenterStory = Template.bind({}); AlignmentCenterStory.args = { - variant: 'body-1', - alignment: 'center', - color: '#2A2C35', - children: - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.', + variant: 'body-1', + alignment: 'center', + color: '#2A2C35', + children: + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.', }; // Alignment Left export const AlignmentLeftStory = Template.bind({}); AlignmentLeftStory.args = { - variant: 'body-1', - alignment: 'left', - color: '#2A2C35', - children: - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi.', + variant: 'body-1', + alignment: 'left', + color: '#2A2C35', + children: + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi.', }; // Alignment Right export const AlignmentRightStory = Template.bind({}); AlignmentRightStory.args = { - variant: 'body-1', - alignment: 'right', - color: '#2A2C35', - children: - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi.', + variant: 'body-1', + alignment: 'right', + color: '#2A2C35', + children: + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi.', }; // Alignment Justify export const AlignmentJustifyStory = Template.bind({}); AlignmentJustifyStory.args = { - variant: 'body-1', - alignment: 'justify', - color: '#2A2C35', - children: - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi.', + variant: 'body-1', + alignment: 'justify', + color: '#2A2C35', + children: + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi.', }; // story for maxLines export const Body2MaxLinesEllipsis = Template.bind({}); Body2MaxLinesEllipsis.args = { - variant: 'body-2', - alignment: 'left', - color: '#2A2C35', - width: 400, - children: - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi.', - maxLines: 2, // Limit the maximum lines + variant: 'body-2', + alignment: 'left', + color: '#2A2C35', + width: 400, + children: + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi.', + maxLines: 2, // Limit the maximum lines }; export const asChild = Template.bind({}); asChild.args = { - variant: 'body-1', - asChild: true, - alignment: 'center', - color: '#2A2C35', - children:

This is heading 1

, + variant: 'body-1', + asChild: true, + alignment: 'center', + color: '#2A2C35', + children:

This is heading 1

, }; diff --git a/apps/ui/lib/index.tsx b/apps/ui/lib/index.tsx index 6c74336..b34e0d1 100644 --- a/apps/ui/lib/index.tsx +++ b/apps/ui/lib/index.tsx @@ -12,4 +12,5 @@ export * from './components/Navigation-menu'; export * from './components/Switch'; export * from './components/Toast'; export * from './components/Progress'; -export * from './components/Chip'; \ No newline at end of file +export * from './components/Chip'; +export * from './components/Modal'; \ No newline at end of file diff --git a/apps/ui/lib/tailwind.css b/apps/ui/lib/tailwind.css index 17f910e..29784c9 100644 --- a/apps/ui/lib/tailwind.css +++ b/apps/ui/lib/tailwind.css @@ -36,11 +36,12 @@ --warning-900: 222, 193, 110; --text-primary: 235, 235, 235; - --text-secondary: 30, 30, 30; + --text-secondary: 93, 97, 102; --accent: 0, 0, 0; --background-paper: 255 255 255; --background-opacity: 0, 0, 0, 0.05; + --background-overlay: 0, 0, 0, 0.7; } /* Dark Mode Colors */ @@ -76,12 +77,13 @@ --warning-900: 187, 167, 81; --text-primary: 245, 245, 245; - --text-secondary: 23, 23, 23; + --text-secondary: 102, 98, 93; --accent: 255, 245, 245; --background-paper: 253, 253, 253; --background-opacity: 253, 253, 253, 0.1; + --background-overlay: 0, 0, 0, 0.7; } } diff --git a/apps/ui/package.json b/apps/ui/package.json index c02b2c9..b2e8b98 100644 --- a/apps/ui/package.json +++ b/apps/ui/package.json @@ -21,7 +21,7 @@ "build": "npx sort-package-json && tsc && vite build", "build-storybook": "storybook build", "dev": "storybook dev -p 6006", - "format": "prettier --write lib/**/* stories/**/*", + "format": "prettier --write lib/**/*", "lint": "eslint ./lib --ext .ts,.tsx", "lint-fix": "eslint --fix .", "pub:beta": "npm run build && npm publish --no-git-checks --access public --tag beta", @@ -44,6 +44,7 @@ }, "dependencies": { "@radix-ui/react-avatar": "^1.0.4", + "@radix-ui/react-dialog": "^1.1.4", "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-select": "^2.0.0", "class-variance-authority": "^0.7.0", diff --git a/apps/ui/tailwind.config.ts b/apps/ui/tailwind.config.ts index e5e28b5..66915cd 100644 --- a/apps/ui/tailwind.config.ts +++ b/apps/ui/tailwind.config.ts @@ -19,6 +19,23 @@ module.exports = { extend: { fontFamily: groovyFontFamily, }, + keyframes: { + overlayShow: { + from: { opacity: "0" }, + to: { opacity: "1" }, + }, + contentShow: { + from: { + opacity: "0", + transform: "translate(-50%, -48%) scale(0.96)", + }, + to: { opacity: "1", transform: "translate(-50%, -50%) scale(1)" }, + }, + }, + animation: { + overlayShow: "overlayShow 150ms cubic-bezier(0.16, 1, 0.3, 1)", + contentShow: "contentShow 150ms cubic-bezier(0.16, 1, 0.3, 1)", + }, colors: { primary: { 100: 'rgb(var(--primary-100))', @@ -62,6 +79,7 @@ module.exports = { accent: 'rgb(var(--accent))', backgroundPaper: 'rgb(var(--background-paper))', bgopacity: 'rgb(var( --background-opacity))', + bgOverlay: 'rgb(var(--background-overlay))', }, fontWeight: { thin: '100', @@ -71,6 +89,9 @@ module.exports = { semibold: '600', bold: '700', }, + fontFamily: { + sans: ['"Inter var"', 'system-ui', 'sans-serif'] + }, }, plugins: [ plugin(({ addUtilities }) => { diff --git a/package-lock.json b/package-lock.json index d76c833..76549d2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -85,6 +85,7 @@ "license": "MIT", "dependencies": { "@radix-ui/react-avatar": "^1.0.4", + "@radix-ui/react-dialog": "^1.1.4", "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-select": "^2.0.0", "class-variance-authority": "^0.7.0", @@ -174,6 +175,309 @@ "react": ">=16" } }, + "apps/ui/node_modules/@radix-ui/primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz", + "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==" + }, + "apps/ui/node_modules/@radix-ui/react-dialog": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.4.tgz", + "integrity": "sha512-Ur7EV1IwQGCyaAuyDRiOLA5JIUZxELJljF+MbM/2NC0BYwfuRrbpS30BiQBJrVruscgUkieKkqXYDOoByaxIoA==", + "dependencies": { + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.3", + "@radix-ui/react-focus-guards": "1.1.1", + "@radix-ui/react-focus-scope": "1.1.1", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-portal": "1.1.3", + "@radix-ui/react-presence": "1.1.2", + "@radix-ui/react-primitive": "2.0.1", + "@radix-ui/react-slot": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.1.0", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "^2.6.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "apps/ui/node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", + "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "apps/ui/node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-context": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", + "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "apps/ui/node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.3.tgz", + "integrity": "sha512-onrWn/72lQoEucDmJnr8uczSNTujT0vJnA/X5+3AkChVPowr8n1yvIKIabhWyMQeMvvmdpsvcyDqx3X1LEXCPg==", + "dependencies": { + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-primitive": "2.0.1", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-escape-keydown": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "apps/ui/node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-focus-guards": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz", + "integrity": "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "apps/ui/node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-focus-scope": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.1.tgz", + "integrity": "sha512-01omzJAYRxXdG2/he/+xy+c8a8gCydoQ1yOxnWNcRhrrBW5W+RQJ22EK1SaO8tb3WoUsuEw7mJjBozPzihDFjA==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-primitive": "2.0.1", + "@radix-ui/react-use-callback-ref": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "apps/ui/node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-portal": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.3.tgz", + "integrity": "sha512-NciRqhXnGojhT93RPyDaMPfLH3ZSl4jjIFbZQ1b/vxvZEdHsBZ49wP9w8L3HzUQwep01LcWtkUvm0OVB5JAHTw==", + "dependencies": { + "@radix-ui/react-primitive": "2.0.1", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "apps/ui/node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-presence": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.2.tgz", + "integrity": "sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "apps/ui/node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-primitive": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz", + "integrity": "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==", + "dependencies": { + "@radix-ui/react-slot": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "apps/ui/node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz", + "integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "apps/ui/node_modules/@radix-ui/react-dialog/node_modules/react-remove-scroll": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.2.tgz", + "integrity": "sha512-KmONPx5fnlXYJQqC62Q+lwIeAk64ws/cUw6omIumRzMRPqgnYqhSSti99nbj0Ry13bv7dF+BKn7NB+OqkdZGTw==", + "dependencies": { + "react-remove-scroll-bar": "^2.3.7", + "react-style-singleton": "^2.2.1", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.3", + "use-sidecar": "^1.1.2" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "apps/ui/node_modules/@radix-ui/react-dialog/node_modules/react-remove-scroll/node_modules/react-remove-scroll-bar": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", + "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", + "dependencies": { + "react-style-singleton": "^2.2.2", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "apps/ui/node_modules/@radix-ui/react-dialog/node_modules/react-remove-scroll/node_modules/react-remove-scroll-bar/node_modules/react-style-singleton": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", + "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", + "dependencies": { + "get-nonce": "^1.0.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "apps/ui/node_modules/@radix-ui/react-dialog/node_modules/react-remove-scroll/node_modules/use-callback-ref": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", + "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "apps/ui/node_modules/@storybook/manager-api": { "version": "8.3.5", "resolved": "https://registry.npmjs.org/@storybook/manager-api/-/manager-api-8.3.5.tgz", From 30592336581c06bcde22ffd5c2a7cd7add061d32 Mon Sep 17 00:00:00 2001 From: SySagar Date: Sun, 12 Jan 2025 23:05:15 +0530 Subject: [PATCH 4/6] chore: textfield component revamp --- apps/ui/lib/components/Button/index.tsx | 77 ++-- apps/ui/lib/components/Chip/Chip.tsx | 220 ++++++----- .../Textfield/Textfield.stories.tsx | 368 ++++++++++-------- apps/ui/lib/components/Textfield/index.tsx | 362 +++++++++-------- 4 files changed, 563 insertions(+), 464 deletions(-) diff --git a/apps/ui/lib/components/Button/index.tsx b/apps/ui/lib/components/Button/index.tsx index 4ffb8bc..2d07ff1 100644 --- a/apps/ui/lib/components/Button/index.tsx +++ b/apps/ui/lib/components/Button/index.tsx @@ -5,53 +5,52 @@ import { cva, type VariantProps } from 'class-variance-authority'; import { cn } from '@utils/utils'; const buttonVariants = cva( - 'grv-inline-flex grv-items-center grv-justify-center grv-whitespace-nowrap grv-rounded-md grv-text-sm grv-font-medium grv-ring-offset-background grv-transition-colors focus-visible:grv-outline-none focus-visible:grv-ring-2 focus-visible:grv-ring-ring focus-visible:grv-ring-offset-2 disabled:grv-pointer-events-none disabled:grv-opacity-50', - { - variants: { - variant: { - default: - 'grv-bg-primary-700 grv-text-text-primary hover:grv-bg-primary-500 grv-border-none', - destructive: - 'grv-bg-error-900 grv-text-text-primary hover:grv-bg-error-700 grv-border-none grv-outline-0 grv-shadow-none', - outline: - ' grv-border-none hover:grv-bg-bgopacity grv-text-accent grv-bg-primary-100/0 grv-outline grv-font-medium grv-outline-2 grv-outline-primary-500 grv-shadow-none', - secondary: - 'grv-bg-secondary-700 grv-text-text-primary hover:grv-bg-secondary-500 grv-border-none grv-outline-0 grv-shadow-none', - link: 'grv-text-accent grv-underline-offset-4 hover:grv-underline grv-bg-primary-100/0 grv-font-medium grv-border-none hover:grv-cursor-pointer p-0 m-0', - }, - size: { - default: 'grv-h-10 grv-px-4 grv-py-2', - sm: 'grv-h-9 grv-rounded-md grv-px-3', - lg: 'grv-h-11 grv-rounded-md grv-px-8', - icon: 'grv-h-10 grv-w-10', - }, - }, - defaultVariants: { - variant: 'default', - size: 'default', - }, - } + 'grv-inline-flex grv-items-center grv-justify-center grv-whitespace-nowrap grv-rounded-md grv-text-sm grv-font-medium grv-ring-offset-background grv-transition-colors focus-visible:grv-outline-none focus-visible:grv-ring-2 focus-visible:grv-ring-ring focus-visible:grv-ring-offset-2 disabled:grv-pointer-events-none disabled:grv-opacity-50', + { + variants: { + variant: { + default: + 'grv-bg-primary-700 grv-text-text-primary hover:grv-bg-primary-500 grv-border-none', + destructive: + 'grv-bg-error-900 grv-text-text-primary hover:grv-bg-error-700 grv-border-none grv-outline-0 grv-shadow-none', + outline: + ' grv-border-none hover:grv-bg-bgopacity grv-text-accent grv-bg-primary-100/0 grv-outline grv-font-medium grv-outline-2 grv-outline-primary-500 grv-shadow-none', + secondary: + 'grv-bg-secondary-700 grv-text-text-primary hover:grv-bg-secondary-500 grv-border-none grv-outline-0 grv-shadow-none', + link: 'grv-text-accent grv-underline-offset-4 hover:grv-underline grv-bg-primary-100/0 grv-font-medium grv-border-none hover:grv-cursor-pointer p-0 m-0', + }, + size: { + default: 'grv-h-10 grv-px-4 grv-py-2', + sm: 'grv-h-9 grv-rounded-md grv-px-3', + lg: 'grv-h-11 grv-rounded-md grv-px-8', + icon: 'grv-h-10 grv-w-10', + }, + }, + defaultVariants: { + variant: 'default', + size: 'default', + }, + } ); export interface ButtonProps - extends React.ButtonHTMLAttributes, + extends React.ButtonHTMLAttributes, VariantProps { - asChild?: boolean; + asChild?: boolean; } const Button = React.forwardRef( - ({ className, variant, size, asChild = false, ...props }, ref) => { - const Comp = asChild ? Slot : 'button'; + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : 'button'; - console.log('cn', cn(buttonVariants({ variant, size, className }))); - return ( - - ); - } + return ( + + ); + } ); Button.displayName = 'Button'; diff --git a/apps/ui/lib/components/Chip/Chip.tsx b/apps/ui/lib/components/Chip/Chip.tsx index 9053f0c..fdac16d 100644 --- a/apps/ui/lib/components/Chip/Chip.tsx +++ b/apps/ui/lib/components/Chip/Chip.tsx @@ -6,134 +6,132 @@ import { X as CloseIcon } from 'lucide-react'; import { cn } from '@utils/utils'; const chipVariants = cva( - 'grv-inline-flex ui grv-items-center grv-rounded-full grv-text-sm grv-font-medium grv-transition-colors focus:grv-outline-none focus:grv-ring-2 grv-ring-ring grv-ring-offset-2', - { - variants: { - variant: { - filled: 'grv-bg-primary-500 ui', - outlined: 'grv-border-2 grv-border-solid grv-border-accent ui', - }, - size: { - sm: 'grv-h-6 grv-px-3 ui', - md: 'grv-h-8 grv-px-4 ui', - lg: 'grv-h-10 grv-px-5 ui', - }, - clickable: { - true: 'grv-cursor-pointer', - false: '', - }, - }, - defaultVariants: { - variant: 'filled', - size: 'md', - clickable: false, - }, - } + 'grv-inline-flex ui grv-items-center grv-rounded-full grv-text-sm grv-font-medium grv-transition-colors focus:grv-outline-none focus:grv-ring-2 grv-ring-ring grv-ring-offset-2', + { + variants: { + variant: { + filled: 'grv-bg-primary-500 ui', + outlined: 'grv-border-2 grv-border-solid grv-border-accent ui', + }, + size: { + sm: 'grv-h-6 grv-px-3 ui', + md: 'grv-h-8 grv-px-4 ui', + lg: 'grv-h-10 grv-px-5 ui', + }, + clickable: { + true: 'grv-cursor-pointer', + false: '', + }, + }, + defaultVariants: { + variant: 'filled', + size: 'md', + clickable: false, + }, + } ); export interface ChipDivProps - extends React.HTMLAttributes, + extends React.HTMLAttributes, VariantProps { - onDelete?: () => void; - as?: React.ElementType; - href?: never; - beforeChildren?: React.ReactNode; - afterChildren?: React.ReactNode; + onDelete?: () => void; + as?: React.ElementType; + href?: never; + beforeChildren?: React.ReactNode; + afterChildren?: React.ReactNode; } export interface ChipAnchorProps - extends React.HTMLAttributes, + extends React.HTMLAttributes, VariantProps { - onDelete?: () => void; - href?: string; - target?: string; - as?: React.ElementType; - beforeChildren?: React.ReactNode; - afterChildren?: React.ReactNode; + onDelete?: () => void; + href?: string; + target?: string; + as?: React.ElementType; + beforeChildren?: React.ReactNode; + afterChildren?: React.ReactNode; } export type ChipProps = ChipAnchorProps | ChipDivProps; const Chip = React.forwardRef( - ( - { - className, - variant, - size, - clickable, - onDelete, - href, - as, - beforeChildren, - afterChildren, - children, - ...props - }, - ref - ) => { - const Component = as || (href ? 'a' : 'div'); - const isClickable = Boolean(clickable || href || props.onClick); + ( + { + className, + variant, + size, + clickable, + onDelete, + href, + as, + beforeChildren, + afterChildren, + children, + ...props + }, + ref + ) => { + const Component = as || (href ? 'a' : 'div'); + const isClickable = Boolean(clickable || href || props.onClick); - console.log(variant); - const textColor = - variant === 'outlined' ? 'grv-text-accent' : 'grv-text-text-primary'; + const textColor = + variant === 'outlined' ? 'grv-text-accent' : 'grv-text-text-primary'; - console.log(size); - const textSize = - size === 'sm' - ? 'grv-text-[10px]' - : size === 'md' - ? 'grv-text-[12px]' - : 'grv-text-[14px]'; + const textSize = + size === 'sm' + ? 'grv-text-[10px]' + : size === 'md' + ? 'grv-text-[12px]' + : 'grv-text-[14px]'; - return ( - - {beforeChildren && ( -
- {beforeChildren} -
- )} -
{children}
- {afterChildren && ( -
- {afterChildren} -
- )} - {onDelete && ( -
{ - e.stopPropagation(); - onDelete(); - }} - > - -
- )} -
- ); - } + return ( + + {beforeChildren && ( +
+ {beforeChildren} +
+ )} +
{children}
+ {afterChildren && ( +
+ {afterChildren} +
+ )} + {onDelete && ( +
{ + e.stopPropagation(); + onDelete(); + }} + > + +
+ )} +
+ ); + } ); Chip.displayName = 'Chip'; diff --git a/apps/ui/lib/components/Textfield/Textfield.stories.tsx b/apps/ui/lib/components/Textfield/Textfield.stories.tsx index 95f2676..65e4777 100644 --- a/apps/ui/lib/components/Textfield/Textfield.stories.tsx +++ b/apps/ui/lib/components/Textfield/Textfield.stories.tsx @@ -1,175 +1,219 @@ -import { TextField } from '../..'; - -export default { - title: 'Components/TextField', - component: TextField, - argTypes: { - variant: { - options: ['filled', 'outlined', 'standard'], - control: { type: 'radio' }, - }, - size: { - options: ['sm', 'md', 'lg'], - control: { type: 'radio' }, - }, - type: { - options: ['password', 'number', 'email', 'text'], - control: { type: 'radio' }, - }, - color: { - options: ['primary', 'secondary'], - control: { type: 'radio' }, - }, - placeholder: { - control: { type: 'text' }, - }, - disabled: { - control: { type: 'boolean' }, - }, - required: { - control: { type: 'boolean' }, - }, - readOnly: { - control: { type: 'boolean' }, - }, - fullWidth: { - control: { type: 'boolean' }, - }, - multiline: { - control: { type: 'boolean' }, - }, - rows: { - control: { type: 'number' }, - }, - rowsMax: { - control: { type: 'number' }, - }, - startIcon: { - control: { type: 'text' }, - }, - endIcon: { - control: { type: 'text' }, - }, - onChange: { - control: { type: 'text' }, - }, - onClick: { - control: { type: 'text' }, - }, - onFocus: { - control: { type: 'text' }, - }, - onBlur: { - control: { type: 'text' }, - }, - onKeyPress: { - control: { type: 'text' }, - }, - onKeyUp: { - control: { type: 'text' }, +import type { Meta, StoryObj } from '@storybook/react'; +import { TextField } from './index'; +import { Mail, Lock, Eye, EyeOff, Search, User, Check, AlertCircle } from 'lucide-react'; +import { useState } from 'react'; +import { Button } from '../Button'; + +const meta: Meta = { + title: 'Components/TextField', + component: TextField.Root, + tags: ['autodocs'], + argTypes: { + variant: { + control: 'select', + options: ['standard', 'outlined', 'filled'], + description: 'The visual style of the text field', + }, + size: { + control: 'select', + options: ['sm', 'md', 'lg'], + description: 'The size of the text field', + }, + error: { + control: 'boolean', + description: 'Whether the text field is in an error state', + }, }, - onKeyDown: { - control: { type: 'text' }, +}; + +export default meta; +type Story = StoryObj; + +// Basic TextField +export const Basic: Story = { + render: (args) => ( + + + + ), +}; + +// With Icons +export const WithIcons: Story = { + render: () => ( +
+ + + + + + + + + + + + + + + + +
+ ), +}; + +// Password Input with Toggle +export const PasswordInput: Story = { + render: () => { + const [showPassword, setShowPassword] = useState(false); + return ( + + + + + + + + + + ); }, - }, }; -export const Default = (args: any) => ; +// Different Variants +export const Variants: Story = { + render: () => ( +
+ + + + + + + -Default.args = { - label: 'Label', - placeholder: 'Placeholder', - startIcon: '👋', - endIcon: '👋', + + + +
+ ), }; -export const Colors = (args: any) => ( -
-
- -
-
- -
-
-); - -Colors.args = { - variant: 'filled', +// Different Sizes +export const Sizes: Story = { + render: () => ( +
+ + + + + + + + + + + +
+ ), }; -export const Variants = (args: any) => ( -
-
- -
-
- -
-
-); - -Variants.args = { - color: 'primary', +// With Helper Text +export const WithHelperText: Story = { + render: () => ( +
+ + + + This is a helpful message + + + + + + + This field is required + + +
+ ), }; -export const Sizes = (args: any) => ( -
-
- -
-
- -
-
- -
-
-); - -Sizes.args = { - color: 'primary', +// Form Example +export const FormExample: Story = { + render: () => ( +
+ + + + + + + + + + Username is available + + + + + + + + + + Please enter a valid email address + + + + + + + + + + Must be at least 8 characters + + +
+ ), }; -export const Multiline = (args: any) => ( -
-
- -
-
- -
-
-); +// Disabled State +export const DisabledStates: Story = { + render: () => ( +
+ + + + + + + + + + + + + +
+ ), +}; \ No newline at end of file diff --git a/apps/ui/lib/components/Textfield/index.tsx b/apps/ui/lib/components/Textfield/index.tsx index 657652c..1ca5296 100644 --- a/apps/ui/lib/components/Textfield/index.tsx +++ b/apps/ui/lib/components/Textfield/index.tsx @@ -1,157 +1,215 @@ -import React from 'react'; -import { useRef, useEffect } from 'react'; - -type textFieldVariant = 'filled' | 'outlined' | 'standard'; -type textFieldSize = 'sm' | 'md' | 'lg'; -type textFieldType = 'password' | 'number' | 'email' | 'text'; - -export interface textFieldProps - extends Omit, 'size'> { - variant?: textFieldVariant; - size?: textFieldSize; - type?: textFieldType; - label?: string; - color?: string; - placeholder?: string; - error?: boolean; - disabled?: boolean; - required?: boolean; - readOnly?: boolean; - fullWidth?: boolean; - multiline?: boolean; - rows?: number; - rowsMax?: number; - startIcon?: React.ReactNode; - endIcon?: React.ReactNode; - onChange?: React.ChangeEventHandler; - onClick?: React.MouseEventHandler; - onFocus?: React.FocusEventHandler; - onBlur?: React.FocusEventHandler; - onKeyPress?: React.KeyboardEventHandler; - onKeyUp?: React.KeyboardEventHandler; - onKeyDown?: React.KeyboardEventHandler; -} - -export const TextField: React.FC = ({ - variant = 'standard', - size = 'md', - type = 'text', - label, - - placeholder, - - disabled, - required, - readOnly, - - startIcon, - endIcon, - onChange, - onClick, - - onKeyPress, - onKeyUp, - onKeyDown, - ...props -}) => { - const baseStyles = - 'grv-rounded grv-font-semibold grv-flex grv-items-center focus:grv-outline-none'; - - const sizeStyles = { - sm: 'grv-py-1 grv-px-2 grv-text-sm', - md: 'grv-py-2 grv-px-2', - lg: 'grv-py-3 grv-px-2 grv-text-lg', - }; - - const variantStyles = { - filled: - 'grv-bg-primary-700 hover:grv-bg-opacity-95 grv-text-[#21351B] focus:grv-border-b-2', - outlined: - 'grv-bg-transparent hover:grv-border-[#A6B1A0] grv-text-[#21351B] grv-border-[#DAE6D4] grv-border focus:grv-border-[#35FF1F]', - standard: - ' grv-bg-transparent grv-text-[#21351B] grv-border-b-2 grv-border-[#DAE6D4] hover:grv-border-[#A6B1A0] focus:grv-border-b-2 focus:grv-border-[#35FF1F]', - }; - - const textFieldStyles = `${baseStyles} ${sizeStyles[size]} ${ - variantStyles[variant as keyof typeof variantStyles] - }`; - - const iconStyles = `grv-inline-block grv-h-auto grv-w-auto ${startIcon ? 'grv-mr-2' : 'grv-ml-2'}`; - const inputRef = useRef(null); - const parentInputRef = useRef(null); - - useEffect(() => { - if (inputRef.current && variant === 'filled') { - inputRef.current.className = 'grv-text-primaryText'; +import React, { forwardRef, useState, createContext, useContext } from 'react'; +import { motion, AnimatePresence, MotionProps } from 'framer-motion'; +import { cva, VariantProps } from 'class-variance-authority'; +import { cn } from '@utils/utils'; +import { Text } from '../Typography'; + +const textFieldVariants = cva( + 'grv-w-full grv-rounded-md grv-transition-all grv-duration-200 grv-ease-in-out', + { + variants: { + variant: { + filled: 'grv-bg-secondary-100 focus:bg-primary-50 grv-border-b-2 grv-border-primary focus:grv-outline-secondary-500 focus:grv-outline-2 focus:grv-border-secondary-500 ', + outlined: 'grv-bg-transparent grv-outline-2 focus:grv-outline-secondary-300 focus:border-primary-500 focus:grv-outline-2 focus:grv-border-secondary-500', + standard: 'grv-bg-transparent grv-border-none grv-outline-none grv-relative', + }, + size: { + sm: 'grv-py-1 grv-px-2 grv-text-sm', + md: 'grv-py-2 grv-px-3 grv-text-base', + lg: 'grv-py-3 grv-px-4 grv-text-lg', + }, + error: { + true: 'grv-border-error-500 focus:grv-border-error-500', + false: '', + }, + }, + defaultVariants: { + variant: 'standard', + size: 'md', + error: false, + }, } +); + +type TextFieldContextType = { + variant?: VariantProps['variant']; + size?: VariantProps['size']; + error?: boolean; + isFocused: boolean; + setIsFocused: (value: boolean) => void; +}; - if (inputRef.current && (variant === 'filled' || variant === 'outlined')) { - inputRef.current.className = 'grv-text-secondaryText'; - } - }, [variant]); - - const handleFocus = () => { - const parent = document.getElementById('parent'); - if (parent) { - if (variant === 'standard' || variant === 'filled') - parent.style.borderBottom = '2px solid #35FF1F'; - else parent.style.border = '2px solid #35FF1F'; +const TextFieldContext = createContext(undefined); + +const useTextField = () => { + const context = useContext(TextFieldContext); + if (!context) { + throw new Error('TextField components must be used within a TextField.Root'); } - }; - - const handleBlur = () => { - const parent = document.getElementById('parent'); - if (parent) { - if (variant === 'standard' || variant === 'filled') - parent.style.borderBottom = '2px solid #DAE6D4'; - else parent.style.border = '2px solid #DAE6D4'; + return context; +}; + +interface TextFieldRootProps extends MotionProps { + children: React.ReactNode; + variant?: VariantProps['variant']; + size?: VariantProps['size']; + error?: boolean; + className?: string; +} + +interface TextFieldInputProps extends Omit, 'size'> { + className?: string; +} + +interface TextFieldIconProps { + children: React.ReactNode; + position: 'start' | 'end'; + className?: string; +} + +interface TextFieldHelperTextProps { + children: React.ReactNode; + className?: string; +} + +const Root = ({ children, variant, size, error = false, className, ...props }: TextFieldRootProps) => { + const [isFocused, setIsFocused] = useState(false); + + const containerVariants = { + initial: { scale: 1 }, + focus: { scale: 1.01 }, + }; + + const dashVariants = { + initial: { + scaleX: 1, + backgroundColor: '#e5e7eb' + }, + focus: { + scaleX: 1, + backgroundColor: '#3b82f6' + }, + }; + + return ( + +
+ +
+ {children} +
+ {variant === 'standard' && ( + + )} + +
+
+ ); +}; + +const Input = forwardRef( + ({ className, type = 'text', placeholder, disabled, required, readOnly, onFocus, onBlur, ...props }, ref) => { + const { variant, size, error, setIsFocused } = useTextField(); + + return ( + { + setIsFocused(true); + onFocus?.(e); + }} + onBlur={(e) => { + setIsFocused(false); + onBlur?.(e); + }} + {...props} + /> + ); } - }; - - return ( -
- {label && } -
- {startIcon && {startIcon}} - - {endIcon && {endIcon}} -
-
- ); +); + +const Icon = ({ children, position, className }: TextFieldIconProps) => { + const { isFocused } = useTextField(); + + const iconVariants = { + initial: { opacity: 0.7 }, + focus: { opacity: 1 }, + }; + + return ( + + {children} + + ); }; + +const HelperText = ({ children, className }: TextFieldHelperTextProps) => { + const { error } = useTextField(); + + return ( + + + + {children} + + + + ); +}; + +export const TextField = { + Root, + Input: Input, + Icon, + HelperText, +}; + +Input.displayName = 'TextField.Input'; \ No newline at end of file From 370613b8e5f2ecbc86e5b1967c3ec004c467acdc Mon Sep 17 00:00:00 2001 From: SySagar Date: Sun, 12 Jan 2025 23:07:55 +0530 Subject: [PATCH 5/6] =?UTF-8?q?=F0=9F=93=A6=20chore:=20Version=20packages?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .changeset/tidy-drinks-doubt.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/tidy-drinks-doubt.md diff --git a/.changeset/tidy-drinks-doubt.md b/.changeset/tidy-drinks-doubt.md new file mode 100644 index 0000000..05ac4f3 --- /dev/null +++ b/.changeset/tidy-drinks-doubt.md @@ -0,0 +1,5 @@ +--- +'@groovy-box/ui': minor +--- + +storybook directory change, modal component, textfield and button component revamp From e138034adc10f2df8cfbdb3b2310b328538de2e0 Mon Sep 17 00:00:00 2001 From: SySagar Date: Sun, 12 Jan 2025 23:13:02 +0530 Subject: [PATCH 6/6] chore: removed useless tests --- .github/workflows/button-tests.yaml | 36 ------------ .github/workflows/code_coverage.yml | 80 +++++++++++++-------------- .github/workflows/textfield-test.yaml | 36 ------------ 3 files changed, 40 insertions(+), 112 deletions(-) delete mode 100644 .github/workflows/button-tests.yaml delete mode 100644 .github/workflows/textfield-test.yaml diff --git a/.github/workflows/button-tests.yaml b/.github/workflows/button-tests.yaml deleted file mode 100644 index 306f33d..0000000 --- a/.github/workflows/button-tests.yaml +++ /dev/null @@ -1,36 +0,0 @@ -name: Button-Tests - -on: - push: - branches: [button] - pull_request: - branches: [button] - -jobs: - test_button: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Install Dependencies - run: npm install - - - name: Run Button Component Tests - run: npm run test __test__/Button.test.js - - id: test_button_output - continue-on-error: true - - - name: Set Test Result - if: always() - run: echo "::set-output name=button_tests_result::${{ job.status }}" - - - name: Final Message - if: success() - run: echo "Button component tests passed! 🎉" - - - name: Final Message on Failure - if: failure() - run: echo "Button component tests failed! ❌" diff --git a/.github/workflows/code_coverage.yml b/.github/workflows/code_coverage.yml index 7ea9144..ddd5957 100644 --- a/.github/workflows/code_coverage.yml +++ b/.github/workflows/code_coverage.yml @@ -1,40 +1,40 @@ -name: Running Code Coverage - -on: - push: - branches: - - dev - pull_request: - branches: - - dev - -jobs: - build: - runs-on: ubuntu-latest - - strategy: - matrix: - node-version: [20.x] - - steps: - - name: Checkout repository - uses: actions/checkout@v2 - with: - fetch-depth: 2 - - - name: Set up Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 - with: - node-version: ${{ matrix.node-version }} - - - name: Install dependencies - run: npm install - - - name: Run tests - run: npm run ui:coverage - - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4 - with: - token: ${{ secrets.CODECOV_TOKEN }} - directory: apps/ui/coverage +# name: Running Code Coverage + +# on: +# push: +# branches: +# - dev +# pull_request: +# branches: +# - dev + +# jobs: +# build: +# runs-on: ubuntu-latest + +# strategy: +# matrix: +# node-version: [20.x] + +# steps: +# - name: Checkout repository +# uses: actions/checkout@v2 +# with: +# fetch-depth: 2 + +# - name: Set up Node.js ${{ matrix.node-version }} +# uses: actions/setup-node@v3 +# with: +# node-version: ${{ matrix.node-version }} + +# - name: Install dependencies +# run: npm install + +# - name: Run tests +# run: npm run ui:coverage + +# - name: Upload coverage to Codecov +# uses: codecov/codecov-action@v4 +# with: +# token: ${{ secrets.CODECOV_TOKEN }} +# directory: apps/ui/coverage diff --git a/.github/workflows/textfield-test.yaml b/.github/workflows/textfield-test.yaml deleted file mode 100644 index 30ccf1e..0000000 --- a/.github/workflows/textfield-test.yaml +++ /dev/null @@ -1,36 +0,0 @@ -name: Textfield-Tests - -on: - push: - branches: [textfield] - pull_request: - branches: [textfield] - -jobs: - test_button: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Install Dependencies - run: npm install - - - name: Run Button Component Tests - run: npm run test __test__/Textfield.test.js - - id: test_textField_output - continue-on-error: true - - - name: Set Test Result - if: always() - run: echo "::set-output name=textField_tests_result::${{ job.status }}" - - - name: Final Message - if: success() - run: echo "TextField component tests passed! 🎉" - - - name: Final Message on Failure - if: failure() - run: echo "Textfield component tests failed! ❌"