learning_ai_clock/web/src/components/ui/Primitives.tsx
root ce7e04a158 feat(ux): add UX testing setup guide and common platform integration
- Add UX_TESTING_SETUP_GUIDE.md for ChronoMind
- Create .pnpmfile.cjs for local package resolution
- Update .npmrc to remove repo-level Gitea auth
- Create Primitives.tsx product adapter with ChronoMind-specific status types
- Add ui directory for shared component imports

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-09 22:10:55 +00:00

369 lines
9.9 KiB
TypeScript

import {
AppShell as BytelystAppShell,
AppShellMain as BytelystAppShellMain,
AppShellMobileToggle as BytelystAppShellMobileToggle,
AppShellNav as BytelystAppShellNav,
AppShellNavItem as BytelystAppShellNavItem,
AppShellOverlay as BytelystAppShellOverlay,
AppShellPageHeader as BytelystAppShellPageHeader,
AppShellSidebar as BytelystAppShellSidebar,
AppShellSkipLink as BytelystAppShellSkipLink,
Badge as BytelystBadge,
Button as BytelystButton,
Card as BytelystCard,
Checkbox,
DataList as BytelystDataList,
DataListItem as BytelystDataListItem,
DataListMeta,
DataTable,
DataTableBody,
DataTableCell,
DataTableHead,
DataTableHeader,
DataTableRow,
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuRadioGroup,
DropdownMenuSeparator,
DropdownMenuSub,
DropdownMenuSubTrigger,
DropdownMenuTrigger,
EmptyState as BytelystEmptyState,
IconButton as BytelystIconButton,
Input as BytelystInput,
Label as BytelystLabel,
ListItemButton as BytelystListItemButton,
LoadingSpinner as BytelystLoadingSpinner,
Panel as BytelystPanel,
PanelBody as BytelystPanelBody,
PanelDescription as BytelystPanelDescription,
PanelHeader as BytelystPanelHeader,
PanelTitle as BytelystPanelTitle,
RadioGroup,
RadioGroupItem,
SegmentedControl,
Select as BytelystSelect,
StatusBadge as BytelystStatusBadge,
Surface as BytelystSurface,
SurfaceList as BytelystSurfaceList,
SurfaceListItem as BytelystSurfaceListItem,
Switch,
Tabs,
TabsContent,
TabsList,
TabsTrigger,
Textarea as BytelystTextarea,
Timeline as BytelystTimeline,
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
type AppShellMainProps,
type AppShellMobileToggleProps,
type AppShellNavItemProps,
type AppShellNavProps,
type AppShellOverlayProps,
type AppShellPageHeaderProps,
type AppShellProps,
type AppShellSidebarProps,
type AppShellSkipLinkProps,
type BadgeProps,
type ButtonProps,
type CardProps,
type DataListItemProps,
type DataListProps,
type EmptyStateProps,
type IconButtonProps,
type InputProps,
type LabelProps,
type ListItemButtonProps,
type LoadingSpinnerProps,
type PanelBodyProps,
type PanelDescriptionProps,
type PanelHeaderProps,
type PanelProps,
type PanelTitleProps,
type SelectProps,
type StatusBadgeProps,
type StatusTone,
type SurfaceListItemProps,
type SurfaceListProps,
type SurfaceProps,
type TextareaProps,
type TimelineProps,
} from "@bytelyst/ui";
function mergeClassNames(...classes: Array<string | undefined>) {
return classes.filter(Boolean).join(" ");
}
export {
Checkbox,
DataListMeta,
DataTable,
DataTableBody,
DataTableCell,
DataTableHead,
DataTableHeader,
DataTableRow,
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuRadioGroup,
DropdownMenuSeparator,
DropdownMenuSub,
DropdownMenuSubTrigger,
DropdownMenuTrigger,
RadioGroup,
RadioGroupItem,
SegmentedControl,
Switch,
Tabs,
TabsContent,
TabsList,
TabsTrigger,
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
};
export type ChronoMindStatus =
| "running"
| "paused"
| "stopped"
| "completed"
| "alarm"
| "snoozed"
| "overdue"
| "upcoming"
| "recurring"
| "one-time"
| "focus"
| "break"
| "pomodoro"
| "routine"
| "error"
| "success";
const statusToneMap: Record<ChronoMindStatus, StatusTone> = {
running: "success",
paused: "warning",
stopped: "neutral",
completed: "success",
alarm: "danger",
snoozed: "warning",
overdue: "danger",
upcoming: "info",
recurring: "info",
"one-time": "neutral",
focus: "success",
break: "info",
pomodoro: "success",
routine: "info",
error: "danger",
success: "success",
};
export function AppShell({ className, ...props }: AppShellProps) {
return <BytelystAppShell className={className} {...props} />;
}
export function AppShellSkipLink({ className, ...props }: AppShellSkipLinkProps) {
return <BytelystAppShellSkipLink className={className} {...props} />;
}
export function AppShellMobileToggle({ className, ...props }: AppShellMobileToggleProps) {
return <BytelystAppShellMobileToggle className={className} {...props} />;
}
export function AppShellOverlay({ className, ...props }: AppShellOverlayProps) {
return <BytelystAppShellOverlay className={className} {...props} />;
}
export function AppShellSidebar({ className, ...props }: AppShellSidebarProps) {
return <BytelystAppShellSidebar className={className} {...props} />;
}
export function AppShellMain({ className, ...props }: AppShellMainProps) {
return <BytelystAppShellMain className={className} {...props} />;
}
export function AppShellPageHeader({ className, ...props }: AppShellPageHeaderProps) {
return <BytelystAppShellPageHeader className={className} {...props} />;
}
export function AppShellNav({ className, ...props }: AppShellNavProps) {
return <BytelystAppShellNav className={className} {...props} />;
}
export function AppShellNavItem({ className, ...props }: AppShellNavItemProps) {
return <BytelystAppShellNavItem className={className} {...props} />;
}
export function getStatusTone(status: ChronoMindStatus): StatusTone {
return statusToneMap[status];
}
export function Button({ className, ...props }: ButtonProps) {
return (
<BytelystButton
className={mergeClassNames("rounded-[var(--cm-radius-sm)]", className)}
{...props}
/>
);
}
export function Badge({ className, ...props }: BadgeProps) {
return <BytelystBadge className={className} {...props} />;
}
export function Card({ className, ...props }: CardProps) {
return (
<BytelystCard
className={mergeClassNames(
"rounded-[var(--cm-radius-md)] shadow-[var(--cm-elevation-md)]",
className,
)}
{...props}
/>
);
}
export function Panel({ className, ...props }: PanelProps) {
return (
<BytelystPanel
className={mergeClassNames(
"rounded-[var(--cm-radius-md)] shadow-[var(--cm-elevation-md)]",
className,
)}
{...props}
/>
);
}
export function PanelHeader({ className, ...props }: PanelHeaderProps) {
return <BytelystPanelHeader className={mergeClassNames("gap-[var(--cm-space-3)]", className)} {...props} />;
}
export function PanelBody({ className, ...props }: PanelBodyProps) {
return <BytelystPanelBody className={mergeClassNames("gap-[var(--cm-space-3)]", className)} {...props} />;
}
export function PanelTitle({ className, ...props }: PanelTitleProps) {
return <BytelystPanelTitle className={className} {...props} />;
}
export function PanelDescription({ className, ...props }: PanelDescriptionProps) {
return <BytelystPanelDescription className={className} {...props} />;
}
export function IconButton({ className, ...props }: IconButtonProps) {
return <BytelystIconButton className={mergeClassNames("rounded-[var(--cm-radius-sm)]", className)} {...props} />;
}
export function ListItemButton({ className, ...props }: ListItemButtonProps) {
return (
<BytelystListItemButton
className={mergeClassNames(
"rounded-[var(--cm-radius-sm)]",
className,
)}
{...props}
/>
);
}
export interface ChronoMindStatusBadgeProps extends StatusBadgeProps {
status?: ChronoMindStatus;
}
export function StatusBadge({ className, status, tone, ...props }: ChronoMindStatusBadgeProps) {
return <BytelystStatusBadge className={className} tone={tone ?? (status ? getStatusTone(status) : undefined)} {...props} />;
}
export function Input({ className, ...props }: InputProps) {
return (
<BytelystInput
className={mergeClassNames(
"rounded-[var(--cm-radius-sm)]",
className,
)}
{...props}
/>
);
}
export function Textarea({ className, ...props }: TextareaProps) {
return (
<BytelystTextarea
className={mergeClassNames(
"rounded-[var(--cm-radius-sm)]",
className,
)}
{...props}
/>
);
}
export function Select({ className, ...props }: SelectProps) {
return (
<BytelystSelect
className={mergeClassNames(
"rounded-[var(--cm-radius-sm)]",
className,
)}
{...props}
/>
);
}
export function Label({ className, ...props }: LabelProps) {
return <BytelystLabel className={className} {...props} />;
}
export function Timeline({ className, ...props }: TimelineProps) {
return <BytelystTimeline className={mergeClassNames("gap-[var(--cm-space-3)]", className)} {...props} />;
}
export function Surface({ className, padding = "md", ...props }: SurfaceProps) {
return (
<BytelystSurface
padding={padding}
className={mergeClassNames("rounded-[var(--cm-radius-md)]", className)}
{...props}
/>
);
}
export function SurfaceList({ density = "normal", className, ...props }: SurfaceListProps) {
return <BytelystSurfaceList density={density} className={mergeClassNames("gap-[var(--cm-space-3)]", className)} {...props} />;
}
export function SurfaceListItem({ className, ...props }: SurfaceListItemProps) {
return <BytelystSurfaceListItem className={mergeClassNames("rounded-[var(--cm-radius-sm)]", className)} {...props} />;
}
export function DataList({ density = "normal", className, ...props }: DataListProps) {
return <BytelystDataList density={density} className={mergeClassNames("gap-[var(--cm-space-3)]", className)} {...props} />;
}
export function DataListItem({ className, ...props }: DataListItemProps) {
return <BytelystDataListItem className={mergeClassNames("rounded-[var(--cm-radius-sm)]", className)} {...props} />;
}
export const OperationalList = DataList;
export const OperationalListItem = DataListItem;
export function EmptyState({ className, ...props }: EmptyStateProps) {
return <BytelystEmptyState className={mergeClassNames("rounded-[var(--cm-radius-md)]", className)} {...props} />;
}
export function LoadingSpinner({ className, ...props }: LoadingSpinnerProps) {
return <BytelystLoadingSpinner className={className} {...props} />;
}