From f2f648acfa64e14f9fabb51419e6b0922adb60fe Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Sun, 1 Mar 2026 17:07:31 +1000 Subject: [PATCH 1/2] chore: replace eslint with biome for linting and formatting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the unused ESLint infrastructure (tooling/eslint-config/) with Biome v2 — a Rust-based linter and formatter that is 10-100x faster. - Add biome.json with recommended rules, react domain, and formatter config (single quotes, no semicolons, trailing commas, 2-space indent) - Update root package.json: add @biomejs/biome, replace turbo lint with biome check, add lint:fix and format scripts - Remove lint task from turbo.json (was a no-op since no packages had lint scripts) - Delete tooling/eslint-config/ (private package, never wired up) - Fix all lint violations: add button types, remove unused imports, prefix unused variables, fix forEach return values - Disable noisy a11y rules that conflict with intentional ARIA patterns in this component library (noSvgWithoutTitle, useSemanticElements, noStaticElementInteractions, etc.) - Exclude Tailwind CSS files from biome (uses @theme/@apply directives that biome cannot parse) - Add .git-blame-ignore-revs for the bulk formatting changes --- .git-blame-ignore-revs | 4 + apps/docs/app/(home)/layout.tsx | 8 +- apps/docs/app/(home)/page.tsx | 27 +- apps/docs/app/docs/[[...slug]]/page.tsx | 37 +- apps/docs/app/docs/layout.tsx | 10 +- apps/docs/app/layout.tsx | 14 +- .../content/docs/components/core/meta.json | 14 +- apps/docs/content/docs/meta.json | 10 +- apps/docs/content/docs/patterns/meta.json | 10 +- apps/docs/global.d.ts | 2 +- apps/docs/lib/layout.shared.tsx | 4 +- apps/docs/lib/source.ts | 6 +- apps/docs/next.config.mjs | 14 +- apps/docs/postcss.config.mjs | 4 +- apps/docs/source.config.ts | 6 +- apps/docs/tailwind.config.ts | 8 +- apps/docs/tsconfig.json | 14 +- apps/playground/src/App.tsx | 56 +- .../src/demos/full-page/FullPageDemo.tsx | 331 ++-- .../src/demos/layouts/LayoutDemos.tsx | 16 +- .../src/demos/showcase/ShowcasePage.tsx | 207 ++- .../sections/AgentComponentsSection.tsx | 60 +- .../sections/AgentStreamingSection.tsx | 52 +- .../sections/ButtonsInputsSection.tsx | 86 +- .../showcase/sections/DataDisplaySection.tsx | 75 +- .../showcase/sections/FeedbackSection.tsx | 45 +- .../demos/showcase/sections/HooksSection.tsx | 59 +- .../demos/showcase/sections/IconsSection.tsx | 144 +- .../demos/showcase/sections/LayoutSection.tsx | 6 +- .../demos/showcase/sections/MCPSection.tsx | 39 +- .../showcase/sections/NavigationSection.tsx | 44 +- .../showcase/sections/OverlaysSection.tsx | 74 +- .../showcase/sections/PrimitivesSection.tsx | 15 +- .../showcase/sections/SectionWrapper.tsx | 12 +- .../demos/showcase/sections/ToastTrigger.tsx | 18 +- .../src/demos/showcase/showcase-data.ts | 255 ++- apps/playground/src/mock-api/responses.ts | 38 +- apps/playground/src/mock-api/server.ts | 2 +- apps/playground/src/styles.css | 134 +- apps/playground/vite.config.ts | 4 +- apps/storybook/.storybook/main.ts | 13 +- apps/storybook/.storybook/preview.css | 49 +- apps/storybook/.storybook/preview.tsx | 1 - apps/storybook/postcss.config.mjs | 4 +- .../stories/agent/AgentPanel.stories.tsx | 7 +- .../stories/agent/AgentResponse.stories.tsx | 2 +- .../stories/agent/MCPResourceView.stories.tsx | 3 +- .../stories/agent/MCPServerStatus.stories.tsx | 14 +- .../stories/agent/MCPToolCall.stories.tsx | 2 +- .../stories/agent/MessageBubble.stories.tsx | 2 +- .../stories/agent/MessageThread.stories.tsx | 5 +- .../stories/agent/SourceCard.stories.tsx | 3 +- .../stories/agent/SourceDrawer.stories.tsx | 6 +- .../stories/agent/SourceInline.stories.tsx | 9 +- .../stories/agent/StreamingList.stories.tsx | 6 +- .../agent/StreamingMessage.stories.tsx | 4 +- .../agent/StreamingStructure.stories.tsx | 2 +- .../stories/agent/TypewriterText.stories.tsx | 8 +- .../agent/VerificationBadge.stories.tsx | 14 +- apps/storybook/stories/ai/AIChat.stories.tsx | 6 +- .../stories/core/Accordion.stories.tsx | 13 +- apps/storybook/stories/core/Alert.stories.tsx | 2 +- .../stories/core/AspectRatio.stories.tsx | 25 +- .../storybook/stories/core/Avatar.stories.tsx | 1 - .../core/AvatarGenerationLoader.stories.tsx | 1 - .../stories/core/AvatarRings.stories.tsx | 1 - apps/storybook/stories/core/Badge.stories.tsx | 2 +- .../stories/core/Breadcrumb.stories.tsx | 8 +- apps/storybook/stories/core/Card.stories.tsx | 1 - .../stories/core/Carousel.stories.tsx | 109 +- .../stories/core/Collapsible.stories.tsx | 1 - .../stories/core/Command.stories.tsx | 12 +- .../stories/core/ContextMenu.stories.tsx | 1 - .../stories/core/DataList.stories.tsx | 1 - .../storybook/stories/core/Dialog.stories.tsx | 14 +- .../storybook/stories/core/Drawer.stories.tsx | 13 +- .../stories/core/DropdownMenu.stories.tsx | 3 +- .../stories/core/HoverCard.stories.tsx | 3 +- .../stories/core/Menubar.stories.tsx | 1 - .../stories/core/NavigationMenu.stories.tsx | 5 +- .../stories/core/Pagination.stories.tsx | 2 +- .../stories/core/Popover.stories.tsx | 11 +- .../stories/core/Primitives.stories.tsx | 23 +- .../stories/core/Resizable.stories.tsx | 16 +- .../stories/core/ScrollArea.stories.tsx | 22 +- apps/storybook/stories/core/Sheet.stories.tsx | 13 +- .../stories/core/Sidebar.stories.tsx | 2 +- apps/storybook/stories/core/Table.stories.tsx | 6 +- apps/storybook/stories/core/Tabs.stories.tsx | 4 +- apps/storybook/stories/core/Toast.stories.tsx | 9 +- .../storybook/stories/core/Toggle.stories.tsx | 1 - .../stories/core/ToggleGroup.stories.tsx | 1 - .../stories/core/Tooltip.stories.tsx | 3 +- .../stories/tokens/Colors.stories.tsx | 9 +- apps/storybook/tailwind.config.ts | 8 +- biome.json | 60 + package.json | 5 +- .../AgentAvatar/AgentAvatar.tsx | 3 +- .../__tests__/AgentAvatar.test.tsx | 14 +- .../src/agent-identity/AgentAvatar/index.ts | 2 +- .../AgentHandoff/AgentHandoff.tsx | 5 +- .../__tests__/AgentHandoff.test.tsx | 11 +- .../src/agent-identity/AgentHandoff/index.ts | 2 +- .../agent-identity/AgentLabel/AgentLabel.tsx | 9 +- .../AgentLabel/__tests__/AgentLabel.test.tsx | 7 +- .../src/agent-identity/AgentLabel/index.ts | 2 +- .../RoutingIndicator/RoutingIndicator.tsx | 6 +- .../__tests__/RoutingIndicator.test.tsx | 16 +- .../agent-identity/RoutingIndicator/index.ts | 2 +- packages/agent/src/agent-identity/index.ts | 13 +- .../agent/src/chat/AgentChat/AgentChat.tsx | 7 +- .../AgentChat/__tests__/AgentChat.test.tsx | 12 +- packages/agent/src/chat/AgentChat/index.ts | 2 +- .../ConversationList/ConversationList.tsx | 1 - .../__tests__/ConversationList.test.tsx | 51 +- .../agent/src/chat/ConversationList/index.ts | 2 +- .../src/chat/MessageBubble/MessageBubble.tsx | 8 +- .../__tests__/MessageBubble.test.tsx | 11 +- .../agent/src/chat/MessageBubble/index.ts | 2 +- .../chat/MessageComposer/MessageComposer.tsx | 22 +- .../__tests__/MessageComposer.test.tsx | 11 +- .../agent/src/chat/MessageComposer/index.ts | 2 +- .../src/chat/MessageThread/MessageThread.tsx | 19 +- .../__tests__/MessageThread.test.tsx | 7 +- .../agent/src/chat/MessageThread/index.ts | 2 +- .../src/chat/WelcomeScreen/WelcomeScreen.tsx | 8 +- .../__tests__/WelcomeScreen.test.tsx | 12 +- .../agent/src/chat/WelcomeScreen/index.ts | 2 +- packages/agent/src/chat/index.ts | 21 +- .../ConfidenceBadge/ConfidenceBadge.tsx | 1 - .../__tests__/ConfidenceBadge.test.tsx | 11 +- .../src/confidence/ConfidenceBadge/index.ts | 2 +- .../ConfidenceBreakdown.tsx | 21 +- .../__tests__/ConfidenceBreakdown.test.tsx | 7 +- .../confidence/ConfidenceBreakdown/index.ts | 2 +- .../ConfidenceMeter/ConfidenceMeter.tsx | 2 - .../__tests__/ConfidenceMeter.test.tsx | 8 +- .../src/confidence/ConfidenceMeter/index.ts | 2 +- .../VerificationBadge/VerificationBadge.tsx | 13 +- .../__tests__/VerificationBadge.test.tsx | 11 +- .../src/confidence/VerificationBadge/index.ts | 2 +- .../VerificationDetail/VerificationDetail.tsx | 17 +- .../__tests__/VerificationDetail.test.tsx | 7 +- .../confidence/VerificationDetail/index.ts | 2 +- packages/agent/src/confidence/index.ts | 14 +- .../FeedbackConfirmation.tsx | 2 - .../__tests__/FeedbackConfirmation.test.tsx | 4 +- .../feedback/FeedbackConfirmation/index.ts | 2 +- .../FeedbackDialog/FeedbackDialog.tsx | 4 +- .../__tests__/FeedbackDialog.test.tsx | 8 +- .../src/feedback/FeedbackDialog/index.ts | 2 +- .../ThumbsFeedback/ThumbsFeedback.tsx | 2 +- .../__tests__/ThumbsFeedback.test.tsx | 16 +- .../src/feedback/ThumbsFeedback/index.ts | 2 +- packages/agent/src/feedback/index.ts | 12 +- packages/agent/src/hooks.ts | 23 +- .../src/hooks/__tests__/useAgentChat.test.ts | 68 +- .../src/hooks/__tests__/useAgentTheme.test.ts | 4 +- .../hooks/__tests__/useCharacterDrain.test.ts | 124 +- .../hooks/__tests__/useConversation.test.ts | 28 +- .../src/hooks/__tests__/useFeedback.test.ts | 36 +- .../src/hooks/__tests__/useStreaming.test.ts | 45 +- packages/agent/src/hooks/useAgentChat.ts | 26 +- packages/agent/src/hooks/useCharacterDrain.ts | 5 +- packages/agent/src/hooks/useConversation.ts | 10 +- packages/agent/src/hooks/useFeedback.ts | 2 +- packages/agent/src/hooks/useStreaming.ts | 5 +- packages/agent/src/index.ts | 265 ++- .../src/layouts/AgentEmbed/AgentEmbed.tsx | 18 +- .../AgentEmbed/__tests__/AgentEmbed.test.tsx | 9 +- .../agent/src/layouts/AgentEmbed/index.ts | 2 +- .../layouts/AgentFullPage/AgentFullPage.tsx | 8 +- .../__tests__/AgentFullPage.test.tsx | 12 +- .../agent/src/layouts/AgentFullPage/index.ts | 2 +- .../src/layouts/AgentPanel/AgentPanel.tsx | 15 +- .../AgentPanel/__tests__/AgentPanel.test.tsx | 57 +- .../agent/src/layouts/AgentPanel/index.ts | 2 +- .../src/layouts/AgentWidget/AgentWidget.tsx | 44 +- .../__tests__/AgentWidget.test.tsx | 17 +- .../agent/src/layouts/AgentWidget/index.ts | 2 +- packages/agent/src/layouts/index.ts | 13 +- .../MCPApprovalDialog/MCPApprovalDialog.tsx | 37 +- .../__tests__/MCPApprovalDialog.test.tsx | 75 +- .../agent/src/mcp/MCPApprovalDialog/index.ts | 2 +- .../mcp/MCPResourceView/MCPResourceView.tsx | 1 - .../__tests__/MCPResourceView.test.tsx | 7 +- .../agent/src/mcp/MCPResourceView/index.ts | 2 +- .../mcp/MCPServerStatus/MCPServerStatus.tsx | 2 +- .../__tests__/MCPServerStatus.test.tsx | 29 +- .../agent/src/mcp/MCPServerStatus/index.ts | 2 +- .../agent/src/mcp/MCPToolCall/MCPToolCall.tsx | 37 +- .../__tests__/MCPToolCall.test.tsx | 13 +- packages/agent/src/mcp/MCPToolCall/index.ts | 2 +- packages/agent/src/mcp/index.ts | 15 +- .../response/AgentResponse/AgentResponse.tsx | 23 +- .../__tests__/AgentResponse.test.tsx | 7 +- .../agent/src/response/AgentResponse/index.ts | 2 +- .../response/ErrorResponse/ErrorResponse.tsx | 8 +- .../__tests__/ErrorResponse.test.tsx | 11 +- .../agent/src/response/ErrorResponse/index.ts | 2 +- .../response/FollowUpChips/FollowUpChips.tsx | 3 +- .../__tests__/FollowUpChips.test.tsx | 12 +- .../agent/src/response/FollowUpChips/index.ts | 2 +- .../ResponseMessage/ResponseMessage.tsx | 7 +- .../__tests__/ResponseMessage.test.tsx | 4 +- .../src/response/ResponseMessage/index.ts | 2 +- .../StructuredResponse/StructuredResponse.tsx | 49 +- .../__tests__/StructuredResponse.test.tsx | 29 +- .../src/response/StructuredResponse/index.ts | 2 +- packages/agent/src/response/index.ts | 18 +- .../src/sources/SourceBadge/SourceBadge.tsx | 1 - .../__tests__/SourceBadge.test.tsx | 4 +- .../agent/src/sources/SourceBadge/index.ts | 2 +- .../src/sources/SourceCard/SourceCard.tsx | 11 +- .../SourceCard/__tests__/SourceCard.test.tsx | 11 +- .../agent/src/sources/SourceCard/index.ts | 2 +- .../src/sources/SourceDrawer/SourceDrawer.tsx | 15 +- .../__tests__/SourceDrawer.test.tsx | 27 +- .../agent/src/sources/SourceDrawer/index.ts | 2 +- .../src/sources/SourceInline/SourceInline.tsx | 1 - .../__tests__/SourceInline.test.tsx | 11 +- .../agent/src/sources/SourceInline/index.ts | 2 +- .../src/sources/SourceList/SourceList.tsx | 4 +- .../SourceList/__tests__/SourceList.test.tsx | 27 +- .../agent/src/sources/SourceList/index.ts | 2 +- packages/agent/src/sources/index.ts | 20 +- .../RetrievalProgress/RetrievalProgress.tsx | 6 +- .../__tests__/RetrievalProgress.test.tsx | 15 +- .../src/streaming/RetrievalProgress/index.ts | 2 +- .../streaming/StreamingList/StreamingList.tsx | 15 +- .../__tests__/StreamingList.test.tsx | 14 +- .../src/streaming/StreamingList/index.ts | 2 +- .../StreamingMessage/StreamingMessage.tsx | 4 +- .../__tests__/StreamingMessage.test.tsx | 9 +- .../src/streaming/StreamingMessage/index.ts | 2 +- .../StreamingStructure/StreamingStructure.tsx | 33 +- .../__tests__/StreamingStructure.test.tsx | 12 +- .../src/streaming/StreamingStructure/index.ts | 2 +- .../src/streaming/TextGlimmer/TextGlimmer.tsx | 3 +- .../__tests__/TextGlimmer.test.tsx | 5 +- .../agent/src/streaming/TextGlimmer/index.ts | 2 +- .../ThinkingIndicator/ThinkingIndicator.tsx | 1 - .../__tests__/ThinkingIndicator.test.tsx | 5 +- .../src/streaming/ThinkingIndicator/index.ts | 2 +- .../streaming/ToolExecution/ToolExecution.tsx | 1 - .../__tests__/ToolExecution.test.tsx | 4 +- .../src/streaming/ToolExecution/index.ts | 2 +- .../TypewriterText/TypewriterText.tsx | 12 +- .../src/streaming/TypewriterText/index.ts | 2 +- .../TypingIndicator/TypingIndicator.tsx | 13 +- .../__tests__/TypingIndicator.test.tsx | 5 +- .../src/streaming/TypingIndicator/index.ts | 2 +- .../VerificationProgress.tsx | 17 +- .../__tests__/VerificationProgress.test.tsx | 4 +- .../streaming/VerificationProgress/index.ts | 2 +- packages/agent/src/streaming/index.ts | 39 +- packages/agent/src/types/index.ts | 15 +- packages/agent/src/types/streaming.ts | 2 +- packages/ai/src/__tests__/useAIChat.test.ts | 4 +- packages/ai/src/__tests__/useAIStream.test.ts | 4 +- packages/ai/src/components/AIChat.tsx | 7 +- packages/ai/src/hooks/useAIChat.ts | 9 +- packages/ai/src/index.ts | 21 +- .../core/src/data/Accordion/Accordion.tsx | 7 +- .../Accordion/__tests__/Accordion.test.tsx | 8 +- packages/core/src/data/Accordion/index.ts | 2 +- packages/core/src/data/Card/Card.tsx | 22 +- .../src/data/Card/__tests__/Card.test.tsx | 4 +- packages/core/src/data/Card/index.ts | 2 +- packages/core/src/data/Carousel/Carousel.tsx | 18 +- .../data/Carousel/__tests__/Carousel.test.tsx | 3 +- packages/core/src/data/Carousel/index.ts | 2 +- .../__tests__/Collapsible.test.tsx | 2 +- packages/core/src/data/Collapsible/index.ts | 6 +- packages/core/src/data/DataList/DataList.tsx | 2 +- .../data/DataList/__tests__/DataList.test.tsx | 4 +- packages/core/src/data/DataList/index.ts | 2 +- packages/core/src/data/Table/Table.tsx | 39 +- .../src/data/Table/__tests__/Table.test.tsx | 4 +- packages/core/src/data/Table/index.ts | 2 +- packages/core/src/data/index.ts | 24 +- packages/core/src/feedback/Alert/Alert.tsx | 28 +- .../feedback/Alert/__tests__/Alert.test.tsx | 2 +- packages/core/src/feedback/Alert/index.ts | 2 +- packages/core/src/feedback/Avatar/Avatar.tsx | 4 +- .../feedback/Avatar/__tests__/Avatar.test.tsx | 4 +- packages/core/src/feedback/Avatar/index.ts | 2 +- .../AvatarGenerationLoader.tsx | 3 +- .../feedback/AvatarGenerationLoader/index.ts | 4 +- packages/core/src/feedback/Badge/Badge.tsx | 14 +- .../feedback/Badge/__tests__/Badge.test.tsx | 2 +- packages/core/src/feedback/Badge/index.ts | 2 +- .../src/feedback/ProgressBar/ProgressBar.tsx | 5 +- .../__tests__/ProgressBar.test.tsx | 4 +- .../core/src/feedback/ProgressBar/index.ts | 2 +- .../core/src/feedback/Skeleton/Skeleton.tsx | 7 +- .../Skeleton/__tests__/Skeleton.test.tsx | 2 +- packages/core/src/feedback/Skeleton/index.ts | 2 +- .../core/src/feedback/Spinner/Spinner.tsx | 31 +- .../Spinner/__tests__/Spinner.test.tsx | 2 +- packages/core/src/feedback/Spinner/index.ts | 2 +- packages/core/src/feedback/Toast/Toast.tsx | 25 +- .../feedback/Toast/__tests__/Toast.test.tsx | 11 +- packages/core/src/feedback/Toast/index.ts | 2 +- packages/core/src/feedback/index.ts | 26 +- packages/core/src/index.ts | 10 +- packages/core/src/inputs/Button/Button.tsx | 66 +- .../inputs/Button/__tests__/Button.test.tsx | 2 +- packages/core/src/inputs/Button/index.ts | 2 +- .../core/src/inputs/Calendar/Calendar.tsx | 34 +- .../Calendar/__tests__/Calendar.test.tsx | 2 +- packages/core/src/inputs/Calendar/index.ts | 2 +- .../core/src/inputs/Checkbox/Checkbox.tsx | 20 +- .../Checkbox/__tests__/Checkbox.test.tsx | 2 +- packages/core/src/inputs/Checkbox/index.ts | 2 +- .../core/src/inputs/IconButton/IconButton.tsx | 19 +- .../IconButton/__tests__/IconButton.test.tsx | 2 +- packages/core/src/inputs/IconButton/index.ts | 2 +- .../core/src/inputs/RadioGroup/RadioGroup.tsx | 17 +- .../RadioGroup/__tests__/RadioGroup.test.tsx | 2 +- packages/core/src/inputs/RadioGroup/index.ts | 2 +- .../src/inputs/SearchInput/SearchInput.tsx | 14 +- .../__tests__/SearchInput.test.tsx | 2 +- packages/core/src/inputs/SearchInput/index.ts | 2 +- packages/core/src/inputs/Select/Select.tsx | 27 +- .../inputs/Select/__tests__/Select.test.tsx | 2 +- packages/core/src/inputs/Select/index.ts | 2 +- packages/core/src/inputs/Slider/Slider.tsx | 11 +- .../inputs/Slider/__tests__/Slider.test.tsx | 2 +- packages/core/src/inputs/Slider/index.ts | 2 +- packages/core/src/inputs/Switch/Switch.tsx | 12 +- .../inputs/Switch/__tests__/Switch.test.tsx | 2 +- packages/core/src/inputs/Switch/index.ts | 2 +- .../core/src/inputs/TextArea/TextArea.tsx | 4 +- .../TextArea/__tests__/TextArea.test.tsx | 2 +- packages/core/src/inputs/TextArea/index.ts | 2 +- .../core/src/inputs/TextInput/TextInput.tsx | 4 +- .../TextInput/__tests__/TextInput.test.tsx | 2 +- packages/core/src/inputs/TextInput/index.ts | 2 +- packages/core/src/inputs/Toggle/Toggle.tsx | 9 +- .../inputs/Toggle/__tests__/Toggle.test.tsx | 18 +- packages/core/src/inputs/Toggle/index.ts | 2 +- .../src/inputs/ToggleGroup/ToggleGroup.tsx | 3 +- .../__tests__/ToggleGroup.test.tsx | 2 +- packages/core/src/inputs/ToggleGroup/index.ts | 2 +- packages/core/src/inputs/index.ts | 40 +- .../src/layout/AspectRatio/AspectRatio.tsx | 2 +- .../__tests__/AspectRatio.test.tsx | 10 +- packages/core/src/layout/AspectRatio/index.ts | 2 +- .../core/src/layout/Resizable/Resizable.tsx | 15 +- .../Resizable/__tests__/Resizable.test.tsx | 4 +- packages/core/src/layout/Resizable/index.ts | 2 +- .../core/src/layout/ScrollArea/ScrollArea.tsx | 2 +- .../ScrollArea/__tests__/ScrollArea.test.tsx | 8 +- packages/core/src/layout/ScrollArea/index.ts | 2 +- packages/core/src/layout/index.ts | 8 +- .../src/navigation/Breadcrumb/Breadcrumb.tsx | 13 +- .../Breadcrumb/__tests__/Breadcrumb.test.tsx | 4 +- .../core/src/navigation/Breadcrumb/index.ts | 2 +- .../core/src/navigation/Menubar/Menubar.tsx | 27 +- .../Menubar/__tests__/Menubar.test.tsx | 2 +- packages/core/src/navigation/Menubar/index.ts | 7 +- .../NavigationMenu/NavigationMenu.tsx | 3 +- .../__tests__/NavigationMenu.test.tsx | 2 +- .../src/navigation/NavigationMenu/index.ts | 2 +- .../src/navigation/Pagination/Pagination.tsx | 14 +- .../Pagination/__tests__/Pagination.test.tsx | 9 +- .../core/src/navigation/Pagination/index.ts | 2 +- .../core/src/navigation/Sidebar/Sidebar.tsx | 15 +- .../Sidebar/__tests__/Sidebar.test.tsx | 10 +- packages/core/src/navigation/Sidebar/index.ts | 2 +- packages/core/src/navigation/Tabs/Tabs.tsx | 27 +- .../navigation/Tabs/__tests__/Tabs.test.tsx | 4 +- packages/core/src/navigation/Tabs/index.ts | 2 +- packages/core/src/navigation/index.ts | 25 +- packages/core/src/overlay/Command/Command.tsx | 40 +- .../Command/__tests__/Command.test.tsx | 2 +- packages/core/src/overlay/Command/index.ts | 2 +- .../src/overlay/ContextMenu/ContextMenu.tsx | 14 +- .../__tests__/ContextMenu.test.tsx | 5 +- .../core/src/overlay/ContextMenu/index.ts | 2 +- packages/core/src/overlay/Dialog/Dialog.tsx | 29 +- .../overlay/Dialog/__tests__/Dialog.test.tsx | 4 +- packages/core/src/overlay/Dialog/index.ts | 2 +- packages/core/src/overlay/Drawer/Drawer.tsx | 25 +- .../overlay/Drawer/__tests__/Drawer.test.tsx | 2 +- packages/core/src/overlay/Drawer/index.ts | 2 +- .../src/overlay/DropdownMenu/DropdownMenu.tsx | 37 +- .../__tests__/DropdownMenu.test.tsx | 8 +- .../core/src/overlay/DropdownMenu/index.ts | 2 +- .../core/src/overlay/HoverCard/HoverCard.tsx | 3 +- .../HoverCard/__tests__/HoverCard.test.tsx | 4 +- packages/core/src/overlay/HoverCard/index.ts | 2 +- packages/core/src/overlay/Popover/Popover.tsx | 7 +- .../Popover/__tests__/Popover.test.tsx | 8 +- packages/core/src/overlay/Popover/index.ts | 2 +- packages/core/src/overlay/Sheet/Sheet.tsx | 19 +- .../overlay/Sheet/__tests__/Sheet.test.tsx | 3 +- packages/core/src/overlay/Sheet/index.ts | 2 +- packages/core/src/overlay/Tooltip/Tooltip.tsx | 29 +- .../Tooltip/__tests__/Tooltip.test.tsx | 6 +- packages/core/src/overlay/Tooltip/index.ts | 2 +- packages/core/src/overlay/index.ts | 30 +- packages/core/src/primitives/Box/Box.tsx | 2 +- .../src/primitives/Box/__tests__/Box.test.tsx | 2 +- packages/core/src/primitives/Box/index.ts | 2 +- packages/core/src/primitives/Grid/Grid.tsx | 2 +- .../primitives/Grid/__tests__/Grid.test.tsx | 2 +- packages/core/src/primitives/Grid/index.ts | 2 +- .../src/primitives/Separator/Separator.tsx | 2 +- .../Separator/__tests__/Separator.test.tsx | 2 +- .../core/src/primitives/Separator/index.ts | 2 +- packages/core/src/primitives/Stack/Stack.tsx | 6 +- .../primitives/Stack/__tests__/Stack.test.tsx | 2 +- packages/core/src/primitives/Stack/index.ts | 2 +- packages/core/src/primitives/Text/Text.tsx | 2 +- .../primitives/Text/__tests__/Text.test.tsx | 2 +- packages/core/src/primitives/Text/index.ts | 2 +- .../VisuallyHidden/VisuallyHidden.tsx | 2 +- .../__tests__/VisuallyHidden.test.tsx | 2 +- packages/core/src/primitives/index.ts | 14 +- packages/hooks/src/index.ts | 10 +- packages/hooks/src/useClipboard.ts | 2 +- packages/hooks/src/useFocusTrap.ts | 6 +- packages/hooks/src/useLocalStorage.ts | 7 +- packages/hooks/src/useMediaQuery.ts | 2 +- .../icons/src/generated/AgentCoordinator.tsx | 33 +- .../icons/src/generated/AgentFacilities.tsx | 32 +- packages/icons/src/generated/AgentFinance.tsx | 31 +- .../icons/src/generated/AgentGovernance.tsx | 32 +- packages/icons/src/generated/AgentHr.tsx | 33 +- packages/icons/src/generated/AgentIt.tsx | 34 +- .../icons/src/generated/ConfidenceHigh.tsx | 31 +- .../icons/src/generated/ConfidenceLow.tsx | 31 +- .../icons/src/generated/ConfidenceMedium.tsx | 32 +- .../src/generated/VerificationFailed.tsx | 31 +- .../src/generated/VerificationFlagged.tsx | 32 +- .../src/generated/VerificationPassed.tsx | 32 +- packages/icons/src/index.ts | 30 +- packages/icons/src/scripts/generate.ts | 8 +- packages/theme/src/ThemeProvider.tsx | 34 +- packages/theme/src/index.ts | 8 +- packages/theme/src/tailwind-preset.ts | 6 +- packages/theme/src/useColorMode.ts | 10 +- packages/tokens/src/config.ts | 181 +- pnpm-lock.yaml | 1470 ++--------------- tooling/eslint-config/index.js | 19 - tooling/eslint-config/package.json | 17 - tooling/test-utils/src/fixtures/responses.ts | 6 +- tooling/test-utils/src/index.ts | 13 +- tooling/test-utils/src/render.tsx | 8 +- turbo.json | 3 - 452 files changed, 3427 insertions(+), 4762 deletions(-) create mode 100644 .git-blame-ignore-revs create mode 100644 biome.json delete mode 100644 tooling/eslint-config/index.js delete mode 100644 tooling/eslint-config/package.json diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000..13a67fa --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,4 @@ +# Biome formatter migration — bulk formatting changes +# To use: git config blame.ignoreRevsFile .git-blame-ignore-revs +# GitHub uses this file automatically. +# Commit hash will be added after committing. diff --git a/apps/docs/app/(home)/layout.tsx b/apps/docs/app/(home)/layout.tsx index cf05597..45ec0eb 100644 --- a/apps/docs/app/(home)/layout.tsx +++ b/apps/docs/app/(home)/layout.tsx @@ -1,7 +1,7 @@ -import { HomeLayout } from 'fumadocs-ui/layouts/home'; -import { baseOptions } from '@/lib/layout.shared'; -import type { ReactNode } from 'react'; +import { HomeLayout } from 'fumadocs-ui/layouts/home' +import type { ReactNode } from 'react' +import { baseOptions } from '@/lib/layout.shared' export default function Layout({ children }: { children: ReactNode }) { - return {children}; + return {children} } diff --git a/apps/docs/app/(home)/page.tsx b/apps/docs/app/(home)/page.tsx index 2125a48..9e42fd2 100644 --- a/apps/docs/app/(home)/page.tsx +++ b/apps/docs/app/(home)/page.tsx @@ -1,18 +1,13 @@ -import Link from 'next/link'; +import Link from 'next/link' export default function HomePage() { return (
-

