@tangle-network/ui 11.32.1 → 11.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/index.d.ts +2 -1
  3. package/dist/index.js +3 -2
  4. package/dist/lib/control-presentation.js +2 -1
  5. package/dist/lib/focus.d.ts +5 -1
  6. package/dist/lib/focus.js +6 -1
  7. package/dist/lib/interaction.d.ts +41 -0
  8. package/dist/lib/interaction.js +42 -0
  9. package/dist/primitives/button.js +19 -18
  10. package/dist/primitives/card.d.ts +14 -1
  11. package/dist/primitives/card.js +15 -5
  12. package/dist/primitives/dropdown-menu.js +7 -6
  13. package/dist/primitives/segmented-control.d.ts +5 -1
  14. package/dist/primitives/segmented-control.js +12 -5
  15. package/dist/primitives/select.js +4 -3
  16. package/dist/primitives/tabs.js +4 -3
  17. package/dist/run/run-group.js +3 -2
  18. package/dist/utils.d.ts +2 -1
  19. package/dist/utils.js +2 -1
  20. package/package.json +2 -2
  21. package/src/files/file-artifact-pane.test.tsx +4 -2
  22. package/src/lib/control-presentation.ts +10 -4
  23. package/src/lib/focus.ts +7 -1
  24. package/src/lib/interaction.ts +64 -0
  25. package/src/primitives/button.tsx +29 -10
  26. package/src/primitives/card.tsx +23 -6
  27. package/src/primitives/control-presentation.test.tsx +6 -3
  28. package/src/primitives/date-picker.test.tsx +1 -1
  29. package/src/primitives/dropdown-menu.tsx +15 -10
  30. package/src/primitives/interaction-states.test.tsx +285 -0
  31. package/src/primitives/segmented-control.test.tsx +4 -2
  32. package/src/primitives/segmented-control.tsx +13 -14
  33. package/src/primitives/select.tsx +11 -5
  34. package/src/primitives/tabs.tsx +7 -3
  35. package/src/run/run-group.tsx +3 -2
  36. package/src/utils/index.ts +9 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @tangle-network/ui
2
2
 
