Base Components
Alert
Alerts often appear between inputs or around important UI elements to convey critical information, such as an incorrect password during login attempts.
Installation
Create an alert.tsx file and paste the following code into it.
// CoreUI Alert v0.0.0import * as React from 'react';import { RiCloseLine } from '@remixicon/react';import type { PolymorphicComponentProps } from '@/utils/polymorphic';import { recursiveCloneChildren } from '@/utils/recursive-clone-children';import { tv, type ClassValue, type VariantProps,} from '@/utils/tv';const ALERT_ROOT_NAME = 'AlertRoot';const ALERT_ICON_NAME = 'AlertIcon';const ALERT_CLOSE_ICON_NAME = 'AlertCloseIcon';export const alertVariants = tv({ slots: { root: 'w-full', wrapper: [ 'grid w-full auto-cols-auto grid-flow-col grid-cols-1 items-start has-[>svg:first-child]:grid-cols-[auto_minmax(0,1fr)]', 'transition duration-200 ease-out group-data-[expanded=false]/toast:group-data-[front=false]/toast:opacity-0', ], icon: 'shrink-0', closeIcon: '', }, variants: { variant: { filled: { root: 'text-static-white', closeIcon: 'text-static-white opacity-[.72]', }, light: { root: 'text-text-strong-950', closeIcon: 'text-text-strong-950 opacity-40', }, lighter: { root: 'text-text-strong-950', closeIcon: 'text-text-strong-950 opacity-40', }, stroke: { root: 'bg-bg-white-0 text-text-strong-950 shadow-regular-md ring-1 ring-inset ring-stroke-soft-200', closeIcon: 'text-text-strong-950 opacity-40', }, }, status: { error: {}, warning: {}, success: {}, information: {}, feature: {}, }, size: { xsmall: { root: 'rounded-lg p-2 text-paragraph-xs', wrapper: 'items-center gap-2', icon: 'size-4', closeIcon: 'size-4', }, small: { root: 'rounded-lg px-2.5 py-2 text-paragraph-sm', wrapper: 'items-center gap-2', icon: 'size-5', closeIcon: 'size-5', }, large: { root: 'rounded-xl p-3.5 pb-4 text-paragraph-sm', wrapper: 'items-start gap-3', icon: 'size-5', closeIcon: 'size-5', }, }, }, compoundVariants: [ //#region filled { variant: 'filled', status: 'error', class: { root: 'bg-error-base', }, }, { variant: 'filled', status: 'warning', class: { root: 'bg-warning-base', }, }, { variant: 'filled', status: 'success', class: { root: 'bg-success-base', }, }, { variant: 'filled', status: 'information', class: { root: 'bg-information-base', }, }, { variant: 'filled', status: 'feature', class: { root: 'bg-faded-base', }, }, //#endregion //#region light { variant: 'light', status: 'error', class: { root: 'bg-error-light', }, }, { variant: 'light', status: 'warning', class: { root: 'bg-warning-light', }, }, { variant: 'light', status: 'success', class: { root: 'bg-success-light', }, }, { variant: 'light', status: 'information', class: { root: 'bg-information-light', }, }, { variant: 'light', status: 'feature', class: { root: 'bg-faded-light', }, }, //#endregion //#region lighter { variant: 'lighter', status: 'error', class: { root: 'bg-error-lighter', }, }, { variant: 'lighter', status: 'warning', class: { root: 'bg-warning-lighter', }, }, { variant: 'lighter', status: 'success', class: { root: 'bg-success-lighter', }, }, { variant: 'lighter', status: 'information', class: { root: 'bg-information-lighter', }, }, { variant: 'lighter', status: 'feature', class: { root: 'bg-faded-lighter', }, }, //#endregion //#region light, lighter, stroke { variant: ['light', 'lighter', 'stroke'], status: 'error', class: { icon: 'text-error-base', }, }, { variant: ['light', 'lighter', 'stroke'], status: 'warning', class: { icon: 'text-warning-base', }, }, { variant: ['light', 'lighter', 'stroke'], status: 'success', class: { icon: 'text-success-base', }, }, { variant: ['light', 'lighter', 'stroke'], status: 'information', class: { icon: 'text-information-base', }, }, { variant: ['light', 'lighter', 'stroke'], status: 'feature', class: { icon: 'text-faded-base', }, }, //#endregion ], defaultVariants: { size: 'small', variant: 'filled', status: 'information', },});type AlertSharedProps = VariantProps<typeof alertVariants>;export type AlertProps = VariantProps<typeof alertVariants> & React.HTMLAttributes<HTMLDivElement> & { wrapperClassName?: ClassValue; };const AlertRoot = React.forwardRef<HTMLDivElement, AlertProps>( ( { children, className, wrapperClassName, size, variant, status, ...rest }, forwardedRef, ) => { const uniqueId = React.useId(); const { root, wrapper } = alertVariants({ size, variant, status }); const sharedProps: AlertSharedProps = { size, variant, status, }; const extendedChildren = recursiveCloneChildren( children as React.ReactElement[], sharedProps, [ALERT_ICON_NAME, ALERT_CLOSE_ICON_NAME], uniqueId, ); return ( <div ref={forwardedRef} className={root({ class: className })} {...rest}> <div className={wrapper({ class: wrapperClassName })}> {extendedChildren} </div> </div> ); },);AlertRoot.displayName = ALERT_ROOT_NAME;function AlertIcon<T extends React.ElementType>({ size, variant, status, className, as,}: PolymorphicComponentProps<T, AlertSharedProps>) { const Component = as || 'div'; const { icon } = alertVariants({ size, variant, status }); return <Component className={icon({ class: className })} />;}AlertIcon.displayName = ALERT_ICON_NAME;function AlertCloseIcon<T extends React.ElementType>({ size, variant, status, className, as,}: PolymorphicComponentProps<T, AlertSharedProps>) { const Component = as || RiCloseLine; const { closeIcon } = alertVariants({ size, variant, status }); return <Component className={closeIcon({ class: className })} />;}AlertCloseIcon.displayName = ALERT_CLOSE_ICON_NAME;export { AlertRoot as Root, AlertIcon as Icon, AlertCloseIcon as CloseIcon };Examples
Variants
filled (Default)
light
lighter
stroke
Size
xsmall
small (Default)
large
API Reference
Alert.Root
This component is based on the <div> element and supports all of its props. And adds:
| Prop | Type | Default |
|---|---|---|
variant | "filled" | "light" | "lighter" | "stroke" | "filled" |
size | "xsmall" | "small" | "large" | "small" |
status | "error" | "warning" | "success" | "information" | "feature" | "information" |
wrapperClassName | string |
Alert.Icon
The Alert.Icon component is polymorphic, allowing you to change the underlying HTML element using the as prop.
| Prop | Type | Default |
|---|---|---|
as | React.ElementType | div |
Alert.CloseIcon
The Alert.CloseIcon component is polymorphic, allowing you to change the underlying HTML element using the as prop.
| Prop | Type | Default |
|---|---|---|
as | React.ElementType | RiCloseLine |