Aceternity screens
StableFive screens in the Aceternity style: a spotlight hero, a borderless sidebar, a signup-style form, a floating navbar and a lamp.
Grid and dot backgrounds that fade at the edges, a spotlight, gradient headlines, a button with a glowing border and the lamp effect, recreated in plain CSS. The darkest of the four styles: dark mode is true black. Hero takes no props; Navbar wraps your page.
Aceternity hero
import { AceternityHero } from '@rchursin/screens'
/** * A hero in the Aceternity style: a spotlight over a grid that fades at the edges, a gradient * headline and a button with a glowing border. The page wraps it in a <main>. */export default function AceternityHeroPage() { return ( <main className="min-h-dvh bg-white dark:bg-black"> <AceternityHero /> </main> )}Usage
import { AceternityAppShell, AceternityHero, AceternityLoading, AceternityNavbar, AceternitySignIn,} from '@rchursin/screens'<AceternityNavbar className="min-h-dvh"> <main>{/* your page */}</main></AceternityNavbar>Examples
Aceternity app shell
A borderless sidebar and the page in a panel rounded at the top left, holding a sample weekly report.
import { SampleBadge } from '@rchursin/product/shell/layout'import { AceternityAppShell } from '@rchursin/screens'
/** * A borderless sidebar with the page in a panel rounded at the top left. Without children it * shows pulsing placeholders; here it holds a page that starts with its <h1>. The sidebar * shows from 768px up. */const verdicts = [ { verdict: 'Keep', count: 5, note: 'Used every week and finish the job' }, { verdict: 'Fix', count: 2, note: 'Run often, fail more than half the time' }, { verdict: 'Merge', count: 6, note: 'Two skills doing the same job' }, { verdict: 'Cut', count: 68, note: 'No runs in 30 days or more' },]
export default function AceternityAppShellPage() { return ( <AceternityAppShell> <div className="flex flex-wrap items-center justify-between gap-3"> <h1 className="text-2xl font-semibold tracking-tight text-ink dark:text-white">This week’s report</h1> <SampleBadge /> </div> <ul className="mt-4 grid grid-cols-1 gap-2 sm:grid-cols-2"> {verdicts.map((v) => ( <li key={v.verdict} className="flex flex-col gap-1 rounded-lg bg-neutral-100 p-4 dark:bg-neutral-800"> <span className="flex items-baseline justify-between gap-3"> <span className="font-medium text-ink dark:text-white">{v.verdict}</span> <span className="text-2xl font-semibold text-ink tabular-nums dark:text-white">{v.count}</span> </span> <span className="text-sm text-neutral-600 dark:text-neutral-300">{v.note}</span> </li> ))} </ul> </AceternityAppShell> )}Aceternity sign-in
Soft-shadow fields, a gradient button with a glowing bottom edge, and SSO, over a dot background.
import { AceternitySignIn } from '@rchursin/screens'
/** * The signup-form pattern: soft-shadow fields, a gradient button with a glowing bottom edge, a * gradient divider and SSO, over a dot background. Its title is an <h2>, so the page adds a * <main> and a visually hidden <h1>. Connect your own submit. */export default function AceternitySignInPage() { return ( <main> <h1 className="sr-only">Sign in to RChursin_</h1> <AceternitySignIn /> </main> )}Aceternity navbar
A pill-shaped bar floating over a grid background. It stays 24 pixels from the top as you scroll.
import { AceternityNavbar } from '@rchursin/screens'
/** * A pill-shaped bar that floats over a grid background and stays 24px from the top as the page * scrolls. Your page goes in as children. Below 768px only the logo and the button remain. */export default function AceternityNavbarPage() { return ( <AceternityNavbar className="min-h-dvh"> <main className="mx-auto flex max-w-3xl flex-col items-center gap-5 px-6 pt-28 pb-32 text-center"> <h1 className="text-4xl font-semibold tracking-[-0.03em] text-balance sm:text-5xl">[Your page title]</h1> <p className="max-w-xl text-lg text-pretty text-stone dark:text-fog">[One line on what this page is for.]</p> <div className="mt-6 flex min-h-72 w-full items-center justify-center rounded-2xl border border-dashed border-neutral-900/15 bg-white/60 text-sm text-stone dark:border-white/15 dark:bg-black/60 dark:text-fog"> Page content </div> </main> </AceternityNavbar> )}Aceternity loading screen
A lamp: a cone of light and a glowing line above the mark.
import { AceternityLoading } from '@rchursin/screens'
/** * A lamp: a cone of light and a glowing line above the mark, with the words "Loading * workspace" in a role="status" region. The page adds a <main> and a hidden <h1>. */export default function AceternityLoadingPage() { return ( <main> <h1 className="sr-only">Loading your workspace</h1> <AceternityLoading /> </main> )}API
AceternityAppShell props
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | – | The page inside <main>. Without it, pulsing placeholder tiles. Start it with the page’s <h1>. |
className | string | 'min-h-dvh' | Classes on the root. Sets the height: pass your own (e.g. "h-[640px]") to fit a frame. |
AceternityNavbar props
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | – | Your page, under the floating bar and over the grid. Put your <main> here. |
className | string | – | Classes on the wrapper. It has no height of its own: pass min-h-dvh for a full page. |
AceternitySignIn props
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | 'min-h-dvh' | Classes on the root. Sets the height: pass your own (e.g. "h-[640px]") to fit a frame. |
AceternityLoading props
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | 'min-h-dvh' | Classes on the root. Sets the height: pass your own (e.g. "h-[640px]") to fit a frame. |
Accessibility
Keyboard
| Key | What it does |
|---|---|
| Tab | Moves through the links, fields and buttons in reading order. Every control is a native element. |
| Enter | In a sign-in form: submits it. The form only calls preventDefault(), so connect your own handler. |
- Backgrounds, the spotlight and the lamp are aria-hidden; the lamp and spotlight play once and stop with reduced motion.
- The floating bar is a navigation named “Global” with aria-current="page" on its first link. Below 768 pixels only the logo and the button remain, with no menu.
- The loading screen is a role="status" region that reads “Loading workspace”. AceternityLoading has no message prop.
- Without children, the app shell’s placeholders pulse only when motion is allowed (motion-safe:animate-pulse); with your content in it, nothing moves.
- Sign-in fields have labels and autocomplete; the title is an <h2>, so give the page an <h1>.
- The hero’s own header shows its three links from 640 pixels up; below that only the logo remains, so nothing runs into it.
Guidelines
Do
- Copy the screen into your app and swap its placeholder links, [bracketed] copy and handlers for your own.
- Wrap a screen without a <main> in one, and give a sign-in or loading page an <h1> (hidden is fine), as the examples do.
- Keep the Aceternity look within a screen: its spacing, radius and round-capped icons belong together.
Don’t
- Don’t ship the placeholder buttons that open nothing (menu triggers, search) without wiring them up.
- Don’t mix screens from two styles on one page.
- Don’t pass a height class that cuts off the content on a phone; min-h-dvh is the default for a reason.
In use
Related
- BackgroundsDot and grid patterns, masks and vignettes to fade them, a retro floor grid, a spotlight, a lamp and a softly lit card.
- Animated accentsShiny and gradient text, a beam round a border, a shine border, ripples, lines that type in and a scanning column.
- Effect buttonsA shimmer button, a shiny announcement pill and a glowing border, from the launch-page screens.
- Magic UI screensFive screens with Magic UI’s effects: retro grid, border beam, shiny and gradient text, shimmer buttons, ripples and a dock.
- Screen iconsFifteen small round-capped icons used by the library-style screens, each its own component.
- Tailwind Plus screensFive screens in the Tailwind Plus style: a centred hero, a sidebar app shell, a sign-in form, a header and a loading screen.
Source
The component’s own files, exactly as they run on this site.
/** * Aceternity style · Sidebar: borderless sidebar with icon links, content in a * rounded-top-left panel, loading placeholders that pulse. * Pass `children` for page content and `className` to control height (defaults to full viewport). */import type { ComponentType, ReactNode, SVGProps } from "react"import { Logo } from "../../brand/Logo"import { cx } from "../../components/cx"import { ActivityIcon, FolderIcon, HomeIcon, SlidersIcon } from "../../components/icons"
const nav: { label: string; icon: ComponentType<SVGProps<SVGSVGElement>>; current?: boolean }[] = [ { label: "Home", icon: HomeIcon, current: true }, { label: "Projects", icon: FolderIcon }, { label: "Activity", icon: ActivityIcon }, { label: "Settings", icon: SlidersIcon },]
const box = "rounded-lg bg-neutral-100 motion-safe:animate-pulse dark:bg-neutral-800"
export function AceternityAppShell({