From debf55748f22453fcabfeada7835a413a8ccb297 Mon Sep 17 00:00:00 2001 From: ehmasuk Date: Tue, 13 Jan 2026 23:25:33 +0600 Subject: [PATCH 1/5] feat:empty half --- components/retroui/Empty.tsx | 49 ++++++++++++++++++++++ components/retroui/index.ts | 3 +- config/components.ts | 10 ++++- config/navigation.ts | 1 + content/docs/components/empty.mdx | 8 ++++ preview/components/empty-style-default.tsx | 15 +++++++ 6 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 components/retroui/Empty.tsx create mode 100644 content/docs/components/empty.mdx create mode 100644 preview/components/empty-style-default.tsx diff --git a/components/retroui/Empty.tsx b/components/retroui/Empty.tsx new file mode 100644 index 0000000..587bea6 --- /dev/null +++ b/components/retroui/Empty.tsx @@ -0,0 +1,49 @@ +import { cn } from "@/lib/utils"; +import { HTMLAttributes } from "react"; +import { Text } from "@/components/retroui/Text"; + +interface IEmptyProps extends HTMLAttributes { + className?: string; +} + +const Empty = ({ className, ...props }: IEmptyProps) => { + return ( +
+ ); +}; + +const EmptyHeader = ({ className, ...props }: IEmptyProps) => { + return ( +
+ ); +}; + +const EmptyTitle = ({ className, ...props }: IEmptyProps) => { + return ; +}; + +const EmptyDescription = ({ className, ...props }: IEmptyProps) => ( +

+); + +const EmptyContent = ({ className, ...props }: IEmptyProps) => { + return

; +}; + +const EmptyComponent = Object.assign(Empty, { + Header: EmptyHeader, + Title: EmptyTitle, + Description: EmptyDescription, + Content: EmptyContent, +}); + +export { EmptyComponent as Empty }; diff --git a/components/retroui/index.ts b/components/retroui/index.ts index 62de553..0a233ce 100644 --- a/components/retroui/index.ts +++ b/components/retroui/index.ts @@ -26,4 +26,5 @@ export * from "./Breadcrumb"; export * from "./CommandDisplay"; export * from "./Command"; export * from "./Loader"; -export * from "./ContextMenu"; \ No newline at end of file +export * from "./ContextMenu"; +export * from "./Empty"; \ No newline at end of file diff --git a/config/components.ts b/config/components.ts index e9e3e61..fb72ad5 100644 --- a/config/components.ts +++ b/config/components.ts @@ -1,4 +1,3 @@ -import { table } from "console"; import { lazy } from "react"; export const componentConfig: { @@ -161,6 +160,10 @@ export const componentConfig: { name: "tooltip", filePath: "components/retroui/Tooltip.tsx", }, + empty: { + name: "empty", + filePath: "components/retroui/Empty.tsx", + }, }, examples: { "accordion-style-default": { @@ -716,5 +719,10 @@ export const componentConfig: { filePath: "preview/components/typography-p.tsx", preview: lazy(() => import("@/preview/components/typography-p")), }, + "empty-style-default": { + name: "empty-style-default", + filePath: "preview/components/empty-style-default.tsx", + preview: lazy(() => import("@/preview/components/empty-style-default")) + }, }, }; diff --git a/config/navigation.ts b/config/navigation.ts index f13514e..0706e5f 100644 --- a/config/navigation.ts +++ b/config/navigation.ts @@ -58,6 +58,7 @@ export const navConfig: INavigationConfig = { { title: "Command", href: `${componentsRoute}/command` }, { title: "Dialog", href: `${componentsRoute}/dialog` }, { title: "Drawer", href: `${componentsRoute}/drawer`, tag: "New" }, + { title: "Empty", href: `${componentsRoute}/empty`, tag: "New" }, { title: "Input", href: `${componentsRoute}/input` }, { title: "Label", href: `${componentsRoute}/label` }, { title: "Loader", href: `${componentsRoute}/loader` }, diff --git a/content/docs/components/empty.mdx b/content/docs/components/empty.mdx new file mode 100644 index 0000000..5662724 --- /dev/null +++ b/content/docs/components/empty.mdx @@ -0,0 +1,8 @@ +--- +title: Empty +description: The component that shows when there is no data to show! +lastUpdated: 13 Jan, 2026 +--- + + + \ No newline at end of file diff --git a/preview/components/empty-style-default.tsx b/preview/components/empty-style-default.tsx new file mode 100644 index 0000000..a82ea87 --- /dev/null +++ b/preview/components/empty-style-default.tsx @@ -0,0 +1,15 @@ +import { Empty } from "@/components/retroui/Empty"; + +export default function DefaultEmpty() { + return ( + + + This is Empty Title + + I can not find what to write here.. so imagine I wrote some good + stuff. + + + + ); +} From 9f71abf5991445291342704d88d01c5edab8e6b3 Mon Sep 17 00:00:00 2001 From: ehmasuk Date: Wed, 14 Jan 2026 13:59:09 +0600 Subject: [PATCH 2/5] feat: new empty component that shows when there is no data to show --- components/retroui/Empty.tsx | 54 ++++++++++++---- config/components.ts | 15 +++++ content/docs/components/empty.mdx | 64 ++++++++++++++++++- .../empty-style-custom-everything.tsx | 20 ++++++ .../components/empty-style-custom-icon.tsx | 19 ++++++ preview/components/empty-style-default.tsx | 11 ++-- preview/components/empty-style-table.tsx | 39 +++++++++++ 7 files changed, 203 insertions(+), 19 deletions(-) create mode 100644 preview/components/empty-style-custom-everything.tsx create mode 100644 preview/components/empty-style-custom-icon.tsx create mode 100644 preview/components/empty-style-table.tsx diff --git a/components/retroui/Empty.tsx b/components/retroui/Empty.tsx index 587bea6..b9a694f 100644 --- a/components/retroui/Empty.tsx +++ b/components/retroui/Empty.tsx @@ -1,6 +1,7 @@ +import { Text } from "@/components/retroui/Text"; import { cn } from "@/lib/utils"; +import { Ghost } from "lucide-react"; import { HTMLAttributes } from "react"; -import { Text } from "@/components/retroui/Text"; interface IEmptyProps extends HTMLAttributes { className?: string; @@ -10,40 +11,67 @@ const Empty = ({ className, ...props }: IEmptyProps) => { return (
); }; +Empty.displayName = "Empty"; -const EmptyHeader = ({ className, ...props }: IEmptyProps) => { +const EmptyContent = ({ className, ...props }: IEmptyProps) => { return (
); }; +EmptyContent.displayName = "Empty.Content"; -const EmptyTitle = ({ className, ...props }: IEmptyProps) => { - return ; +const EmptyIcon = ({ children, className, ...props }: IEmptyProps) => { + return ( +
+ {children || } +
+ ); }; +EmptyIcon.displayName = "Empty.Icon"; -const EmptyDescription = ({ className, ...props }: IEmptyProps) => ( -

-); +const EmptyTitle = ({ className, ...props }: IEmptyProps) => { + return ( + + ); +}; +EmptyTitle.displayName = "Empty.Title"; -const EmptyContent = ({ className, ...props }: IEmptyProps) => { - return

; +const EmptySeparator = ({ className, ...props }: IEmptyProps) => { + return
; }; +EmptySeparator.displayName = "Empty.Separator"; + +const EmptyDescription = ({ + className, + ...props +}: HTMLAttributes) => ( +

+); +EmptyDescription.displayName = "Empty.Description"; const EmptyComponent = Object.assign(Empty, { - Header: EmptyHeader, + Content: EmptyContent, + Icon: EmptyIcon, Title: EmptyTitle, + Separator: EmptySeparator, Description: EmptyDescription, - Content: EmptyContent, }); export { EmptyComponent as Empty }; diff --git a/config/components.ts b/config/components.ts index fb72ad5..bd898ef 100644 --- a/config/components.ts +++ b/config/components.ts @@ -724,5 +724,20 @@ export const componentConfig: { filePath: "preview/components/empty-style-default.tsx", preview: lazy(() => import("@/preview/components/empty-style-default")) }, + "empty-style-custom-icon": { + name: "empty-style-custom-icon", + filePath: "preview/components/empty-style-custom-icon.tsx", + preview: lazy(() => import("@/preview/components/empty-style-custom-icon")) + }, + "empty-style-custom-everything": { + name: "empty-style-custom-everything", + filePath: "preview/components/empty-style-custom-everything.tsx", + preview: lazy(() => import("@/preview/components/empty-style-custom-everything")) + }, + "empty-style-table": { + name: "empty-style-table", + filePath: "preview/components/empty-style-table.tsx", + preview: lazy(() => import("@/preview/components/empty-style-table")) + }, }, }; diff --git a/content/docs/components/empty.mdx b/content/docs/components/empty.mdx index 5662724..f93b229 100644 --- a/content/docs/components/empty.mdx +++ b/content/docs/components/empty.mdx @@ -2,7 +2,69 @@ title: Empty description: The component that shows when there is no data to show! lastUpdated: 13 Jan, 2026 +links: + source: https://github.com/Logging-Stuff/RetroUI/blob/main/components/retroui/Empty.tsx --- + - \ No newline at end of file +
+
+ +## Installation + + + + + +#### Copy the code 👇 into your project: + + + + + +
+
+ +## Examples + +### Default + + + +
+
+ +### Custom Icon + + + +
+
+ +### Customize everything + + + +
+
+ +### Using with table + + + +
+
+ +## API Reference + +The Empty component is composed of several sub-components: + +
+ +- `Empty` - The main component wrapper +- `Empty.Content` - Wrapper for the content elements +- `Empty.Icon` - Section for displaying an icon +- `Empty.Title` - The main heading for the empty state +- `Empty.Separator` - A visual separator line +- `Empty.Description` - Supporting text for the empty state diff --git a/preview/components/empty-style-custom-everything.tsx b/preview/components/empty-style-custom-everything.tsx new file mode 100644 index 0000000..e8624ad --- /dev/null +++ b/preview/components/empty-style-custom-everything.tsx @@ -0,0 +1,20 @@ +import { Button } from "@/components/retroui"; +import { Empty } from "@/components/retroui/Empty"; +import { InboxIcon } from "lucide-react"; + +export default function CustomEverythingEmpty() { + return ( + + + + + + No data + + Get started by creating your first item + + + + + ); +} diff --git a/preview/components/empty-style-custom-icon.tsx b/preview/components/empty-style-custom-icon.tsx new file mode 100644 index 0000000..0221f61 --- /dev/null +++ b/preview/components/empty-style-custom-icon.tsx @@ -0,0 +1,19 @@ +import { Empty } from "@/components/retroui/Empty"; + +export default function CustomIconEmpty() { + return ( + + + + 👻 + + No data + + + There is nothing to show here yet. Imagine you wrote some good stuff + here. + + + + ); +} diff --git a/preview/components/empty-style-default.tsx b/preview/components/empty-style-default.tsx index a82ea87..12b192e 100644 --- a/preview/components/empty-style-default.tsx +++ b/preview/components/empty-style-default.tsx @@ -3,13 +3,14 @@ import { Empty } from "@/components/retroui/Empty"; export default function DefaultEmpty() { return ( - - This is Empty Title + + + No Results + - I can not find what to write here.. so imagine I wrote some good - stuff. + Your search didn't match any items. Try adjusting your filters. - + ); } diff --git a/preview/components/empty-style-table.tsx b/preview/components/empty-style-table.tsx new file mode 100644 index 0000000..f8e31a9 --- /dev/null +++ b/preview/components/empty-style-table.tsx @@ -0,0 +1,39 @@ +import { Empty } from "@/components/retroui/Empty"; + +import { Table } from "@/components/retroui/Table"; + +const invoices = []; + +export default function TableEmpty() { + return ( + + + + Invoice + Customer + Status + Method + Amount + + + + + {invoices?.length == 0 && ( + + + + + + Empty + + Get started by creating your first invoice. + + + + + + )} + +
+ ); +} From e17c9edfa866e2fd6e036381069d1cc698f33a24 Mon Sep 17 00:00:00 2001 From: ehmasuk Date: Tue, 13 Jan 2026 23:25:33 +0600 Subject: [PATCH 3/5] feat:empty half --- config/components.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/config/components.ts b/config/components.ts index bd898ef..2fdcf06 100644 --- a/config/components.ts +++ b/config/components.ts @@ -83,6 +83,7 @@ export const componentConfig: { name: "drawer", filePath: "components/retroui/Drawer.tsx", }, + input: { name: "input", filePath: "components/retroui/Input.tsx", From caf12414fa3d0d5f0b2b4c304a721ef64a1dcb45 Mon Sep 17 00:00:00 2001 From: ehmasuk Date: Wed, 14 Jan 2026 15:00:09 +0600 Subject: [PATCH 4/5] fix: update invalid Tailwind class and minor suggestions --- preview/components/empty-style-table.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/preview/components/empty-style-table.tsx b/preview/components/empty-style-table.tsx index f8e31a9..faef53e 100644 --- a/preview/components/empty-style-table.tsx +++ b/preview/components/empty-style-table.tsx @@ -24,7 +24,7 @@ export default function TableEmpty() { - Empty + Empty Get started by creating your first invoice. From 2829c75354c47a6e0c3307dd032223d1e5744b83 Mon Sep 17 00:00:00 2001 From: ehmasuk Date: Wed, 14 Jan 2026 19:12:31 +0600 Subject: [PATCH 5/5] fix: minor suggesions from coderabbitai --- components/retroui/Empty.tsx | 2 +- components/retroui/index.ts | 1 - config/components.ts | 9 ++++----- preview/components/empty-style-custom-everything.tsx | 4 ++-- preview/components/empty-style-default.tsx | 2 +- preview/components/empty-style-table.tsx | 4 ++-- 6 files changed, 10 insertions(+), 12 deletions(-) diff --git a/components/retroui/Empty.tsx b/components/retroui/Empty.tsx index b9a694f..99f1eb2 100644 --- a/components/retroui/Empty.tsx +++ b/components/retroui/Empty.tsx @@ -51,7 +51,7 @@ const EmptyTitle = ({ className, ...props }: IEmptyProps) => { EmptyTitle.displayName = "Empty.Title"; const EmptySeparator = ({ className, ...props }: IEmptyProps) => { - return

; + return
; }; EmptySeparator.displayName = "Empty.Separator"; diff --git a/components/retroui/index.ts b/components/retroui/index.ts index 0a233ce..b19c5fb 100644 --- a/components/retroui/index.ts +++ b/components/retroui/index.ts @@ -6,7 +6,6 @@ export * from "./Radio"; export * from "./Select"; export * from "./Switch"; export * from "./Label"; -export * from "./Input"; export * from "./Text"; export * from "./Accordion"; export * from "./Alert"; diff --git a/config/components.ts b/config/components.ts index 2fdcf06..8f0e122 100644 --- a/config/components.ts +++ b/config/components.ts @@ -83,7 +83,10 @@ export const componentConfig: { name: "drawer", filePath: "components/retroui/Drawer.tsx", }, - + empty: { + name: "empty", + filePath: "components/retroui/Empty.tsx", + }, input: { name: "input", filePath: "components/retroui/Input.tsx", @@ -161,10 +164,6 @@ export const componentConfig: { name: "tooltip", filePath: "components/retroui/Tooltip.tsx", }, - empty: { - name: "empty", - filePath: "components/retroui/Empty.tsx", - }, }, examples: { "accordion-style-default": { diff --git a/preview/components/empty-style-custom-everything.tsx b/preview/components/empty-style-custom-everything.tsx index e8624ad..551e6c1 100644 --- a/preview/components/empty-style-custom-everything.tsx +++ b/preview/components/empty-style-custom-everything.tsx @@ -1,7 +1,7 @@ -import { Button } from "@/components/retroui"; -import { Empty } from "@/components/retroui/Empty"; +import { Button, Empty } from "@/components/retroui"; import { InboxIcon } from "lucide-react"; + export default function CustomEverythingEmpty() { return ( diff --git a/preview/components/empty-style-default.tsx b/preview/components/empty-style-default.tsx index 12b192e..7ccaf02 100644 --- a/preview/components/empty-style-default.tsx +++ b/preview/components/empty-style-default.tsx @@ -1,4 +1,4 @@ -import { Empty } from "@/components/retroui/Empty"; +import { Empty } from "@/components/retroui"; export default function DefaultEmpty() { return ( diff --git a/preview/components/empty-style-table.tsx b/preview/components/empty-style-table.tsx index faef53e..01d6632 100644 --- a/preview/components/empty-style-table.tsx +++ b/preview/components/empty-style-table.tsx @@ -18,9 +18,9 @@ export default function TableEmpty() { - {invoices?.length == 0 && ( + {invoices?.length === 0 && ( - +