diff --git a/apps/web/app/app.dub.co/(dashboard)/[slug]/settings/domains/page-client.tsx b/apps/web/app/app.dub.co/(dashboard)/[slug]/settings/domains/page-client.tsx index f86e4eee80..a4b755a0bf 100644 --- a/apps/web/app/app.dub.co/(dashboard)/[slug]/settings/domains/page-client.tsx +++ b/apps/web/app/app.dub.co/(dashboard)/[slug]/settings/domains/page-client.tsx @@ -11,6 +11,7 @@ import { FreeDotLinkBanner } from "@/ui/domains/free-dot-link-banner"; import { useAddEditDomainModal } from "@/ui/modals/add-edit-domain-modal"; import { useRegisterDomainModal } from "@/ui/modals/register-domain-modal"; import { useRegisterDomainSuccessModal } from "@/ui/modals/register-domain-success-modal"; +import { AnimatedEmptyState } from "@/ui/shared/animated-empty-state"; import EmptyState from "@/ui/shared/empty-state"; import { SearchBoxPersisted } from "@/ui/shared/search-box"; import { PaginationControls } from "@dub/blocks/src/pagination-controls"; @@ -22,7 +23,7 @@ import { usePagination, useRouterStuff, } from "@dub/ui"; -import { LinkBroken } from "@dub/ui/src/icons"; +import { CursorRays, LinkBroken } from "@dub/ui/src/icons"; import { ToggleGroup } from "@dub/ui/src/toggle-group"; import { InfoTooltip, TooltipContent } from "@dub/ui/src/tooltip"; import { capitalize } from "@dub/utils"; @@ -216,20 +217,34 @@ export default function WorkspaceDomainsClient() { ))} - ) : ( + ) : archived || search ? (
+ ) : ( + + +
+
+ +
+ + } + addButton={} + learnMoreHref="https://dub.co/help/article/how-to-add-custom-domain" + /> ) ) : (
    diff --git a/apps/web/app/app.dub.co/(dashboard)/[slug]/settings/library/header.tsx b/apps/web/app/app.dub.co/(dashboard)/[slug]/settings/library/header.tsx index 76156ee24f..d4418a047a 100644 --- a/apps/web/app/app.dub.co/(dashboard)/[slug]/settings/library/header.tsx +++ b/apps/web/app/app.dub.co/(dashboard)/[slug]/settings/library/header.tsx @@ -16,7 +16,11 @@ export default function LibraryHeader() {

    Library

    +

    + Manage and organize your links with customizable tags and UTM templates. +

    ) : ( - ) : ( - } addButton={} - learnMoreHref="https://dub.co/help/article/how-to-create-utm-templates" // + learnMoreHref="https://dub.co/help/article/how-to-create-utm-templates" /> )}
diff --git a/apps/web/ui/links/link-not-found.tsx b/apps/web/ui/links/link-not-found.tsx index 468ec48fc2..b192540c7f 100644 --- a/apps/web/ui/links/link-not-found.tsx +++ b/apps/web/ui/links/link-not-found.tsx @@ -2,7 +2,7 @@ import { FileX2 } from "lucide-react"; export default function LinkNotFound() { return ( -
+
diff --git a/apps/web/ui/links/links-container.tsx b/apps/web/ui/links/links-container.tsx index cccb8831da..95d80c258b 100644 --- a/apps/web/ui/links/links-container.tsx +++ b/apps/web/ui/links/links-container.tsx @@ -5,7 +5,7 @@ import useLinksCount from "@/lib/swr/use-links-count"; import { LinkWithTagsProps, UserProps } from "@/lib/types"; import { PaginationControls } from "@dub/blocks/src/pagination-controls"; import { CardList, MaxWidthWrapper, usePagination } from "@dub/ui"; -import { LoadingSpinner } from "@dub/ui/src/icons"; +import { CursorRays, Hyperlink, LoadingSpinner } from "@dub/ui/src/icons"; import { cn } from "@dub/utils"; import { useSearchParams } from "next/navigation"; import { @@ -15,12 +15,12 @@ import { useContext, useState, } from "react"; +import { AnimatedEmptyState } from "../shared/animated-empty-state"; import ArchivedLinksHint from "./archived-links-hint"; import { LinkCard } from "./link-card"; import LinkCardPlaceholder from "./link-card-placeholder"; import LinkNotFound from "./link-not-found"; import { LinksDisplayContext } from "./links-display-provider"; -import NoLinksPlaceholder from "./no-links-placeholder"; export type ResponseLink = LinkWithTagsProps & { user: UserProps; @@ -110,7 +110,26 @@ function LinksList({ ) : isFiltered ? ( ) : ( - + + +
+
+ +
+ + } + addButton={ +
+ +
+ } + learnMoreHref="https://dub.co/help/article/how-to-create-link" + learnMoreClassName="h-10" + /> )} {/* Pagination */} diff --git a/apps/web/ui/links/no-links-placeholder.tsx b/apps/web/ui/links/no-links-placeholder.tsx deleted file mode 100644 index edde1e6392..0000000000 --- a/apps/web/ui/links/no-links-placeholder.tsx +++ /dev/null @@ -1,24 +0,0 @@ -export default function NoLinksPlaceholder({ - CreateLinkButton, -}: { - CreateLinkButton: () => JSX.Element; -}) { - return ( -
-

- No links found. -

- No links yet -
- -
-

or edit your search filters

-
- ); -} diff --git a/apps/web/app/app.dub.co/(dashboard)/[slug]/settings/library/library-empty-state.tsx b/apps/web/ui/shared/animated-empty-state.tsx similarity index 72% rename from apps/web/app/app.dub.co/(dashboard)/[slug]/settings/library/library-empty-state.tsx rename to apps/web/ui/shared/animated-empty-state.tsx index 5a58b6eea5..b45c541345 100644 --- a/apps/web/app/app.dub.co/(dashboard)/[slug]/settings/library/library-empty-state.tsx +++ b/apps/web/ui/shared/animated-empty-state.tsx @@ -3,22 +3,31 @@ import { cn } from "@dub/utils"; import Link from "next/link"; import { CSSProperties, PropsWithChildren, ReactNode } from "react"; -export function LibraryEmptyState({ +export function AnimatedEmptyState({ title, description, cardContent, addButton, learnMoreHref, + learnMoreClassName, + className, }: { title: string; description: string; cardContent: ReactNode; addButton: ReactNode; learnMoreHref?: string; + learnMoreClassName?: string; + className?: string; }) { return ( -
-
+
+
Learn more @@ -53,7 +63,7 @@ export function LibraryEmptyState({ function Card({ children }: PropsWithChildren) { return ( -
+
{children}
); diff --git a/packages/ui/src/tab-select.tsx b/packages/ui/src/tab-select.tsx index e589cad382..40edb0c915 100644 --- a/packages/ui/src/tab-select.tsx +++ b/packages/ui/src/tab-select.tsx @@ -1,13 +1,41 @@ import { cn } from "@dub/utils"; +import { cva, VariantProps } from "class-variance-authority"; import { LayoutGroup, motion } from "framer-motion"; import { Dispatch, SetStateAction, useId } from "react"; +const tabSelectButtonVariants = cva("p-4 transition-colors duration-75", { + variants: { + variant: { + default: + "text-gray-400 data-[selected=true]:text-black data-[selected=false]:hover:text-gray-500", + accent: + "text-neutral-500 transition-[color,font-weight] data-[selected=true]:text-blue-600 data-[selected=false]:hover:text-neutral-700 data-[selected=true]:font-medium", + }, + }, + defaultVariants: { + variant: "default", + }, +}); + +const tabSelectIndicatorVariants = cva("absolute bottom-0 w-full px-1.5", { + variants: { + variant: { + default: "text-black", + accent: "text-blue-600", + }, + }, + defaultVariants: { + variant: "default", + }, +}); + export function TabSelect({ + variant, options, selected, onSelect, className, -}: { +}: VariantProps & { options: { id: T; label: string }[]; selected: string | null; onSelect?: Dispatch> | ((id: T) => void); @@ -23,12 +51,8 @@ export function TabSelect({