Empty State
A centered placeholder with an icon, title, and hint shown when a list or view has no content.
A centered placeholder with an icon, title, and hint shown when a list or view has no content. Compose it from the exported registry parts so local content and behaviour stay in the application while the visual contract stays token-driven.
newt-empty-stateimport {
EmptyState,
EmptyStateDescription,
EmptyStateIcon,
EmptyStateTitle,
} from "@/registry/bases/newt/ui/empty-state"
export default function EmptyStateDemo() {
return (
<EmptyState>
<EmptyStateIcon>📭</EmptyStateIcon>
<EmptyStateTitle>Nothing here yet</EmptyStateTitle>
<EmptyStateDescription>
Description of what to do next.
</EmptyStateDescription>
</EmptyState>
)
}<script setup lang="ts">
import {
EmptyState,
EmptyStateDescription,
EmptyStateIcon,
EmptyStateTitle,
} from "~~/registry/bases/newt/ui/empty-state"
</script>
<template>
<EmptyState>
<EmptyStateIcon>📭</EmptyStateIcon>
<EmptyStateTitle>Nothing here yet</EmptyStateTitle>
<EmptyStateDescription
>Description of what to do next.</EmptyStateDescription
>
</EmptyState>
</template>Installation
pnpm dlx newtui@latest add empty-statenpx newtui@latest add empty-stateyarn dlx newtui@latest add empty-statebunx newtui@latest add empty-stateCopy the source into your project
import * as React from "react"
import { cn } from "@/lib/utils"
const EmptyState = React.forwardRef<
HTMLDivElement,
React.ComponentProps<"div">
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn(
"flex flex-col items-center gap-2 px-5 py-10 text-center text-newt-text-muted",
className
)}
{...props}
/>
))
EmptyState.displayName = "EmptyState"
const EmptyStateIcon = React.forwardRef<
HTMLDivElement,
React.ComponentProps<"div">
>(({ className, ...props }, ref) => (
<div
ref={ref}
aria-hidden="true"
className={cn("mb-1 text-[40px] leading-none opacity-60", className)}
{...props}
/>
))
EmptyStateIcon.displayName = "EmptyStateIcon"
const EmptyStateTitle = React.forwardRef<
HTMLDivElement,
React.ComponentProps<"div">
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("text-base font-semibold text-newt-text-primary", className)}
{...props}
/>
))
EmptyStateTitle.displayName = "EmptyStateTitle"
const EmptyStateDescription = React.forwardRef<
HTMLDivElement,
React.ComponentProps<"div">
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("max-w-[320px] text-sm leading-normal", className)}
{...props}
/>
))
EmptyStateDescription.displayName = "EmptyStateDescription"
export { EmptyState, EmptyStateIcon, EmptyStateTitle, EmptyStateDescription }<script setup lang="ts">
import type { HTMLAttributes } from "vue"
import { cn } from "@/lib/utils"
const props = defineProps<{ class?: HTMLAttributes["class"] }>()
</script>
<template>
<div
:class="
cn(
'flex flex-col items-center gap-2 px-5 py-10 text-center text-newt-text-muted',
props.class
)
"
>
<slot />
</div>
</template><script setup lang="ts">
import type { HTMLAttributes } from "vue"
import { cn } from "@/lib/utils"
const props = defineProps<{ class?: HTMLAttributes["class"] }>()
</script>
<template>
<div
aria-hidden="true"
:class="cn('mb-1 text-[40px] leading-none opacity-60', props.class)"
>
<slot />
</div>
</template><script setup lang="ts">
import type { HTMLAttributes } from "vue"
import { cn } from "@/lib/utils"
const props = defineProps<{ class?: HTMLAttributes["class"] }>()
</script>
<template>
<div
:class="cn('text-base font-semibold text-newt-text-primary', props.class)"
>
<slot />
</div>
</template><script setup lang="ts">
import type { HTMLAttributes } from "vue"
import { cn } from "@/lib/utils"
const props = defineProps<{ class?: HTMLAttributes["class"] }>()
</script>
<template>
<div :class="cn('max-w-[320px] text-sm leading-normal', props.class)">
<slot />
</div>
</template>export { default as EmptyState } from "./EmptyState.vue"
export { default as EmptyStateIcon } from "./EmptyStateIcon.vue"
export { default as EmptyStateTitle } from "./EmptyStateTitle.vue"
export { default as EmptyStateDescription } from "./EmptyStateDescription.vue"Update the import paths
The files import @/lib/utils and sibling components through the aliases in your components.json. Point them at wherever those live in your project.
Usage
import { EmptyState } from "@/components/ui/empty-state"
export function Example() {
return <EmptyState />
}<script setup lang="ts">
import { EmptyState, EmptyStateIcon, EmptyStateTitle, EmptyStateDescription } from "@/components/ui/empty-state"
</script>
<template>
<EmptyState />
</template>API reference
EmptyState
children / default slot?React.ReactNode / Vue slot
Content rendered inside the component.
React.ReactNode / Vue slotclassName / class?string
Additional classes merged with the component defaults.
stringThe registry exports EmptyState, EmptyStateIcon, EmptyStateTitle, EmptyStateDescription. Parts without a table accept the native attributes for the element they render; React uses className, while Vue uses class and fallthrough attributes.
Accessibility
Preserve the native semantics of the rendered elements and pass through ARIA attributes when the surrounding context needs a label or description. Any interactive child needs a visible focus indicator, and meaning must not rely on colour alone.
Tokens
Empty State reads its colours, radii and motion from the --newt-* tokens installed with the library. Override a token and every component that reads it follows, including this one — see the token layer. In the plain HTML and CSS distribution the same component is newt-empty-state.