- surf-kit -

-

- AI-First Design System -

+

surf-kit

+

AI-First Design System

- Purpose-built components for agent interfaces. Trust through - transparency, accessible by default, enterprise-grade theming, and a - composable architecture. + Purpose-built components for agent interfaces. Trust through transparency, accessible by + default, enterprise-grade theming, and a composable architecture.

- ); + ) } -function FeatureCard({ - title, - description, -}: { - title: string; - description: string; -}) { +function FeatureCard({ title, description }: { title: string; description: string }) { return (

{title}

{description}

- ); + ) } diff --git a/apps/docs/app/docs/[[...slug]]/page.tsx b/apps/docs/app/docs/[[...slug]]/page.tsx index fd64ba1..119b23b 100644 --- a/apps/docs/app/docs/[[...slug]]/page.tsx +++ b/apps/docs/app/docs/[[...slug]]/page.tsx @@ -1,25 +1,20 @@ -import { source } from '@/lib/source'; -import { - DocsPage, - DocsBody, - DocsDescription, - DocsTitle, -} from 'fumadocs-ui/page'; -import { notFound } from 'next/navigation'; -import defaultMdxComponents from 'fumadocs-ui/mdx'; -import type { Metadata } from 'next'; +import defaultMdxComponents from 'fumadocs-ui/mdx' +import { DocsBody, DocsDescription, DocsPage, DocsTitle } from 'fumadocs-ui/page' +import type { Metadata } from 'next' +import { notFound } from 'next/navigation' +import { source } from '@/lib/source' interface PageProps { - params: Promise<{ slug?: string[] }>; + params: Promise<{ slug?: string[] }> } export default async function Page(props: PageProps) { - const params = await props.params; - const page = source.getPage(params.slug); + const params = await props.params + const page = source.getPage(params.slug) - if (!page) notFound(); + if (!page) notFound() - const MDX = page.data.body; + const MDX = page.data.body return ( @@ -29,21 +24,21 @@ export default async function Page(props: PageProps) { - ); + ) } export async function generateStaticParams() { - return source.generateParams(); + return source.generateParams() } export async function generateMetadata(props: PageProps): Promise { - const params = await props.params; - const page = source.getPage(params.slug); + const params = await props.params + const page = source.getPage(params.slug) - if (!page) notFound(); + if (!page) notFound() return { title: page.data.title, description: page.data.description, - }; + } } diff --git a/apps/docs/app/docs/layout.tsx b/apps/docs/app/docs/layout.tsx index 04c158e..3985f7b 100644 --- a/apps/docs/app/docs/layout.tsx +++ b/apps/docs/app/docs/layout.tsx @@ -1,12 +1,12 @@ -import { DocsLayout } from 'fumadocs-ui/layouts/docs'; -import { baseOptions } from '@/lib/layout.shared'; -import { source } from '@/lib/source'; -import type { ReactNode } from 'react'; +import { DocsLayout } from 'fumadocs-ui/layouts/docs' +import type { ReactNode } from 'react' +import { baseOptions } from '@/lib/layout.shared' +import { source } from '@/lib/source' export default function Layout({ children }: { children: ReactNode }) { return ( {children} - ); + ) } diff --git a/apps/docs/app/layout.tsx b/apps/docs/app/layout.tsx index b6543d4..9afa8d2 100644 --- a/apps/docs/app/layout.tsx +++ b/apps/docs/app/layout.tsx @@ -1,8 +1,8 @@ -import { RootProvider } from 'fumadocs-ui/provider'; -import 'fumadocs-ui/style.css'; -import './globals.css'; -import type { ReactNode } from 'react'; -import type { Metadata } from 'next'; +import { RootProvider } from 'fumadocs-ui/provider' +import 'fumadocs-ui/style.css' +import './globals.css' +import type { Metadata } from 'next' +import type { ReactNode } from 'react' export const metadata: Metadata = { title: { @@ -11,7 +11,7 @@ export const metadata: Metadata = { }, description: 'Purpose-built component library for agent interfaces. Trust, transparency, and accessibility by default.', -}; +} export default function RootLayout({ children }: { children: ReactNode }) { return ( @@ -20,5 +20,5 @@ export default function RootLayout({ children }: { children: ReactNode }) { {children} - ); + ) } diff --git a/apps/docs/content/docs/components/core/meta.json b/apps/docs/content/docs/components/core/meta.json index 16e3fc4..928b488 100644 --- a/apps/docs/content/docs/components/core/meta.json +++ b/apps/docs/content/docs/components/core/meta.json @@ -1,4 +1,16 @@ { "title": "Core", - "pages": ["button", "text-input", "select", "badge", "spinner", "alert", "dialog", "tabs", "table", "card", "accordion"] + "pages": [ + "button", + "text-input", + "select", + "badge", + "spinner", + "alert", + "dialog", + "tabs", + "table", + "card", + "accordion" + ] } diff --git a/apps/docs/content/docs/meta.json b/apps/docs/content/docs/meta.json index ca88e73..985def9 100644 --- a/apps/docs/content/docs/meta.json +++ b/apps/docs/content/docs/meta.json @@ -1,4 +1,12 @@ { "title": "Documentation", - "pages": ["getting-started", "design-principles", "tokens", "components", "patterns", "theming", "recipes"] + "pages": [ + "getting-started", + "design-principles", + "tokens", + "components", + "patterns", + "theming", + "recipes" + ] } diff --git a/apps/docs/content/docs/patterns/meta.json b/apps/docs/content/docs/patterns/meta.json index f20859b..4785cf9 100644 --- a/apps/docs/content/docs/patterns/meta.json +++ b/apps/docs/content/docs/patterns/meta.json @@ -1,4 +1,12 @@ { "title": "Patterns", - "pages": ["agent-chat", "source-attribution", "confidence-display", "multi-agent", "streaming", "error-handling", "accessibility"] + "pages": [ + "agent-chat", + "source-attribution", + "confidence-display", + "multi-agent", + "streaming", + "error-handling", + "accessibility" + ] } diff --git a/apps/docs/global.d.ts b/apps/docs/global.d.ts index 35306c6..5894ae0 100644 --- a/apps/docs/global.d.ts +++ b/apps/docs/global.d.ts @@ -1 +1 @@ -declare module '*.css'; +declare module '*.css' diff --git a/apps/docs/lib/layout.shared.tsx b/apps/docs/lib/layout.shared.tsx index 3080d0d..e2a2fd3 100644 --- a/apps/docs/lib/layout.shared.tsx +++ b/apps/docs/lib/layout.shared.tsx @@ -1,4 +1,4 @@ -import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared'; +import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared' export function baseOptions(): BaseLayoutProps { return { @@ -17,5 +17,5 @@ export function baseOptions(): BaseLayoutProps { external: true, }, ], - }; + } } diff --git a/apps/docs/lib/source.ts b/apps/docs/lib/source.ts index 0edc758..12e7475 100644 --- a/apps/docs/lib/source.ts +++ b/apps/docs/lib/source.ts @@ -1,7 +1,7 @@ -import { docs } from '@/.source'; -import { loader } from 'fumadocs-core/source'; +import { loader } from 'fumadocs-core/source' +import { docs } from '@/.source' export const source = loader({ baseUrl: '/docs', source: docs.toFumadocsSource(), -}); +}) diff --git a/apps/docs/next.config.mjs b/apps/docs/next.config.mjs index bb54628..636752e 100644 --- a/apps/docs/next.config.mjs +++ b/apps/docs/next.config.mjs @@ -1,15 +1,15 @@ -import { createMDX } from 'fumadocs-mdx/next'; -import { fileURLToPath } from 'url'; -import path from 'path'; +import path from 'node:path' +import { fileURLToPath } from 'node:url' +import { createMDX } from 'fumadocs-mdx/next' -const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const __dirname = path.dirname(fileURLToPath(import.meta.url)) /** @type {import('next').NextConfig} */ const config = { reactStrictMode: true, outputFileTracingRoot: path.resolve(__dirname, '../../'), -}; +} -const withMDX = createMDX(); +const withMDX = createMDX() -export default withMDX(config); +export default withMDX(config) diff --git a/apps/docs/postcss.config.mjs b/apps/docs/postcss.config.mjs index 5d6d845..a869506 100644 --- a/apps/docs/postcss.config.mjs +++ b/apps/docs/postcss.config.mjs @@ -3,6 +3,6 @@ const config = { plugins: { '@tailwindcss/postcss': {}, }, -}; +} -export default config; +export default config diff --git a/apps/docs/source.config.ts b/apps/docs/source.config.ts index 0b6ee4d..4605ea8 100644 --- a/apps/docs/source.config.ts +++ b/apps/docs/source.config.ts @@ -1,7 +1,7 @@ -import { defineDocs, defineConfig } from 'fumadocs-mdx/config'; +import { defineConfig, defineDocs } from 'fumadocs-mdx/config' export const docs = defineDocs({ dir: 'content/docs', -}); +}) -export default defineConfig(); +export default defineConfig() diff --git a/apps/docs/tailwind.config.ts b/apps/docs/tailwind.config.ts index 8d673e5..0f0041f 100644 --- a/apps/docs/tailwind.config.ts +++ b/apps/docs/tailwind.config.ts @@ -1,5 +1,5 @@ -import { createPreset } from 'fumadocs-ui/tailwind-plugin'; -import type { Config } from 'tailwindcss'; +import { createPreset } from 'fumadocs-ui/tailwind-plugin' +import type { Config } from 'tailwindcss' const config: Config = { content: [ @@ -9,6 +9,6 @@ const config: Config = { './node_modules/fumadocs-ui/dist/**/*.js', ], presets: [createPreset()], -}; +} -export default config; +export default config diff --git a/apps/docs/tsconfig.json b/apps/docs/tsconfig.json index d064c44..8ba9017 100644 --- a/apps/docs/tsconfig.json +++ b/apps/docs/tsconfig.json @@ -14,12 +14,8 @@ } ], "paths": { - "@/*": [ - "./*" - ], - "@/.source": [ - "./.source" - ] + "@/*": ["./*"], + "@/.source": ["./.source"] }, "allowJs": true, "incremental": true, @@ -33,9 +29,5 @@ "next-env.d.ts", ".next/types/**/*.ts" ], - "exclude": [ - "node_modules", - ".next", - "dist" - ] + "exclude": ["node_modules", ".next", "dist"] } diff --git a/apps/playground/src/App.tsx b/apps/playground/src/App.tsx index fc00a74..22708cc 100644 --- a/apps/playground/src/App.tsx +++ b/apps/playground/src/App.tsx @@ -1,20 +1,19 @@ -import { useState } from "react"; -import { ThemeProvider } from "@surf-kit/theme"; -import { FullPageDemo, LIVE_API_URL } from "./demos/full-page/FullPageDemo"; -import { ShowcasePage } from "./demos/showcase/ShowcasePage"; +import { ThemeProvider } from '@surf-kit/theme' +import { useState } from 'react' +import { FullPageDemo, LIVE_API_URL } from './demos/full-page/FullPageDemo' +import { ShowcasePage } from './demos/showcase/ShowcasePage' -type Page = "chat" | "showcase"; +type Page = 'chat' | 'showcase' export function App() { - const [page, setPage] = useState("chat"); + const [page, setPage] = useState('chat') return (
{/* Header */} @@ -26,46 +25,38 @@ export function App() { alt="Surf Kit" className="w-7 h-7 rounded-md" /> - - Surf - + Surf / - - Playground - + Playground - {LIVE_API_URL ? `Live: ${LIVE_API_URL}` : "Mock API"} + {LIVE_API_URL ? `Live: ${LIVE_API_URL}` : 'Mock API'}
{/* Right — page tabs */} {/* Main content */}
- {page === "chat" ? : } + {page === 'chat' ? : }
- ); + ) } function PageTab({ @@ -73,20 +64,21 @@ function PageTab({ isActive, onClick, }: { - label: string; - isActive: boolean; - onClick: () => void; + label: string + isActive: boolean + onClick: () => void }) { return ( - ); + ) } diff --git a/apps/playground/src/demos/full-page/FullPageDemo.tsx b/apps/playground/src/demos/full-page/FullPageDemo.tsx index 5a53cf2..c0a34c0 100644 --- a/apps/playground/src/demos/full-page/FullPageDemo.tsx +++ b/apps/playground/src/demos/full-page/FullPageDemo.tsx @@ -1,48 +1,39 @@ -import React, { useCallback, useEffect, useRef, useState } from "react"; -import { useAgentChat, useCharacterDrain } from "@surf-kit/agent/hooks"; -import { - AgentResponseView, - TypewriterText, - type ChatMessage, -} from "@surf-kit/agent"; - -export const LIVE_API_URL = import.meta.env.VITE_SURF_API_URL as - | string - | undefined; - -const base = import.meta.env.BASE_URL; - -const BG_IMAGES = [ - `${base}branding/bg.jpg`, - `${base}branding/bg2.jpg`, - `${base}branding/bg3.jpg`, -]; +import { AgentResponseView, type ChatMessage, TypewriterText } from '@surf-kit/agent' +import { useAgentChat, useCharacterDrain } from '@surf-kit/agent/hooks' +import type React from 'react' +import { useCallback, useEffect, useRef, useState } from 'react' + +export const LIVE_API_URL = import.meta.env.VITE_SURF_API_URL as string | undefined + +const base = import.meta.env.BASE_URL + +const BG_IMAGES = [`${base}branding/bg.jpg`, `${base}branding/bg2.jpg`, `${base}branding/bg3.jpg`] const CHAT_CONFIG = { - apiUrl: LIVE_API_URL ?? "/api/v1", - streamPath: "/chat/stream", - feedbackPath: "/feedback", - conversationsPath: "/conversations", + apiUrl: LIVE_API_URL ?? '/api/v1', + streamPath: '/chat/stream', + feedbackPath: '/feedback', + conversationsPath: '/conversations', timeout: 60000, -}; +} /* ------------------------------------------------------------------ */ /* Phase indicator */ /* ------------------------------------------------------------------ */ function PhaseIndicator({ phase }: { phase: string }) { - if (phase === "idle") return null; + if (phase === 'idle') return null const labels: Record = { - thinking: "Thinking...", - retrieving: "Searching knowledge base...", - generating: "Writing response...", - waiting: "Still working, please wait...", - }; + thinking: 'Thinking...', + retrieving: 'Searching knowledge base...', + generating: 'Writing response...', + waiting: 'Still working, please wait...', + } return (
- {phase === "verifying" ? ( + {phase === 'verifying' ? ( <> - ); + ) } /* ------------------------------------------------------------------ */ @@ -70,12 +61,12 @@ function MessageBubble({ onFollowUp, noEntryAnimation = false, }: { - msg: ChatMessage; - onFollowUp: (text: string) => void; - noEntryAnimation?: boolean; + msg: ChatMessage + onFollowUp: (text: string) => void + noEntryAnimation?: boolean }) { - const isUser = msg.role === "user"; - const suggestions = msg.response?.follow_up_suggestions ?? []; + const isUser = msg.role === 'user' + const suggestions = msg.response?.follow_up_suggestions ?? [] if (isUser) { return ( @@ -84,16 +75,16 @@ function MessageBubble({ {msg.content}
- ); + ) } return (
{msg.agent && (
- {msg.agent.replace("_agent", "").replace("_", " ")} + {msg.agent.replace('_agent', '').replace('_', ' ')}
)} @@ -101,9 +92,7 @@ function MessageBubble({ {msg.response ? ( ) : ( -

- {msg.content} -

+

{msg.content}

)}
@@ -111,6 +100,7 @@ function MessageBubble({
{suggestions.map((s) => (
)} - ); + ) } /* ------------------------------------------------------------------ */ @@ -132,20 +122,19 @@ function StreamingBubble({ streamingContent, onDrainingChange, }: { - streamingContent: string; - onDrainingChange: (isDraining: boolean) => void; + streamingContent: string + onDrainingChange: (isDraining: boolean) => void }) { - const { displayed: displayedContent, isDraining } = - useCharacterDrain(streamingContent); + const { displayed: displayedContent, isDraining } = useCharacterDrain(streamingContent) // Always notify parent of the current draining state, including on mount. // The previous prevDrainingRef pattern skipped the initial notification // when isDraining was true at mount time, leaving the parent stuck at false. useEffect(() => { - onDrainingChange(isDraining); - }, [isDraining, onDrainingChange]); + onDrainingChange(isDraining) + }, [isDraining, onDrainingChange]) - if (!displayedContent) return null; + if (!displayedContent) return null return (
@@ -156,7 +145,7 @@ function StreamingBubble({

- ); + ) } /* ------------------------------------------------------------------ */ @@ -165,21 +154,21 @@ function StreamingBubble({ /* ------------------------------------------------------------------ */ function BackgroundSlideshow() { - const [bgIndex, setBgIndex] = useState(0); + const [bgIndex, setBgIndex] = useState(0) useEffect(() => { BG_IMAGES.forEach((src) => { - const img = new Image(); - img.src = src; - }); - }, []); + const img = new Image() + img.src = src + }) + }, []) useEffect(() => { const id = setInterval(() => { - setBgIndex((prev) => (prev + 1) % BG_IMAGES.length); - }, 15000); - return () => clearInterval(id); - }, []); + setBgIndex((prev) => (prev + 1) % BG_IMAGES.length) + }, 15000) + return () => clearInterval(id) + }, []) return ( <> @@ -194,7 +183,7 @@ function BackgroundSlideshow() { /> ))} - ); + ) } /* ------------------------------------------------------------------ */ @@ -202,142 +191,125 @@ function BackgroundSlideshow() { /* ------------------------------------------------------------------ */ export function FullPageDemo() { - const { state, actions } = useAgentChat(CHAT_CONFIG); - const threadRef = useRef(null); - const inputRef = useRef(null); - const [isDraining, setIsDraining] = useState(false); - const prevIsLoadingRef = useRef(state.isLoading); - const prevIsDrainingRef = useRef(isDraining); - const justStoppedLoading = prevIsLoadingRef.current && !state.isLoading; - const justStoppedDraining = prevIsDrainingRef.current && !isDraining; - prevIsLoadingRef.current = state.isLoading; - prevIsDrainingRef.current = isDraining; + const { state, actions } = useAgentChat(CHAT_CONFIG) + const threadRef = useRef(null) + const inputRef = useRef(null) + const [isDraining, setIsDraining] = useState(false) + const prevIsLoadingRef = useRef(state.isLoading) + const prevIsDrainingRef = useRef(isDraining) + const justStoppedLoading = prevIsLoadingRef.current && !state.isLoading + const justStoppedDraining = prevIsDrainingRef.current && !isDraining + prevIsLoadingRef.current = state.isLoading + prevIsDrainingRef.current = isDraining const handleDrainingChange = useCallback((draining: boolean) => { - setIsDraining(draining); - }, []); + setIsDraining(draining) + }, []) useEffect(() => { - const el = threadRef.current; - if (el) el.scrollTop = el.scrollHeight; - }, [state.messages, state.streamPhase]); + const el = threadRef.current + if (el) el.scrollTop = el.scrollHeight + }, []) const handleSend = useCallback(() => { - const text = state.inputValue.trim(); - if (!text || state.isLoading) return; - actions.sendMessage(text); + const text = state.inputValue.trim() + if (!text || state.isLoading) return + actions.sendMessage(text) if (inputRef.current) { - inputRef.current.style.height = "auto"; + inputRef.current.style.height = 'auto' } - }, [state.inputValue, state.isLoading, actions]); + }, [state.inputValue, state.isLoading, actions]) const handleKeyDown = useCallback( (e: React.KeyboardEvent) => { - if (e.key === "Enter" && !e.shiftKey) { - e.preventDefault(); - handleSend(); + if (e.key === 'Enter' && !e.shiftKey) { + e.preventDefault() + handleSend() } }, [handleSend], - ); + ) - const isEmpty = state.messages.length === 0 && !state.isLoading; + const isEmpty = state.messages.length === 0 && !state.isLoading return (
{/* Message thread */} -
+
{isEmpty ? ( -
- {/* Pulsing icon */} - Surf Kit - -
-

- Hi, I'm Surf. -

-

- -

-
- -
- {[ - "What pricing plans are available?", - "How do I get started with the API?", - "What are the rate limits for the Pro plan?", - ].map((chip) => ( - - ))} -
+
+ {/* Pulsing icon */} + Surf Kit + +
+

Hi, I'm Surf.

+

+ +

- ) : ( -
- {state.messages.map((msg, i) => { - // Hide the final assistant message while the drain animation - // is still typing it out — prevents the jump from streaming - // bubble to fully-rendered message. - const isLastAssistant = - i === state.messages.length - 1 && msg.role === "assistant"; - if (isLastAssistant && isDraining) return null; - - return ( - { - actions.setInputValue(text); - inputRef.current?.focus(); - }} - /> - ); - })} -
- )} - {state.isLoading && - !state.streamingContent && ( -
- +
+ {[ + 'What pricing plans are available?', + 'How do I get started with the API?', + 'What are the rate limits for the Pro plan?', + ].map((chip) => ( + + ))}
- )} +
+ ) : ( +
+ {state.messages.map((msg, i) => { + // Hide the final assistant message while the drain animation + // is still typing it out — prevents the jump from streaming + // bubble to fully-rendered message. + const isLastAssistant = i === state.messages.length - 1 && msg.role === 'assistant' + if (isLastAssistant && isDraining) return null + + return ( + { + actions.setInputValue(text) + inputRef.current?.focus() + }} + /> + ) + })} +
+ )} + + {state.isLoading && !state.streamingContent && ( +
+ +
+ )} {state.error && (
- - Error:{" "} - - - {state.error.message} - + Error: + {state.error.message} {state.error.retryable && (
- ); + ) } diff --git a/apps/playground/src/demos/layouts/LayoutDemos.tsx b/apps/playground/src/demos/layouts/LayoutDemos.tsx index f057a92..5c8820d 100644 --- a/apps/playground/src/demos/layouts/LayoutDemos.tsx +++ b/apps/playground/src/demos/layouts/LayoutDemos.tsx @@ -1,11 +1,11 @@ -import React, { useState } from 'react' import { + AgentEmbed, AgentPanel, AgentWidget, - AgentEmbed, ConversationList, type ConversationSummary, } from '@surf-kit/agent' +import { useState } from 'react' const DEMO_ENDPOINT = '/api/v1' @@ -61,14 +61,22 @@ export function LayoutDemos() {
diff --git a/apps/playground/src/demos/showcase/ShowcasePage.tsx b/apps/playground/src/demos/showcase/ShowcasePage.tsx index 3ae2905..651cf8a 100644 --- a/apps/playground/src/demos/showcase/ShowcasePage.tsx +++ b/apps/playground/src/demos/showcase/ShowcasePage.tsx @@ -1,48 +1,47 @@ -import { useCallback, useEffect, useState } from "react"; -import { useAgentChat, useCharacterDrain } from "@surf-kit/agent/hooks"; import { + AgentAvatar, + AgentLabel, + ErrorResponse, + FollowUpChips, MessageBubble, MessageComposer, - WelcomeScreen, StreamingMessage, + type StreamState, ThinkingIndicator, VerificationProgress, - FollowUpChips, - ErrorResponse, - AgentAvatar, - AgentLabel, - type StreamState, -} from "@surf-kit/agent"; -import { Badge, Tabs } from "@surf-kit/core"; -import { ThemeProvider, type ColorMode } from "@surf-kit/theme"; -import { LIVE_API_URL } from "../full-page/FullPageDemo"; - -import { PrimitivesSection } from "./sections/PrimitivesSection"; -import { ButtonsInputsSection } from "./sections/ButtonsInputsSection"; -import { FeedbackSection } from "./sections/FeedbackSection"; -import { OverlaysSection } from "./sections/OverlaysSection"; -import { NavigationSection } from "./sections/NavigationSection"; -import { DataDisplaySection } from "./sections/DataDisplaySection"; -import { LayoutSection } from "./sections/LayoutSection"; -import { AgentComponentsSection } from "./sections/AgentComponentsSection"; -import { AgentStreamingSection } from "./sections/AgentStreamingSection"; -import { MCPSection } from "./sections/MCPSection"; -import { IconsSection } from "./sections/IconsSection"; -import { HooksSection } from "./sections/HooksSection"; + WelcomeScreen, +} from '@surf-kit/agent' +import { useAgentChat, useCharacterDrain } from '@surf-kit/agent/hooks' +import { Badge, Tabs } from '@surf-kit/core' +import { type ColorMode, ThemeProvider } from '@surf-kit/theme' +import { useCallback, useEffect, useState } from 'react' +import { LIVE_API_URL } from '../full-page/FullPageDemo' +import { AgentComponentsSection } from './sections/AgentComponentsSection' +import { AgentStreamingSection } from './sections/AgentStreamingSection' +import { ButtonsInputsSection } from './sections/ButtonsInputsSection' +import { DataDisplaySection } from './sections/DataDisplaySection' +import { FeedbackSection } from './sections/FeedbackSection' +import { HooksSection } from './sections/HooksSection' +import { IconsSection } from './sections/IconsSection' +import { LayoutSection } from './sections/LayoutSection' +import { MCPSection } from './sections/MCPSection' +import { NavigationSection } from './sections/NavigationSection' +import { OverlaysSection } from './sections/OverlaysSection' +import { PrimitivesSection } from './sections/PrimitivesSection' const CHAT_CONFIG = { - apiUrl: LIVE_API_URL ?? "/api/v1", - streamPath: "/chat/stream", - feedbackPath: "/feedback", - conversationsPath: "/conversations", + apiUrl: LIVE_API_URL ?? '/api/v1', + streamPath: '/chat/stream', + feedbackPath: '/feedback', + conversationsPath: '/conversations', timeout: 60000, -}; +} const WELCOME_QUESTIONS = [ - "What pricing plans are available?", - "How do I get started with the API?", - "What are the rate limits for the Pro plan?", -]; + 'What pricing plans are available?', + 'How do I get started with the API?', + 'What are the rate limits for the Pro plan?', +] /* ------------------------------------------------------------------ */ /* Streaming bubble — uses library's character drain */ @@ -53,29 +52,29 @@ function ShowcaseStreamingBubble({ streamPhase, onDrainingChange, }: { - streamingContent: string; - streamPhase: string; - onDrainingChange: (isDraining: boolean) => void; + streamingContent: string + streamPhase: string + onDrainingChange: (isDraining: boolean) => void }) { - const { displayed, isDraining } = useCharacterDrain(streamingContent); + const { displayed, isDraining } = useCharacterDrain(streamingContent) useEffect(() => { - onDrainingChange(isDraining); - }, [isDraining, onDrainingChange]); + onDrainingChange(isDraining) + }, [isDraining, onDrainingChange]) // Build a StreamState to pass to StreamingMessage const streamState: StreamState = { active: true, - phase: streamPhase as StreamState["phase"], + phase: streamPhase as StreamState['phase'], content: displayed, sources: [], agent: null, agentLabel: null, - }; + } - if (!displayed && streamPhase === "idle") return null; + if (!displayed && streamPhase === 'idle') return null - return ; + return } /* ------------------------------------------------------------------ */ @@ -83,40 +82,36 @@ function ShowcaseStreamingBubble({ /* ------------------------------------------------------------------ */ function ShowcaseChat() { - const { state, actions } = useAgentChat(CHAT_CONFIG); - const [isDraining, setIsDraining] = useState(false); + const { state, actions } = useAgentChat(CHAT_CONFIG) + const [isDraining, setIsDraining] = useState(false) const handleDrainingChange = useCallback((draining: boolean) => { - setIsDraining(draining); - }, []); + setIsDraining(draining) + }, []) - const isEmpty = state.messages.length === 0 && !state.isLoading; + const isEmpty = state.messages.length === 0 && !state.isLoading // Filter messages for display (hide last assistant while draining) const visibleMessages = state.messages.filter((msg, i) => { - const isLastAssistant = - i === state.messages.length - 1 && msg.role === "assistant"; - return !(isLastAssistant && isDraining); - }); + const isLastAssistant = i === state.messages.length - 1 && msg.role === 'assistant' + return !(isLastAssistant && isDraining) + }) // Get last message's follow-up suggestions - const lastMsg = state.messages[state.messages.length - 1]; + const lastMsg = state.messages[state.messages.length - 1] const suggestions = - lastMsg?.role === "assistant" && !isDraining - ? lastMsg.response?.follow_up_suggestions ?? [] - : []; + lastMsg?.role === 'assistant' && !isDraining + ? (lastMsg.response?.follow_up_suggestions ?? []) + : [] return (
{/* Chat header */}
- - - - {LIVE_API_URL ? "Live" : "Mock API"} + + + + {LIVE_API_URL ? 'Live' : 'Mock API'}
@@ -132,12 +127,7 @@ function ShowcaseChat() { ) : (
{visibleMessages.map((msg) => ( - + ))}
)} @@ -145,14 +135,14 @@ function ShowcaseChat() { {/* Phase indicators using library components */} {state.isLoading && !state.streamingContent && (
- {state.streamPhase === "thinking" && } - {state.streamPhase === "retrieving" && ( + {state.streamPhase === 'thinking' && } + {state.streamPhase === 'retrieving' && ( )} - {state.streamPhase === "generating" && ( + {state.streamPhase === 'generating' && ( )} - {state.streamPhase === "waiting" && ( + {state.streamPhase === 'waiting' && ( )}
@@ -168,7 +158,7 @@ function ShowcaseChat() { )} {/* Verification in-progress */} - {state.streamPhase === "verifying" && state.streamingContent && ( + {state.streamPhase === 'verifying' && state.streamingContent && (
@@ -204,7 +194,7 @@ function ShowcaseChat() { />
- ); + ) } /* ------------------------------------------------------------------ */ @@ -212,20 +202,24 @@ function ShowcaseChat() { /* ------------------------------------------------------------------ */ const THEME_OPTIONS: { label: string; value: ColorMode }[] = [ - { label: "Brand", value: "brand" }, - { label: "Dark", value: "dark" }, - { label: "Light", value: "light" }, -]; + { label: 'Brand', value: 'brand' }, + { label: 'Dark', value: 'dark' }, + { label: 'Light', value: 'light' }, +] function ThemeSwitcher({ value, onChange, }: { - value: ColorMode; - onChange: (mode: ColorMode) => void; + value: ColorMode + onChange: (mode: ColorMode) => void }) { return ( -
+
{THEME_OPTIONS.map((opt) => ( ))}
- ); + ) } /* ------------------------------------------------------------------ */ @@ -254,23 +248,23 @@ function ShowcaseSections({ colorMode, onColorModeChange, }: { - colorMode: ColorMode; - onColorModeChange: (mode: ColorMode) => void; + colorMode: ColorMode + onColorModeChange: (mode: ColorMode) => void }) { const tabItems = [ - { key: "primitives", title: "Primitives", content: }, - { key: "inputs", title: "Buttons & Inputs", content: }, - { key: "feedback", title: "Feedback", content: }, - { key: "overlays", title: "Overlays", content: }, - { key: "navigation", title: "Navigation", content: }, - { key: "data", title: "Data Display", content: }, - { key: "layout", title: "Layout", content: }, - { key: "agent", title: "Agent", content: }, - { key: "streaming", title: "Streaming", content: }, - { key: "mcp", title: "MCP", content: }, - { key: "icons", title: "Icons", content: }, - { key: "hooks", title: "Hooks", content: }, - ]; + { key: 'primitives', title: 'Primitives', content: }, + { key: 'inputs', title: 'Buttons & Inputs', content: }, + { key: 'feedback', title: 'Feedback', content: }, + { key: 'overlays', title: 'Overlays', content: }, + { key: 'navigation', title: 'Navigation', content: }, + { key: 'data', title: 'Data Display', content: }, + { key: 'layout', title: 'Layout', content: }, + { key: 'agent', title: 'Agent', content: }, + { key: 'streaming', title: 'Streaming', content: }, + { key: 'mcp', title: 'MCP', content: }, + { key: 'icons', title: 'Icons', content: }, + { key: 'hooks', title: 'Hooks', content: }, + ] return (
@@ -279,7 +273,7 @@ function ShowcaseSections({
- ); + ) } /* ------------------------------------------------------------------ */ @@ -287,7 +281,7 @@ function ShowcaseSections({ /* ------------------------------------------------------------------ */ export function ShowcasePage() { - const [colorMode, setColorMode] = useState("brand"); + const [colorMode, setColorMode] = useState('brand') return ( @@ -299,12 +293,9 @@ export function ShowcasePage() { {/* Right: component showcase tabs */}
- +
- ); + ) } diff --git a/apps/playground/src/demos/showcase/sections/AgentComponentsSection.tsx b/apps/playground/src/demos/showcase/sections/AgentComponentsSection.tsx index 26d74e1..fe987a5 100644 --- a/apps/playground/src/demos/showcase/sections/AgentComponentsSection.tsx +++ b/apps/playground/src/demos/showcase/sections/AgentComponentsSection.tsx @@ -1,35 +1,35 @@ -import { useState } from "react"; import { AgentAvatar, - AgentLabel, AgentHandoff, + AgentLabel, + ConfidenceBadge, + ConfidenceBreakdownView, + ConfidenceMeter, + FeedbackDialog, RoutingIndicator, + SourceBadge, SourceCard, SourceList, - SourceBadge, - ConfidenceBadge, - ConfidenceMeter, - ConfidenceBreakdownView, + ThumbsFeedback, VerificationBadge, VerificationDetail, - ThumbsFeedback, - FeedbackDialog, -} from "@surf-kit/agent"; -import { Stack, Text, Separator } from "@surf-kit/core"; +} from '@surf-kit/agent' +import { Separator, Stack, Text } from '@surf-kit/core' +import { useState } from 'react' import { mockAgents, - mockSources, mockConfidenceHigh, - mockConfidenceMedium, mockConfidenceLow, - mockVerificationPassed, - mockVerificationFlagged, + mockConfidenceMedium, + mockSources, mockVerificationFailed, -} from "../showcase-data"; -import { SectionWrapper } from "./SectionWrapper"; + mockVerificationFlagged, + mockVerificationPassed, +} from '../showcase-data' +import { SectionWrapper } from './SectionWrapper' export function AgentComponentsSection() { - const [feedbackDialogOpen, setFeedbackDialogOpen] = useState(false); + const [feedbackDialogOpen, setFeedbackDialogOpen] = useState(false) return ( @@ -92,11 +92,7 @@ export function AgentComponentsSection() { - + SourceBadge: @@ -124,10 +120,7 @@ export function AgentComponentsSection() { - +
@@ -144,10 +137,7 @@ export function AgentComponentsSection() { - +
@@ -161,22 +151,20 @@ export function AgentComponentsSection() { - console.log("Feedback:", id, rating) - } + onFeedback={(id, rating) => console.log('Feedback:', id, rating)} onNegative={() => setFeedbackDialogOpen(true)} /> setFeedbackDialogOpen(false)} onSubmit={(comment) => { - console.log("Feedback submitted:", comment); - setFeedbackDialogOpen(false); + console.log('Feedback submitted:', comment) + setFeedbackDialogOpen(false) }} /> - ); + ) } diff --git a/apps/playground/src/demos/showcase/sections/AgentStreamingSection.tsx b/apps/playground/src/demos/showcase/sections/AgentStreamingSection.tsx index 81c0c8b..6556a1d 100644 --- a/apps/playground/src/demos/showcase/sections/AgentStreamingSection.tsx +++ b/apps/playground/src/demos/showcase/sections/AgentStreamingSection.tsx @@ -1,22 +1,22 @@ -import { useState } from "react"; import { - ThinkingIndicator, - TypingIndicator, - TextGlimmer, - TypewriterText, + RetrievalProgress, StreamingList, StreamingStructure, + TextGlimmer, + ThinkingIndicator, ToolExecution, - RetrievalProgress, + TypewriterText, + TypingIndicator, VerificationProgress, -} from "@surf-kit/agent"; -import { Stack, Text, Separator, Button } from "@surf-kit/core"; -import { mockSources } from "../showcase-data"; -import { SectionWrapper } from "./SectionWrapper"; +} from '@surf-kit/agent' +import { Button, Separator, Stack, Text } from '@surf-kit/core' +import { useState } from 'react' +import { mockSources } from '../showcase-data' +import { SectionWrapper } from './SectionWrapper' export function AgentStreamingSection() { - const [streamingActive, setStreamingActive] = useState(true); - const [listItems, setListItems] = useState(["Item 1", "Item 2"]); + const [streamingActive, setStreamingActive] = useState(true) + const [listItems, setListItems] = useState(['Item 1', 'Item 2']) return ( @@ -87,21 +87,12 @@ export function AgentStreamingSection() { - @@ -115,9 +106,9 @@ export function AgentStreamingSection() { @@ -151,12 +142,9 @@ export function AgentStreamingSection() { VerificationProgress - + - ); + ) } diff --git a/apps/playground/src/demos/showcase/sections/ButtonsInputsSection.tsx b/apps/playground/src/demos/showcase/sections/ButtonsInputsSection.tsx index 307e085..d790155 100644 --- a/apps/playground/src/demos/showcase/sections/ButtonsInputsSection.tsx +++ b/apps/playground/src/demos/showcase/sections/ButtonsInputsSection.tsx @@ -1,33 +1,33 @@ -import { useState } from "react"; import { Button, - IconButton, - Toggle, - ToggleGroup, - TextInput, - TextArea, - Select, + Calendar, Checkbox, + IconButton, RadioGroup, - Switch, SearchInput, + Select, + Separator, Slider, - Calendar, Stack, + Switch, Text, - Separator, -} from "@surf-kit/core"; -import { Settings, Copy, Check } from "@surf-kit/icons"; -import { SectionWrapper } from "./SectionWrapper"; + TextArea, + TextInput, + Toggle, + ToggleGroup, +} from '@surf-kit/core' +import { Check, Copy, Settings } from '@surf-kit/icons' +import { useState } from 'react' +import { SectionWrapper } from './SectionWrapper' export function ButtonsInputsSection() { - const [switchOn, setSwitchOn] = useState(false); - const [checkboxOn, setCheckboxOn] = useState(true); - const [radioValue, setRadioValue] = useState("light"); - const [selectKey, setSelectKey] = useState("pro"); - const [searchValue, setSearchValue] = useState(""); - const [sliderValue, setSliderValue] = useState(65); - const [toggleOn, setToggleOn] = useState(false); + const [switchOn, setSwitchOn] = useState(false) + const [checkboxOn, setCheckboxOn] = useState(true) + const [radioValue, setRadioValue] = useState('light') + const [selectKey, setSelectKey] = useState('pro') + const [searchValue, setSearchValue] = useState('') + const [sliderValue, setSliderValue] = useState(65) + const [toggleOn, setToggleOn] = useState(false) return ( @@ -76,12 +76,7 @@ export function ButtonsInputsSection() { Toggle & ToggleGroup - + B @@ -106,20 +101,9 @@ export function ButtonsInputsSection() { TextInput & TextArea - - -