ui(component): Added new Toast (Sonner) component (#4412)
This commit is contained in:
1 parent
43f54aa49c
commit
e0fca8c88c
16 files changed
+1212
-247
No files matched your search
@@ -176,12 +176,14 @@ module.exports = {
|
||||
target: '_blank',
|
||||
position: 'left',
|
||||
},
|
||||
/*
|
||||
{
|
||||
to: '/playground',
|
||||
label: 'UI Playground',
|
||||
position: 'left',
|
||||
className: 'new-badge',
|
||||
},
|
||||
*/
|
||||
{
|
||||
to: '/help',
|
||||
//activeBaseRegex: '(^/help$)|(/help)',
|
||||
|
||||
@@ -10,16 +10,22 @@ export default function Patterns() {
|
||||
<h1>Patterns</h1>
|
||||
<button
|
||||
className="bg-slate-400"
|
||||
onClick={() => history.push('/patterns/segmentation-panel')}
|
||||
onClick={() => history.push('/patterns/patterns-segmentation')}
|
||||
>
|
||||
{'Segmentation Panel'}
|
||||
</button>
|
||||
<button
|
||||
className="bg-slate-400"
|
||||
onClick={() => history.push('/patterns/measurement-panel')}
|
||||
onClick={() => history.push('/patterns/patterns-measurements')}
|
||||
>
|
||||
{'Measurements Panel'}
|
||||
</button>
|
||||
<button
|
||||
className="bg-slate-400"
|
||||
onClick={() => history.push('/patterns/patterns-tmtv')}
|
||||
>
|
||||
{'tmtv'}
|
||||
</button>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
File renamed without changes.
+56
@@ -10,6 +10,18 @@ import {
|
||||
SelectItem,
|
||||
} from '../../../../ui-next/src/components/Select';
|
||||
import { Icons } from '../../../../ui-next/src/components/Icons';
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuTrigger,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSub,
|
||||
DropdownMenuSubTrigger,
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuPortal,
|
||||
} from '../../../../ui-next/src/components/DropdownMenu';
|
||||
import {
|
||||
Accordion,
|
||||
AccordionItem,
|
||||
@@ -85,6 +97,50 @@ export default function SegmentationPanel() {
|
||||
<div className="mb-0">
|
||||
{/* Header Controls */}
|
||||
<div className="bg-muted flex h-10 w-full items-center space-x-1 rounded-t px-1.5">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
>
|
||||
<Icons.More className="h-6 w-6" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="start">
|
||||
<DropdownMenuItem>
|
||||
<Icons.Add className="text-foreground" />
|
||||
<span className="pl-2">Create New Segmentation</span>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuLabel>Manage Current Segmentation</DropdownMenuLabel>
|
||||
<DropdownMenuItem>
|
||||
<Icons.Series className="text-foreground" />
|
||||
<span className="pl-2">Remove from Viewport</span>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
<Icons.Rename className="text-foreground" />
|
||||
<span className="pl-2">Rename</span>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSub>
|
||||
<DropdownMenuSubTrigger>
|
||||
<Icons.Export className="text-foreground" />
|
||||
<span className="pl-2">Export & Download</span>
|
||||
</DropdownMenuSubTrigger>
|
||||
<DropdownMenuPortal>
|
||||
<DropdownMenuSubContent>
|
||||
<DropdownMenuItem>Export DICOM SEG</DropdownMenuItem>
|
||||
<DropdownMenuItem>Download DICOM SEG</DropdownMenuItem>
|
||||
<DropdownMenuItem>Download DICOM RTSTRUCT</DropdownMenuItem>
|
||||
</DropdownMenuSubContent>
|
||||
</DropdownMenuPortal>
|
||||
</DropdownMenuSub>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>
|
||||
<Icons.Delete className="text-red-600" />
|
||||
<span className="pl-2 text-red-600">Delete</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
<Select>
|
||||
<SelectTrigger className="w-full overflow-hidden">
|
||||
<SelectValue placeholder="Segmentation 1" />
|
||||
@@ -0,0 +1,43 @@
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import { DataRow } from '../../../../ui-next/src/components/DataRow';
|
||||
import { Button } from '../../../../ui-next/src/components/Button';
|
||||
import {
|
||||
Select,
|
||||
SelectValue,
|
||||
SelectTrigger,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
} from '../../../../ui-next/src/components/Select';
|
||||
import { Icons } from '../../../../ui-next/src/components/Icons';
|
||||
import {
|
||||
Accordion,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
AccordionContent,
|
||||
} from '../../../../ui-next/src/components/Accordion';
|
||||
import { Slider } from '../../../../ui-next/src/components/Slider';
|
||||
import { Switch } from '../../../../ui-next/src/components/Switch';
|
||||
import { Label } from '../../../../ui-next/src/components/Label';
|
||||
import { Input } from '../../../../ui-next/src/components/Input';
|
||||
import { Tabs, TabsList, TabsTrigger } from '../../../../ui-next/src/components/Tabs';
|
||||
import { actionOptionsMap, dataList } from '../../../../ui-next/assets/data';
|
||||
|
||||
interface DataItem {
|
||||
id: number;
|
||||
title: string;
|
||||
description: string;
|
||||
optionalField?: string;
|
||||
colorHex?: string;
|
||||
details?: string;
|
||||
series?: string;
|
||||
}
|
||||
|
||||
interface ListGroup {
|
||||
type: string;
|
||||
items: DataItem[];
|
||||
}
|
||||
|
||||
export default function SplitPanel() {
|
||||
return <div>hellosssssss</div>;
|
||||
}
|
||||
@@ -0,0 +1,403 @@
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import { Button } from '../../../../ui-next/src/components/Button';
|
||||
import {
|
||||
Select,
|
||||
SelectGroup,
|
||||
SelectValue,
|
||||
SelectTrigger,
|
||||
SelectContent,
|
||||
SelectLabel,
|
||||
SelectItem,
|
||||
SelectSeparator,
|
||||
SelectScrollUpButton,
|
||||
SelectScrollDownButton,
|
||||
} from '../../../../ui-next/src/components/Select';
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuTrigger,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSub,
|
||||
DropdownMenuSubTrigger,
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuPortal,
|
||||
} from '../../../../ui-next/src/components/DropdownMenu';
|
||||
import { Icons } from '../../../../ui-next/src/components/Icons/Icons';
|
||||
import { DataRow } from '../../../../ui-next/src/components/DataRow';
|
||||
import { actionOptionsMap, dataList } from '../../../../ui-next/assets/data';
|
||||
|
||||
import {
|
||||
Accordion,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
AccordionContent,
|
||||
} from '../../../../ui-next/src/components/Accordion/Accordion';
|
||||
import { Slider } from '../../../../ui-next/src/components/Slider';
|
||||
import { Switch } from '../../../../ui-next/src/components/Switch';
|
||||
import { Label } from '../../../../ui-next/src/components/Label';
|
||||
import { Input } from '../../../../ui-next/src/components/Input';
|
||||
import { Tabs, TabsList, TabsTrigger, TabsContent } from '../../../../ui-next/src/components/Tabs';
|
||||
|
||||
import { ChevronDownIcon } from '@radix-ui/react-icons';
|
||||
|
||||
interface DataItem {
|
||||
id: number;
|
||||
title: string;
|
||||
description: string;
|
||||
optionalField?: string;
|
||||
colorHex?: string;
|
||||
details?: string;
|
||||
series?: string;
|
||||
}
|
||||
|
||||
interface ListGroup {
|
||||
type: string;
|
||||
items: DataItem[];
|
||||
}
|
||||
|
||||
export default function TMTVPatterns() {
|
||||
const [selectedRowId, setSelectedRowId] = useState<string | null>(null);
|
||||
const [selectedTab, setSelectedTab] = useState<string>('Fill & Outline');
|
||||
|
||||
const handleAction = (id: string, action: string) => {
|
||||
console.log(`Action "${action}" triggered for item with id: ${id}`);
|
||||
// Implement actual action logic here
|
||||
};
|
||||
|
||||
// Handle row selection
|
||||
const handleRowSelect = (id: string) => {
|
||||
setSelectedRowId(prevSelectedId => (prevSelectedId === id ? null : id));
|
||||
};
|
||||
|
||||
// Find the "TMTV2" group
|
||||
const tmv2Group = dataList.find((listGroup: ListGroup) => listGroup.type === 'TMTV2');
|
||||
|
||||
// Find the "TMTV1" group
|
||||
const tmvGroup = dataList.find((listGroup: ListGroup) => listGroup.type === 'TMTV1');
|
||||
|
||||
// Check if both groups exist
|
||||
if (!tmv2Group) {
|
||||
return <div className="text-red-500">TMTV2 data not found.</div>;
|
||||
}
|
||||
|
||||
if (!tmvGroup) {
|
||||
return <div className="text-red-500">TMTV1 data not found.</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="px-auto my-4 flex h-full w-full justify-center bg-black py-6">
|
||||
<div className="w-64 space-y-0">
|
||||
<Accordion
|
||||
type="multiple"
|
||||
defaultValue={['segmentation-tools', 'segmentation-list', 'tmv1-group', 'tmv2-group']}
|
||||
collapsible
|
||||
>
|
||||
{/* Segmentation Tools */}
|
||||
<AccordionItem value="segmentation-tools">
|
||||
<AccordionTrigger className="bg-popover hover:bg-accent text-muted-foreground my-0.5 flex h-7 w-full items-center justify-between rounded py-2 pr-1 pl-2 font-normal">
|
||||
<span>Segmentation Tools</span>
|
||||
</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<div className="bg-muted mb-0.5 h-32 rounded-b pb-3"></div>
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
{/* Segmentation List */}
|
||||
<AccordionItem value="segmentation-list">
|
||||
<AccordionTrigger className="bg-popover hover:bg-accent text-muted-foreground my-0.5 flex h-7 w-full items-center justify-between rounded py-2 pr-1 pl-2 font-normal">
|
||||
<span>Segmentation List</span>
|
||||
</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
{/* Appearance Settings */}
|
||||
<AccordionItem value="segmentation-display">
|
||||
<AccordionTrigger className="bg-muted hover:bg-accent mt-0.5 flex h-7 w-full items-center justify-between rounded-b pr-1 pl-2 font-normal text-white">
|
||||
<div className="flex space-x-2">
|
||||
<Icons.Controls className="text-primary" />
|
||||
<span className="text-primary pr-1">Appearance Settings</span>
|
||||
</div>
|
||||
</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<div className="bg-muted mb-0.5 space-y-2 rounded-b px-px pt-0.5 pb-3">
|
||||
<div className="mx-1 mb-2.5 mt-1 flex items-center justify-between space-x-4">
|
||||
{/* Display Label with Selected Tab */}
|
||||
<div className="text-muted-foreground text-xs">Show: {selectedTab}</div>
|
||||
{/* Tabs Controls */}
|
||||
<Tabs
|
||||
value={selectedTab}
|
||||
onValueChange={setSelectedTab}
|
||||
>
|
||||
<TabsList>
|
||||
<TabsTrigger value="Fill & Outline">
|
||||
<Icons.DisplayFillAndOutline className="text-primary" />
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="Outline Only">
|
||||
<Icons.DisplayOutlineOnly className="text-primary" />
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="Fill Only">
|
||||
<Icons.DisplayFillOnly className="text-primary" />
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
</Tabs>
|
||||
</div>
|
||||
{/* Opacity Slider */}
|
||||
<div className="my-2 flex items-center ">
|
||||
<Label className="text-muted-foreground mx-1 w-14 flex-none whitespace-nowrap text-xs">
|
||||
Opacity
|
||||
</Label>
|
||||
<Slider
|
||||
className="mx-1 flex-1"
|
||||
defaultValue={[85]}
|
||||
max={100}
|
||||
step={1}
|
||||
/>
|
||||
<Input
|
||||
className="mx-1 w-10 flex-none"
|
||||
placeholder="85"
|
||||
/>
|
||||
</div>
|
||||
{/* Border Slider */}
|
||||
<div className="my-2 flex items-center">
|
||||
<Label className="text-muted-foreground mx-1 w-14 flex-none whitespace-nowrap text-xs">
|
||||
Border
|
||||
</Label>
|
||||
<Slider
|
||||
className="mx-1 flex-1"
|
||||
defaultValue={[10]}
|
||||
max={100}
|
||||
step={1}
|
||||
/>
|
||||
<Input
|
||||
className="mx-1 w-10 flex-none"
|
||||
placeholder="2"
|
||||
/>
|
||||
</div>
|
||||
{/* Sync Changes Switch */}
|
||||
<div className="my-2 flex items-center pl-1 pb-1">
|
||||
<Switch defaultChecked />
|
||||
<Label className="text-muted-foreground mx-2 w-14 flex-none whitespace-nowrap text-xs">
|
||||
Sync changes in all viewports
|
||||
</Label>
|
||||
</div>
|
||||
<div className="border-input w-full border"></div>
|
||||
{/* Display Inactive Segmentations Switch */}
|
||||
<div className="my-2 flex items-center pl-1">
|
||||
<Switch defaultChecked />
|
||||
<Label className="text-muted-foreground mx-2 w-14 flex-none whitespace-nowrap text-xs">
|
||||
Display inactive segmentations
|
||||
</Label>
|
||||
</div>
|
||||
{/* Additional Opacity Slider */}
|
||||
<div className="my-2 flex items-center ">
|
||||
<Label className="text-muted-foreground mx-1 w-14 flex-none whitespace-nowrap text-xs">
|
||||
Opacity
|
||||
</Label>
|
||||
<Slider
|
||||
className="mx-1 flex-1"
|
||||
defaultValue={[65]}
|
||||
max={100}
|
||||
step={1}
|
||||
/>
|
||||
<Input
|
||||
className="mx-1 w-10 flex-none"
|
||||
placeholder="65"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
{/* TMTV1 Group */}
|
||||
<AccordionItem value="tmv1-group">
|
||||
<AccordionTrigger className="hover:bg-popover mr-0 flex h-8 w-full items-center pl-0 pr-1">
|
||||
<div className="text-foreground border-input flex h-8 w-full items-center justify-between border-t-2">
|
||||
{/* Left Group: DropdownMenu and TMTV1 Label */}
|
||||
<div className="flex items-center space-x-1">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="ml-1"
|
||||
>
|
||||
<Icons.More className="h-6 w-6" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="start">
|
||||
<DropdownMenuItem>
|
||||
<Icons.Add className="text-foreground" />
|
||||
<span className="pl-2">Add Segment</span>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>
|
||||
<Icons.Series className="text-foreground" />
|
||||
<span className="pl-2">Remove from Viewport</span>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
<Icons.Rename className="text-foreground" />
|
||||
<span className="pl-2">Rename</span>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
<Icons.Hide className="text-foreground" />
|
||||
<span className="pl-2">Hide or Show all Segments</span>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSub>
|
||||
<DropdownMenuSubTrigger>
|
||||
<Icons.Export className="text-foreground" />
|
||||
<span className="pl-2">Export & Download</span>
|
||||
</DropdownMenuSubTrigger>
|
||||
<DropdownMenuPortal>
|
||||
<DropdownMenuSubContent>
|
||||
<DropdownMenuItem>Export DICOM SEG</DropdownMenuItem>
|
||||
<DropdownMenuItem>Download DICOM SEG</DropdownMenuItem>
|
||||
<DropdownMenuItem>Download DICOM RTSTRUCT</DropdownMenuItem>
|
||||
</DropdownMenuSubContent>
|
||||
</DropdownMenuPortal>
|
||||
</DropdownMenuSub>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>
|
||||
<Icons.Delete className="text-red-600" />
|
||||
<span className="pl-2 text-red-600">Delete</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
<div className="pl-1.5">TMTV1 Segmentation</div>
|
||||
</div>
|
||||
<div className="mr-1 flex items-center">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
>
|
||||
<Icons.Info className="h-6 w-6" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
{/* Data Rows for TMTV1 */}
|
||||
<div className="space-y-px">
|
||||
{tmvGroup.items.map((item, index) => {
|
||||
const compositeId = `${tmvGroup.type}-${item.id}-panel`; // Ensure unique composite ID
|
||||
return (
|
||||
<DataRow
|
||||
key={`panel-${compositeId}`} // Prefix to ensure uniqueness
|
||||
number={index + 1}
|
||||
title={item.title}
|
||||
description={item.description}
|
||||
optionalField={item.optionalField}
|
||||
colorHex={item.colorHex}
|
||||
details={item.details}
|
||||
series={item.series}
|
||||
actionOptions={actionOptionsMap[tmvGroup.type] || ['Action']}
|
||||
onAction={(action: string) => handleAction(compositeId, action)}
|
||||
isSelected={selectedRowId === compositeId}
|
||||
onSelect={() => handleRowSelect(compositeId)}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
{/* TMTV2 Group */}
|
||||
<AccordionItem value="tmv2-group">
|
||||
<AccordionTrigger className="hover:bg-popover mr-0 flex h-8 w-full items-center pl-0 pr-1">
|
||||
<div className="text-foreground border-input flex h-8 w-full items-center justify-between border-t-2">
|
||||
<div className="flex items-center space-x-1">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="ml-1"
|
||||
>
|
||||
<Icons.More className="h-6 w-6" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="start">
|
||||
<DropdownMenuItem>
|
||||
<Icons.Add className="text-foreground" />
|
||||
<span className="pl-2">Add Segment</span>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>
|
||||
<Icons.Series className="text-foreground" />
|
||||
<span className="pl-2">Remove from Viewport</span>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
<Icons.Rename className="text-foreground" />
|
||||
<span className="pl-2">Rename</span>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
<Icons.Hide className="text-foreground" />
|
||||
<span className="pl-2">Hide or Show all Segments</span>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSub>
|
||||
<DropdownMenuSubTrigger>
|
||||
<Icons.Export className="text-foreground" />
|
||||
<span className="pl-2">Export & Download</span>
|
||||
</DropdownMenuSubTrigger>
|
||||
<DropdownMenuPortal>
|
||||
<DropdownMenuSubContent>
|
||||
<DropdownMenuItem>Export DICOM SEG</DropdownMenuItem>
|
||||
<DropdownMenuItem>Download DICOM SEG</DropdownMenuItem>
|
||||
<DropdownMenuItem>Download DICOM RTSTRUCT</DropdownMenuItem>
|
||||
</DropdownMenuSubContent>
|
||||
</DropdownMenuPortal>
|
||||
</DropdownMenuSub>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>
|
||||
<Icons.Delete className="text-red-600" />
|
||||
<span className="pl-2 text-red-600">Delete</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
|
||||
<div className="pl-1.5">TMTV2 Segmentation</div>
|
||||
</div>
|
||||
<div className="mr-1 flex items-center ">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
>
|
||||
<Icons.Info className="h-6 w-6" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
{/* Data Rows for TMTV2 */}
|
||||
<div className="space-y-px">
|
||||
{tmv2Group.items.map((item, index) => {
|
||||
const compositeId = `${tmv2Group.type}-${item.id}-panel`; // Ensure unique composite ID
|
||||
return (
|
||||
<DataRow
|
||||
key={`panel-${compositeId}`} // Prefix to ensure uniqueness
|
||||
number={index + 1}
|
||||
title={item.title}
|
||||
description={item.description}
|
||||
optionalField={item.optionalField}
|
||||
colorHex={item.colorHex}
|
||||
details={item.details}
|
||||
series={item.series}
|
||||
actionOptions={actionOptionsMap[tmv2Group.type] || ['Action']}
|
||||
onAction={(action: string) => handleAction(compositeId, action)}
|
||||
isSelected={selectedRowId === compositeId}
|
||||
onSelect={() => handleRowSelect(compositeId)}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
{/* Footer or Additional Information */}
|
||||
<div className="bg-popover text-foreground flex h-8 items-center justify-between pl-9 pr-3 text-sm font-semibold">
|
||||
<span>TMTV</span>
|
||||
<span>21.555 mL</span>
|
||||
</div>
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
DropdownMenuItem,
|
||||
} from '../../../ui-next/src/components/DropdownMenu';
|
||||
import { Icons } from '../../../ui-next/src/components/Icons';
|
||||
import { Toaster, toast } from '../../../ui-next/src/components/Sonner';
|
||||
|
||||
interface ShowcaseRowProps {
|
||||
title: string;
|
||||
@@ -34,6 +35,106 @@ interface ShowcaseRowProps {
|
||||
}
|
||||
|
||||
export default function ComponentShowcase() {
|
||||
// Handlers to trigger different types of toasts
|
||||
const triggerSuccess = () => {
|
||||
toast.success('This is a success toast!');
|
||||
};
|
||||
|
||||
const triggerError = () => {
|
||||
toast.error('This is an error toast!');
|
||||
};
|
||||
|
||||
const triggerInfo = () => {
|
||||
toast.info('This is an info toast!');
|
||||
};
|
||||
|
||||
const triggerWarning = () => {
|
||||
toast.warning('This is a warning toast!');
|
||||
};
|
||||
|
||||
// Handler to trigger a toast.promise example
|
||||
const triggerPromiseToast = () => {
|
||||
const promise = () =>
|
||||
new Promise<{ name: string }>(resolve =>
|
||||
setTimeout(() => resolve({ name: 'Segmentation 1' }), 3000)
|
||||
);
|
||||
|
||||
toast.promise(promise(), {
|
||||
loading: 'Loading Segmentation...',
|
||||
success: data => `${data.name} has been added`,
|
||||
error: 'Error',
|
||||
});
|
||||
};
|
||||
|
||||
// Handler to trigger a toast with description
|
||||
const triggerDescriptionToast = () => {
|
||||
toast.success('Success heading', {
|
||||
description: 'This is a detailed description of the success message.',
|
||||
});
|
||||
};
|
||||
|
||||
// Handler to trigger a toast with an action button
|
||||
const triggerActionButtonToast = () => {
|
||||
toast.info('Info heading', {
|
||||
description: 'This is an info message with an action button.',
|
||||
action: (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
onClick={() => alert('Action button clicked')}
|
||||
>
|
||||
Undo
|
||||
</Button>
|
||||
),
|
||||
});
|
||||
};
|
||||
|
||||
// Handler to trigger a toast with a cancel button
|
||||
const triggerCancelButtonToast = () => {
|
||||
toast.error('Error!', {
|
||||
description: 'This is an error message with a cancel button.',
|
||||
cancel: (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
onClick={() => toast.dismiss()}
|
||||
>
|
||||
Dismiss
|
||||
</Button>
|
||||
),
|
||||
});
|
||||
};
|
||||
|
||||
// Handler to trigger a toast with both action and cancel buttons
|
||||
const triggerCombinedToast = () => {
|
||||
toast.warning('Warning!', {
|
||||
description: 'This is a warning with both action and cancel buttons.',
|
||||
action: (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
onClick={() => alert('Retry action clicked')}
|
||||
>
|
||||
Retry
|
||||
</Button>
|
||||
),
|
||||
cancel: (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
onClick={() => toast.dismiss()}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
),
|
||||
});
|
||||
};
|
||||
|
||||
// Handler to trigger a loading toast using Toaster's default loading icon
|
||||
const showLoadingToast = () => {
|
||||
toast.loading('Loading your data...');
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="bg-background text-foreground h-full">
|
||||
<div className="mx-auto my-4 max-w-6xl py-6">
|
||||
@@ -488,6 +589,82 @@ export default function ComponentShowcase() {
|
||||
do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
</ScrollArea>
|
||||
</ShowcaseRow>
|
||||
<ShowcaseRow
|
||||
title="sonner 1"
|
||||
description="sonner1"
|
||||
code={`sdf`}
|
||||
>
|
||||
{/* Toast Examples Section */}
|
||||
<div className="space-x-2">
|
||||
<Button
|
||||
variant="default"
|
||||
onClick={triggerSuccess}
|
||||
>
|
||||
Show Success Toast
|
||||
</Button>
|
||||
<Button
|
||||
variant="default"
|
||||
onClick={triggerError}
|
||||
>
|
||||
Show Error Toast
|
||||
</Button>
|
||||
<Button
|
||||
variant="default"
|
||||
onClick={triggerInfo}
|
||||
>
|
||||
Show Info Toast
|
||||
</Button>
|
||||
<Button
|
||||
variant="default"
|
||||
onClick={triggerWarning}
|
||||
>
|
||||
Show Warning Toast
|
||||
</Button>
|
||||
<Button
|
||||
variant="default"
|
||||
onClick={triggerPromiseToast}
|
||||
>
|
||||
Loading & Success Toast
|
||||
</Button>
|
||||
</div>
|
||||
</ShowcaseRow>
|
||||
|
||||
<ShowcaseRow
|
||||
title="sonner 2"
|
||||
description="sonner2"
|
||||
code={`sdf`}
|
||||
>
|
||||
<Button
|
||||
variant="default"
|
||||
onClick={triggerDescriptionToast}
|
||||
>
|
||||
Show Toast with Description
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="default"
|
||||
onClick={triggerActionButtonToast}
|
||||
>
|
||||
Show Toast with Action Button
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="default"
|
||||
onClick={triggerCancelButtonToast}
|
||||
>
|
||||
Show Toast with Cancel Button
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="default"
|
||||
onClick={triggerCombinedToast}
|
||||
>
|
||||
Show Toast with Action & Cancel Buttons
|
||||
</Button>
|
||||
|
||||
{/* Render the Toaster component */}
|
||||
<Toaster />
|
||||
</ShowcaseRow>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user