Aura Design System

Presence

Keeps content mounted while it fades out.

Preview

Visible while present
import { Presence } from "@/components/ui/Presence";

export function PresenceDemo() {
  return (
  <Presence present>
    <div className="rounded-sm bg-accent-3 p-1">Visible while present</div>
  </Presence>
)
}

Installation

Make sure that namespace is set in your component.json file. Namespace docs: Learn more about namespaces

pnpm dlx shadcn@latest add @aura/presence

Manual

Copy and paste the class names utility into your utils/class-names.ts file.

import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs))
}

Copy and paste the Presence component into your components/ui/Presence.tsx file.

"use client";

import * as React from "react";
import { cn } from "@/utils/class-names";

function Presence({
  className,
  present,
  children,
}: {
  className?: string;
  present: boolean;
  children?: React.ReactNode;
}) {
  const [shown, setShown] = React.useState(present);

  React.useEffect(() => {
    if (present) {
      setShown(true);
      return;
    }
    const reduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    if (reduced) setShown(false);
  }, [present]);

  if (!shown) return null;

  return (
    <div
      data-slot="presence"
      data-present={present ? "" : undefined}
      className={cn(
        "transition duration-300 motion-reduce:transition-none",
        present ? "scale-100 opacity-100" : "scale-95 opacity-0",
        className,
      )}
      onTransitionEnd={() => {
        if (!present) setShown(false);
      }}
    >
      {children}
    </div>
  );
}

export { Presence };