Skip to content

Empty State

ComponentMantine ≥ 9

Centered empty/zero-data placeholder with an optional icon and call to action.

Install

One command copies the item's source into your project, where you own and edit it.

Terminal window
npx manteen add @house/empty-state

Dependencies

  • @mantine/core@^9npm
  • @tabler/icons-react@^3npm

Preview

Usage

A copy-ready example published by the registry author. Imports use the aliases Manteen configures at init.

empty-state.usage.tsx
import { EmptyState } from "@/components/ui/empty-state";
export function EmptyInbox() {
return (
<EmptyState
title="No messages yet"
description="When someone sends you a message, it will show up here."
action={{
label: "Compose message",
onClick: () => console.log("compose"),
}}
/>
);
}

Props

Author-documented props, carried verbatim from the registry item.

PropTypeDefaultDescription
titlestring"Nothing here yet"Heading text shown below the icon.
descriptionReactNodeSupporting text rendered under the title; nothing renders when omitted.
iconReactNodeCustom icon rendered inside the theme icon circle; defaults to an inbox icon.
action{ label: string; onClick: () => void }Renders a button below the description that calls onClick when clicked; no button renders when omitted.
...othersBoxProps & ElementProps<"div", "title">All other props are forwarded to the root <Center>, after its own py="xl", so both can be overridden. Mantine Styles API props (classNames, styles, unstyled) are also accepted.

* required

Styling

EmptyState exposes these parts through the public classNames/styles interface:

  • root
  • icon
  • title
  • description
  • action

Author-declared; Manteen reports the declaration but does not verify each selector is wired.

Source

2 installable files ship with this item.

registry/ui/empty-state.tsxcomponent · 2.3 kB · tsx
import {
type BoxProps,
Button,
Center,
type ElementProps,
type Factory,
factory,
Stack,
type StylesApiProps,
Text,
ThemeIcon,
Title,
useProps,
useStyles,
} from "@mantine/core";
import { IconInbox } from "@tabler/icons-react";
import type { ReactNode } from "react";
import classes from "./empty-state.module.css";
export type EmptyStateStylesNames = "root" | "icon" | "title" | "description" | "action";
export interface EmptyStateProps
extends BoxProps,
StylesApiProps<EmptyStateFactory>,
ElementProps<"div", "title"> {
title?: string;
description?: ReactNode;
icon?: ReactNode;
action?: { label: string; onClick: () => void };
}
export type EmptyStateFactory = Factory<{
props: EmptyStateProps;
ref: HTMLDivElement;
stylesNames: EmptyStateStylesNames;
}>;
export const EmptyState = factory<EmptyStateFactory>((_props) => {
const props = useProps("EmptyState", null, _props);
const {
classNames,
className,
style,
styles,
unstyled,
vars,
attributes,
ref,
title = "Nothing here yet",
description,
icon,
action,
...others
} = props;
const getStyles = useStyles<EmptyStateFactory>({
name: "EmptyState",
classes,
props,
className,
style,
classNames,
styles,
unstyled,
attributes,
vars,
});
return (
<Center ref={ref} py="xl" unstyled={unstyled} {...getStyles("root")} {...others}>
<Stack align="center" gap="xs" maw={360} ta="center">
<ThemeIcon variant="light" size={48} radius="xl" {...getStyles("icon")}>
{icon ?? <IconInbox size={24} />}
</ThemeIcon>
<Title order={4} {...getStyles("title")}>
{title}
</Title>
{description && (
<Text c="dimmed" size="sm" {...getStyles("description")}>
{description}
</Text>
)}
{action && (
<Button mt="sm" onClick={action.onClick} {...getStyles("action")}>
{action.label}
</Button>
)}
</Stack>
</Center>
);
});
EmptyState.classes = classes;
EmptyState.displayName = "EmptyState";
export namespace EmptyState {
export type Props = EmptyStateProps;
export type StylesNames = EmptyStateStylesNames;
export type Factory = EmptyStateFactory;
}
registry/ui/empty-state.module.cssstyle · 199 B · css
.root {
--empty-state-root: 1;
}
.icon {
--empty-state-icon: 1;
}
.title {
--empty-state-title: 1;
}
.description {
--empty-state-description: 1;
}
.action {
--empty-state-action: 1;
}