CoreUI is in beta - APIs and components may change.
CoreUI
Base Components

Compact Button

Buttons that are ideal for when space is limited.


Installation

Install the following dependencies:

npm install @radix-ui/react-slot

Create a compact-button.tsx file and paste the following code into it.

components/ui/compact-button.tsx
// CoreUI CompactButton 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 COMPACT_BUTTON_ROOT_NAME = 'CompactButtonRoot';const COMPACT_BUTTON_ICON_NAME = 'CompactButtonIcon';export const compactButtonVariants = tv({  slots: {    root: [      // base      'relative flex shrink-0 items-center justify-center outline-none',      'transition duration-200 ease-out',      // disabled      'disabled:text-text-disabled-300 disabled:pointer-events-none disabled:border-transparent disabled:bg-transparent disabled:shadow-none',      // focus      'focus:outline-none',    ],    icon: '',  },  variants: {    variant: {      stroke: {        root: [          // base          'border-stroke-soft-200 bg-bg-white-0 text-text-sub-600 shadow-regular-xs border',          // hover          'hover:bg-bg-weak-50 hover:text-text-strong-950 hover:border-transparent hover:shadow-none',          // focus          'focus-visible:bg-bg-strong-950 focus-visible:text-text-white-0 focus-visible:border-transparent focus-visible:shadow-none',        ],      },      ghost: {        root: [          // base          'text-text-sub-600 bg-transparent',          // hover          'hover:bg-bg-weak-50 hover:text-text-strong-950',          // focus          'focus-visible:bg-bg-strong-950 focus-visible:text-text-white-0',        ],      },      white: {        root: [          // base          'bg-bg-white-0 text-text-sub-600 shadow-regular-xs',          // hover          'hover:bg-bg-weak-50 hover:text-text-strong-950',          // focus          'focus-visible:bg-bg-strong-950 focus-visible:text-text-white-0',        ],      },      modifiable: {},    },    size: {      large: {        root: 'size-6',        icon: 'size-5',      },      medium: {        root: 'size-5',        icon: 'size-[18px]',      },    },    fullRadius: {      true: {        root: 'rounded-full',      },      false: {        root: 'rounded-md',      },    },  },  defaultVariants: {    variant: 'stroke',    size: 'large',    fullRadius: false,  },});type CompactButtonSharedProps = Omit<  VariantProps<typeof compactButtonVariants>,  'fullRadius'>;type CompactButtonProps = VariantProps<typeof compactButtonVariants> &  React.ButtonHTMLAttributes<HTMLButtonElement> & {    asChild?: boolean;  };const CompactButtonRoot = React.forwardRef<  HTMLButtonElement,  CompactButtonProps>(  (    { asChild, variant, size, fullRadius, children, className, ...rest },    forwardedRef,  ) => {    const uniqueId = React.useId();    const Component = asChild ? Slot : 'button';    const { root } = compactButtonVariants({ variant, size, fullRadius });    const sharedProps: CompactButtonSharedProps = {      variant,      size,    };    const extendedChildren = recursiveCloneChildren(      children as React.ReactElement[],      sharedProps,      [COMPACT_BUTTON_ICON_NAME],      uniqueId,      asChild,    );    return (      <Component        ref={forwardedRef}        className={root({ class: className })}        {...rest}      >        {extendedChildren}      </Component>    );  },);CompactButtonRoot.displayName = COMPACT_BUTTON_ROOT_NAME;function CompactButtonIcon<T extends React.ElementType>({  variant,  size,  as,  className,  ...rest}: PolymorphicComponentProps<T, CompactButtonSharedProps>) {  const Component = as || 'div';  const { icon } = compactButtonVariants({ variant, size });  return <Component className={icon({ class: className })} {...rest} />;}CompactButtonIcon.displayName = COMPACT_BUTTON_ICON_NAME;export { CompactButtonRoot as Root, CompactButtonIcon as Icon };

Examples

Stroke (Default)

Ghost

White

Modifiable

Text color inherits from the parent by default. No default color, background or hover colors are applied, allowing for full customization.

Here's an example with custom colors specified:

Size

Full Radius

Disabled

asChild

Composition

You can simplify component usage by creating a custom API that abstracts the core functionalities.

An example with a required icon prop:

API Reference

CompactButton.Root

This component is based on the <button> element and supports all of its props. And adds:

PropTypeDefault
variant"stroke" | "ghost" | "white" | "modifiable""stroke"
size"large" | "medium""large"
fullRadiusbooleanfalse
asChildboolean

CompactButton.Icon

The CompactButton.Icon component is polymorphic, allowing you to change the underlying HTML element using the as prop.

PropTypeDefault
asReact.ElementTypediv

On this page