Skip to content

Commit

Permalink
[UI-v2] feat: add artifacts list view (#17025)
Browse files Browse the repository at this point in the history
Co-authored-by: Devan Grose <=>
  • Loading branch information
devangrose authored Feb 6, 2025
1 parent 0145cbb commit 9e834e6
Show file tree
Hide file tree
Showing 9 changed files with 230 additions and 5 deletions.
54 changes: 54 additions & 0 deletions ui-v2/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions ui-v2/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
"@radix-ui/react-switch": "^1.1.2",
"@radix-ui/react-tabs": "^1.1.2",
"@radix-ui/react-toast": "^1.2.5",
"@radix-ui/react-toggle": "^1.1.1",
"@radix-ui/react-toggle-group": "^1.1.1",
"@radix-ui/react-tooltip": "^1.1.7",
"@tanstack/react-query": "^5.66.0",
"@tanstack/react-query-devtools": "^5.66.0",
Expand Down
25 changes: 25 additions & 0 deletions ui-v2/src/components/artifacts/artifacts-filter.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ describe("Artifacts Filter", () => {
filters={defaultFilters}
onFilterChange={onFilterChange}
totalCount={defaultCount}
setDisplayMode={vi.fn()}
displayMode="grid"
/>,
{
wrapper: createWrapper(),
Expand All @@ -50,6 +52,8 @@ describe("Artifacts Filter", () => {
filters={defaultFilters}
onFilterChange={onFilterChange}
totalCount={defaultCount}
setDisplayMode={vi.fn()}
displayMode="grid"
/>,
{
wrapper: createWrapper(),
Expand All @@ -75,6 +79,8 @@ describe("Artifacts Filter", () => {
filters={defaultFilters}
onFilterChange={onFilterChange}
totalCount={defaultCount}
setDisplayMode={vi.fn()}
displayMode="grid"
/>,
{
wrapper: createWrapper(),
Expand All @@ -89,4 +95,23 @@ describe("Artifacts Filter", () => {
{ id: "type", label: "Type", value: "markdown" },
]);
});

it("changes display mode", () => {
const setDisplayMode = vi.fn();
const { getByTestId } = render(
<ArtifactsFilterComponent
filters={defaultFilters}
onFilterChange={vi.fn()}
totalCount={defaultCount}
setDisplayMode={setDisplayMode}
displayMode="grid"
/>,
{
wrapper: createWrapper(),
},
);

fireEvent.click(getByTestId("list-layout"));
expect(setDisplayMode).toHaveBeenCalledWith("list");
});
});
25 changes: 23 additions & 2 deletions ui-v2/src/components/artifacts/artifacts-filter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,17 @@ import {
} from "@/components/ui/select";
import { pluralize } from "@/utils";
import { useCallback, useMemo } from "react";
import { Icon } from "../ui/icons";
import { ToggleGroup, ToggleGroupItem } from "../ui/toggle-group";
import { Typography } from "../ui/typography";
import { filterType } from "./types";

interface ArtifactsFilterProps {
filters: filterType[];
onFilterChange: (newFilters: filterType[]) => void;
totalCount: number;
setDisplayMode: (mode: string) => void;
displayMode: string;
}

const artifactTypeOptions = [
Expand All @@ -29,6 +33,8 @@ export const ArtifactsFilterComponent = ({
filters,
onFilterChange,
totalCount,
displayMode,
setDisplayMode,
}: ArtifactsFilterProps) => {
const changeArtifactName = useCallback(
(value: string) => {
Expand Down Expand Up @@ -62,7 +68,7 @@ export const ArtifactsFilterComponent = ({
return (
<div
data-testid="artifact-filter"
className="flex justify-between items-center mt-4"
className="flex justify-between items-center"
>
<div>
<Typography variant="body" className="text-sm text-muted-foreground">
Expand All @@ -77,7 +83,7 @@ export const ArtifactsFilterComponent = ({
onChange={(e) => changeArtifactName(e.target.value)}
/>

<div className="xs:col-span-1 md:col-span-2 lg:col-span-2">
<div className="flex gap-4">
<Select
data-testid="type-select"
value={typeValue}
Expand All @@ -94,7 +100,22 @@ export const ArtifactsFilterComponent = ({
))}
</SelectContent>
</Select>
<div>
<ToggleGroup
type="single"
defaultValue={displayMode}
onValueChange={(value: string) => setDisplayMode(value)}
>
<ToggleGroupItem data-testid="grid-layout" value="grid">
<Icon id="LayoutGrid" />
</ToggleGroupItem>
<ToggleGroupItem data-testid="list-layout" value="list">
<Icon id="AlignJustify" />
</ToggleGroupItem>
</ToggleGroup>
</div>
</div>
<div></div>
</div>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion ui-v2/src/components/artifacts/artifacts-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const ArtifactsHeader = () => {
};

const Header = () => (
<div className="flex items-center gap-2">
<div className="flex items-center ">
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem className="text-xl font-semibold">
Expand Down
19 changes: 17 additions & 2 deletions ui-v2/src/components/artifacts/artifacts-page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { Artifact } from "@/api/artifacts";
import { useLocalStorage } from "@/hooks/use-local-storage";
import { useMemo } from "react";
import { ArtifactCard } from "./artifact-card";
import { ArtifactsFilterComponent } from "./artifacts-filter";
import { ArtifactsHeader } from "./artifacts-header";
Expand All @@ -17,15 +19,28 @@ export const ArtifactsPage = ({
artifactsList,
artifactsCount,
}: ArtifactsPageProps) => {
const [displayMode, setDisplayMode] = useLocalStorage<string>(
"artifacts-grid-style",
"grid",
);

const gridClass = useMemo(() => {
return displayMode === "grid"
? "grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-4"
: "grid-cols-1";
}, [displayMode]);
return (
<div>
<div className="flex flex-col gap-4">
<ArtifactsHeader />
<ArtifactsFilterComponent
filters={filters}
onFilterChange={onFilterChange}
totalCount={artifactsCount}
setDisplayMode={setDisplayMode}
displayMode={displayMode}
/>
<div className="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-4">

<div className={gridClass}>
{artifactsList.map((artifact) => (
<ArtifactCard key={artifact.id} artifact={artifact} />
))}
Expand Down
4 changes: 4 additions & 0 deletions ui-v2/src/components/ui/icons/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
AlignJustify,
AlignVerticalJustifyStart,
Ban,
Bot,
Expand All @@ -16,6 +17,7 @@ import {
Clock,
Cpu,
ExternalLink,
LayoutGrid,
Loader2,
Moon,
MoreHorizontal,
Expand All @@ -35,6 +37,7 @@ import {
} from "lucide-react";

export const ICONS = {
AlignJustify,
AlignVerticalJustifyStart,
Ban,
Bot,
Expand All @@ -52,6 +55,7 @@ export const ICONS = {
Clock,
Cpu,
ExternalLink,
LayoutGrid,
Loader2,
Moon,
MoreHorizontal,
Expand Down
59 changes: 59 additions & 0 deletions ui-v2/src/components/ui/toggle-group.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group";
import { type VariantProps } from "class-variance-authority";
import * as React from "react";

import { toggleVariants } from "@/components/ui/toggle";
import { cn } from "@/lib/utils";

const ToggleGroupContext = React.createContext<
VariantProps<typeof toggleVariants>
>({
size: "default",
variant: "default",
});

const ToggleGroup = React.forwardRef<
React.ElementRef<typeof ToggleGroupPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Root> &
VariantProps<typeof toggleVariants>
>(({ className, variant, size, children, ...props }, ref) => (
<ToggleGroupPrimitive.Root
ref={ref}
className={cn("flex items-center justify-center gap-1", className)}
{...props}
>
<ToggleGroupContext.Provider value={{ variant, size }}>
{children}
</ToggleGroupContext.Provider>
</ToggleGroupPrimitive.Root>
));

ToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName;

const ToggleGroupItem = React.forwardRef<
React.ElementRef<typeof ToggleGroupPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Item> &
VariantProps<typeof toggleVariants>
>(({ className, children, variant, size, ...props }, ref) => {
const context = React.useContext(ToggleGroupContext);

return (
<ToggleGroupPrimitive.Item
ref={ref}
className={cn(
toggleVariants({
variant: context.variant || variant,
size: context.size || size,
}),
className,
)}
{...props}
>
{children}
</ToggleGroupPrimitive.Item>
);
});

ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName;

export { ToggleGroup, ToggleGroupItem };
45 changes: 45 additions & 0 deletions ui-v2/src/components/ui/toggle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"use client";

import * as TogglePrimitive from "@radix-ui/react-toggle";
import { type VariantProps, cva } from "class-variance-authority";
import * as React from "react";

import { cn } from "@/lib/utils";

const toggleVariants = cva(
"inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
{
variants: {
variant: {
default: "bg-transparent",
outline:
"border border-input bg-transparent shadow-sm hover:bg-accent hover:text-accent-foreground",
},
size: {
default: "h-9 px-2 min-w-9",
sm: "h-8 px-1.5 min-w-8",
lg: "h-10 px-2.5 min-w-10",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
},
);

const Toggle = React.forwardRef<
React.ElementRef<typeof TogglePrimitive.Root>,
React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> &
VariantProps<typeof toggleVariants>
>(({ className, variant, size, ...props }, ref) => (
<TogglePrimitive.Root
ref={ref}
className={cn(toggleVariants({ variant, size, className }))}
{...props}
/>
));

Toggle.displayName = TogglePrimitive.Root.displayName;

export { Toggle, toggleVariants };

Check warning on line 45 in ui-v2/src/components/ui/toggle.tsx

View workflow job for this annotation

GitHub Actions / Build ui

Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components

0 comments on commit 9e834e6

Please sign in to comment.