Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: new empty placeholder component #2792

Merged
merged 40 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
89962d1
first draft
MichaelUnkey Jan 7, 2025
6d7930d
Empty component and styled
MichaelUnkey Jan 7, 2025
4bad5c8
missing import
MichaelUnkey Jan 7, 2025
2ac7e0f
Merge branch 'main' of https://github.com/unkeyed/unkey into eng-1606…
MichaelUnkey Jan 7, 2025
19c2ce9
[autofix.ci] apply automated fixes
autofix-ci[bot] Jan 7, 2025
b3c14ef
small chages
MichaelUnkey Jan 7, 2025
543e379
styling fixes
MichaelUnkey Jan 8, 2025
3804973
[autofix.ci] apply automated fixes
autofix-ci[bot] Jan 8, 2025
f856e8e
reverted colors
MichaelUnkey Jan 8, 2025
b75ed45
typo
MichaelUnkey Jan 8, 2025
27d13d9
Merge branch 'main' of https://github.com/unkeyed/unkey into eng-1606…
MichaelUnkey Jan 8, 2025
c9ab08c
revert color file
MichaelUnkey Jan 8, 2025
bd3310c
revert experiment
MichaelUnkey Jan 8, 2025
850cb8b
icon size
MichaelUnkey Jan 8, 2025
5abbdf6
[autofix.ci] apply automated fixes
autofix-ci[bot] Jan 8, 2025
fd854f3
pr changes
MichaelUnkey Jan 9, 2025
a97882d
wording
MichaelUnkey Jan 9, 2025
79cf10a
remove children from icon
MichaelUnkey Jan 9, 2025
c09cf6b
fmt
MichaelUnkey Jan 9, 2025
a017ae3
[autofix.ci] apply automated fixes
autofix-ci[bot] Jan 9, 2025
4061e16
[autofix.ci] apply automated fixes (attempt 2/3)
autofix-ci[bot] Jan 9, 2025
e356e5d
[autofix.ci] apply automated fixes (attempt 3/3)
autofix-ci[bot] Jan 9, 2025
3e5ecad
Merge branch 'main' of https://github.com/unkeyed/unkey into eng-1606…
MichaelUnkey Jan 9, 2025
8d39f26
[autofix.ci] apply automated fixes
autofix-ci[bot] Jan 9, 2025
242bbd5
missed
MichaelUnkey Jan 9, 2025
d2c920d
Merge branch 'eng-1606-overhaul-emptyplaceholder' of https://github.c…
MichaelUnkey Jan 9, 2025
b5daf97
[autofix.ci] apply automated fixes
autofix-ci[bot] Jan 9, 2025
561b24e
icon changes
MichaelUnkey Jan 9, 2025
21d3111
Merge branch 'eng-1606-overhaul-emptyplaceholder' of https://github.c…
MichaelUnkey Jan 9, 2025
78a5c35
small change
MichaelUnkey Jan 9, 2025
9cc00e1
Merge branch 'main' of https://github.com/unkeyed/unkey into eng-1606…
MichaelUnkey Jan 10, 2025
86ce284
small changes
MichaelUnkey Jan 10, 2025
e165c58
Update apps/engineering/content/design/components/empty.mdx
MichaelUnkey Jan 14, 2025
5312970
Update apps/dashboard/app/(app)/ratelimits/[namespaceId]/logs/page.tsx
MichaelUnkey Jan 14, 2025
9cfb7ff
Merge branch 'main' of https://github.com/unkeyed/unkey into eng-1606…
MichaelUnkey Jan 14, 2025
ff6cd4f
removed empty added loading
MichaelUnkey Jan 14, 2025
d290e96
Merge branch 'main' of https://github.com/unkeyed/unkey into eng-1606…
MichaelUnkey Jan 14, 2025
eead2f8
corrected loading import
MichaelUnkey Jan 14, 2025
152f95c
centered loading
MichaelUnkey Jan 14, 2025
62013ff
Merge branch 'main' into eng-1606-overhaul-emptyplaceholder
MichaelUnkey Jan 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions apps/dashboard/app/(app)/[...not-found]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import { EmptyPlaceholder } from "@/components/dashboard/empty-placeholder";
import { Empty } from "@unkey/ui";
import { Button } from "@unkey/ui";
import Link from "next/link";
export default function NotFound() {
return (
<EmptyPlaceholder className="my-4 ">
<EmptyPlaceholder.Title>404 Not Found</EmptyPlaceholder.Title>
<EmptyPlaceholder.Description>
We couldn't find the page that you're looking for!
</EmptyPlaceholder.Description>
<Empty className="my-4" fill={true}>
<Empty.Title>404 Not Found</Empty.Title>
MichaelUnkey marked this conversation as resolved.
Show resolved Hide resolved
<Empty.Description>We couldn't find the page that you're looking for!</Empty.Description>
<div className="flex flex-col items-center justify-center gap-2 md:flex-row">
<Link href="/">
MichaelUnkey marked this conversation as resolved.
Show resolved Hide resolved
<Button variant="default">Go Back</Button>
</Link>
</div>
</EmptyPlaceholder>
</Empty>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { CreateNewRole } from "@/app/(app)/authorization/roles/create-new-role";
import { StackedColumnChart } from "@/components/dashboard/charts";
import { CopyButton } from "@/components/dashboard/copy-button";
import { CreateKeyButton } from "@/components/dashboard/create-key-button";
import { EmptyPlaceholder } from "@/components/dashboard/empty-placeholder";
import { Navbar } from "@/components/navbar";
import { PageContent } from "@/components/page-content";
import { Badge } from "@/components/ui/badge";
Expand All @@ -20,6 +19,7 @@ import { clickhouse } from "@/lib/clickhouse";
import { and, db, eq, isNull, schema } from "@/lib/db";
import { formatNumber } from "@/lib/fmt";
import { Nodes } from "@unkey/icons";
import { Empty } from "@unkey/ui";
import { Button } from "@unkey/ui";
import { BarChart, Minus } from "lucide-react";
import ms from "ms";
Expand Down Expand Up @@ -352,15 +352,13 @@ export default async function APIKeyDetailPage(props: {
</CardContent>
</Card>
) : (
<EmptyPlaceholder>
<EmptyPlaceholder.Icon>
<Empty fill={true}>
<Empty.Icon>
<BarChart />
</EmptyPlaceholder.Icon>
<EmptyPlaceholder.Title>Not used</EmptyPlaceholder.Title>
<EmptyPlaceholder.Description>
This key was not used in the last {interval}
</EmptyPlaceholder.Description>
</EmptyPlaceholder>
</Empty.Icon>
<Empty.Title>Not used</Empty.Title>
<Empty.Description>This key was not used in the last {interval}</Empty.Description>
</Empty>
)}

{latestVerifications.val && latestVerifications.val.length > 0 ? (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { CreateKeyButton } from "@/components/dashboard/create-key-button";
import { EmptyPlaceholder } from "@/components/dashboard/empty-placeholder";
import BackButton from "@/components/ui/back-button";
import { Badge } from "@/components/ui/badge";
import { db } from "@/lib/db";
import { Empty } from "@unkey/ui";
import { Button } from "@unkey/ui";
import { ChevronRight, Scan, User, VenetianMask } from "lucide-react";
import Link from "next/link";
Expand Down Expand Up @@ -59,19 +59,19 @@ export const Keys: React.FC<Props> = async ({ keyAuthId, apiId }) => {
return (
<div className="flex flex-col gap-8 mb-20 ">
{keys.length === 0 ? (
<EmptyPlaceholder>
<EmptyPlaceholder.Icon>
<Empty fill={true}>
<Empty.Icon>
<Scan />
</EmptyPlaceholder.Icon>
<EmptyPlaceholder.Title>No keys found</EmptyPlaceholder.Title>
<EmptyPlaceholder.Description>Create your first key</EmptyPlaceholder.Description>
<div className="flex flex-row">
</Empty.Icon>
<Empty.Title>No keys found</Empty.Title>
<Empty.Description>Create your first key</Empty.Description>
<Empty.Action>
<CreateKeyButton apiId={apiId} keyAuthId={keyAuthId!} />
<BackButton className="ml-4">Go Back</BackButton>
</div>
</Empty.Action>

{/* <CreateNewRole trigger={<Button variant="primary">Create New Role</Button>} /> */}
</EmptyPlaceholder>
</Empty>
) : (
Object.entries(keysByOwnerId).map(([ownerId, ks]) => (
<div className="flex flex-col gap-2">
Expand Down
30 changes: 13 additions & 17 deletions apps/dashboard/app/(app)/apis/[apiId]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { AreaChart, StackedColumnChart } from "@/components/dashboard/charts";
import { CopyButton } from "@/components/dashboard/copy-button";
import { CreateKeyButton } from "@/components/dashboard/create-key-button";
import { EmptyPlaceholder } from "@/components/dashboard/empty-placeholder";
import { Navbar as SubMenu } from "@/components/dashboard/navbar";
import { Navbar } from "@/components/navbar";
import { PageContent } from "@/components/page-content";
Expand All @@ -14,6 +13,7 @@ import { clickhouse } from "@/lib/clickhouse";
import { db } from "@/lib/db";
import { formatNumber } from "@/lib/fmt";
import { Nodes } from "@unkey/icons";
import { Empty } from "@unkey/ui";
import { BarChart } from "lucide-react";
import { redirect } from "next/navigation";
import { navigation } from "./constants";
Expand Down Expand Up @@ -246,15 +246,13 @@ export default async function ApiPage(props: {
</CardContent>
</Card>
) : (
<EmptyPlaceholder>
<EmptyPlaceholder.Icon>
<Empty fill={true}>
<Empty.Icon>
<BarChart />
</EmptyPlaceholder.Icon>
<EmptyPlaceholder.Title>No usage</EmptyPlaceholder.Title>
<EmptyPlaceholder.Description>
Verify a key or change the range
</EmptyPlaceholder.Description>
</EmptyPlaceholder>
</Empty.Icon>
<Empty.Title>No usage</Empty.Title>
<Empty.Description>Verify a key or change the range</Empty.Description>
</Empty>
)}

<Separator className="my-8" />
Expand Down Expand Up @@ -290,15 +288,13 @@ export default async function ApiPage(props: {
</CardContent>
</Card>
) : (
<EmptyPlaceholder>
<EmptyPlaceholder.Icon>
<Empty fill={true}>
<Empty.Icon>
<BarChart />
</EmptyPlaceholder.Icon>
<EmptyPlaceholder.Title>No usage</EmptyPlaceholder.Title>
<EmptyPlaceholder.Description>
Verify a key or change the range
</EmptyPlaceholder.Description>
</EmptyPlaceholder>
</Empty.Icon>
<Empty.Title>No usage</Empty.Title>
<Empty.Description>Verify a key or change the range</Empty.Description>
</Empty>
)}
</div>
</PageContent>
Expand Down
20 changes: 10 additions & 10 deletions apps/dashboard/app/(app)/apis/client.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"use client";
import { EmptyPlaceholder } from "@/components/dashboard/empty-placeholder";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { PostHogIdentify } from "@/providers/PostHogProvider";
import { useUser } from "@clerk/nextjs";
import { Empty } from "@unkey/ui";
import { Button } from "@unkey/ui";
import { BookOpen, Code, Search } from "lucide-react";
import Link from "next/link";
Expand Down Expand Up @@ -76,24 +76,24 @@ export function ApiList({ apis }: { apis: ApiWithKeys }) {
))}
</ul>
) : (
<EmptyPlaceholder className="my-4 ">
<EmptyPlaceholder.Icon>
<Empty className="my-4" fill={true}>
<Empty.Icon>
<Code />
</EmptyPlaceholder.Icon>
<EmptyPlaceholder.Title>No APIs found</EmptyPlaceholder.Title>
<EmptyPlaceholder.Description>
</Empty.Icon>
<Empty.Title>No APIs found</Empty.Title>
<Empty.Description>
You haven&apos;t created any APIs yet. Create one to get started.
</EmptyPlaceholder.Description>
<div className="flex flex-col items-center justify-center gap-2 md:flex-row">
</Empty.Description>
<Empty.Action>
<CreateApiButton key="createApi" />
<Link href="/docs" target="_blank">
<Button>
<BookOpen />
Read the docs
</Button>
</Link>
</div>
</EmptyPlaceholder>
</Empty.Action>
</Empty>
)}
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"use client";

import { EmptyPlaceholder } from "@/components/dashboard/empty-placeholder";
import { VirtualTable } from "@/components/virtual-table";
import { trpc } from "@/lib/trpc/client";
import { Empty } from "@unkey/ui";
import { cn } from "@unkey/ui/src/lib/utils";
import { useState } from "react";
import { useAuditLogParams } from "../../query-state";
Expand Down Expand Up @@ -78,17 +78,13 @@ export const AuditLogTableClient = () => {

if (isError) {
return (
<EmptyPlaceholder>
<div className="w-[400px] mx-auto flex gap-2 items-center flex-col">
<div className="text-center">
<div className="font-medium mb-1">Failed to load audit logs</div>
<div className="text-sm text-muted-foreground">
There was a problem fetching the audit logs. Please try refreshing the page or contact
support if the issue persists.
</div>
</div>
</div>
</EmptyPlaceholder>
<Empty fill={true}>
<Empty.Title>Failed to load audit logs</Empty.Title>
<Empty.Description>
There was a problem fetching the audit logs. Please try refreshing the page or contact
support if the issue persists.
</Empty.Description>
</Empty>
);
}

Expand Down
16 changes: 8 additions & 8 deletions apps/dashboard/app/(app)/audit/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { EmptyPlaceholder } from "@/components/dashboard/empty-placeholder";
import { Navbar } from "@/components/navbar";
import { PageContent } from "@/components/page-content";
import { getTenantId } from "@/lib/auth";
import { InputSearch, Ufo } from "@unkey/icons";
import { Empty } from "@unkey/ui";
import { type SearchParams, getWorkspace, parseFilterParams } from "./actions";
import { Filters } from "./components/filters";
import { AuditLogTableClient } from "./components/table/audit-log-table-client";
Expand Down Expand Up @@ -38,16 +38,16 @@ export default async function AuditPage(props: Props) {
<AuditLogTableClient />
</main>
) : (
<EmptyPlaceholder>
<EmptyPlaceholder.Icon>
<Empty fill={true}>
<Empty.Icon>
<Ufo />
</EmptyPlaceholder.Icon>
<EmptyPlaceholder.Title>No logs</EmptyPlaceholder.Title>
<EmptyPlaceholder.Description>
</Empty.Icon>
<Empty.Title>No logs</Empty.Title>
<Empty.Description>
There are no audit logs available yet. Create a key or another resource and come back
here.
</EmptyPlaceholder.Description>
</EmptyPlaceholder>
</Empty.Description>
</Empty>
)}
</PageContent>
</div>
Expand Down
24 changes: 12 additions & 12 deletions apps/dashboard/app/(app)/authorization/permissions/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { EmptyPlaceholder } from "@/components/dashboard/empty-placeholder";
import { Navbar as SubMenu } from "@/components/dashboard/navbar";
import { Navbar } from "@/components/navbar";
import { PageContent } from "@/components/page-content";
Expand All @@ -7,6 +6,7 @@ import { getTenantId } from "@/lib/auth";
import { asc, db } from "@/lib/db";
import { permissions } from "@unkey/db/src/schema";
import { ShieldKey } from "@unkey/icons";
import { Empty } from "@unkey/ui";
import { Button } from "@unkey/ui";
import { ChevronRight, Scan } from "lucide-react";
import Link from "next/link";
Expand Down Expand Up @@ -80,18 +80,18 @@ export default async function RolesPage() {
<div className="mt-8 mb-20 overflow-x-auto">
<div className="flex items-center justify-between flex-1 space-x-2 w-full">
{workspace.permissions.length === 0 ? (
<EmptyPlaceholder className="w-full">
<EmptyPlaceholder.Icon>
<Empty className="w-full" fill={true}>
<Empty.Icon>
MichaelUnkey marked this conversation as resolved.
Show resolved Hide resolved
<Scan />
</EmptyPlaceholder.Icon>
<EmptyPlaceholder.Title>No permissions found</EmptyPlaceholder.Title>
<EmptyPlaceholder.Description>
Create your first permission
</EmptyPlaceholder.Description>
<CreateNewPermission
trigger={<Button variant="primary">Create New Permission</Button>}
/>
</EmptyPlaceholder>
</Empty.Icon>
<Empty.Title>No permissions found</Empty.Title>
<Empty.Description>Create your first permission</Empty.Description>
<Empty.Action>
<CreateNewPermission
trigger={<Button variant="primary">Create New Permission</Button>}
/>
</Empty.Action>
</Empty>
) : (
<ul className="flex flex-col overflow-hidden border divide-y rounded-lg divide-border bg-background border-border w-full">
{workspace.permissions.map((p) => (
Expand Down
24 changes: 13 additions & 11 deletions apps/dashboard/app/(app)/authorization/roles/page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { EmptyPlaceholder } from "@/components/dashboard/empty-placeholder";
import { Navbar as SubMenu } from "@/components/dashboard/navbar";
import { Navbar } from "@/components/navbar";
import { PageContent } from "@/components/page-content";
import { Badge } from "@/components/ui/badge";
import { getTenantId } from "@/lib/auth";
import { db } from "@/lib/db";
import { ShieldKey } from "@unkey/icons";
import { Empty } from "@unkey/ui";
import { Button } from "@unkey/ui";
import { ChevronRight, Scan } from "lucide-react";
import Link from "next/link";
Expand Down Expand Up @@ -83,17 +83,19 @@ export default async function RolesPage() {
<div className="mt-8 mb-20 overflow-x-auto">
<div className="flex flex-col gap-8 mb-20 ">
{workspace.roles.length === 0 ? (
<EmptyPlaceholder>
<EmptyPlaceholder.Icon>
<Empty fill={true}>
<Empty.Icon>
<Scan />
</EmptyPlaceholder.Icon>
<EmptyPlaceholder.Title>No roles found</EmptyPlaceholder.Title>
<EmptyPlaceholder.Description>Create your first role</EmptyPlaceholder.Description>
<CreateNewRole
trigger={<Button variant="primary">Create New Role</Button>}
permissions={workspace.permissions}
/>
</EmptyPlaceholder>
</Empty.Icon>
<Empty.Title>No roles found</Empty.Title>
<Empty.Description>Create your first role</Empty.Description>
<Empty.Action>
<CreateNewRole
trigger={<Button variant="primary">Create New Role</Button>}
permissions={workspace.permissions}
/>
</Empty.Action>
</Empty>
) : (
<ul className="flex flex-col overflow-hidden border divide-y rounded-lg divide-border bg-background border-border">
{workspace.roles.map((r) => (
Expand Down
13 changes: 6 additions & 7 deletions apps/dashboard/app/(app)/identities/page.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import { redirect } from "next/navigation";

import { EmptyPlaceholder } from "@/components/dashboard/empty-placeholder";
import { Navbar } from "@/components/navbar";
import { OptIn } from "@/components/opt-in";
import { PageContent } from "@/components/page-content";
import { Table, TableBody, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { getTenantId } from "@/lib/auth";
import { db } from "@/lib/db";
import { Fingerprint } from "@unkey/icons";
import { Empty } from "@unkey/ui";
import { Loader2 } from "lucide-react";
import { unstable_cache as cache } from "next/cache";
import { redirect } from "next/navigation";
import { parseAsInteger, parseAsString } from "nuqs/server";
MichaelUnkey marked this conversation as resolved.
Show resolved Hide resolved
import { Suspense } from "react";
import { SearchField } from "./filter";
Expand Down Expand Up @@ -52,11 +51,11 @@ export default async function Page(props: Props) {
<div className="flex flex-col gap-8 mb-20 mt-8">
<Suspense
fallback={
<EmptyPlaceholder>
<EmptyPlaceholder.Title>
<Empty fill={true}>
<Empty.Title>
<Loader2 className="w-4 h-4 animate-spin" />
</EmptyPlaceholder.Title>
</EmptyPlaceholder>
</Empty.Title>
</Empty>
}
>
<Results search={search ?? ""} limit={limit ?? 10} />
Expand Down
Loading
Loading