diff --git a/apps/web/package.json b/apps/web/package.json index 25d05a44f..0e8bb27af 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -22,12 +22,13 @@ "@corbits/error-sink": "workspace:*", "@corbits/mcp": "github:corbitsdev/corbits-mcp#9df1ab81d2f50d798bca2d2f44eb4759c92fac0e", "@corbits/myra": "workspace:*", - "@corbits/react-ui": "github:corbitsdev/react-ui#3b122812a307ccb35be31386f7696020c5a84635", + "@corbits/react-ui": "0.3.0", "@corbits/url-path": "workspace:*", "@corbits/workflows": "workspace:*", "@intx/types": "workspace:*", "@isomorphic-git/lightning-fs": "4.7.0", "@radix-ui/react-dialog": "^1.1.15", + "@radix-ui/react-dropdown-menu": "^2.1.16", "@radix-ui/react-slot": "^1.2.3", "@tanstack/react-query": "catalog:", "arktype": "catalog:", diff --git a/apps/web/src/app.css b/apps/web/src/app.css index fe9afa566..bc3df6a70 100644 --- a/apps/web/src/app.css +++ b/apps/web/src/app.css @@ -800,74 +800,7 @@ select:disabled, font-weight: 650; } -.wb-av { - position: relative; - display: inline-flex; - flex: 0 0 auto; -} - -.wb-av-st { - position: absolute; - right: -3px; - bottom: -3px; - width: 10px; - height: 10px; - border-radius: 50%; - border: 2px solid var(--background); - background: var(--muted-foreground); -} - -.wb-av-st--ready { - background: var(--success); -} - -.wb-av-st--idle { - background: color-mix(in srgb, var(--muted-foreground) 50%, transparent); -} - -/* The arc travels a ring concentric with the mark. The conic angle is what - animates, so the masked shape itself never rotates. */ -@property --orbit-a { - syntax: ""; - inherits: false; - initial-value: 0deg; -} - -.wb-av-orbit { - position: absolute; - inset: -3.5px; - padding: 1.5px; - pointer-events: none; - border-radius: calc(var(--av-r) + 3.5px); - background: conic-gradient( - from var(--orbit-a), - transparent 0deg, - color-mix(in srgb, var(--primary) 20%, transparent) 20deg, - var(--primary) 130deg, - transparent 131deg 360deg - ); - -webkit-mask: - linear-gradient(#000 0 0) content-box, - linear-gradient(#000 0 0); - -webkit-mask-composite: xor; - mask-composite: exclude; - animation: wb-av-orbit 1.4s linear infinite; -} - -.wb-av[data-kind="person"] .wb-av-orbit { - border-radius: 50%; -} - -@keyframes wb-av-orbit { - to { - --orbit-a: 360deg; - } -} - @media (prefers-reduced-motion: reduce) { - .wb-av-orbit { - animation: none; - } .shell-ch-row { transition: none; } diff --git a/apps/web/src/auth-screen.tsx b/apps/web/src/auth-screen.tsx index 64295de43..20a978e91 100644 --- a/apps/web/src/auth-screen.tsx +++ b/apps/web/src/auth-screen.tsx @@ -2,8 +2,7 @@ // seeds a default dev account, and hosted deployments already have accounts — // with creating an account one click away in the form's footer. -import { Button } from "@corbits/react-ui"; -import { LoginForm } from "@corbits/react-ui/blocks/login/login-form"; +import { Button, LoginForm } from "@corbits/react-ui"; import { useState } from "react"; import { AuthLayout } from "./auth/auth-layout"; diff --git a/apps/web/src/bench/grants-tab.tsx b/apps/web/src/bench/grants-tab.tsx index abf841d50..2656de2d6 100644 --- a/apps/web/src/bench/grants-tab.tsx +++ b/apps/web/src/bench/grants-tab.tsx @@ -1,4 +1,5 @@ -import { ConfirmButton, toast } from "@corbits/react-ui"; +import { ConfirmButton } from "@corbits/react-ui"; +import { toast } from "@corbits/react-ui/ui/toast"; import type { GrantEffect } from "@intx/types"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; diff --git a/apps/web/src/bench/information-tab.tsx b/apps/web/src/bench/information-tab.tsx index c28e88adc..b719e6f60 100644 --- a/apps/web/src/bench/information-tab.tsx +++ b/apps/web/src/bench/information-tab.tsx @@ -1,4 +1,5 @@ -import { Button, Skeleton, formatRelativeTime, toast } from "@corbits/react-ui"; +import { Button, Skeleton, formatRelativeTime } from "@corbits/react-ui"; +import { toast } from "@corbits/react-ui/ui/toast"; import { useQuery } from "@tanstack/react-query"; import { useState } from "react"; diff --git a/apps/web/src/chat/approval-row.tsx b/apps/web/src/chat/approval-row.tsx index e60177c67..5562b4967 100644 --- a/apps/web/src/chat/approval-row.tsx +++ b/apps/web/src/chat/approval-row.tsx @@ -2,7 +2,8 @@ // workbench workbench's info column and the chat transcript, so a person can // answer an agent's ask wherever they are looking when it lands. -import { Button, formatRelativeTime, toast } from "@corbits/react-ui"; +import { Button, formatRelativeTime } from "@corbits/react-ui"; +import { toast } from "@corbits/react-ui/ui/toast"; import { useMutation, useQueryClient } from "@tanstack/react-query"; import { approveApproval, rejectApproval } from "../api"; diff --git a/apps/web/src/chat/avatar.tsx b/apps/web/src/chat/avatar.tsx index 3f46103c6..83a78bfde 100644 --- a/apps/web/src/chat/avatar.tsx +++ b/apps/web/src/chat/avatar.tsx @@ -1,4 +1,11 @@ -import { Avatar, AvatarStack, type AvatarStackItem, type AvatarTone } from "@corbits/react-ui"; +import { + Avatar, + AvatarStack, + type AvatarSize, + type AvatarStackItem, + type AvatarStatus, + type AvatarTone, +} from "@corbits/react-ui"; import { agentInitials } from "@/chat/threads-api"; @@ -61,18 +68,8 @@ export function resolveAvatarFill( return { kind: "generated", className: avatarClassForPrincipal(principalId) }; } -export type CorbitAvatarSize = "xs" | "sm" | "md" | "lg" | "xl" | number; -export type AvatarStatus = "working" | "ready" | "idle"; - -// react-ui ships sm/md/lg only; the wrapper sizes xs/xl/numeric and the -// mark fills it. -const SIZE_PX = { xs: 16, sm: 24, md: 32, lg: 40, xl: 80 } as const; - -function baseSize(px: number): "sm" | "md" | "lg" { - if (px <= 24) return "sm"; - if (px <= 32) return "md"; - return "lg"; -} +export type CorbitAvatarSize = AvatarSize; +export type { AvatarStatus }; export interface WorkbenchAvatarProps { /** Workers are rounded squares, people circles. */ @@ -92,28 +89,17 @@ export function WorkbenchAvatar({ status, className, }: WorkbenchAvatarProps) { - const px = typeof size === "number" ? size : SIZE_PX[size]; - const radius = kind === "person" ? "50%" : `${Math.round(px * 0.28)}px`; - const working = kind === "worker" && status === "working"; return ( - - - {working ?