Base Components
Banner
Delivering crucial alerts and information prominently at the top of the screen.
Insert your alert title here!∙Insert your description here.
Installation
Install the following dependencies:
npm install @radix-ui/react-slotCreate a banner.tsx file and paste the following code into it.
// CoreUI Banner v0.0.0import * as React from 'react';import { Slot } from '@radix-ui/react-slot';import { PolymorphicComponentProps } from '@/utils/polymorphic';import { recursiveCloneChildren } from '@/utils/recursive-clone-children';import { tv, type VariantProps } from '@/utils/tv';const BANNER_ROOT_NAME = 'BannerRoot';const BANNER_CONTENT_NAME = 'BannerContent';const BANNER_ICON_NAME = 'BannerIcon';const BANNER_CLOSE_BUTTON_NAME = 'BannerCloseButton';export const bannerVariants = tv({ slots: { root: 'relative grid h-11 w-full grid-cols-[1fr_auto_1fr] items-center justify-center gap-3 px-3', content: 'col-start-2 flex items-center justify-center gap-3', icon: 'size-5 shrink-0', closeButton: 'size-5', }, variants: { variant: { filled: {}, light: {}, lighter: {}, stroke: { root: 'bg-bg-white-0 text-text-strong-950 before:absolute before:bottom-0 before:h-px before:w-full before:bg-stroke-soft-200', }, }, status: { error: {}, warning: {}, success: {}, information: {}, feature: {}, }, }, compoundVariants: [ //#region closeButton { variant: 'filled', class: { closeButton: 'opacity-[.72]', }, }, { variant: ['light', 'lighter', 'stroke'], class: { closeButton: 'opacity-[.48]', }, }, //#endregion //#region status=error { variant: 'filled', status: 'error', class: { icon: 'text-static-white', root: 'bg-error-base text-static-white', }, }, { variant: 'light', status: 'error', class: { icon: 'text-error-base', root: 'bg-error-light text-text-strong-950', }, }, { variant: 'lighter', status: 'error', class: { icon: 'text-error-base', root: 'bg-error-lighter text-text-strong-950', }, }, { variant: 'stroke', status: 'error', class: { icon: 'text-error-base', }, }, //#endregion //#region status=warning { variant: 'filled', status: 'warning', class: { icon: 'text-static-white', root: 'bg-warning-base text-static-white', }, }, { variant: 'light', status: 'warning', class: { icon: 'text-warning-base', root: 'bg-warning-light text-text-strong-950', }, }, { variant: 'lighter', status: 'warning', class: { icon: 'text-warning-base', root: 'bg-warning-lighter text-text-strong-950', }, }, { variant: 'stroke', status: 'warning', class: { icon: 'text-warning-base', }, }, //#endregion //#region status=success { variant: 'filled', status: 'success', class: { icon: 'text-static-white', root: 'bg-success-base text-static-white', }, }, { variant: 'light', status: 'success', class: { icon: 'text-success-base', root: 'bg-success-light text-text-strong-950', }, }, { variant: 'lighter', status: 'success', class: { icon: 'text-success-base', root: 'bg-success-lighter text-text-strong-950', }, }, { variant: 'stroke', status: 'success', class: { icon: 'text-success-base', }, }, //#endregion //#region status=information { variant: 'filled', status: 'information', class: { icon: 'text-static-white', root: 'bg-information-base text-static-white', }, }, { variant: 'light', status: 'information', class: { icon: 'text-information-base', root: 'bg-information-light text-text-strong-950', }, }, { variant: 'lighter', status: 'information', class: { icon: 'text-information-base', root: 'bg-information-lighter text-text-strong-950', }, }, { variant: 'stroke', status: 'information', class: { icon: 'text-information-base', }, }, //#endregion //#region status=feature { variant: 'filled', status: 'feature', class: { icon: 'text-static-white', root: 'bg-faded-base text-static-white', }, }, { variant: 'light', status: 'feature', class: { icon: 'text-faded-base', root: 'bg-faded-light text-text-strong-950', }, }, { variant: 'lighter', status: 'feature', class: { icon: 'text-faded-base', root: 'bg-faded-lighter text-text-strong-950', }, }, { variant: 'stroke', status: 'feature', class: { icon: 'text-faded-base', }, }, //#endregion ], defaultVariants: { variant: 'filled', status: 'feature', },});type BannerSharedProps = VariantProps<typeof bannerVariants>;type BannerProps = VariantProps<typeof bannerVariants> & React.HTMLAttributes<HTMLDivElement>;function Banner({ children, className, variant, status, ...rest}: BannerProps) { const uniqueId = React.useId(); const { root } = bannerVariants({ variant, status }); const sharedProps: BannerSharedProps = { variant, status, }; const extendedChildren = recursiveCloneChildren( children as React.ReactElement[], sharedProps, [BANNER_ICON_NAME, BANNER_CLOSE_BUTTON_NAME], uniqueId, ); return ( <div className={root({ class: className })} {...rest}> {extendedChildren} </div> );}Banner.displayName = BANNER_ROOT_NAME;function BannerContent({ className, ...rest}: React.HTMLAttributes<HTMLDivElement>) { const { content } = bannerVariants(); return <div className={content({ class: className })} {...rest} />;}BannerContent.displayName = BANNER_CONTENT_NAME;type BannerIconProps = BannerSharedProps & React.HTMLAttributes<HTMLDivElement>;function BannerIcon<T extends React.ElementType>({ className, variant, status, as, ...rest}: PolymorphicComponentProps<T, BannerIconProps>) { const Component = as || 'div'; const { icon } = bannerVariants({ variant, status }); return <Component className={icon({ class: className })} {...rest} />;}BannerIcon.displayName = BANNER_ICON_NAME;type BannerCloseButtonProps = BannerSharedProps & React.ButtonHTMLAttributes<HTMLButtonElement> & { asChild?: boolean; };const BannerCloseButton = React.forwardRef< HTMLButtonElement, BannerCloseButtonProps>( ( { asChild, children, variant, status, className, ...rest }, forwardedRef, ) => { const Component = asChild ? Slot : 'button'; const { closeButton } = bannerVariants({ variant, status }); return ( <div className="col-start-3 flex items-center justify-end self-center"> <Component ref={forwardedRef} className={closeButton({ class: className })} {...rest} > {children} </Component> </div> ); },);BannerCloseButton.displayName = BANNER_CLOSE_BUTTON_NAME;export { Banner as Root, BannerContent as Content, BannerIcon as Icon, BannerCloseButton as CloseButton,};Examples
variant="error"
Insert your alert title here!∙Insert your description here.
Insert your alert title here!∙Insert your description here.
Insert your alert title here!∙Insert your description here.
Insert your alert title here!∙Insert your description here.
variant="warning"
Insert your alert title here!∙Insert your description here.
Insert your alert title here!∙Insert your description here.
Insert your alert title here!∙Insert your description here.
Insert your alert title here!∙Insert your description here.
variant="success"
Insert your alert title here!∙Insert your description here.
Insert your alert title here!∙Insert your description here.
Insert your alert title here!∙Insert your description here.
Insert your alert title here!∙Insert your description here.
variant="information"
Insert your alert title here!∙Insert your description here.
Insert your alert title here!∙Insert your description here.
Insert your alert title here!∙Insert your description here.
Insert your alert title here!∙Insert your description here.
variant="feature"
Insert your alert title here!∙Insert your description here.
Insert your alert title here!∙Insert your description here.
Insert your alert title here!∙Insert your description here.
Insert your alert title here!∙Insert your description here.
API Reference
Banner.Root
| Prop | Type | Default |
|---|---|---|
variant | "filled" | "light" | "lighter" | "stroke" | "filled" |
status | "error" | "warning" | "success" | "information" | "feature" | "feature" |
Banner.Content
The content section of the banner. This component is based on the <div> element and supports all of its props.
Banner.Icon
The Banner.Icon component is polymorphic, allowing you to change the underlying HTML element using the as prop.
| Prop | Type | Default |
|---|---|---|
as | React.ElementType | div |
Banner.CloseButton
This component is based on the <button> element and supports all of its props. And adds:
| Prop | Type | Default |
|---|---|---|
asChild | boolean |
Badge
A badge is a piece of text that is visually stylized to differentiate it as contextual metadata. It can be used to add a status, category, or other metadata to a design.
Data Table
Data table is a 2-dimensional data structure where each row is an item, and each column is a data point about the item.