Skip to content

Commit

Permalink
Merge branch 'main' into soft-delete-v2
Browse files Browse the repository at this point in the history
  • Loading branch information
devkiran committed Oct 18, 2024
2 parents c4ab92b + cd177fc commit 3ad616c
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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";
Expand Down Expand Up @@ -216,20 +217,34 @@ export default function WorkspaceDomainsClient() {
</li>
))}
</ul>
) : (
) : archived || search ? (
<div className="flex flex-col items-center gap-4 rounded-xl border border-gray-200 py-10">
<EmptyState
icon={Globe}
title={
archived
? "No archived domains found for this workspace"
: search
? "No custom domains found"
: "No custom domains found for this workspace"
? "No archived domains found"
: "No custom domains found"
}
/>
<AddDomainButton />
</div>
) : (
<AnimatedEmptyState
title="No domains found"
description="Use custom domains for better brand recognition and click-through rates"
cardContent={
<>
<Globe className="size-4 text-neutral-700" />
<div className="h-2.5 w-24 min-w-0 rounded-sm bg-neutral-200" />
<div className="xs:flex hidden grow items-center justify-end gap-1.5 text-gray-500">
<CursorRays className="size-3.5" />
</div>
</>
}
addButton={<AddDomainButton />}
learnMoreHref="https://dub.co/help/article/how-to-add-custom-domain"
/>
)
) : (
<ul className="grid grid-cols-1 gap-3">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ export default function LibraryHeader() {
<h1 className="text-2xl font-semibold tracking-tight text-black">
Library
</h1>
<p className="mb-2 mt-2 text-base text-neutral-600">
Manage and organize your links with customizable tags and UTM templates.
</p>
<TabSelect
variant="accent"
options={[
{ id: "tags", label: "Tags" },
{ id: "utm", label: "UTM Templates" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import useTagsCount from "@/lib/swr/use-tags-count";
import useWorkspace from "@/lib/swr/use-workspace";
import { TAGS_MAX_PAGE_SIZE } from "@/lib/zod/schemas/tags";
import { useAddEditTagModal } from "@/ui/modals/add-edit-tag-modal";
import { AnimatedEmptyState } from "@/ui/shared/animated-empty-state";
import { SearchBoxPersisted } from "@/ui/shared/search-box";
import { PaginationControls } from "@dub/blocks";
import { CardList, Tag, usePagination, useRouterStuff } from "@dub/ui";
Expand All @@ -16,7 +17,6 @@ import {
useEffect,
useState,
} from "react";
import { LibraryEmptyState } from "../library-empty-state";
import { TagCard } from "./tag-card";
import { TagCardPlaceholder } from "./tag-card-placeholder";

Expand Down Expand Up @@ -119,7 +119,8 @@ export default function WorkspaceTagsClient() {
)}
</>
) : (
<LibraryEmptyState
<AnimatedEmptyState
className="mt-6"
title="No tags found"
description="Create tags to organize your links"
cardContent={
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import useWorkspace from "@/lib/swr/use-workspace";
import { UtmTemplateWithUserProps } from "@/lib/types";
import { useAddEditUtmTemplateModal } from "@/ui/modals/add-edit-utm-template.modal";
import { AnimatedEmptyState } from "@/ui/shared/animated-empty-state";
import { CardList } from "@dub/ui";
import { DiamondTurnRight, Flag6, GlobePointer } from "@dub/ui/src";
import { fetcher } from "@dub/utils";
Expand All @@ -14,7 +15,6 @@ import {
useState,
} from "react";
import useSWR from "swr";
import { LibraryEmptyState } from "../library-empty-state";
import { TemplateCard } from "./template-card";
import { TemplateCardPlaceholder } from "./template-card-placeholder";

Expand Down Expand Up @@ -79,7 +79,8 @@ export default function WorkspaceUtmTemplatesClient() {
</TemplatesListContext.Provider>
</>
) : (
<LibraryEmptyState
<AnimatedEmptyState
className="mt-6"
title="No UTM Templates Found"
description="Create shared templates to streamline UTM campaign management across your team"
cardContent={
Expand All @@ -93,7 +94,7 @@ export default function WorkspaceUtmTemplatesClient() {
</>
}
addButton={<AddUtmTemplateButton />}
learnMoreHref="https://dub.co/help/article/how-to-create-utm-templates" //
learnMoreHref="https://dub.co/help/article/how-to-create-utm-templates"
/>
)}
</div>
Expand Down
2 changes: 1 addition & 1 deletion apps/web/ui/links/link-not-found.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { FileX2 } from "lucide-react";

export default function LinkNotFound() {
return (
<div className="my-4 flex flex-col items-center justify-center rounded-md border border-gray-200 bg-white py-12">
<div className="flex flex-col items-center justify-center rounded-md border border-gray-200 bg-white py-12">
<div className="rounded-full bg-gray-100 p-3">
<FileX2 className="h-6 w-6 text-gray-600" />
</div>
Expand Down
25 changes: 22 additions & 3 deletions apps/web/ui/links/links-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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;
Expand Down Expand Up @@ -110,7 +110,26 @@ function LinksList({
) : isFiltered ? (
<LinkNotFound />
) : (
<NoLinksPlaceholder CreateLinkButton={CreateLinkButton} />
<AnimatedEmptyState
title="No links found"
description="Start creating short links for your marketing campaigns, referral programs, and more."
cardContent={
<>
<Hyperlink className="size-4 text-neutral-700" />
<div className="h-2.5 w-24 min-w-0 rounded-sm bg-neutral-200" />
<div className="xs:flex hidden grow items-center justify-end gap-1.5 text-gray-500">
<CursorRays className="size-3.5" />
</div>
</>
}
addButton={
<div>
<CreateLinkButton />
</div>
}
learnMoreHref="https://dub.co/help/article/how-to-create-link"
learnMoreClassName="h-10"
/>
)}

{/* Pagination */}
Expand Down
24 changes: 0 additions & 24 deletions apps/web/ui/links/no-links-placeholder.tsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<div className="mt-6 flex flex-col items-center justify-center gap-6 rounded-lg border border-gray-200 px-4 py-10 md:min-h-[500px]">
<div className="animate-fade-in h-36 w-64 max-w-full overflow-hidden px-4 [mask-image:linear-gradient(transparent,black_10%,black_90%,transparent)]">
<div
className={cn(
"flex flex-col items-center justify-center gap-6 rounded-lg border border-gray-200 px-4 py-10 md:min-h-[500px]",
className,
)}
>
<div className="animate-fade-in h-36 w-full max-w-64 overflow-hidden px-4 [mask-image:linear-gradient(transparent,black_10%,black_90%,transparent)]">
<div
style={{ "--scroll": "-50%" } as CSSProperties}
className="animate-infinite-scroll-y flex flex-col [animation-duration:10s]"
Expand All @@ -40,7 +49,8 @@ export function LibraryEmptyState({
target="_blank"
className={cn(
buttonVariants({ variant: "secondary" }),
"flex h-9 items-center rounded-lg border px-4 text-sm",
"flex h-9 items-center whitespace-nowrap rounded-lg border px-4 text-sm",
learnMoreClassName,
)}
>
Learn more
Expand All @@ -53,7 +63,7 @@ export function LibraryEmptyState({

function Card({ children }: PropsWithChildren) {
return (
<div className="mt-4 flex items-center gap-3 rounded-lg border border-neutral-200 bg-white px-5 py-4 shadow-[0_4px_12px_0_#0000000D]">
<div className="mt-4 flex items-center gap-3 rounded-lg border border-neutral-200 bg-white p-4 shadow-[0_4px_12px_0_#0000000D]">
{children}
</div>
);
Expand Down
42 changes: 33 additions & 9 deletions packages/ui/src/tab-select.tsx
Original file line number Diff line number Diff line change
@@ -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<T extends string>({
variant,
options,
selected,
onSelect,
className,
}: {
}: VariantProps<typeof tabSelectButtonVariants> & {
options: { id: T; label: string }[];
selected: string | null;
onSelect?: Dispatch<SetStateAction<T>> | ((id: T) => void);
Expand All @@ -23,12 +51,8 @@ export function TabSelect<T extends string>({
<button
type="button"
onClick={() => onSelect?.(id)}
className={cn(
"p-4 transition-colors duration-75",
id === selected
? "text-black"
: "text-gray-400 hover:text-gray-500",
)}
className={tabSelectButtonVariants({ variant })}
data-selected={id === selected}
aria-selected={id === selected}
>
{label}
Expand All @@ -39,9 +63,9 @@ export function TabSelect<T extends string>({
transition={{
duration: 0.1,
}}
className="absolute bottom-0 w-full px-1.5"
className={tabSelectIndicatorVariants({ variant })}
>
<div className="h-0.5 bg-black" />
<div className="h-0.5 rounded-t-full bg-current" />
</motion.div>
)}
</div>
Expand Down

0 comments on commit 3ad616c

Please sign in to comment.