diff --git a/libs/react/ui/index.css b/libs/react/ui/index.css index cba4ca6f..3a6d0a61 100644 --- a/libs/react/ui/index.css +++ b/libs/react/ui/index.css @@ -307,7 +307,7 @@ --background-highlight-base: var(--color-primary-950); --background-neutral-hover: var(--color-neutral-800); --background-neutral-overlay: var(--color-neutral-800); - --background-components-base: var(--color-neutral-900); + --background-components-base: var(--color-neutral-800); --background-field-component: var(--color-neutral-900); --background-switch-off-hover: var(--color-neutral-600); --background-field-component-hover: var(--color-neutral-800); diff --git a/libs/react/ui/src/components/alert/alert.stories.tsx b/libs/react/ui/src/components/alert/alert.stories.tsx new file mode 100644 index 00000000..308f5f4f --- /dev/null +++ b/libs/react/ui/src/components/alert/alert.stories.tsx @@ -0,0 +1,77 @@ +import type {Meta, StoryObj} from '@storybook/react'; +import {Header} from 'components/typography'; +import { + Alert, + AlertAction, + AlertActions, + AlertClose, + AlertContent, + AlertDescription, + AlertTitle, +} from './alert'; + +const meta = { + title: 'Components/Alert', + component: Alert, + tags: ['autodocs'], + argTypes: { + variant: { + control: 'select', + options: ['default', 'info', 'success', 'warning', 'destructive'], + }, + }, + args: { + variant: 'default', + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +const variants = ['default', 'info', 'success', 'warning', 'destructive'] as const; + +export const Default: Story = { + render: (args) => { + return ( + + + Title + Description + + Download + View + + + + + ); + }, +}; + +export const DesignMock: Story = { + render: () => { + return ( +
+
+ ALERTS +
+
+ {variants.map((variant) => ( + + + Title + Description + + Download + View + + + + + ))} +
+
+ ); + }, +}; diff --git a/libs/react/ui/src/components/alert/alert.tsx b/libs/react/ui/src/components/alert/alert.tsx new file mode 100644 index 00000000..f3bca62b --- /dev/null +++ b/libs/react/ui/src/components/alert/alert.tsx @@ -0,0 +1,144 @@ +import {cva, type VariantProps} from 'class-variance-authority'; +import {Icon} from 'components/icon'; +import type {ComponentProps} from 'react'; +import {cn} from 'utils/cn'; + +const alertVariants = cva( + 'relative w-full rounded-l-4 rounded-r-8 px-16 py-12 text-sm flex gap-12 items-start border', + { + variants: { + variant: { + default: 'bg-tag-neutral-bg text-foreground-neutral-base border-tag-neutral-border', + info: 'bg-tag-blue-bg text-foreground-neutral-base border-tag-blue-border', + success: 'bg-tag-success-bg text-foreground-neutral-base border-tag-success-border', + warning: 'bg-tag-warning-bg text-foreground-neutral-base border-tag-warning-border', + destructive: 'bg-tag-error-bg text-foreground-neutral-base border-tag-error-border', + }, + }, + defaultVariants: { + variant: 'default', + }, + }, +); + +const alertLineVariants = cva('w-4 self-stretch rounded-full', { + variants: { + variant: { + default: 'bg-tag-neutral-icon', + info: 'bg-tag-blue-icon', + success: 'bg-tag-success-icon', + warning: 'bg-tag-warning-icon', + destructive: 'bg-tag-error-icon', + }, + }, + defaultVariants: { + variant: 'default', + }, +}); + +const closeIconVariants = cva('w-16 h-16', { + variants: { + variant: { + default: 'text-tag-neutral-icon', + info: 'text-tag-blue-icon', + success: 'text-tag-success-icon', + warning: 'text-tag-warning-icon', + destructive: 'text-tag-error-icon', + }, + }, + defaultVariants: { + variant: 'default', + }, +}); + +type AlertProps = ComponentProps<'div'> & VariantProps; + +function Alert({className, variant, children, ...props}: AlertProps) { + return ( +
+ + ); +} + +function AlertContent({className, ...props}: ComponentProps<'div'>) { + return
; +} + +function AlertTitle({className, ...props}: ComponentProps<'div'>) { + return ( +
+ ); +} + +function AlertDescription({className, ...props}: ComponentProps<'div'>) { + return ( +
+ ); +} + +function AlertActions({className, ...props}: ComponentProps<'div'>) { + return ( +
+ ); +} + +function AlertAction({className, ...props}: ComponentProps<'button'>) { + return ( + + ); +} + +export {Alert, AlertContent, AlertTitle, AlertDescription, AlertActions, AlertAction, AlertClose}; diff --git a/libs/react/ui/src/components/alert/index.ts b/libs/react/ui/src/components/alert/index.ts new file mode 100644 index 00000000..ab34032f --- /dev/null +++ b/libs/react/ui/src/components/alert/index.ts @@ -0,0 +1 @@ +export * from './alert'; diff --git a/libs/react/ui/src/components/icon/icon.tsx b/libs/react/ui/src/components/icon/icon.tsx index 262c54f2..25ea2016 100644 --- a/libs/react/ui/src/components/icon/icon.tsx +++ b/libs/react/ui/src/components/icon/icon.tsx @@ -1,4 +1,9 @@ -import {type RemixiconComponentType, RiGoogleFill, RiMicrosoftFill} from '@remixicon/react'; +import { + type RemixiconComponentType, + RiCloseLine, + RiGoogleFill, + RiMicrosoftFill, +} from '@remixicon/react'; import type {ComponentProps} from 'react'; import { BadgeIcon, @@ -28,6 +33,7 @@ const iconsMap = { spinner: SpinnerIcon, ellipseMiniSolid: EllipseMiniSolidIcon, componentLine: ComponentLineIcon, + close: RiCloseLine, } as const satisfies Record; export type IconName = keyof typeof iconsMap; diff --git a/libs/react/ui/src/components/index.ts b/libs/react/ui/src/components/index.ts index fe49263b..f8c47221 100644 --- a/libs/react/ui/src/components/index.ts +++ b/libs/react/ui/src/components/index.ts @@ -1,5 +1,7 @@ +export * from './alert'; export * from './button'; export * from './icon'; +export * from './inline-tips'; export * from './textarea'; export * from './theme-provider'; export * from './typography'; diff --git a/libs/react/ui/src/components/inline-tips/index.ts b/libs/react/ui/src/components/inline-tips/index.ts new file mode 100644 index 00000000..00b416e0 --- /dev/null +++ b/libs/react/ui/src/components/inline-tips/index.ts @@ -0,0 +1 @@ +export * from './inline-tips'; diff --git a/libs/react/ui/src/components/inline-tips/inline-tips.stories.tsx b/libs/react/ui/src/components/inline-tips/inline-tips.stories.tsx new file mode 100644 index 00000000..2081aa44 --- /dev/null +++ b/libs/react/ui/src/components/inline-tips/inline-tips.stories.tsx @@ -0,0 +1,126 @@ +import type {Meta, StoryObj} from '@storybook/react'; +import {Code, Header} from 'components/typography'; +import { + InlineTips, + InlineTipsAction, + InlineTipsActions, + InlineTipsContent, + InlineTipsDescription, + InlineTipsTitle, +} from './inline-tips'; + +const meta = { + title: 'Components/InlineTips', + component: InlineTips, + tags: ['autodocs'], + argTypes: { + type: { + control: 'select', + options: ['default', 'info', 'success', 'destructive'], + }, + variant: { + control: 'select', + options: ['primary', 'secondary'], + }, + }, + args: { + type: 'default', + variant: 'primary', + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +const types = ['default', 'info', 'success', 'destructive'] as const; +const variants = ['primary', 'secondary'] as const; + +export const Default: Story = { + render: (args) => { + return ( + + + Title + Description + + + Label + Label + + + ); + }, +}; + +export const Variants: Story = { + render: () => { + return ( +
+ {variants.map((variant) => ( + + + Title + Description + + + Label + Label + + + ))} +
+ ); + }, +}; + +export const DesignMock: Story = { + render: () => { + const content = { + default: {title: 'Title', description: 'Description'}, + info: {title: 'Title', description: 'Description'}, + success: {title: 'Title', description: 'Description'}, + destructive: {title: "Don't's", description: 'Title'}, + }; + + return ( +
+
+ INLINE TIPS +
+
+ + Primary + + {types.map((type) => ( + + + {content[type].title} + {content[type].description} + + + Label + Label + + + ))} + + Secondary + + {types.map((type) => ( + + + {content[type].title} + {content[type].description} + + + Label + Label + + + ))} +
+
+ ); + }, +}; diff --git a/libs/react/ui/src/components/inline-tips/inline-tips.tsx b/libs/react/ui/src/components/inline-tips/inline-tips.tsx new file mode 100644 index 00000000..feeb718a --- /dev/null +++ b/libs/react/ui/src/components/inline-tips/inline-tips.tsx @@ -0,0 +1,132 @@ +import {cva, type VariantProps} from 'class-variance-authority'; +import type {ComponentProps} from 'react'; +import {cn} from 'utils/cn'; + +const inlineTipsBaseVariants = cva('w-full text-sm flex gap-12 items-center', { + variants: { + variant: { + primary: + 'bg-background-components-base text-foreground-neutral-base border border-border-neutral-base shadow-button-neutral rounded-8 px-12 py-8', + secondary: 'bg-transparent text-foreground-neutral-base', + }, + }, + defaultVariants: { + variant: 'primary', + }, +}); + +const inlineTipsLineVariants = cva('w-4 self-stretch my-4 rounded-full', { + variants: { + type: { + default: 'bg-tag-neutral-icon', + info: 'bg-tag-warning-icon', + success: 'bg-tag-success-icon', + destructive: 'bg-tag-error-icon', + }, + }, + defaultVariants: { + type: 'default', + }, +}); + +type InlineTipsProps = ComponentProps<'div'> & + VariantProps & { + type?: 'default' | 'info' | 'success' | 'destructive'; + }; + +function InlineTips({className, variant, type = 'default', children, ...props}: InlineTipsProps) { + return ( +
+ + ); +} + +function InlineTipsContent({className, ...props}: ComponentProps<'div'>) { + return ( +
+ ); +} + +function InlineTipsTitle({className, ...props}: ComponentProps<'div'>) { + return ( +
+ ); +} + +function InlineTipsDescription({className, ...props}: ComponentProps<'div'>) { + return ( +
+ ); +} + +function InlineTipsActions({className, ...props}: ComponentProps<'div'>) { + return ( +
+ ); +} + +const inlineTipsActionVariants = cva( + 'rounded-6 px-10 py-6 text-xs font-medium leading-20 transition-colors duration-150 outline-none focus-visible:ring-2 focus-visible:ring-background-accent-blue-base focus-visible:ring-offset-2', + { + variants: { + variant: { + primary: + 'bg-background-button-inverted-default text-foreground-contrast-primary shadow-button-inverted hover:bg-background-button-inverted-hover active:bg-background-button-inverted-pressed focus-visible:shadow-button-inverted-focus disabled:bg-background-neutral-disabled disabled:text-foreground-neutral-disabled disabled:shadow-none ', + secondary: + 'bg-background-button-neutral-default text-foreground-neutral-base shadow-button-neutral hover:bg-background-button-neutral-hover active:bg-background-button-neutral-pressed disabled:bg-background-neutral-disabled focus-visible:shadow-button-neutral-focus disabled:text-foreground-neutral-disabled disabled:shadow-none', + }, + }, + defaultVariants: { + variant: 'primary', + }, + }, +); + +function InlineTipsAction({ + className, + variant, + ...props +}: ComponentProps<'button'> & VariantProps) { + return ( +