3
+ ## 11.33.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 03c7da0: Surface ladder and one interaction language.
8
+
9
+ Brand: Hospitality gets a stepped ladder (light page 91.6, white cards with a two-layer shadow, raised 95.6; dark page 16.9, card 31.1, raised 37.9 with a top highlight, popover 42.0), field wells that are always the opposite step from their parent, a 3:1 `--field-border`, darker muted text, and status fills retuned for its planes (success, warning, danger, neutral). Dark accent text (#b2dbc2) and the dark destructive red (0 80% 88%) are lifted so they keep 4.5:1 on the lighter raised and popover planes. New tokens `--hsl-raised`, `--hsl-raised-2`, `--well-page`, `--well-card`, `--well-raised`, `--well-raised-2`, `--well`, `--field-border`, `--shadow-raised`, `--shadow-well` and `--edge-highlight` default to the plain spine, so other themes look as before. Shared `--ix-hover`, `--ix-hover-border`, `--ix-press`, `--ix-after`, `--ix-sel-ring`, `--ix-sel-bg` and `--ix-hover-bg` derive from `--hsl-ring`. A `[data-slot="card"]` rule re-declares `--card` and `--well` per card level.
10
+
11
+ UI: new `ixControl`, `ixControlAfter`, `ixControlSoft`, `ixField`, `ixSelected`, `ixTabUnderline` and `ixRow` (exported from `@tangle-network/ui/utils`) give hover, press, after-click and selected states in the focus ring hue; the keyboard focus glow is unchanged. Button, Input, Textarea, `focusFieldWithin`, SelectTrigger/Item/Content, DropdownMenu content and items, Card, SegmentedControl and TabsTrigger apply them. Card renders `data-slot="card"` with `--edge-highlight` + `--shadow-card`, gains `interactive`, and CardDescription clamps at two lines. Select and DropdownMenu content paint the popover level. See docs/surfaces-and-states.md.
12
+
13
+ ## 11.32.2
14
+
15
+ ### Patch Changes
16
+
17
+ - 07e7a78: tangle-drift ignores CSS comments when counting header_height_literal and transcript_type_override, and no longer counts a step-progress bar (`.steps-bar`) as a header row. UI's RunGroup sets its Markdown with the shared TRANSCRIPT_TEXT instead of a fixed 15px / leading-7, so a run reads at the transcript scale.
18
+
3
19
  ## 11.32.1
4
20
 
5
21
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -120,6 +120,7 @@ import { timeAgo } from "./utils/time-ago.js";
120
120
  import { TOOL_CATEGORY_ICONS, getToolCategory, getToolDisplayMetadata, getToolErrorText } from "./utils/tool-display.js";
121
121
  import { cn } from "./lib/utils.js";
122
122
  import { focusField, focusFieldInvalid, focusFieldWithin, focusRing, focusRingInset } from "./lib/focus.js";
123
+ import { ixControl, ixControlAfter, ixControlSoft, ixField, ixRow, ixSelected, ixTabUnderline } from "./lib/interaction.js";
123
124
  import "./utils.js";
124
125
  import { CommandPreview, CommandPreviewProps } from "./tool-previews/command-preview.js";
125
126
  import { WriteFilePreview, WriteFilePreviewProps } from "./tool-previews/write-file-preview.js";
@@ -130,4 +131,4 @@ import { QuestionPreview, QuestionPreviewProps } from "./tool-previews/question-
130
131
  import { DiffPreview, DiffPreviewProps } from "./tool-previews/diff-preview.js";
131
132
  import { RedactedDocSegment, RedactedDocument, RedactedDocumentData, RedactedDocumentProps, RevealResult } from "./redaction/redacted-document.js";
132
133
  import "./redaction.js";
133
- export { ActiveProjectActivity, ActiveSessionActivityOptions, ActiveSessionConnectionOptions, ActiveSessionConnectionState, ActiveSessionReconnectState, ActiveSessionRecord, ActiveSessionStatus, ActiveSessionTransportMode, ActiveSessionsState, AgentBranding, AgentStreamEvent, AgentTimeline, type AgentTimelineArtifactItem, type AgentTimelineCustomItem, type AgentTimelineItem, type AgentTimelineMessageItem, type AgentTimelineProps, type AgentTimelineStatusItem, type AgentTimelineTone, type AgentTimelineToolGroupItem, type AgentTimelineToolItem, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, type AlertProps, AlertTitle, type AlertTone, AppendUserMessageOptions, ApplySdkEventOptions, ApprovalCard, type ApprovalCardProps, type ApprovalDiffFile, ApprovalDiffSummary, type ApprovalPlanStep, ArtifactPane, type ArtifactPaneProps, AuthHeader, type AuthHeaderProps, AuthUser, AutomationStreamEvent, Avatar, AvatarFallback, AvatarImage, Badge, type BadgeProps, BeginAssistantMessageOptions, BotStreamEvent, Button, type ButtonProps, CATEGORY_TONES, CSV_PREVIEW_ROW_LIMIT, Calendar, type CalendarDate, type CalendarProps, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, type CardTitleProps, type CategoryTone, ChatAuthor, ChatContainer, type ChatContainerProps, ChatMessage, type ChatMessageProps, Checkbox, Chip, type ChipProps, CodeBlock, type CodeBlockProps, Collapsible, CollapsibleContent, CollapsibleTrigger, CommandPreview, type CommandPreviewProps, CompleteAssistantMessageOptions, ConnectionState, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, CopyButton, CustomToolRenderer, DatePicker, type DatePickerProps, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DiffPreview, type DiffPreviewProps, DisplayVariant, DropZone, type DropZoneProps, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, type EmptyStateProps, ExpandedToolDetail, type ExpandedToolDetailProps, type FeedSegment, FileArtifactPane, type FileArtifactPaneProps, FileCard, type FileCardProps, type FileDetails, type FileFormat, FileList, type FileListItem, type FileListProps, type FileNode, FilePreview, type FilePreviewKind, type FilePreviewProps, type FileTabData, FileTabs, type FileTabsProps, FileTree, type FileTreeProps, type FileTreeVisibilityOptions, type FileUploader, FilterField, type FilterFieldProps, FinalTextPart, GitHubLoginButton, type GitHubLoginButtonProps, GlobResultsPreview, type GlobResultsPreviewProps, GrepResultsPreview, type GrepResultsPreviewProps, GroupedMessage, Heading, type HeadingProps, type HeadingVariant, HelpText, type HelpTextProps, IconTile, type IconTileProps, InlineCode, type InlineCodeProps, InlineThinkingItem, type InlineThinkingItemProps, InlineToolItem, type InlineToolItemProps, Input, type InputProps, Label, LiveDuration, LoginLayout, type LoginLayoutProps, Logo, type LogoProps, Markdown, type MarkdownLinkChip, type MarkdownLinkChipResolver, type MarkdownProps, MessageAuthor, type MessageAuthorProps, MessageList, type MessageListProps, type MessageRole, MessageRun, MessageUser, Metric, type MetricProps, MetricStrip, type MetricStripProps, OPENUI_NODE_JSON_SCHEMA, OPENUI_NODE_TYPES, type OpenUIAction, type OpenUIActionsNode, OpenUIArtifactRenderer, type OpenUIArtifactRendererProps, type OpenUIBadgeNode, type OpenUICardNode, type OpenUICodeNode, type OpenUIComponentNode, type OpenUIGridNode, type OpenUIHeadingNode, type OpenUIKeyValueNode, type OpenUIMarkdownNode, type OpenUIPrimitive, type OpenUISchemaIssue, type OpenUISchemaValidation, type OpenUISeparatorNode, type OpenUIStackNode, type OpenUIStatNode, type OpenUITableNode, type OpenUITextNode, PageHeader, type PageHeaderProps, PageShell, type PageShellProps, Pagination, type PaginationProps, PdfViewer, type PdfViewerConfig, type PdfViewerProps, Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverTrigger, Progress, QuestionPreview, type QuestionPreviewProps, RadioGroup, RadioGroupItem, RealtimeSessionOptions, RealtimeSessionRegistry, RealtimeSessionRegistryProps, RealtimeSessionState, RealtimeSessionTarget, ReasoningPart, type RedactedDocSegment, RedactedDocument, type RedactedDocumentData, type RedactedDocumentProps, RegisterActiveSessionOptions, type RevealResult, RichFileTree, type RichFileTreeGitEntry, type RichFileTreeGitStatus, type RichFileTreeProps, type RichFileTreeThemeVars, Run, RunGroup, type RunGroupProps, type RunPhase, RunPhaseList, RunRowShell, type RunRowShellProps, type RunRowStatus, RunRowStatusDot, RunStats, SSEEvent, SdkSessionAttachment, SdkSessionEvent, SdkSessionSeed, SegmentedControl, type SegmentedControlOption, type SegmentedControlProps, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, SessionMessage, SessionPart, SessionProjectKey, type SessionUser, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, SidebarDropZone, type SidebarDropZoneProps, Skeleton, SkeletonCard, SkeletonTable, Slider, StatCard, type StatCardProps, StatusPill, type StatusPillProps, type StatusTone, Switch, TONE_CLASSES, TOOL_CATEGORY_ICONS, TRANSCRIPT_TEXT, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, type TableProps, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Tag, type TagProps, TangleKnot, TaskList, type TaskListItem, type TaskListProps, type TaskStatus, TaskStreamEvent, TerminalCursor, TerminalDisplay, TerminalInput, TerminalLine, TerminalStreamEvent, TextPart, TextShimmer, type TextShimmerProps, Textarea, type TextareaProps, ThemeToggle, ThinkingIndicator, type ThinkingIndicatorProps, TimeSelect, type TimeSelectProps, type Toast, ToastContainer, ToastProvider, type Tone, type ToneClasses, type ToolCallData, ToolCallFeed, type ToolCallFeedProps, type ToolCallStatus, type ToolCallType, ToolCategory, ToolDisplayMetadata, ToolPart, ToolState, ToolStatus, ToolTime, Toolbar, type ToolbarProps, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, type UploadFile, UploadProgress, type UploadProgressProps, UseAuthOptions, UseAuthResult, UseRunGroupsOptions, UseSSEStreamOptions, UseSSEStreamResult, UseSdkSessionOptions, UseSdkSessionReturn, UseToolCallStreamReturn, UserMenu, type UserMenuProps, UserMessage, type UserMessageProps, WebSearchPreview, type WebSearchPreviewProps, WriteFilePreview, type WriteFilePreviewProps, activeSessionsAtom, addMessage, addParts, badgeVariants, bumpActiveSessionActivity, buttonVariants, clearChat, cn, codeBlockGrammar, configurePdfViewer, copyText, createAuthFetcher, detectFileFormat, fenceInfo, fileExtension, filterFileTree, findUnsupportedOpenUINode, focusField, focusFieldInvalid, focusFieldWithin, focusRing, focusRingInset, formatBytes, formatCalendarDate, formatDuration, formatUptime, getActiveSession, getAllActiveSessions, getAllProjectActivity, getCodeLanguage, getFormatLabel, getSanitizedMarkdownHeadingIdFromRawFragment, getSessionsByActivity, getSessionsForNavbar, getSessionsForProject, getSyntaxLanguage, getToolCategory, getToolDisplayMetadata, getToolErrorText, getTotalRunningSessionCount, hasBackgroundRunningSessions, initialsOf, isStreamingAtom, isViewerMessage, localToday, messagesAtom, numericColumns, parseCalendarDate, parseCsv, parseToolEvent, partMapAtom, registerActiveSession, resetActiveSessions, resolveFilePreviewKind, setActiveSessionAttention, setActiveSessionConnection, setActiveSessionError, setActiveSessionRunning, setForegroundActiveSession, showsTaskPriority, tableCsv, taskProgress, taskStatus, timeAgo, toneFor, truncateText, unregisterActiveSession, updateActiveSessionMeta, updatePart, useActiveSession, useActiveSessions, useActiveSessionsState, useApiKey, useAuth, useAutoScroll, useDropdownMenu, useHasBackgroundRunningSessions, useLiveTime, useNavbarSessions, useProjectActivity, useProjectSessions, useRealtimeSession, useRunCollapseState, useRunGroups, useSSEStream, useSdkSession, useSessionsByActivity, useTheme, useToast, useToolCallStream, useTotalRunningSessions, validateOpenUIJsonArtifact, validateOpenUIJsonNode };
134
+ export { ActiveProjectActivity, ActiveSessionActivityOptions, ActiveSessionConnectionOptions, ActiveSessionConnectionState, ActiveSessionReconnectState, ActiveSessionRecord, ActiveSessionStatus, ActiveSessionTransportMode, ActiveSessionsState, AgentBranding, AgentStreamEvent, AgentTimeline, type AgentTimelineArtifactItem, type AgentTimelineCustomItem, type AgentTimelineItem, type AgentTimelineMessageItem, type AgentTimelineProps, type AgentTimelineStatusItem, type AgentTimelineTone, type AgentTimelineToolGroupItem, type AgentTimelineToolItem, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, type AlertProps, AlertTitle, type AlertTone, AppendUserMessageOptions, ApplySdkEventOptions, ApprovalCard, type ApprovalCardProps, type ApprovalDiffFile, ApprovalDiffSummary, type ApprovalPlanStep, ArtifactPane, type ArtifactPaneProps, AuthHeader, type AuthHeaderProps, AuthUser, AutomationStreamEvent, Avatar, AvatarFallback, AvatarImage, Badge, type BadgeProps, BeginAssistantMessageOptions, BotStreamEvent, Button, type ButtonProps, CATEGORY_TONES, CSV_PREVIEW_ROW_LIMIT, Calendar, type CalendarDate, type CalendarProps, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, type CardTitleProps, type CategoryTone, ChatAuthor, ChatContainer, type ChatContainerProps, ChatMessage, type ChatMessageProps, Checkbox, Chip, type ChipProps, CodeBlock, type CodeBlockProps, Collapsible, CollapsibleContent, CollapsibleTrigger, CommandPreview, type CommandPreviewProps, CompleteAssistantMessageOptions, ConnectionState, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, CopyButton, CustomToolRenderer, DatePicker, type DatePickerProps, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DiffPreview, type DiffPreviewProps, DisplayVariant, DropZone, type DropZoneProps, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, type EmptyStateProps, ExpandedToolDetail, type ExpandedToolDetailProps, type FeedSegment, FileArtifactPane, type FileArtifactPaneProps, FileCard, type FileCardProps, type FileDetails, type FileFormat, FileList, type FileListItem, type FileListProps, type FileNode, FilePreview, type FilePreviewKind, type FilePreviewProps, type FileTabData, FileTabs, type FileTabsProps, FileTree, type FileTreeProps, type FileTreeVisibilityOptions, type FileUploader, FilterField, type FilterFieldProps, FinalTextPart, GitHubLoginButton, type GitHubLoginButtonProps, GlobResultsPreview, type GlobResultsPreviewProps, GrepResultsPreview, type GrepResultsPreviewProps, GroupedMessage, Heading, type HeadingProps, type HeadingVariant, HelpText, type HelpTextProps, IconTile, type IconTileProps, InlineCode, type InlineCodeProps, InlineThinkingItem, type InlineThinkingItemProps, InlineToolItem, type InlineToolItemProps, Input, type InputProps, Label, LiveDuration, LoginLayout, type LoginLayoutProps, Logo, type LogoProps, Markdown, type MarkdownLinkChip, type MarkdownLinkChipResolver, type MarkdownProps, MessageAuthor, type MessageAuthorProps, MessageList, type MessageListProps, type MessageRole, MessageRun, MessageUser, Metric, type MetricProps, MetricStrip, type MetricStripProps, OPENUI_NODE_JSON_SCHEMA, OPENUI_NODE_TYPES, type OpenUIAction, type OpenUIActionsNode, OpenUIArtifactRenderer, type OpenUIArtifactRendererProps, type OpenUIBadgeNode, type OpenUICardNode, type OpenUICodeNode, type OpenUIComponentNode, type OpenUIGridNode, type OpenUIHeadingNode, type OpenUIKeyValueNode, type OpenUIMarkdownNode, type OpenUIPrimitive, type OpenUISchemaIssue, type OpenUISchemaValidation, type OpenUISeparatorNode, type OpenUIStackNode, type OpenUIStatNode, type OpenUITableNode, type OpenUITextNode, PageHeader, type PageHeaderProps, PageShell, type PageShellProps, Pagination, type PaginationProps, PdfViewer, type PdfViewerConfig, type PdfViewerProps, Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverTrigger, Progress, QuestionPreview, type QuestionPreviewProps, RadioGroup, RadioGroupItem, RealtimeSessionOptions, RealtimeSessionRegistry, RealtimeSessionRegistryProps, RealtimeSessionState, RealtimeSessionTarget, ReasoningPart, type RedactedDocSegment, RedactedDocument, type RedactedDocumentData, type RedactedDocumentProps, RegisterActiveSessionOptions, type RevealResult, RichFileTree, type RichFileTreeGitEntry, type RichFileTreeGitStatus, type RichFileTreeProps, type RichFileTreeThemeVars, Run, RunGroup, type RunGroupProps, type RunPhase, RunPhaseList, RunRowShell, type RunRowShellProps, type RunRowStatus, RunRowStatusDot, RunStats, SSEEvent, SdkSessionAttachment, SdkSessionEvent, SdkSessionSeed, SegmentedControl, type SegmentedControlOption, type SegmentedControlProps, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, SessionMessage, SessionPart, SessionProjectKey, type SessionUser, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, SidebarDropZone, type SidebarDropZoneProps, Skeleton, SkeletonCard, SkeletonTable, Slider, StatCard, type StatCardProps, StatusPill, type StatusPillProps, type StatusTone, Switch, TONE_CLASSES, TOOL_CATEGORY_ICONS, TRANSCRIPT_TEXT, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, type TableProps, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Tag, type TagProps, TangleKnot, TaskList, type TaskListItem, type TaskListProps, type TaskStatus, TaskStreamEvent, TerminalCursor, TerminalDisplay, TerminalInput, TerminalLine, TerminalStreamEvent, TextPart, TextShimmer, type TextShimmerProps, Textarea, type TextareaProps, ThemeToggle, ThinkingIndicator, type ThinkingIndicatorProps, TimeSelect, type TimeSelectProps, type Toast, ToastContainer, ToastProvider, type Tone, type ToneClasses, type ToolCallData, ToolCallFeed, type ToolCallFeedProps, type ToolCallStatus, type ToolCallType, ToolCategory, ToolDisplayMetadata, ToolPart, ToolState, ToolStatus, ToolTime, Toolbar, type ToolbarProps, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, type UploadFile, UploadProgress, type UploadProgressProps, UseAuthOptions, UseAuthResult, UseRunGroupsOptions, UseSSEStreamOptions, UseSSEStreamResult, UseSdkSessionOptions, UseSdkSessionReturn, UseToolCallStreamReturn, UserMenu, type UserMenuProps, UserMessage, type UserMessageProps, WebSearchPreview, type WebSearchPreviewProps, WriteFilePreview, type WriteFilePreviewProps, activeSessionsAtom, addMessage, addParts, badgeVariants, bumpActiveSessionActivity, buttonVariants, clearChat, cn, codeBlockGrammar, configurePdfViewer, copyText, createAuthFetcher, detectFileFormat, fenceInfo, fileExtension, filterFileTree, findUnsupportedOpenUINode, focusField, focusFieldInvalid, focusFieldWithin, focusRing, focusRingInset, formatBytes, formatCalendarDate, formatDuration, formatUptime, getActiveSession, getAllActiveSessions, getAllProjectActivity, getCodeLanguage, getFormatLabel, getSanitizedMarkdownHeadingIdFromRawFragment, getSessionsByActivity, getSessionsForNavbar, getSessionsForProject, getSyntaxLanguage, getToolCategory, getToolDisplayMetadata, getToolErrorText, getTotalRunningSessionCount, hasBackgroundRunningSessions, initialsOf, isStreamingAtom, isViewerMessage, ixControl, ixControlAfter, ixControlSoft, ixField, ixRow, ixSelected, ixTabUnderline, localToday, messagesAtom, numericColumns, parseCalendarDate, parseCsv, parseToolEvent, partMapAtom, registerActiveSession, resetActiveSessions, resolveFilePreviewKind, setActiveSessionAttention, setActiveSessionConnection, setActiveSessionError, setActiveSessionRunning, setForegroundActiveSession, showsTaskPriority, tableCsv, taskProgress, taskStatus, timeAgo, toneFor, truncateText, unregisterActiveSession, updateActiveSessionMeta, updatePart, useActiveSession, useActiveSessions, useActiveSessionsState, useApiKey, useAuth, useAutoScroll, useDropdownMenu, useHasBackgroundRunningSessions, useLiveTime, useNavbarSessions, useProjectActivity, useProjectSessions, useRealtimeSession, useRunCollapseState, useRunGroups, useSSEStream, useSdkSession, useSessionsByActivity, useTheme, useToast, useToolCallStream, useTotalRunningSessions, validateOpenUIJsonArtifact, validateOpenUIJsonNode };
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { ixControl, ixControlAfter, ixControlSoft, ixField, ixRow, ixSelected, ixTabUnderline } from "./lib/interaction.js";
1
2
  import { focusField, focusFieldInvalid, focusFieldWithin, focusRing, focusRingInset } from "./lib/focus.js";
2
3
  import { cn } from "./lib/utils.js";
3
4
  import { Button, buttonVariants } from "./primitives/button.js";
@@ -77,8 +78,8 @@ import { InlineThinkingItem } from "./run/inline-thinking-item.js";
77
78
  import { OPENUI_NODE_JSON_SCHEMA, OPENUI_NODE_TYPES } from "./openui/schema-data.js";
78
79
  import { findUnsupportedOpenUINode, validateOpenUIJsonArtifact, validateOpenUIJsonNode } from "./openui-schema.js";
79
80
  import { OpenUIArtifactRenderer } from "./openui/openui-artifact-renderer.js";
80
- import { RunGroup } from "./run/run-group.js";
81
81
  import { TRANSCRIPT_TEXT } from "./chat/transcript-text.js";
82
+ import { RunGroup } from "./run/run-group.js";
82
83
  import { MessageAuthor, isViewerMessage } from "./chat/message-author.js";
83
84
  import { UserMessage } from "./chat/user-message.js";
84
85
  import { MessageList } from "./chat/message-list.js";
@@ -114,4 +115,4 @@ import { addMessage, addParts, clearChat, isStreamingAtom, messagesAtom, partMap
114
115
  import { copyText } from "./utils/copy-text.js";
115
116
  import { timeAgo } from "./utils/time-ago.js";
116
117
  import { RedactedDocument } from "./redaction/redacted-document.js";
117
- export { AgentTimeline, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, ApprovalCard, ApprovalDiffSummary, ArtifactPane, AuthHeader, Avatar, AvatarFallback, AvatarImage, Badge, Button, CATEGORY_TONES, CSV_PREVIEW_ROW_LIMIT, Calendar, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ChatContainer, ChatMessage, Checkbox, Chip, CodeBlock, Collapsible, CollapsibleContent, CollapsibleTrigger, CommandPreview, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, CopyButton, DatePicker, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DiffPreview, DropZone, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, ExpandedToolDetail, FileArtifactPane, FileCard, FileList, FilePreview, FileTabs, FileTree, FilterField, GitHubLoginButton, GlobResultsPreview, GrepResultsPreview, Heading, HelpText, IconTile, InlineCode, InlineThinkingItem, InlineToolItem, Input, Label, LiveDuration, LoginLayout, Logo, Markdown, MessageAuthor, MessageList, Metric, MetricStrip, OPENUI_NODE_JSON_SCHEMA, OPENUI_NODE_TYPES, OpenUIArtifactRenderer, PageHeader, PageShell, Pagination, PdfViewer, Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverTrigger, Progress, QuestionPreview, RadioGroup, RadioGroupItem, RealtimeSessionRegistry, RedactedDocument, RichFileTree, RunGroup, RunPhaseList, RunRowShell, RunRowStatusDot, SegmentedControl, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, SidebarDropZone, Skeleton, SkeletonCard, SkeletonTable, Slider, StatCard, StatusPill, Switch, TONE_CLASSES, TOOL_CATEGORY_ICONS, TRANSCRIPT_TEXT, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Tag, TangleKnot, TaskList, TerminalCursor, TerminalDisplay, TerminalInput, TerminalLine, TextShimmer, Textarea, ThemeToggle, ThinkingIndicator, TimeSelect, ToastContainer, ToastProvider, ToolCallFeed, Toolbar, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, UploadProgress, UserMenu, UserMessage, WebSearchPreview, WriteFilePreview, activeSessionsAtom, addMessage, addParts, badgeVariants, bumpActiveSessionActivity, buttonVariants, clearChat, cn, codeBlockGrammar, configurePdfViewer, copyText, createAuthFetcher, detectFileFormat, fenceInfo, fileExtension, filterFileTree, findUnsupportedOpenUINode, focusField, focusFieldInvalid, focusFieldWithin, focusRing, focusRingInset, formatBytes, formatCalendarDate, formatDuration, formatUptime, getActiveSession, getAllActiveSessions, getAllProjectActivity, getCodeLanguage, getFormatLabel, getSanitizedMarkdownHeadingIdFromRawFragment, getSessionsByActivity, getSessionsForNavbar, getSessionsForProject, getSyntaxLanguage, getToolCategory, getToolDisplayMetadata, getToolErrorText, getTotalRunningSessionCount, hasBackgroundRunningSessions, initialsOf, isStreamingAtom, isViewerMessage, localToday, messagesAtom, numericColumns, parseCalendarDate, parseCsv, parseToolEvent, partMapAtom, registerActiveSession, resetActiveSessions, resolveFilePreviewKind, setActiveSessionAttention, setActiveSessionConnection, setActiveSessionError, setActiveSessionRunning, setForegroundActiveSession, showsTaskPriority, tableCsv, taskProgress, taskStatus, timeAgo, toneFor, truncateText, unregisterActiveSession, updateActiveSessionMeta, updatePart, useActiveSession, useActiveSessions, useActiveSessionsState, useApiKey, useAuth, useAutoScroll, useDropdownMenu, useHasBackgroundRunningSessions, useLiveTime, useNavbarSessions, useProjectActivity, useProjectSessions, useRealtimeSession, useRunCollapseState, useRunGroups, useSSEStream, useSdkSession, useSessionsByActivity, useTheme, useToast, useToolCallStream, useTotalRunningSessions, validateOpenUIJsonArtifact, validateOpenUIJsonNode };
118
+ export { AgentTimeline, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, ApprovalCard, ApprovalDiffSummary, ArtifactPane, AuthHeader, Avatar, AvatarFallback, AvatarImage, Badge, Button, CATEGORY_TONES, CSV_PREVIEW_ROW_LIMIT, Calendar, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ChatContainer, ChatMessage, Checkbox, Chip, CodeBlock, Collapsible, CollapsibleContent, CollapsibleTrigger, CommandPreview, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, CopyButton, DatePicker, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DiffPreview, DropZone, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, ExpandedToolDetail, FileArtifactPane, FileCard, FileList, FilePreview, FileTabs, FileTree, FilterField, GitHubLoginButton, GlobResultsPreview, GrepResultsPreview, Heading, HelpText, IconTile, InlineCode, InlineThinkingItem, InlineToolItem, Input, Label, LiveDuration, LoginLayout, Logo, Markdown, MessageAuthor, MessageList, Metric, MetricStrip, OPENUI_NODE_JSON_SCHEMA, OPENUI_NODE_TYPES, OpenUIArtifactRenderer, PageHeader, PageShell, Pagination, PdfViewer, Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverTrigger, Progress, QuestionPreview, RadioGroup, RadioGroupItem, RealtimeSessionRegistry, RedactedDocument, RichFileTree, RunGroup, RunPhaseList, RunRowShell, RunRowStatusDot, SegmentedControl, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, SidebarDropZone, Skeleton, SkeletonCard, SkeletonTable, Slider, StatCard, StatusPill, Switch, TONE_CLASSES, TOOL_CATEGORY_ICONS, TRANSCRIPT_TEXT, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Tag, TangleKnot, TaskList, TerminalCursor, TerminalDisplay, TerminalInput, TerminalLine, TextShimmer, Textarea, ThemeToggle, ThinkingIndicator, TimeSelect, ToastContainer, ToastProvider, ToolCallFeed, Toolbar, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, UploadProgress, UserMenu, UserMessage, WebSearchPreview, WriteFilePreview, activeSessionsAtom, addMessage, addParts, badgeVariants, bumpActiveSessionActivity, buttonVariants, clearChat, cn, codeBlockGrammar, configurePdfViewer, copyText, createAuthFetcher, detectFileFormat, fenceInfo, fileExtension, filterFileTree, findUnsupportedOpenUINode, focusField, focusFieldInvalid, focusFieldWithin, focusRing, focusRingInset, formatBytes, formatCalendarDate, formatDuration, formatUptime, getActiveSession, getAllActiveSessions, getAllProjectActivity, getCodeLanguage, getFormatLabel, getSanitizedMarkdownHeadingIdFromRawFragment, getSessionsByActivity, getSessionsForNavbar, getSessionsForProject, getSyntaxLanguage, getToolCategory, getToolDisplayMetadata, getToolErrorText, getTotalRunningSessionCount, hasBackgroundRunningSessions, initialsOf, isStreamingAtom, isViewerMessage, ixControl, ixControlAfter, ixControlSoft, ixField, ixRow, ixSelected, ixTabUnderline, localToday, messagesAtom, numericColumns, parseCalendarDate, parseCsv, parseToolEvent, partMapAtom, registerActiveSession, resetActiveSessions, resolveFilePreviewKind, setActiveSessionAttention, setActiveSessionConnection, setActiveSessionError, setActiveSessionRunning, setForegroundActiveSession, showsTaskPriority, tableCsv, taskProgress, taskStatus, timeAgo, toneFor, truncateText, unregisterActiveSession, updateActiveSessionMeta, updatePart, useActiveSession, useActiveSessions, useActiveSessionsState, useApiKey, useAuth, useAutoScroll, useDropdownMenu, useHasBackgroundRunningSessions, useLiveTime, useNavbarSessions, useProjectActivity, useProjectSessions, useRealtimeSession, useRunCollapseState, useRunGroups, useSSEStream, useSdkSession, useSessionsByActivity, useTheme, useToast, useToolCallStream, useTotalRunningSessions, validateOpenUIJsonArtifact, validateOpenUIJsonNode };
@@ -1,3 +1,4 @@
1
+ import { ixField } from "./interaction.js";
1
2
  import { focusField } from "./focus.js";
2
3
  import { cn } from "./utils.js";
3
4
  //#region src/lib/control-presentation.ts
@@ -43,6 +44,6 @@ const controlSizes = {
43
44
  compact: "h-[var(--control-height)] px-3 py-1 text-sm",
44
45
  touch: "h-11 min-h-11 min-w-11 px-4 py-2 text-base"
45
46
  };
46
- const fieldPresentation = cn(focusField, controlMotion, "min-w-0 bg-[var(--field-surface,var(--bg-input))] text-foreground", "aria-invalid:border-[var(--surface-danger-border)] aria-invalid:hover:border-[var(--surface-danger-border)] aria-invalid:focus:border-[var(--focus-border-danger)] aria-invalid:focus:ring-[var(--focus-halo-danger)]", "autofill:shadow-[inset_0_0_0_1000px_var(--bg-input)] autofill:[-webkit-text-fill-color:var(--text-primary)] autofill:caret-[var(--text-primary)]");
47
+ const fieldPresentation = cn(focusField, ixField, controlMotion, "min-w-0 text-foreground", "aria-invalid:border-[var(--surface-danger-border)] aria-invalid:hover:border-[var(--surface-danger-border)] aria-invalid:focus:border-[var(--focus-border-danger)] aria-invalid:focus:ring-[var(--focus-halo-danger)]", "autofill:shadow-[inset_0_0_0_1000px_var(--field-surface,var(--well))] autofill:[-webkit-text-fill-color:var(--text-primary)] autofill:caret-[var(--text-primary)]");
47
48
  //#endregion
48
49
  export { controlHeight, controlMotion, controlRadius, controlSizes, controlSquare, controlText, fieldPresentation, fieldSizes, fieldTouchText, touchTarget };
@@ -40,8 +40,12 @@ export declare const focusField = "border-border transition-[border-color,box-sh
40
40
  * compose your own classes instead of this helper. The field selector is
41
41
  * written out in full because Tailwind reads class names statically.
42
42
  * Base styles use its marker class to clear the inner editor fallback outline.
43
+ *
44
+ * The container is the field, so it takes `ixField` (lib/interaction.ts): its
45
+ * own well fill, the `--field-border` hairline and the green hover edge. The
46
+ * borderless field inside stays transparent.
43
47
  */
44
- export declare const focusFieldWithin = "focus-field-within border-border transition-[border-color,box-shadow] duration-150 ease-out hover:border-[var(--border-strong)] has-[:is(textarea,select,[contenteditable]:not([contenteditable=false]),input:not([type=button],[type=submit],[type=reset],[type=image],[type=checkbox],[type=radio],[type=range],[type=color],[type=file])):focus]:border-[var(--focus-border)] has-[:is(textarea,select,[contenteditable]:not([contenteditable=false]),input:not([type=button],[type=submit],[type=reset],[type=image],[type=checkbox],[type=radio],[type=range],[type=color],[type=file])):focus]:ring-3 has-[:is(textarea,select,[contenteditable]:not([contenteditable=false]),input:not([type=button],[type=submit],[type=reset],[type=image],[type=checkbox],[type=radio],[type=range],[type=color],[type=file])):focus]:ring-[var(--focus-halo)]";
48
+ export declare const focusFieldWithin = "focus-field-within transition-[border-color,box-shadow] duration-150 ease-out bg-[var(--field-surface,var(--well))] border-[var(--field-border)] shadow-[var(--shadow-well)] hover:border-[var(--ix-hover-border)] hover:shadow-[var(--shadow-well),var(--ix-hover)] has-[:is(textarea,select,[contenteditable]:not([contenteditable=false]),input:not([type=button],[type=submit],[type=reset],[type=image],[type=checkbox],[type=radio],[type=range],[type=color],[type=file])):focus]:border-[var(--focus-border)] has-[:is(textarea,select,[contenteditable]:not([contenteditable=false]),input:not([type=button],[type=submit],[type=reset],[type=image],[type=checkbox],[type=radio],[type=range],[type=color],[type=file])):focus]:ring-3 has-[:is(textarea,select,[contenteditable]:not([contenteditable=false]),input:not([type=button],[type=submit],[type=reset],[type=image],[type=checkbox],[type=radio],[type=range],[type=color],[type=file])):focus]:ring-[var(--focus-halo)]";
45
49
  /** Error state for a field: a danger hairline and the same focus shape in danger. Compose after `focusField`. */
46
50
  export declare const focusFieldInvalid = "border-[var(--surface-danger-border)] hover:border-[var(--surface-danger-border)] focus:border-[var(--focus-border-danger)] focus:ring-[var(--focus-halo-danger)]";
47
51
  /** Keyboard-only focus for a control: a 1px focus line with the halo beyond it. */
package/dist/lib/focus.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { ixField } from "./interaction.js";
1
2
  //#region src/lib/focus.ts
2
3
  /**
3
4
  * The focus treatment every control shares, in two shapes over one palette
@@ -40,8 +41,12 @@ const focusField = "border-border transition-[border-color,box-shadow] duration-
40
41
  * compose your own classes instead of this helper. The field selector is
41
42
  * written out in full because Tailwind reads class names statically.
42
43
  * Base styles use its marker class to clear the inner editor fallback outline.
44
+ *
45
+ * The container is the field, so it takes `ixField` (lib/interaction.ts): its
46
+ * own well fill, the `--field-border` hairline and the green hover edge. The
47
+ * borderless field inside stays transparent.
43
48
  */
44
- const focusFieldWithin = "focus-field-within border-border transition-[border-color,box-shadow] duration-150 ease-out hover:border-[var(--border-strong)] has-[:is(textarea,select,[contenteditable]:not([contenteditable=false]),input:not([type=button],[type=submit],[type=reset],[type=image],[type=checkbox],[type=radio],[type=range],[type=color],[type=file])):focus]:border-[var(--focus-border)] has-[:is(textarea,select,[contenteditable]:not([contenteditable=false]),input:not([type=button],[type=submit],[type=reset],[type=image],[type=checkbox],[type=radio],[type=range],[type=color],[type=file])):focus]:ring-3 has-[:is(textarea,select,[contenteditable]:not([contenteditable=false]),input:not([type=button],[type=submit],[type=reset],[type=image],[type=checkbox],[type=radio],[type=range],[type=color],[type=file])):focus]:ring-[var(--focus-halo)]";
49
+ const focusFieldWithin = `focus-field-within transition-[border-color,box-shadow] duration-150 ease-out ${ixField} has-[:is(textarea,select,[contenteditable]:not([contenteditable=false]),input:not([type=button],[type=submit],[type=reset],[type=image],[type=checkbox],[type=radio],[type=range],[type=color],[type=file])):focus]:border-[var(--focus-border)] has-[:is(textarea,select,[contenteditable]:not([contenteditable=false]),input:not([type=button],[type=submit],[type=reset],[type=image],[type=checkbox],[type=radio],[type=range],[type=color],[type=file])):focus]:ring-3 has-[:is(textarea,select,[contenteditable]:not([contenteditable=false]),input:not([type=button],[type=submit],[type=reset],[type=image],[type=checkbox],[type=radio],[type=range],[type=color],[type=file])):focus]:ring-[var(--focus-halo)]`;
45
50
  /** Error state for a field: a danger hairline and the same focus shape in danger. Compose after `focusField`. */
46
51
  const focusFieldInvalid = "border-[var(--surface-danger-border)] hover:border-[var(--surface-danger-border)] focus:border-[var(--focus-border-danger)] focus:ring-[var(--focus-halo-danger)]";
47
52
  const focusRingBase = "focus-visible:outline-1 focus-visible:outline-[var(--focus-border)] focus-visible:ring-4 focus-visible:ring-[var(--focus-halo)]";
@@ -0,0 +1,41 @@
1
+ //#region src/lib/interaction.d.ts
2
+ /**
3
+ * The interaction states every control shares: one palette in five shapes, all
4
+ * read from `@tangle-network/brand`'s `--ix-*` tokens (tokens.css), which derive
5
+ * from the focus ring hue `--hsl-ring`. So hover, press, after-click and
6
+ * selected are the same green in Hospitality and the same indigo on the spine
7
+ * as the keyboard focus ring.
8
+ *
9
+ * hover 1px edge at .45 plus a 4px halo at .16 (`--ix-hover`)
10
+ * press 1px edge at .95 plus a 4px halo at .30 (`--ix-press`)
11
+ * after a control focused by a mouse click keeps a soft ring (`--ix-after`)
12
+ * selected a tint plus a 1px inset ring at .85 (`--ix-sel-bg`, `--ix-sel-ring`)
13
+ *
14
+ * The keyboard focus-visible glow stays exactly as `focusRing` / `focusField`
15
+ * (lib/focus.ts) draw it. Tailwind composes `--tw-ring-shadow` with
16
+ * `--tw-shadow`, so these shadows coexist with that ring, and
17
+ * `focus-visible:shadow-none` drops the hover glow while the keyboard ring shows.
18
+ *
19
+ * Every class is written out in full because Tailwind reads class names
20
+ * statically.
21
+ */
22
+ /** Bordered or filled control: green edge on hover, deeper on press, a persistent soft ring after a mouse click. */
23
+ export declare const ixControl: string;
24
+ /** The after-click part of `ixControl` alone, for a field that opens a menu (SelectTrigger). */
25
+ export declare const ixControlAfter = "focus:not-focus-visible:border-[var(--ix-hover-border)] focus:not-focus-visible:shadow-[var(--ix-after)]";
26
+ /** Ghost, icon, link and bare controls: a wash, never a glow (too noisy in sidebars and toolbars). */
27
+ export declare const ixControlSoft = "hover:bg-[var(--ix-hover-bg)] active:bg-[var(--ix-sel-bg)]";
28
+ /**
29
+ * Field: its own well and a visible border; hover replaces `focusField`'s
30
+ * neutral `--border-strong`. The well is the `--well` context variable, which a
31
+ * card re-declares for its descendants, so a field never takes its parent's
32
+ * colour. `--field-surface` still lets a context such as Toolbar pick the fill.
33
+ */
34
+ export declare const ixField: string;
35
+ /** Selected / on / current: tint plus a 1px inset green ring. */
36
+ export declare const ixSelected: string;
37
+ /** Underline tab: 2px green underline plus a faint tint, never a box; a faint underline on hover. */
38
+ export declare const ixTabUnderline: string;
39
+ /** List row / menu item: wash plus inset edge on hover or keyboard highlight; checked = selected. */
40
+ export declare const ixRow: string;
41
+ //#endregion
@@ -0,0 +1,42 @@
1
+ //#region src/lib/interaction.ts
2
+ /**
3
+ * The interaction states every control shares: one palette in five shapes, all
4
+ * read from `@tangle-network/brand`'s `--ix-*` tokens (tokens.css), which derive
5
+ * from the focus ring hue `--hsl-ring`. So hover, press, after-click and
6
+ * selected are the same green in Hospitality and the same indigo on the spine
7
+ * as the keyboard focus ring.
8
+ *
9
+ * hover 1px edge at .45 plus a 4px halo at .16 (`--ix-hover`)
10
+ * press 1px edge at .95 plus a 4px halo at .30 (`--ix-press`)
11
+ * after a control focused by a mouse click keeps a soft ring (`--ix-after`)
12
+ * selected a tint plus a 1px inset ring at .85 (`--ix-sel-bg`, `--ix-sel-ring`)
13
+ *
14
+ * The keyboard focus-visible glow stays exactly as `focusRing` / `focusField`
15
+ * (lib/focus.ts) draw it. Tailwind composes `--tw-ring-shadow` with
16
+ * `--tw-shadow`, so these shadows coexist with that ring, and
17
+ * `focus-visible:shadow-none` drops the hover glow while the keyboard ring shows.
18
+ *
19
+ * Every class is written out in full because Tailwind reads class names
20
+ * statically.
21
+ */
22
+ /** Bordered or filled control: green edge on hover, deeper on press, a persistent soft ring after a mouse click. */
23
+ const ixControl = "hover:border-[var(--ix-hover-border)] hover:shadow-[var(--ix-hover)] focus:not-focus-visible:border-[var(--ix-hover-border)] focus:not-focus-visible:shadow-[var(--ix-after)] active:border-[hsl(var(--hsl-ring))] active:shadow-[var(--ix-press)] focus-visible:shadow-none";
24
+ /** The after-click part of `ixControl` alone, for a field that opens a menu (SelectTrigger). */
25
+ const ixControlAfter = "focus:not-focus-visible:border-[var(--ix-hover-border)] focus:not-focus-visible:shadow-[var(--ix-after)]";
26
+ /** Ghost, icon, link and bare controls: a wash, never a glow (too noisy in sidebars and toolbars). */
27
+ const ixControlSoft = "hover:bg-[var(--ix-hover-bg)] active:bg-[var(--ix-sel-bg)]";
28
+ /**
29
+ * Field: its own well and a visible border; hover replaces `focusField`'s
30
+ * neutral `--border-strong`. The well is the `--well` context variable, which a
31
+ * card re-declares for its descendants, so a field never takes its parent's
32
+ * colour. `--field-surface` still lets a context such as Toolbar pick the fill.
33
+ */
34
+ const ixField = "bg-[var(--field-surface,var(--well))] border-[var(--field-border)] shadow-[var(--shadow-well)] hover:border-[var(--ix-hover-border)] hover:shadow-[var(--shadow-well),var(--ix-hover)]";
35
+ /** Selected / on / current: tint plus a 1px inset green ring. */
36
+ const ixSelected = "aria-pressed:bg-[var(--ix-sel-bg)] aria-pressed:text-[var(--accent-text)] aria-pressed:shadow-[inset_0_0_0_1px_var(--ix-sel-ring)] aria-checked:bg-[var(--ix-sel-bg)] aria-checked:text-[var(--accent-text)] aria-checked:shadow-[inset_0_0_0_1px_var(--ix-sel-ring)] aria-[current=page]:bg-[var(--ix-sel-bg)] aria-[current=page]:text-[var(--accent-text)] aria-[current=page]:shadow-[inset_0_0_0_1px_var(--ix-sel-ring)] data-[state=on]:bg-[var(--ix-sel-bg)] data-[state=on]:shadow-[inset_0_0_0_1px_var(--ix-sel-ring)] data-[state=active]:bg-[var(--ix-sel-bg)] data-[state=active]:text-[var(--accent-text)] data-[state=active]:shadow-[inset_0_0_0_1px_var(--ix-sel-ring)]";
37
+ /** Underline tab: 2px green underline plus a faint tint, never a box; a faint underline on hover. */
38
+ const ixTabUnderline = "hover:shadow-[inset_0_-2px_0_hsl(var(--hsl-ring)/0.4)] data-[state=active]:bg-[hsl(var(--hsl-ring)/0.07)] data-[state=active]:text-[var(--accent-text)] data-[state=active]:shadow-[inset_0_-2px_0_var(--ix-sel-ring)] aria-checked:bg-[hsl(var(--hsl-ring)/0.07)] aria-checked:text-[var(--accent-text)] aria-checked:shadow-[inset_0_-2px_0_var(--ix-sel-ring)]";
39
+ /** List row / menu item: wash plus inset edge on hover or keyboard highlight; checked = selected. */
40
+ const ixRow = "hover:bg-[var(--ix-hover-bg)] hover:shadow-[inset_0_0_0_1px_var(--ix-hover-border)] data-[highlighted]:bg-[var(--ix-sel-bg)] data-[highlighted]:shadow-[inset_0_0_0_1px_var(--ix-hover-border)] focus:bg-[var(--ix-sel-bg)] data-[state=checked]:bg-[var(--ix-sel-bg)] data-[state=checked]:shadow-[inset_0_0_0_1px_var(--ix-sel-ring)] active:shadow-[inset_0_0_0_1px_hsl(var(--hsl-ring))]";
41
+ //#endregion
42
+ export { ixControl, ixControlAfter, ixControlSoft, ixField, ixRow, ixSelected, ixTabUnderline };
@@ -1,3 +1,4 @@
1
+ import { ixControl, ixControlSoft, ixSelected } from "../lib/interaction.js";
1
2
  import { focusRing } from "../lib/focus.js";
2
3
  import { cn } from "../lib/utils.js";
3
4
  import { controlHeight, controlMotion, controlRadius, controlSizes, controlSquare, controlText } from "../lib/control-presentation.js";
@@ -9,13 +10,13 @@ import { jsx, jsxs } from "react/jsx-runtime";
9
10
  const buttonVariants = cva(`inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-lg font-medium transition-[color,background-color,border-color,box-shadow,transform,scale] ${controlMotion} ${focusRing} disabled:pointer-events-none disabled:opacity-50 aria-disabled:cursor-not-allowed aria-disabled:opacity-50 motion-reduce:active:scale-100 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0`, {
10
11
  variants: {
11
12
  variant: {
12
- default: "bg-primary text-primary-foreground hover:bg-primary/90 active:scale-[0.97]",
13
- destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90 active:scale-[0.97]",
14
- outline: "border border-border bg-card hover:bg-muted active:scale-[0.97] text-foreground",
15
- secondary: "bg-muted border border-border text-foreground hover:bg-muted/80 active:scale-[0.97]",
16
- ghost: "hover:bg-muted hover:text-foreground text-muted-foreground border border-transparent",
17
- link: "text-[var(--accent-text)] underline-offset-4 hover:underline",
18
- sandbox: "bg-[var(--btn-primary-bg)] text-[var(--btn-primary-text)] border border-[var(--border-accent)] hover:bg-[var(--btn-primary-hover)] active:scale-[0.97]"
13
+ default: `bg-primary text-primary-foreground hover:bg-primary/90 active:scale-[0.97] ${ixControl}`,
14
+ destructive: `bg-destructive text-destructive-foreground hover:bg-destructive/90 active:scale-[0.97] ${ixControl}`,
15
+ outline: `border border-border bg-card hover:bg-muted active:scale-[0.97] text-foreground ${ixControl}`,
16
+ secondary: `bg-muted border border-border text-foreground hover:bg-muted/80 active:scale-[0.97] ${ixControl}`,
17
+ ghost: `hover:text-foreground text-muted-foreground border border-transparent ${ixControlSoft}`,
18
+ link: `text-[var(--accent-text)] underline-offset-4 hover:underline ${ixControlSoft}`,
19
+ sandbox: `bg-[var(--btn-primary-bg)] text-[var(--btn-primary-text)] border border-[var(--border-accent)] hover:bg-[var(--btn-primary-hover)] active:scale-[0.97] ${ixControl}`
19
20
  },
20
21
  size: {
21
22
  default: `${controlHeight.md} ${controlText.md} ${controlRadius.md} px-4 py-2`,
@@ -34,7 +35,15 @@ const buttonVariants = cva(`inline-flex items-center justify-center gap-2 whites
34
35
  size: "default"
35
36
  }
36
37
  });
37
- const bareButton = `${focusRing} disabled:pointer-events-none disabled:opacity-50 aria-disabled:cursor-not-allowed aria-disabled:opacity-50`;
38
+ const bareButton = `${focusRing} ${ixControlSoft} disabled:pointer-events-none disabled:opacity-50 aria-disabled:cursor-not-allowed aria-disabled:opacity-50`;
39
+ /** One Button render's classes: variant and size, the toggle states, then the caller's. */
40
+ function buttonClassName(variant, size, pressed, className) {
41
+ const toggle = pressed === void 0 ? void 0 : `${ixControl} ${ixSelected}`;
42
+ return variant === "bare" ? cn(bareButton, toggle, className) : cn(buttonVariants({
43
+ variant,
44
+ size
45
+ }), toggle, className);
46
+ }
38
47
  function preventActivation(event) {
39
48
  event.preventDefault();
40
49
  event.stopPropagation();
@@ -61,11 +70,7 @@ const Button = React.forwardRef(({ className, variant, size, asChild = false, lo
61
70
  const child = React.isValidElement(children) ? children : null;
62
71
  const isDisabled = disabled || loading || child?.props.disabled;
63
72
  return /* @__PURE__ */ jsx(Slot, {
64
- className: variant === "bare" ? cn(bareButton, className) : cn(buttonVariants({
65
- variant,
66
- size,
67
- className
68
- })),
73
+ className: buttonClassName(variant, size, props["aria-pressed"], className),
69
74
  ref,
70
75
  ...props,
71
76
  ...isDisabled ? disabledHandlers(props) : {},
@@ -84,11 +89,7 @@ const Button = React.forwardRef(({ className, variant, size, asChild = false, lo
84
89
  });
85
90
  }
86
91
  return /* @__PURE__ */ jsxs("button", {
87
- className: variant === "bare" ? cn(bareButton, className) : cn(buttonVariants({
88
- variant,
89
- size,
90
- className
91
- })),
92
+ className: buttonClassName(variant, size, props["aria-pressed"], className),
92
93
  ref,
93
94
  ...props,
94
95
  disabled: disabled || loading,
@@ -1,9 +1,22 @@
1
1
  import * as React from "react";
2
2
  //#region src/primitives/card.d.ts
3
+ /**
4
+ * A card is one level of the brand surface ladder. It carries
5
+ * `data-slot="card"`, and the brand's surface-context rule (tokens.css)
6
+ * re-declares `--card` and `--well` for everything inside it: a Card or a
7
+ * `bg-card` box inside a card paints the raised level, one inside that the
8
+ * raised-2 level, and a field in any of them takes the well that is the
9
+ * opposite step from its parent. Nesting needs no prop and no app selector.
10
+ */
3
11
  declare const Card: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & {
4
12
  variant?: "default" | "glass" | "sandbox" | "elevated";
5
- /** Decorative border feedback only. Put actions in a native button or link. */
13
+ /** Decorative hover feedback only (the shared green edge). Put actions in a native button or link. */
6
14
  hover?: boolean;
15
+ /**
16
+ * The card is itself the control, such as a card wrapped in a link: it takes
17
+ * the full control states (hover glow, press, the ring after a click).
18
+ */
19
+ interactive?: boolean;
7
20
  } & React.RefAttributes<HTMLDivElement>>;
8
21
  declare const CardHeader: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
9
22
  export interface CardTitleProps extends React.HTMLAttributes<HTMLHeadingElement> {
@@ -1,17 +1,27 @@
1
+ import "../lib/interaction.js";
1
2
  import { cn } from "../lib/utils.js";
2
3
  import { Heading } from "./heading.js";
3
4
  import * as React from "react";
4
5
  import { jsx } from "react/jsx-runtime";
5
6
  //#region src/primitives/card.tsx
6
- const Card = React.forwardRef(({ className, variant = "default", hover = false, ...props }, ref) => {
7
+ /**
8
+ * A card is one level of the brand surface ladder. It carries
9
+ * `data-slot="card"`, and the brand's surface-context rule (tokens.css)
10
+ * re-declares `--card` and `--well` for everything inside it: a Card or a
11
+ * `bg-card` box inside a card paints the raised level, one inside that the
12
+ * raised-2 level, and a field in any of them takes the well that is the
13
+ * opposite step from its parent. Nesting needs no prop and no app selector.
14
+ */
15
+ const Card = React.forwardRef(({ className, variant = "default", hover = false, interactive = false, ...props }, ref) => {
7
16
  return /* @__PURE__ */ jsx("div", {
8
17
  ref,
9
- className: cn("rounded-[var(--radius-lg)] border text-card-foreground transition-[border-color,box-shadow]", "duration-[var(--transition-default)]", {
10
- default: "bg-card border-border",
18
+ className: cn("rounded-[var(--radius-lg)] border text-card-foreground transition-[border-color,box-shadow,background-color]", "duration-[var(--transition-default)]", {
19
+ default: "bg-card border-border shadow-[var(--edge-highlight),var(--shadow-card)]",
11
20
  elevated: "bg-muted/50 border-border shadow-[var(--shadow-card)]",
12
21
  glass: "bg-card/80 backdrop-blur-xl border-border shadow-[var(--shadow-card)]",
13
22
  sandbox: "bg-muted/50 border-primary/20 shadow-[var(--shadow-accent)]"
14
- }[variant], hover && "hover:border-[var(--border-strong)]", className),
23
+ }[variant], (hover || interactive) && "hover:border-[var(--ix-hover-border)] hover:shadow-[var(--ix-hover)] focus:not-focus-visible:border-[var(--ix-hover-border)] focus:not-focus-visible:shadow-[var(--ix-after)] active:border-[hsl(var(--hsl-ring))] active:shadow-[var(--ix-press)] focus-visible:shadow-none", className),
24
+ "data-slot": "card",
15
25
  ...props
16
26
  });
17
27
  });
@@ -32,7 +42,7 @@ const CardTitle = React.forwardRef(({ className, as = "h3", ...props }, ref) =>
32
42
  CardTitle.displayName = "CardTitle";
33
43
  const CardDescription = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("p", {
34
44
  ref,
35
- className: cn("text-muted-foreground text-sm", className),
45
+ className: cn("text-muted-foreground text-sm line-clamp-2", className),
36
46
  ...props
37
47
  }));
38
48
  CardDescription.displayName = "CardDescription";
@@ -1,3 +1,4 @@
1
+ import { ixRow } from "../lib/interaction.js";
1
2
  import { cn } from "../lib/utils.js";
2
3
  import * as React from "react";
3
4
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -12,33 +13,33 @@ const DropdownMenuSub = DropdownMenuPrimitive.Sub;
12
13
  const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
13
14
  const DropdownMenuSubTrigger = React.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ jsxs(DropdownMenuPrimitive.SubTrigger, {
14
15
  ref,
15
- className: cn("flex cursor-default select-none items-center rounded-md px-2 py-1.5 text-sm outline-none", "focus:bg-accent data-[state=open]:bg-muted/50", inset && "pl-8", className),
16
+ className: cn("flex cursor-default select-none items-center rounded-md px-2 py-1.5 text-sm outline-none transition-[color,background-color,box-shadow]", "data-[state=open]:bg-[var(--ix-sel-bg)]", ixRow, inset && "pl-8", className),
16
17
  ...props,
17
18
  children: [children, /* @__PURE__ */ jsx(ChevronRight, { className: "ml-auto h-4 w-4" })]
18
19
  }));
19
20
  DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
20
21
  const DropdownMenuSubContent = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(DropdownMenuPrimitive.SubContent, {
21
22
  ref,
22
- className: cn("z-50 min-w-[8rem] overflow-hidden rounded-xl border border-border bg-card p-1 text-foreground shadow-[var(--shadow-card)]", "data-[state=closed]:animate-out data-[state=open]:animate-in", "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95", "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2", "data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", className),
23
+ className: cn("z-50 min-w-[8rem] overflow-hidden rounded-xl border border-border bg-popover p-1 text-popover-foreground shadow-[var(--edge-highlight),var(--shadow-card)]", "data-[state=closed]:animate-out data-[state=open]:animate-in", "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95", "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2", "data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", className),
23
24
  ...props
24
25
  }));
25
26
  DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
26
27
  const DropdownMenuContent = React.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(DropdownMenuPrimitive.Content, {
27
28
  ref,
28
29
  sideOffset,
29
- className: cn("z-50 min-w-[8rem] overflow-hidden rounded-xl border border-border bg-card p-1 text-foreground shadow-[var(--shadow-card)]", "data-[state=closed]:animate-out data-[state=open]:animate-in", "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95", "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2", "data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", className),
30
+ className: cn("z-50 min-w-[8rem] overflow-hidden rounded-xl border border-border bg-popover p-1 text-popover-foreground shadow-[var(--edge-highlight),var(--shadow-card)]", "data-[state=closed]:animate-out data-[state=open]:animate-in", "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95", "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2", "data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", className),
30
31
  ...props
31
32
  }) }));
32
33
  DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
33
34
  const DropdownMenuItem = React.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx(DropdownMenuPrimitive.Item, {
34
35
  ref,
35
- className: cn("relative flex cursor-pointer select-none items-center rounded-md px-2 py-1.5 text-sm outline-none transition-colors", "focus:bg-muted/50 focus:text-foreground", "data-[disabled]:pointer-events-none data-[disabled]:opacity-50", inset && "pl-8", className),
36
+ className: cn("relative flex cursor-pointer select-none items-center rounded-md px-2 py-1.5 text-sm outline-none transition-[color,background-color,box-shadow]", "focus:text-foreground", ixRow, "data-[disabled]:pointer-events-none data-[disabled]:opacity-50", inset && "pl-8", className),
36
37
  ...props
37
38
  }));
38
39
  DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
39
40
  const DropdownMenuCheckboxItem = React.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ jsxs(DropdownMenuPrimitive.CheckboxItem, {
40
41
  ref,
41
- className: cn("relative flex cursor-pointer select-none items-center rounded-md py-1.5 pr-2 pl-8 text-sm outline-none transition-colors", "focus:bg-muted/50 focus:text-foreground", "data-[disabled]:pointer-events-none data-[disabled]:opacity-50", className),
42
+ className: cn("relative flex cursor-pointer select-none items-center rounded-md py-1.5 pr-2 pl-8 text-sm outline-none transition-[color,background-color,box-shadow]", "focus:text-foreground", ixRow, "data-[disabled]:pointer-events-none data-[disabled]:opacity-50", className),
42
43
  checked,
43
44
  ...props,
44
45
  children: [/* @__PURE__ */ jsx("span", {
@@ -49,7 +50,7 @@ const DropdownMenuCheckboxItem = React.forwardRef(({ className, children, checke
49
50
  DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
50
51
  const DropdownMenuRadioItem = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(DropdownMenuPrimitive.RadioItem, {
51
52
  ref,
52
- className: cn("relative flex cursor-pointer select-none items-center rounded-md py-1.5 pr-2 pl-8 text-sm outline-none transition-colors", "focus:bg-muted/50 focus:text-foreground", "data-[disabled]:pointer-events-none data-[disabled]:opacity-50", className),
53
+ className: cn("relative flex cursor-pointer select-none items-center rounded-md py-1.5 pr-2 pl-8 text-sm outline-none transition-[color,background-color,box-shadow]", "focus:text-foreground", ixRow, "data-[disabled]:pointer-events-none data-[disabled]:opacity-50", className),
53
54
  ...props,
54
55
  children: [/* @__PURE__ */ jsx("span", {
55
56
  className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center",
@@ -12,7 +12,11 @@ import * as React from "react";
12
12
  * console warning fires when both are omitted.
13
13
  *
14
14
  * Design rules baked into the default variant:
15
- * - Only the SELECTED segment shows a surface colour + accent text.
15
+ * - The row track is a field well (`--well`, `--field-border`), so the
16
+ * control reads as one inset group on whatever plane it sits on.
17
+ * - Only the SELECTED segment shows a surface colour + accent text: the
18
+ * shared selected state (`ixSelected`: tint plus an inset ring). A tab
19
+ * shows it as an underline instead (`ixTabUnderline`).
16
20
  * - Unselected segments have NO background — they're plain-text labels
17
21
  * that darken on hover. This keeps the selected segment as the
18
22
  * single visual anchor instead of the whole group competing with
@@ -1,4 +1,5 @@
1
1
  "use client";
2
+ import "../lib/interaction.js";
2
3
  import { focusRing, focusRingInset } from "../lib/focus.js";
3
4
  import { cn } from "../lib/utils.js";
4
5
  import "../lib/control-presentation.js";
@@ -83,7 +84,7 @@ function SegmentedControl({ value, onValueChange, options, variant = "row", clas
83
84
  ref: stripRef,
84
85
  onKeyDown: handleKeyDown,
85
86
  onScroll: tabs ? measureOverflow : void 0,
86
- className: cn("flex gap-1", variant === "row" && "flex-wrap items-center rounded-lg border border-border bg-card p-1", variant === "tabs" && ["relative flex-nowrap items-end border-b border-border pb-0 overflow-x-auto", tabEdgeFade], className),
87
+ className: cn("flex gap-1", variant === "row" && "flex-wrap items-center rounded-lg border border-[var(--field-border)] bg-[var(--well)] p-1", variant === "tabs" && ["relative flex-nowrap items-end border-b border-border pb-0 overflow-x-auto", tabEdgeFade], className),
87
88
  children: options.map((option, i) => {
88
89
  const active = option.value === value;
89
90
  const focusable = active || !hasMatch && i === 0;
@@ -100,11 +101,17 @@ function SegmentedControl({ value, onValueChange, options, variant = "row", clas
100
101
  onClick: () => {
101
102
  if (!active) onValueChange(option.value);
102
103
  },
103
- className: cn("relative inline-flex items-center gap-2 whitespace-nowrap text-sm font-medium transition-[color,background-color,border-color,box-shadow]", variant === "row" && ["rounded-md px-3 py-1.5", focusRing], variant === "tabs" && [
104
- "shrink-0 rounded-none border-b-2 -mb-px px-4 py-2",
104
+ className: cn("relative inline-flex items-center gap-2 whitespace-nowrap text-sm font-medium transition-[color,background-color,border-color,box-shadow]", variant === "row" && [
105
+ "rounded-md border border-transparent px-3 py-1.5",
106
+ focusRing,
107
+ "hover:bg-[var(--ix-hover-bg)] active:bg-[var(--ix-sel-bg)]",
108
+ "aria-pressed:bg-[var(--ix-sel-bg)] aria-pressed:text-[var(--accent-text)] aria-pressed:shadow-[inset_0_0_0_1px_var(--ix-sel-ring)] aria-checked:bg-[var(--ix-sel-bg)] aria-checked:text-[var(--accent-text)] aria-checked:shadow-[inset_0_0_0_1px_var(--ix-sel-ring)] aria-[current=page]:bg-[var(--ix-sel-bg)] aria-[current=page]:text-[var(--accent-text)] aria-[current=page]:shadow-[inset_0_0_0_1px_var(--ix-sel-ring)] data-[state=on]:bg-[var(--ix-sel-bg)] data-[state=on]:shadow-[inset_0_0_0_1px_var(--ix-sel-ring)] data-[state=active]:bg-[var(--ix-sel-bg)] data-[state=active]:text-[var(--accent-text)] data-[state=active]:shadow-[inset_0_0_0_1px_var(--ix-sel-ring)]"
109
+ ], variant === "tabs" && [
110
+ "shrink-0 rounded-none border-b-2 border-transparent -mb-px px-4 py-2",
105
111
  "pointer-coarse:min-h-11",
106
- focusRingInset
107
- ], active ? variant === "row" ? "border border-transparent bg-[var(--accent-surface)] text-[var(--accent-text)]" : "border-[var(--accent-text)] text-[var(--accent-text)]" : variant === "row" ? "border border-transparent text-muted-foreground hover:text-foreground" : "border-transparent text-muted-foreground hover:text-foreground"),
112
+ focusRingInset,
113
+ "hover:shadow-[inset_0_-2px_0_hsl(var(--hsl-ring)/0.4)] data-[state=active]:bg-[hsl(var(--hsl-ring)/0.07)] data-[state=active]:text-[var(--accent-text)] data-[state=active]:shadow-[inset_0_-2px_0_var(--ix-sel-ring)] aria-checked:bg-[hsl(var(--hsl-ring)/0.07)] aria-checked:text-[var(--accent-text)] aria-checked:shadow-[inset_0_-2px_0_var(--ix-sel-ring)]"
114
+ ], active ? "text-[var(--accent-text)]" : "text-muted-foreground hover:text-foreground"),
108
115
  children: [/* @__PURE__ */ jsx("span", { children: option.label }), option.adornment && /* @__PURE__ */ jsx("span", {
109
116
  className: cn("text-xs", active ? "text-[var(--accent-text)]/80" : "text-muted-foreground"),
110
117
  children: option.adornment
@@ -1,4 +1,5 @@
1
1
  "use client";
2
+ import { ixControlAfter, ixRow } from "../lib/interaction.js";
2
3
  import { cn } from "../lib/utils.js";
3
4
  import { controlSizes, fieldPresentation, fieldSizes, fieldTouchText } from "../lib/control-presentation.js";
4
5
  import * as React from "react";
@@ -11,7 +12,7 @@ const SelectGroup = SelectPrimitive.Group;
11
12
  const SelectValue = SelectPrimitive.Value;
12
13
  const SelectTrigger = React.forwardRef(({ className, children, size = "default", ...props }, ref) => /* @__PURE__ */ jsxs(SelectPrimitive.Trigger, {
13
14
  ref,
14
- className: cn("flex w-full items-center justify-between gap-2 whitespace-nowrap border py-1 shadow-sm placeholder:text-[var(--text-dim)] disabled:cursor-not-allowed disabled:opacity-50", fieldPresentation, fieldTouchText, "data-[placeholder]:text-[var(--text-dim)] [&>span]:min-w-0 [&>span]:truncate [&>span]:text-left", "data-[state=open]:border-primary data-[state=open]:bg-[var(--accent-surface-strong)] [&[data-state=open]>svg]:rotate-180 [&>svg]:transition-transform", size === "compact" || size === "touch" ? cn(fieldSizes.md, controlSizes[size]) : fieldSizes[size === "default" ? "md" : size], className),
15
+ className: cn("flex w-full items-center justify-between gap-2 whitespace-nowrap border py-1 placeholder:text-[var(--text-dim)] disabled:cursor-not-allowed disabled:opacity-50", fieldPresentation, ixControlAfter, fieldTouchText, "data-[placeholder]:text-[var(--text-dim)] [&>span]:min-w-0 [&>span]:truncate [&>span]:text-left", "data-[state=open]:border-[var(--ix-hover-border)] data-[state=open]:shadow-[var(--ix-after)] [&[data-state=open]>svg]:rotate-180 [&>svg]:transition-transform", size === "compact" || size === "touch" ? cn(fieldSizes.md, controlSizes[size]) : fieldSizes[size === "default" ? "md" : size], className),
15
16
  ...props,
16
17
  children: [children, /* @__PURE__ */ jsx(SelectPrimitive.Icon, {
17
18
  asChild: true,
@@ -35,7 +36,7 @@ const SelectScrollDownButton = React.forwardRef(({ className, ...props }, ref) =
35
36
  SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
36
37
  const SelectContent = React.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(SelectPrimitive.Content, {
37
38
  ref,
38
- className: cn("data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-lg border border-border bg-card text-foreground shadow-[var(--shadow-dropdown)] data-[state=closed]:animate-out data-[state=open]:animate-in", position === "popper" && "data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=bottom]:translate-y-1 data-[side=top]:-translate-y-1", className),
39
+ className: cn("data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-lg border border-border bg-popover text-popover-foreground shadow-[var(--edge-highlight),var(--shadow-card)] data-[state=closed]:animate-out data-[state=open]:animate-in", position === "popper" && "data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=bottom]:translate-y-1 data-[side=top]:-translate-y-1", className),
39
40
  position,
40
41
  ...props,
41
42
  children: [
@@ -56,7 +57,7 @@ const SelectLabel = React.forwardRef(({ className, ...props }, ref) => /* @__PUR
56
57
  SelectLabel.displayName = SelectPrimitive.Label.displayName;
57
58
  const SelectItem = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(SelectPrimitive.Item, {
58
59
  ref,
59
- className: cn("relative flex w-full cursor-default select-none items-center rounded-md py-1.5 pr-8 pl-2 text-sm outline-none transition-colors focus:bg-[var(--accent-surface-strong)] focus:text-foreground data-[state=checked]:bg-[var(--accent-surface-strong)] data-[state=checked]:font-medium data-[disabled]:pointer-events-none data-[disabled]:opacity-50", className),
60
+ className: cn("relative flex w-full cursor-default select-none items-center rounded-md py-1.5 pr-8 pl-2 text-sm outline-none transition-[color,background-color,box-shadow] focus:text-foreground data-[state=checked]:font-medium data-[disabled]:pointer-events-none data-[disabled]:opacity-50", ixRow, className),
60
61
  ...props,
61
62
  children: [/* @__PURE__ */ jsx("span", {
62
63
  className: "absolute right-2 flex h-3.5 w-3.5 items-center justify-center",
@@ -1,3 +1,4 @@
1
+ import { ixControlSoft, ixSelected, ixTabUnderline } from "../lib/interaction.js";
1
2
  import { focusRing } from "../lib/focus.js";
2
3
  import { cn } from "../lib/utils.js";
3
4
  import * as React from "react";
@@ -19,9 +20,9 @@ const TabsList = React.forwardRef(({ className, variant = "default", ...props },
19
20
  TabsList.displayName = TabsPrimitive.List.displayName;
20
21
  const TabsTrigger = React.forwardRef(({ className, variant = "default", ...props }, ref) => {
21
22
  const variants = {
22
- default: `inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1.5 text-sm font-medium transition-all ${focusRing} disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm`,
23
- pills: `inline-flex items-center justify-center whitespace-nowrap rounded-full px-4 py-2 text-sm font-medium transition-all ${focusRing} disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-primary data-[state=active]:text-primary-foreground data-[state=inactive]:text-muted-foreground data-[state=inactive]:hover:bg-muted`,
24
- underline: `inline-flex items-center justify-center whitespace-nowrap rounded-t-md pb-3 text-sm font-medium transition-all ${focusRing} disabled:pointer-events-none disabled:opacity-50 border-b-2 border-transparent data-[state=active]:border-primary data-[state=active]:text-foreground data-[state=inactive]:text-muted-foreground`
23
+ default: `inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1.5 text-sm font-medium transition-all ${focusRing} disabled:pointer-events-none disabled:opacity-50 ${ixControlSoft} ${ixSelected}`,
24
+ pills: `inline-flex items-center justify-center whitespace-nowrap rounded-full px-4 py-2 text-sm font-medium transition-all ${focusRing} disabled:pointer-events-none disabled:opacity-50 data-[state=inactive]:text-muted-foreground ${ixControlSoft} ${ixSelected}`,
25
+ underline: `inline-flex items-center justify-center whitespace-nowrap rounded-t-md pb-3 text-sm font-medium transition-all ${focusRing} disabled:pointer-events-none disabled:opacity-50 border-b-2 border-transparent data-[state=inactive]:text-muted-foreground ${ixTabUnderline}`
25
26
  };
26
27
  return /* @__PURE__ */ jsx(TabsPrimitive.Trigger, {
27
28
  ref,
@@ -5,6 +5,7 @@ import { Markdown } from "../markdown/markdown.js";
5
5
  import { InlineThinkingItem } from "./inline-thinking-item.js";
6
6
  import { SyntheticText } from "../chat/synthetic-text.js";
7
7
  import { OpenUIArtifactRenderer } from "../openui/openui-artifact-renderer.js";
8
+ import { TRANSCRIPT_TEXT } from "../chat/transcript-text.js";
8
9
  import { memo, useMemo } from "react";
9
10
  import { jsx, jsxs } from "react/jsx-runtime";
10
11
  import { Bot, ChevronDown, ChevronRight, ClipboardList, FileEdit, FileSearch, Globe, Loader2, PencilLine, Search, Settings, Sparkles, Terminal } from "lucide-react";
@@ -254,7 +255,7 @@ const RunGroup = memo(({ run, partMap, collapsed, onToggle, branding = DEFAULT_B
254
255
  if (part.type === "text" && !part.synthetic && part.text.trim()) return /* @__PURE__ */ jsx("div", {
255
256
  className: "px-0.5",
256
257
  children: /* @__PURE__ */ jsx(Markdown, {
257
- className: "tangle-prose text-[15px] leading-7 text-[var(--text-primary)]",
258
+ className: `tangle-prose ${TRANSCRIPT_TEXT} text-[var(--text-primary)]`,
258
259
  children: part.text
259
260
  })
260
261
  }, key);
@@ -364,7 +365,7 @@ const RunGroup = memo(({ run, partMap, collapsed, onToggle, branding = DEFAULT_B
364
365
  else if (part.type === "text" && part.text.trim()) node = part.synthetic ? /* @__PURE__ */ jsx(SyntheticText, { text: part.text }) : /* @__PURE__ */ jsx("div", {
365
366
  className: "px-1 py-0.5",
366
367
  children: /* @__PURE__ */ jsx(Markdown, {
367
- className: "tangle-prose text-[15px] leading-7",
368
+ className: `tangle-prose ${TRANSCRIPT_TEXT}`,
368
369
  children: part.text
369
370
  })
370
371
  });