Quick Actions

Grid of dashboard shortcut tiles with icon, label and description. Each tile is a button or, via asChild, a link. Compound API.

Example

Installation

npx shadcn@latest add https://hirael.com/r/quick-actions.json

API

<QuickActions />

+ native element props
PropTypeDefault
columns

Number of columns in the action grid.

number2

<QuickAction />

+ native element props
PropTypeDefault
asChildbooleanfalse

<QuickActionIcon />

+ native element props

No props of its own — forwards everything to the underlying element.

<QuickActionLabel />

+ native element props

No props of its own — forwards everything to the underlying element.

<QuickActionDescription />

+ native element props

No props of its own — forwards everything to the underlying element.

Component source

"use client";

import * as React from "react";
import { Slot } from "@radix-ui/react-slot";

import { cn } from "@/lib/utils";

type QuickActionsProps = React.ComponentProps<"div"> & {
  /** Number of columns in the action grid. */
  columns?: number;
};

function QuickActions({
  columns = 2,
  className,
  style,
  ...props
}: QuickActionsProps) {
  return (
    <div
      data-slot="quick-actions"
      className={cn("grid gap-2", className)}
      style={{
        gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`,
        ...style,
      }}
      {...props}
    />
  );
}

type QuickActionProps = React.ComponentProps<"button"> & {
  asChild?: boolean;
};

function QuickAction({
  asChild = false,
  className,
  ...props
}: QuickActionProps) {
  const Comp = asChild ? Slot : "button";
  return (
    <Comp
      data-slot="quick-action"
      className={cn(
        "group flex flex-col items-start gap-2.5 rounded-lg border border-border bg-card p-3 text-start transition-colors hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
        className,
      )}
      {...(asChild ? {} : { type: "button" })}
      {...props}
    />
  );
}

type QuickActionIconProps = React.ComponentProps<"span">;

function QuickActionIcon({ className, ...props }: QuickActionIconProps) {
  return (
    <span
      data-slot="quick-action-icon"
      className={cn(
        "inline-flex size-8 items-center justify-center rounded-md border border-border bg-background text-foreground transition-colors group-hover:bg-card [&_svg]:size-4",
        className,
      )}
      {...props}
    />
  );
}

type QuickActionLabelProps = React.ComponentProps<"span">;

function QuickActionLabel({ className, ...props }: QuickActionLabelProps) {
  return (
    <span
      data-slot="quick-action-label"
      className={cn("text-sm font-medium text-foreground", className)}
      {...props}
    />
  );
}

type QuickActionDescriptionProps = React.ComponentProps<"span">;

function QuickActionDescription({
  className,
  ...props
}: QuickActionDescriptionProps) {
  return (
    <span
      data-slot="quick-action-description"
      className={cn("text-xs text-muted-foreground", className)}
      {...props}
    />
  );
}

export {
  QuickActions,
  QuickAction,
  QuickActionIcon,
  QuickActionLabel,
  QuickActionDescription,
};

Dependencies

npm

@radix-ui/react-slot