Add documents page to the compliance portal
Build the Trust Center documents page: a unified list of published documents, uploaded files, and audit reports, grouped into category sections. An All/Public/Private tab bar filters the list by trust center visibility. Expose that filter over the trust v1 API by adding a TrustCenterVisibility enum and a shared TrustCenterVisibilityFilter input, wiring it through the documents, audits, and trustCenterFiles connections down to the existing coredata SQL filters. "All" keeps the default public+private slice; the other tabs pin a single visibility. Access controls are display-only for now (auth is handled separately): authorized or public entries open their exported PDF via the export mutations, requested entries show a pending state, and everything else shows an inert Get Access affordance. Add the v2 Tabs and Toaster kit components (Base UI headless) needed by the page and mount a toast provider at the app root for mutation feedback. Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
70
packages/ui/src/v2/Tabs/Tabs.stories.tsx
Normal file
70
packages/ui/src/v2/Tabs/Tabs.stories.tsx
Normal file
@@ -0,0 +1,70 @@
|
||||
// Copyright (c) 2026 Probo Inc <hello@probo.com>.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
import { useState } from "react";
|
||||
|
||||
import { Tabs } from "./Tabs";
|
||||
import { TabsIndicator } from "./TabsIndicator";
|
||||
import { TabsList } from "./TabsList";
|
||||
import { TabsSkeleton } from "./TabsSkeleton";
|
||||
import { TabsTab } from "./TabsTab";
|
||||
|
||||
export default {
|
||||
title: "v2/Tabs",
|
||||
component: Tabs,
|
||||
};
|
||||
|
||||
export function Default() {
|
||||
return (
|
||||
<Tabs defaultValue="all">
|
||||
<TabsList>
|
||||
<TabsTab value="all">All</TabsTab>
|
||||
<TabsTab value="public">Public</TabsTab>
|
||||
<TabsTab value="private">Private</TabsTab>
|
||||
<TabsIndicator />
|
||||
</TabsList>
|
||||
</Tabs>
|
||||
);
|
||||
}
|
||||
|
||||
export function Controlled() {
|
||||
const [value, setValue] = useState<string>("all");
|
||||
return (
|
||||
<div className="flex flex-col gap-3">
|
||||
<Tabs value={value} onValueChange={next => setValue(next as string)}>
|
||||
<TabsList>
|
||||
<TabsTab value="all">All</TabsTab>
|
||||
<TabsTab value="public">Public</TabsTab>
|
||||
<TabsTab value="private">Private</TabsTab>
|
||||
<TabsIndicator />
|
||||
</TabsList>
|
||||
</Tabs>
|
||||
<span className="text-2 text-sand-11">
|
||||
Selected:
|
||||
{" "}
|
||||
{value}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function Skeleton() {
|
||||
return <TabsSkeleton />;
|
||||
}
|
||||
29
packages/ui/src/v2/Tabs/Tabs.tsx
Normal file
29
packages/ui/src/v2/Tabs/Tabs.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) 2026 Probo Inc <hello@probo.com>.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
import { Tabs as BaseTabs } from "@base-ui/react/tabs";
|
||||
|
||||
// Root of the tabs (Radix "Tabs"). Controlled the same way as Base UI's Tabs:
|
||||
// `value` / `onValueChange`, or left uncontrolled. See contrib/claude/ui.md.
|
||||
export type TabsProps = BaseTabs.Root.Props;
|
||||
|
||||
export function Tabs(props: TabsProps) {
|
||||
return <BaseTabs.Root {...props} />;
|
||||
}
|
||||
36
packages/ui/src/v2/Tabs/TabsIndicator.tsx
Normal file
36
packages/ui/src/v2/Tabs/TabsIndicator.tsx
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2026 Probo Inc <hello@probo.com>.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
import { Tabs as BaseTabs } from "@base-ui/react/tabs";
|
||||
import type { ComponentProps } from "react";
|
||||
|
||||
import { tabsIndicator } from "./variants";
|
||||
|
||||
export type TabsIndicatorProps = Omit<ComponentProps<typeof BaseTabs.Indicator>, "className"> & {
|
||||
className?: string;
|
||||
};
|
||||
|
||||
// The sliding underline tracking the active tab, positioned from Base UI's
|
||||
// `--active-tab-left` / `--active-tab-width` CSS variables.
|
||||
export function TabsIndicator(props: TabsIndicatorProps) {
|
||||
const { className, ...rest } = props;
|
||||
|
||||
return <BaseTabs.Indicator className={tabsIndicator({ className })} {...rest} />;
|
||||
}
|
||||
35
packages/ui/src/v2/Tabs/TabsList.tsx
Normal file
35
packages/ui/src/v2/Tabs/TabsList.tsx
Normal file
@@ -0,0 +1,35 @@
|
||||
// Copyright (c) 2026 Probo Inc <hello@probo.com>.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
import { Tabs as BaseTabs } from "@base-ui/react/tabs";
|
||||
import type { ComponentProps } from "react";
|
||||
|
||||
import { tabsList } from "./variants";
|
||||
|
||||
export type TabsListProps = Omit<ComponentProps<typeof BaseTabs.List>, "className"> & {
|
||||
className?: string;
|
||||
};
|
||||
|
||||
// The tab bar: holds the tab triggers and (optionally) the sliding indicator.
|
||||
export function TabsList(props: TabsListProps) {
|
||||
const { className, ...rest } = props;
|
||||
|
||||
return <BaseTabs.List className={tabsList({ className })} {...rest} />;
|
||||
}
|
||||
43
packages/ui/src/v2/Tabs/TabsSkeleton.tsx
Normal file
43
packages/ui/src/v2/Tabs/TabsSkeleton.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
// Copyright (c) 2026 Probo Inc <hello@probo.com>.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
import type { ComponentProps } from "react";
|
||||
|
||||
import { tabsSkeleton } from "./variants";
|
||||
|
||||
export type TabsSkeletonProps = Omit<ComponentProps<"div">, "children"> & {
|
||||
// Number of placeholder tabs to render (defaults to 3).
|
||||
count?: number;
|
||||
};
|
||||
|
||||
// Loading placeholder paired with the tab bar: a row of pulse blocks over the
|
||||
// shared bottom border.
|
||||
export function TabsSkeleton(props: TabsSkeletonProps) {
|
||||
const { count = 3, className, ...rest } = props;
|
||||
const { root, item } = tabsSkeleton();
|
||||
|
||||
return (
|
||||
<div className={root({ className })} aria-hidden {...rest}>
|
||||
{Array.from({ length: count }, (_, index) => (
|
||||
<span key={index} className={item()} style={{ width: `${64 + (index % 3) * 16}px` }} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
35
packages/ui/src/v2/Tabs/TabsTab.tsx
Normal file
35
packages/ui/src/v2/Tabs/TabsTab.tsx
Normal file
@@ -0,0 +1,35 @@
|
||||
// Copyright (c) 2026 Probo Inc <hello@probo.com>.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
import { Tabs as BaseTabs } from "@base-ui/react/tabs";
|
||||
import type { ComponentProps } from "react";
|
||||
|
||||
import { tabsTab } from "./variants";
|
||||
|
||||
export type TabsTabProps = Omit<ComponentProps<typeof BaseTabs.Tab>, "className"> & {
|
||||
className?: string;
|
||||
};
|
||||
|
||||
// A single tab trigger. Selected state is driven by Base UI (`data-active`).
|
||||
export function TabsTab(props: TabsTabProps) {
|
||||
const { className, ...rest } = props;
|
||||
|
||||
return <BaseTabs.Tab className={tabsTab({ className })} {...rest} />;
|
||||
}
|
||||
54
packages/ui/src/v2/Tabs/variants.ts
Normal file
54
packages/ui/src/v2/Tabs/variants.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
// Copyright (c) 2026 Probo Inc <hello@probo.com>.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
import { tv } from "tailwind-variants/lite";
|
||||
|
||||
// Tabs (Radix "Tabs" over Base UI's Tabs). An underlined tab bar whose active
|
||||
// item is tracked by a sliding indicator positioned from Base UI's
|
||||
// `--active-tab-*` CSS variables.
|
||||
|
||||
export const tabsList = tv({
|
||||
base: "relative flex items-center gap-1 border-b border-sand-a3",
|
||||
});
|
||||
|
||||
export const tabsTab = tv({
|
||||
base: [
|
||||
"relative flex h-full cursor-pointer items-center justify-center gap-2 px-2 py-4 text-2 text-sand-a11",
|
||||
"select-none outline-none transition-colors",
|
||||
"hover:text-sand-12",
|
||||
"focus-visible:ring-2 focus-visible:ring-sand-8 focus-visible:ring-offset-1 focus-visible:ring-offset-sand-1",
|
||||
"data-active:font-medium data-active:text-sand-12",
|
||||
"data-disabled:pointer-events-none data-disabled:opacity-50",
|
||||
],
|
||||
});
|
||||
|
||||
export const tabsIndicator = tv({
|
||||
base: [
|
||||
"absolute bottom-0 left-0 h-[2px] w-(--active-tab-width) rounded-1 bg-sand-12",
|
||||
"translate-x-(--active-tab-left) transition-all duration-200 ease-out",
|
||||
],
|
||||
});
|
||||
|
||||
export const tabsSkeleton = tv({
|
||||
slots: {
|
||||
root: "flex items-center gap-4 border-b border-sand-a3",
|
||||
item: "my-4 h-5 animate-pulse rounded-1 bg-sand-3",
|
||||
},
|
||||
});
|
||||
59
packages/ui/src/v2/Toaster/Toaster.tsx
Normal file
59
packages/ui/src/v2/Toaster/Toaster.tsx
Normal file
@@ -0,0 +1,59 @@
|
||||
// Copyright (c) 2026 Probo Inc <hello@probo.com>.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
import { Toast } from "@base-ui/react/toast";
|
||||
import { XIcon } from "@phosphor-icons/react";
|
||||
|
||||
import { toaster } from "./variants";
|
||||
|
||||
type ToastType = "success" | "error" | "neutral";
|
||||
|
||||
function resolveType(type: string | undefined): ToastType {
|
||||
return type === "success" || type === "error" ? type : "neutral";
|
||||
}
|
||||
|
||||
// Renders the active toasts from the Base UI toast manager. Mount once at the
|
||||
// app root, inside a `<Toast.Provider>`.
|
||||
export function Toaster() {
|
||||
const { toasts } = Toast.useToastManager();
|
||||
const slots = toaster();
|
||||
|
||||
return (
|
||||
<Toast.Portal>
|
||||
<Toast.Viewport className={slots.viewport()}>
|
||||
{toasts.map((toast) => {
|
||||
const variant = { type: resolveType(toast.type) };
|
||||
|
||||
return (
|
||||
<Toast.Root key={toast.id} toast={toast} className={slots.toast(variant)}>
|
||||
<div className={slots.content()}>
|
||||
<Toast.Title className={slots.title(variant)} />
|
||||
<Toast.Description className={slots.description()} />
|
||||
</div>
|
||||
<Toast.Close className={slots.close()} aria-label="Close">
|
||||
<XIcon />
|
||||
</Toast.Close>
|
||||
</Toast.Root>
|
||||
);
|
||||
})}
|
||||
</Toast.Viewport>
|
||||
</Toast.Portal>
|
||||
);
|
||||
}
|
||||
50
packages/ui/src/v2/Toaster/variants.ts
Normal file
50
packages/ui/src/v2/Toaster/variants.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
// Copyright (c) 2026 Probo Inc <hello@probo.com>.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
import { tv } from "tailwind-variants/lite";
|
||||
|
||||
// Toaster (Radix "Toast" over Base UI's Toast). A bottom-right stack of
|
||||
// dismissible notifications, colored by type.
|
||||
|
||||
export const toaster = tv({
|
||||
slots: {
|
||||
viewport: "fixed right-4 bottom-4 z-50 flex w-full max-w-sm flex-col gap-2 outline-none",
|
||||
toast: [
|
||||
"pointer-events-auto flex items-start gap-3 rounded-3 border border-sand-a6 bg-sand-1 p-3 shadow-3",
|
||||
"transition-all duration-200 ease-out",
|
||||
"data-starting-style:translate-x-4 data-starting-style:opacity-0",
|
||||
"data-ending-style:translate-x-4 data-ending-style:opacity-0",
|
||||
],
|
||||
content: "flex min-w-0 flex-1 flex-col gap-1",
|
||||
title: "text-2 font-medium text-sand-12",
|
||||
description: "text-2 break-words text-sand-11",
|
||||
close: "flex size-5 shrink-0 items-center justify-center rounded-1 text-sand-a10 outline-none transition-colors hover:bg-sand-3 hover:text-sand-12 [&_svg]:size-4",
|
||||
},
|
||||
variants: {
|
||||
type: {
|
||||
success: { toast: "border-green-6 bg-green-2", title: "text-green-12" },
|
||||
error: { toast: "border-red-6 bg-red-2", title: "text-red-12" },
|
||||
neutral: {},
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
type: "neutral",
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user