@molecule/app-ide-react 1.17.1 → 1.18.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.
- package/dist/components/ActivityCard.d.ts.map +1 -1
- package/dist/components/ActivityCard.js +5 -1
- package/dist/components/ActivityCard.js.map +1 -1
- package/dist/components/AutoCommitBadge.d.ts +6 -4
- package/dist/components/AutoCommitBadge.d.ts.map +1 -1
- package/dist/components/AutoCommitBadge.js +13 -36
- package/dist/components/AutoCommitBadge.js.map +1 -1
- package/dist/components/BackgroundTasksStrip.d.ts +17 -0
- package/dist/components/BackgroundTasksStrip.d.ts.map +1 -0
- package/dist/components/BackgroundTasksStrip.js +56 -0
- package/dist/components/BackgroundTasksStrip.js.map +1 -0
- package/dist/components/ChatPanel.d.ts.map +1 -1
- package/dist/components/ChatPanel.js +179 -206
- package/dist/components/ChatPanel.js.map +1 -1
- package/dist/components/DeviceFrameSelector.d.ts.map +1 -1
- package/dist/components/DeviceFrameSelector.js +12 -2
- package/dist/components/DeviceFrameSelector.js.map +1 -1
- package/dist/components/FileExplorer.d.ts.map +1 -1
- package/dist/components/FileExplorer.js +11 -8
- package/dist/components/FileExplorer.js.map +1 -1
- package/dist/components/FileExplorerContextMenu.d.ts.map +1 -1
- package/dist/components/FileExplorerContextMenu.js +4 -1
- package/dist/components/FileExplorerContextMenu.js.map +1 -1
- package/dist/components/HelpCard.d.ts.map +1 -1
- package/dist/components/HelpCard.js +5 -1
- package/dist/components/HelpCard.js.map +1 -1
- package/dist/components/KeyboardShortcutsPanel.d.ts.map +1 -1
- package/dist/components/KeyboardShortcutsPanel.js +31 -9
- package/dist/components/KeyboardShortcutsPanel.js.map +1 -1
- package/dist/components/MarkdownContent.d.ts.map +1 -1
- package/dist/components/MarkdownContent.js +10 -7
- package/dist/components/MarkdownContent.js.map +1 -1
- package/dist/components/PreviewPanel.d.ts.map +1 -1
- package/dist/components/PreviewPanel.js +52 -27
- package/dist/components/PreviewPanel.js.map +1 -1
- package/dist/components/QuickPicker.d.ts.map +1 -1
- package/dist/components/QuickPicker.js +11 -4
- package/dist/components/QuickPicker.js.map +1 -1
- package/dist/components/RelevantSkillSuggestion.d.ts.map +1 -1
- package/dist/components/RelevantSkillSuggestion.js +24 -7
- package/dist/components/RelevantSkillSuggestion.js.map +1 -1
- package/dist/components/ReportModal.d.ts.map +1 -1
- package/dist/components/ReportModal.js +4 -1
- package/dist/components/ReportModal.js.map +1 -1
- package/dist/components/ScriptsCard.d.ts.map +1 -1
- package/dist/components/ScriptsCard.js +6 -4
- package/dist/components/ScriptsCard.js.map +1 -1
- package/dist/components/SearchPanel.d.ts.map +1 -1
- package/dist/components/SearchPanel.js +65 -54
- package/dist/components/SearchPanel.js.map +1 -1
- package/dist/components/SettingsCard.d.ts.map +1 -1
- package/dist/components/SettingsCard.js +1 -1
- package/dist/components/SettingsCard.js.map +1 -1
- package/dist/components/ShareLinkManager.d.ts.map +1 -1
- package/dist/components/ShareLinkManager.js +5 -5
- package/dist/components/ShareLinkManager.js.map +1 -1
- package/dist/components/ShareModal.js +1 -1
- package/dist/components/ShareModal.js.map +1 -1
- package/dist/components/SidebarTabs.d.ts.map +1 -1
- package/dist/components/SidebarTabs.js +7 -5
- package/dist/components/SidebarTabs.js.map +1 -1
- package/dist/components/SkillsCard.d.ts.map +1 -1
- package/dist/components/SkillsCard.js +15 -7
- package/dist/components/SkillsCard.js.map +1 -1
- package/dist/components/TabBar.d.ts.map +1 -1
- package/dist/components/TabBar.js +11 -6
- package/dist/components/TabBar.js.map +1 -1
- package/dist/components/TestsCard.js +4 -4
- package/dist/components/TestsCard.js.map +1 -1
- package/dist/components/TipCard.d.ts.map +1 -1
- package/dist/components/TipCard.js +6 -2
- package/dist/components/TipCard.js.map +1 -1
- package/dist/components/ToolCallCard.d.ts.map +1 -1
- package/dist/components/ToolCallCard.js +89 -46
- package/dist/components/ToolCallCard.js.map +1 -1
- package/dist/components/UserAvatar.d.ts.map +1 -1
- package/dist/components/UserAvatar.js +9 -1
- package/dist/components/UserAvatar.js.map +1 -1
- package/dist/components/tool-call-utilities.d.ts.map +1 -1
- package/dist/components/tool-call-utilities.js +46 -2
- package/dist/components/tool-call-utilities.js.map +1 -1
- package/package.json +3 -3
|
@@ -16,8 +16,9 @@ import { useCoarsePointer, useNarrowViewport } from '../hooks/useViewport.js';
|
|
|
16
16
|
import { activityFromEvent } from './activity-utilities.js';
|
|
17
17
|
import { ActivityCard } from './ActivityCard.js';
|
|
18
18
|
import { AutoCommitBadge } from './AutoCommitBadge.js';
|
|
19
|
+
import { BackgroundTasksStrip } from './BackgroundTasksStrip.js';
|
|
19
20
|
import { AUTO_COMMIT_DISABLED, autoCommitReducer, isAutoCommitArmed, isAutoCommitDue, isAutoCommitEnabled, parseAutoCommitCommand, resolveAutoCommitSeconds, } from './chat-autocommit-utilities.js';
|
|
20
|
-
import { CHAT_CARD_ICON_SIZE,
|
|
21
|
+
import { CHAT_CARD_ICON_SIZE, chatCardStyle } from './chat-card-style.js';
|
|
21
22
|
import { COMMAND_CATEGORIES, COMMANDS, matchesSideChannelCommand, } from './chat-commands.js';
|
|
22
23
|
import { stripCommitCoauthorTrailer } from './chat-commit-utilities.js';
|
|
23
24
|
import { cachedPromptTokens, formatTokenTotal } from './chat-cost-utilities.js';
|
|
@@ -477,7 +478,9 @@ function ThinkingBlock({ content, durationMs, isStreaming, }) {
|
|
|
477
478
|
: durationMs != null
|
|
478
479
|
? formatThinkingDuration(durationMs)
|
|
479
480
|
: t('ide.chat.thoughtBriefly', undefined, { defaultValue: 'Thought briefly' });
|
|
480
|
-
return (_jsxs("div", { style: { marginBottom: '6px' }, children: [_jsxs("button", {
|
|
481
|
+
return (_jsxs("div", { style: { marginBottom: '6px' }, children: [_jsxs("button", {
|
|
482
|
+
/* mol-bespoke-button: thinking disclosure toggle — chevron + muted label, a summary/details affordance with no button frame */
|
|
483
|
+
type: "button", onClick: () => setManualToggle((v) => !(v ?? isStreaming === true)), style: {
|
|
481
484
|
display: 'inline-flex',
|
|
482
485
|
alignItems: 'center',
|
|
483
486
|
gap: '4px',
|
|
@@ -586,7 +589,9 @@ function CollapsibleUserMessage({ content, isLight, }) {
|
|
|
586
589
|
? 'linear-gradient(transparent, var(--mol-color-surface-secondary, #f5f5f5))'
|
|
587
590
|
: 'linear-gradient(transparent, var(--mol-color-surface-secondary, #1e1e1e))',
|
|
588
591
|
pointerEvents: 'none',
|
|
589
|
-
} })), overflows && (_jsx("button", {
|
|
592
|
+
} })), overflows && (_jsx("button", {
|
|
593
|
+
/* mol-bespoke-button: overflow disclosure strip — full-width unlabelled chevron that expands a clipped card */
|
|
594
|
+
type: "button", onClick: () => setExpanded((v) => !v), onMouseEnter: (e) => {
|
|
590
595
|
;
|
|
591
596
|
e.currentTarget.style.background = isLight
|
|
592
597
|
? 'rgba(99,102,241,0.12)'
|
|
@@ -675,7 +680,9 @@ function VerificationBadge({ status, output, categories, }) {
|
|
|
675
680
|
border: `1px solid ${borderColor}`,
|
|
676
681
|
background: bgColor,
|
|
677
682
|
overflow: 'hidden',
|
|
678
|
-
}, children: [_jsxs("button", {
|
|
683
|
+
}, children: [_jsxs("button", {
|
|
684
|
+
/* mol-bespoke-button: verify-error card header — the card's own expand/collapse header, tinted by severity; a disclosure, not an action */
|
|
685
|
+
type: "button", onClick: () => setExpanded((v) => !v), className: cm.cn(cm.textSize('xs'), cm.w('full')), style: {
|
|
679
686
|
display: 'flex',
|
|
680
687
|
alignItems: 'center',
|
|
681
688
|
gap: 6,
|
|
@@ -719,10 +726,26 @@ const NOTICE_TONE = {
|
|
|
719
726
|
success: { accent: '#3fb950', icon: 'check-circle' },
|
|
720
727
|
signup: { accent: 'var(--mol-color-primary, #6366f1)', icon: 'sign-in' },
|
|
721
728
|
};
|
|
729
|
+
/**
|
|
730
|
+
* The SEMANTIC button colour each notice tone falls back to when the host gives
|
|
731
|
+
* an action no explicit `color`. Every notice-card action is a design-system
|
|
732
|
+
* button; this is only about which semantic it takes when the caller did not
|
|
733
|
+
* say. Without it a coloured action and a colourless one rendered side by side
|
|
734
|
+
* in the SAME card with two different box models (13px/3px vs a hand-rolled
|
|
735
|
+
* 12px/6px) — the exact mismatch this treatment exists to prevent.
|
|
736
|
+
*/
|
|
737
|
+
const NOTICE_TONE_BUTTON_COLOR = {
|
|
738
|
+
info: 'primary',
|
|
739
|
+
gold: 'warning',
|
|
740
|
+
upgrade: 'warning',
|
|
741
|
+
success: 'success',
|
|
742
|
+
signup: 'primary',
|
|
743
|
+
};
|
|
722
744
|
/**
|
|
723
745
|
* The single shared notice-card treatment: a matched-weight accent {@link Icon},
|
|
724
|
-
* an optional composable body (or plain text), and a left-aligned row of
|
|
725
|
-
*
|
|
746
|
+
* an optional composable body (or plain text), and a left-aligned row of
|
|
747
|
+
* design-system action buttons (`cm.button`, `sm`) whose semantic colour comes
|
|
748
|
+
* from the action or, failing that, the tone. EVERY inline notice renders through this — the system
|
|
726
749
|
* tip/notice cards AND the resource-limit / upgrade banners (see
|
|
727
750
|
* {@link ResourceLimitBanner}) — so their icon + buttons can never drift apart
|
|
728
751
|
* again. The host owns the button routes/copy; it passes them in as `action`.
|
|
@@ -732,24 +755,13 @@ const NOTICE_TONE = {
|
|
|
732
755
|
*/
|
|
733
756
|
function NoticeCard({ tone, text, content, action, icon: iconOverride, }) {
|
|
734
757
|
const cm = getClassMap();
|
|
735
|
-
const isCoarse = useCoarsePointer();
|
|
736
758
|
const { accent, icon: defaultIcon } = NOTICE_TONE[tone];
|
|
737
759
|
const icon = iconOverride ?? defaultIcon;
|
|
738
760
|
const actions = action ? (Array.isArray(action) ? action : [action]) : [];
|
|
739
761
|
const multiLine = (text ?? '').includes('\n');
|
|
740
|
-
//
|
|
741
|
-
//
|
|
742
|
-
|
|
743
|
-
const buttonBg = 'var(--mol-color-surface, transparent)';
|
|
744
|
-
const buttonHoverBg = `color-mix(in srgb, ${accent} 15%, var(--mol-color-surface, transparent))`;
|
|
745
|
-
const onEnter = (e) => {
|
|
746
|
-
;
|
|
747
|
-
e.currentTarget.style.background = buttonHoverBg;
|
|
748
|
-
};
|
|
749
|
-
const onLeave = (e) => {
|
|
750
|
-
;
|
|
751
|
-
e.currentTarget.style.background = buttonBg;
|
|
752
|
-
};
|
|
762
|
+
// The semantic colour an action takes when the host did not name one, so every
|
|
763
|
+
// action on the card renders the same design-system button.
|
|
764
|
+
const defaultActionColor = NOTICE_TONE_BUTTON_COLOR[tone];
|
|
753
765
|
return (_jsxs("div", { "data-mol-id": "chat-notice-card", "data-tone": tone, className: cm.textSize('xs'), style: {
|
|
754
766
|
display: 'flex',
|
|
755
767
|
alignItems: 'flex-start',
|
|
@@ -758,41 +770,20 @@ function NoticeCard({ tone, text, content, action, icon: iconOverride, }) {
|
|
|
758
770
|
...chatCardStyle(accent),
|
|
759
771
|
lineHeight: 1.5,
|
|
760
772
|
}, children: [_jsx(Icon, { name: icon, size: CHAT_CARD_ICON_SIZE, "aria-hidden": "true", style: { flexShrink: 0, marginTop: 1, color: accent } }), _jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [content ? (content.map((seg, i) => renderCardSegment(seg, i))) : (_jsx("span", { style: multiLine ? { whiteSpace: 'pre-wrap' } : undefined, children: text })), !content && actions.length > 0 && (_jsx("div", { style: { display: 'flex', flexWrap: 'wrap', gap: 8, marginTop: 8 }, children: actions.map((act, i) => {
|
|
761
|
-
//
|
|
762
|
-
//
|
|
763
|
-
//
|
|
764
|
-
//
|
|
765
|
-
//
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
textDecoration: 'none',
|
|
772
|
-
fontFamily: act.code ? 'var(--mol-font-mono, monospace)' : 'inherit',
|
|
773
|
-
};
|
|
774
|
-
return act.href ? (_jsx("a", { href: act.href, target: act.href.startsWith('http') ? '_blank' : undefined, rel: act.href.startsWith('http') ? 'noopener noreferrer' : undefined, className: className, style: coloredStyle, children: act.label }, i)) : (_jsx("button", { type: "button", onClick: act.onClick, className: className, style: coloredStyle, children: act.label }, i));
|
|
775
|
-
}
|
|
776
|
-
const style = {
|
|
777
|
-
display: 'inline-flex',
|
|
778
|
-
alignItems: 'center',
|
|
779
|
-
fontSize: 12,
|
|
780
|
-
fontWeight: 600,
|
|
781
|
-
padding: '4px 10px',
|
|
782
|
-
// Secondary inline actions: 36px is the touch floor agreed for
|
|
783
|
-
// these (44 would overwhelm the compact card).
|
|
784
|
-
...(isCoarse ? { minHeight: 36 } : {}),
|
|
785
|
-
borderRadius: 6,
|
|
786
|
-
cursor: 'pointer',
|
|
773
|
+
// EVERY action is a REAL design-system button (`cm.button`, sm) so the
|
|
774
|
+
// same CTA looks identical wherever the app shows it (auth page,
|
|
775
|
+
// banners, chat cards) — and so two actions on the SAME card can't
|
|
776
|
+
// render two different box models. The host names the semantic colour
|
|
777
|
+
// when it has one; otherwise the tone supplies it. No inline colors —
|
|
778
|
+
// the ClassMap owns the look, including hover/active/focus states.
|
|
779
|
+
// touchTargetCompact (36px), not the full 44px touchTarget — these sit
|
|
780
|
+
// inside a dense chat card (the floor agreed for its actions).
|
|
781
|
+
const className = cm.cn(cm.button({ color: act.color ?? defaultActionColor, size: 'sm' }), cm.touchTargetCompact);
|
|
782
|
+
const actionStyle = {
|
|
787
783
|
textDecoration: 'none',
|
|
788
784
|
fontFamily: act.code ? 'var(--mol-font-mono, monospace)' : 'inherit',
|
|
789
|
-
border: `1px solid ${chatCardBorder(accent, 55)}`,
|
|
790
|
-
color: accent,
|
|
791
|
-
background: buttonBg,
|
|
792
|
-
boxShadow: '0 1px 2px rgba(0, 0, 0, 0.08)',
|
|
793
|
-
transition: 'background 100ms',
|
|
794
785
|
};
|
|
795
|
-
return act.href ? (_jsx("a", { href: act.href, target: act.href.startsWith('http') ? '_blank' : undefined, rel: act.href.startsWith('http') ? 'noopener noreferrer' : undefined,
|
|
786
|
+
return act.href ? (_jsx("a", { href: act.href, target: act.href.startsWith('http') ? '_blank' : undefined, rel: act.href.startsWith('http') ? 'noopener noreferrer' : undefined, className: className, style: actionStyle, children: act.label }, i)) : (_jsx("button", { type: "button", onClick: act.onClick, className: className, style: actionStyle, children: act.label }, i));
|
|
796
787
|
}) }))] })] }));
|
|
797
788
|
}
|
|
798
789
|
// ResourceLimitBanner — upgrade prompt when sandbox runs out of memory / a limit hits
|
|
@@ -855,7 +846,9 @@ export function CommitCardItem({ card, onRevert, }) {
|
|
|
855
846
|
setIsReverting(false);
|
|
856
847
|
}
|
|
857
848
|
}, [canRevert, isReverting, isReverted, revertHash, card.hash, onRevert]);
|
|
858
|
-
return (_jsx("div", { style: { marginBottom: TIMELINE_ITEM_GAP }, children: _jsxs("div", { style: { marginBottom: '4px' }, children: [_jsxs("button", {
|
|
849
|
+
return (_jsx("div", { style: { marginBottom: TIMELINE_ITEM_GAP }, children: _jsxs("div", { style: { marginBottom: '4px' }, children: [_jsxs("button", {
|
|
850
|
+
/* mol-bespoke-button: commit card header — expand/collapse disclosure for the commit's file list */
|
|
851
|
+
type: "button", onClick: hasFiles ? () => setExpanded((e) => !e) : undefined, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), style: {
|
|
859
852
|
display: 'flex',
|
|
860
853
|
alignItems: 'flex-start',
|
|
861
854
|
gap: '6px',
|
|
@@ -884,7 +877,9 @@ export function CommitCardItem({ card, onRevert, }) {
|
|
|
884
877
|
}, children: isRunning ? (t('ide.chat.committing', undefined, { defaultValue: 'Committing' })) : (_jsxs(_Fragment, { children: [t('ide.chat.commitLabel', undefined, { defaultValue: 'Commit' }), ' ', _jsx("code", { style: {
|
|
885
878
|
fontFamily: '"SF Mono", Menlo, Consolas, "Courier New", monospace',
|
|
886
879
|
fontSize: 'inherit',
|
|
887
|
-
}, children: stripCommitCoauthorTrailer(card.message) })] })) }), canRevert && (_jsx("span", {
|
|
880
|
+
}, children: stripCommitCoauthorTrailer(card.message) })] })) }), canRevert && (_jsx("span", {
|
|
881
|
+
/* mol-bespoke-button: icon-only revert affordance — 20px (32px coarse) hit box inside a dense commit row, no label */
|
|
882
|
+
role: "button", tabIndex: 0, title: isReverted
|
|
888
883
|
? t('ide.chat.redoCommit', undefined, {
|
|
889
884
|
defaultValue: 'Re-apply this commit',
|
|
890
885
|
})
|
|
@@ -952,7 +947,9 @@ export function CommitCardItem({ card, onRevert, }) {
|
|
|
952
947
|
*/
|
|
953
948
|
function AuthorNameButton({ onClick, children, }) {
|
|
954
949
|
const [hover, setHover] = useState(false);
|
|
955
|
-
return (_jsx("button", {
|
|
950
|
+
return (_jsx("button", {
|
|
951
|
+
/* mol-bespoke-button: author name — a full <button> reset so the name renders byte-identical to the bold span it replaced; hover underline is the only affordance */
|
|
952
|
+
type: "button", onClick: onClick, onMouseEnter: () => setHover(true), onMouseLeave: () => setHover(false), onFocus: () => setHover(true), onBlur: () => setHover(false), "data-mol-id": "chat-user-name-button",
|
|
956
953
|
// Full button reset so it is byte-identical to the former bold span at
|
|
957
954
|
// rest — the underline affordance is the only visual change on hover.
|
|
958
955
|
style: {
|
|
@@ -1579,7 +1576,7 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
|
|
|
1579
1576
|
}
|
|
1580
1577
|
onFileChange?.(path, content);
|
|
1581
1578
|
}, [onFileChange, onFileOpen, autoFixCountdown]);
|
|
1582
|
-
const { messages, isLoading, isRemoteStreaming, noteRemoteStreamEvent, error, errorMeta, mode, fastMode, streamingStatus, setMode, setFastMode, sendMessage, abort, clearHistory, editQueuedMessage, deleteQueuedMessage, clearQueuedForFile, applyRemoteEvent, reconcileHistory, retryCountdown, cancelRetry, } = useChat({
|
|
1579
|
+
const { messages, isLoading, isRemoteStreaming, noteRemoteStreamEvent, error, errorMeta, mode, fastMode, streamingStatus, backgroundTasks, setMode, setFastMode, sendMessage, abort, clearHistory, editQueuedMessage, deleteQueuedMessage, clearQueuedForFile, applyRemoteEvent, reconcileHistory, retryCountdown, cancelRetry, } = useChat({
|
|
1583
1580
|
endpoint,
|
|
1584
1581
|
projectId,
|
|
1585
1582
|
agentName,
|
|
@@ -5922,14 +5919,12 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
|
|
|
5922
5919
|
textAlign: 'center',
|
|
5923
5920
|
}, children: [_jsx(Icon, { name: "logo-mark", size: 28, "aria-hidden": "true", style: { opacity: 0.5 } }), _jsx("span", { style: { maxWidth: 320 }, children: t('ide.chat.emptyState', undefined, {
|
|
5924
5921
|
defaultValue: 'Describe what you want to build...',
|
|
5925
|
-
}) })] })), timeline.length > maxVisibleItems && (_jsx("div", { style: { textAlign: 'center', padding: '8px 0' }, children: _jsx("button", { onClick: () => setMaxVisibleItems((n) => n + 40),
|
|
5926
|
-
|
|
5927
|
-
|
|
5928
|
-
|
|
5929
|
-
|
|
5930
|
-
|
|
5931
|
-
opacity: 0.7,
|
|
5932
|
-
}, children: t('ide.chat.showEarlier', undefined, {
|
|
5922
|
+
}) })] })), timeline.length > maxVisibleItems && (_jsx("div", { style: { textAlign: 'center', padding: '8px 0' }, children: _jsx("button", { type: "button", "data-mol-id": "chat-show-earlier", onClick: () => setMaxVisibleItems((n) => n + 40),
|
|
5923
|
+
// A quiet, non-committal timeline action — SECONDARY, the semantic
|
|
5924
|
+
// DESIGN.md reserves for what sits beside the real CTAs. Box model,
|
|
5925
|
+
// type scale and hover come from the ClassMap instead of the
|
|
5926
|
+
// hand-rolled 4px-radius currentColor frame this used to be.
|
|
5927
|
+
className: cm.cn(cm.button({ variant: 'solid', color: 'secondary', size: 'xs' }), cm.touchTargetCompact), children: t('ide.chat.showEarlier', undefined, {
|
|
5933
5928
|
defaultValue: 'Show earlier messages',
|
|
5934
5929
|
}) }) })), renderedTimeline.map((item) => (_jsx(ChatItemBoundary, { onError: onRenderError, render: () => withTimelineTimestamp(item, (() => {
|
|
5935
5930
|
if (item.kind === 'commit')
|
|
@@ -5982,7 +5977,9 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
|
|
|
5982
5977
|
// from `count` if a caller passed none.
|
|
5983
5978
|
const skillsLoadedLabel = item.card.text ||
|
|
5984
5979
|
t('ide.chat.skills.loadedCount', { count: item.card.count ?? 0 }, { defaultValue: '🧠 Loaded {{count}} skills' });
|
|
5985
|
-
return (_jsx("div", { style: { textAlign: 'center', marginBottom: TIMELINE_ITEM_GAP }, children: _jsx("button", {
|
|
5980
|
+
return (_jsx("div", { style: { textAlign: 'center', marginBottom: TIMELINE_ITEM_GAP }, children: _jsx("button", {
|
|
5981
|
+
/* mol-bespoke-button: skills-loaded notice — deliberately a plain centered phase message that happens to be clickable; a button frame would make it shout */
|
|
5982
|
+
type: "button", "data-mol-id": "chat-skills-loaded", onClick: () => openPanelOverlay('skills'), className: cm.cn(cm.textSize('xs'), cm.textMuted), style: {
|
|
5986
5983
|
// Plain text like the build-phase notice — no border/fill/pill.
|
|
5987
5984
|
background: 'none',
|
|
5988
5985
|
border: 'none',
|
|
@@ -6121,7 +6118,7 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
|
|
|
6121
6118
|
pointerEvents: showActivity ? 'auto' : 'none',
|
|
6122
6119
|
transition: 'opacity 0.18s ease-out',
|
|
6123
6120
|
}, children: showActivity && (_jsx(StreamingIndicator, { label: label, tokens: streamingLike ? turnTokens : undefined, startedAt: streamingLike ? turnStartedAt : undefined })) }));
|
|
6124
|
-
})(), _jsx("div", { ref: messagesEndRef })] }), autoFixCountdown && (_jsxs("div", { className: cm.cn(cm.shrink0, cm.borderT), style: {
|
|
6121
|
+
})(), _jsx("div", { ref: messagesEndRef })] }), _jsx(BackgroundTasksStrip, { tasks: backgroundTasks }), autoFixCountdown && (_jsxs("div", { className: cm.cn(cm.shrink0, cm.borderT), style: {
|
|
6125
6122
|
display: 'flex',
|
|
6126
6123
|
alignItems: 'center',
|
|
6127
6124
|
gap: 8,
|
|
@@ -6132,31 +6129,15 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
|
|
|
6132
6129
|
? t('ide.chat.autoFixPaused', undefined, { defaultValue: 'Auto-fix paused' })
|
|
6133
6130
|
: t('ide.chat.autoFixCountdown', { seconds: autoFixCountdown.secondsLeft }, {
|
|
6134
6131
|
defaultValue: `Auto-fixing in ${autoFixCountdown.secondsLeft}s...`,
|
|
6135
|
-
}) }), autoFixCountdown.paused ? (_jsx("button", { type: "button", onClick: () => setAutoFixCountdown((prev) => prev ? { ...prev, paused: false, secondsLeft: 3 } : prev),
|
|
6136
|
-
|
|
6137
|
-
|
|
6138
|
-
|
|
6139
|
-
|
|
6140
|
-
|
|
6141
|
-
|
|
6142
|
-
|
|
6143
|
-
}, children: t('ide.chat.autoFixResume', undefined, { defaultValue: 'Resume' }) })) : (_jsx("button", { type: "button", onClick: () => setAutoFixCountdown((prev) => (prev ? { ...prev, paused: true } : prev)), style: {
|
|
6144
|
-
fontSize: 11,
|
|
6145
|
-
padding: '2px 8px',
|
|
6146
|
-
borderRadius: 4,
|
|
6147
|
-
border: '1px solid rgba(128,128,128,0.3)',
|
|
6148
|
-
background: 'transparent',
|
|
6149
|
-
color: 'inherit',
|
|
6150
|
-
cursor: 'pointer',
|
|
6151
|
-
}, children: t('ide.chat.autoFixPause', undefined, { defaultValue: 'Pause' }) })), _jsx("button", { type: "button", onClick: () => setAutoFixCountdown(null), style: {
|
|
6152
|
-
fontSize: 11,
|
|
6153
|
-
padding: '2px 8px',
|
|
6154
|
-
borderRadius: 4,
|
|
6155
|
-
border: '1px solid rgba(128,128,128,0.3)',
|
|
6156
|
-
background: 'transparent',
|
|
6157
|
-
color: 'inherit',
|
|
6158
|
-
cursor: 'pointer',
|
|
6159
|
-
}, children: t('ide.chat.autoFixCancel', undefined, { defaultValue: 'Cancel' }) })] })), retryCountdown && (_jsxs("div", { className: cm.cn(cm.shrink0, cm.borderT), "data-mol-id": "chat-retry-countdown", style: {
|
|
6132
|
+
}) }), autoFixCountdown.paused ? (_jsx("button", { type: "button", "data-mol-id": "chat-autofix-resume", onClick: () => setAutoFixCountdown((prev) => prev ? { ...prev, paused: false, secondsLeft: 3 } : prev),
|
|
6133
|
+
// This strip and the retry strip below it now share one button
|
|
6134
|
+
// treatment, so a user never sees four near-identical controls at
|
|
6135
|
+
// four slightly different sizes (they were 11px/4px-radius
|
|
6136
|
+
// hand-rolled frames with a hardcoded grey border). Semantics per
|
|
6137
|
+
// DESIGN.md's CTA table: Resume is the affirmative action
|
|
6138
|
+
// (primary), its sibling Pause is pause-like (warning), and the
|
|
6139
|
+
// Cancels are quiet dismissals (secondary).
|
|
6140
|
+
className: cm.cn(cm.button({ variant: 'solid', color: 'primary', size: 'xs' }), cm.touchTargetCompact), children: t('ide.chat.autoFixResume', undefined, { defaultValue: 'Resume' }) })) : (_jsx("button", { type: "button", "data-mol-id": "chat-autofix-pause", onClick: () => setAutoFixCountdown((prev) => (prev ? { ...prev, paused: true } : prev)), className: cm.cn(cm.button({ variant: 'solid', color: 'warning', size: 'xs' }), cm.touchTargetCompact), children: t('ide.chat.autoFixPause', undefined, { defaultValue: 'Pause' }) })), _jsx("button", { type: "button", "data-mol-id": "chat-autofix-cancel", onClick: () => setAutoFixCountdown(null), className: cm.cn(cm.button({ variant: 'solid', color: 'secondary', size: 'xs' }), cm.touchTargetCompact), children: t('ide.chat.autoFixCancel', undefined, { defaultValue: 'Cancel' }) })] })), retryCountdown && (_jsxs("div", { className: cm.cn(cm.shrink0, cm.borderT), "data-mol-id": "chat-retry-countdown", style: {
|
|
6160
6141
|
display: 'flex',
|
|
6161
6142
|
alignItems: 'center',
|
|
6162
6143
|
gap: 8,
|
|
@@ -6165,15 +6146,11 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
|
|
|
6165
6146
|
background: 'rgba(234,179,8,0.06)',
|
|
6166
6147
|
}, children: [_jsx(Icon, { name: "exclamation-triangle", size: 14, "aria-hidden": "true", style: { flexShrink: 0, color: '#d4a017' } }), _jsx("span", { style: { flex: 1, opacity: 0.85 }, children: t('ide.chat.retryCountdown', { seconds: retryCountdown.secondsRemaining, attempt: retryCountdown.attempt }, {
|
|
6167
6148
|
defaultValue: `Server error — retrying in ${retryCountdown.secondsRemaining}s… (attempt ${retryCountdown.attempt})`,
|
|
6168
|
-
}) }), _jsx("button", { type: "button", "data-mol-id": "chat-retry-cancel", onClick: cancelRetry,
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
background: 'transparent',
|
|
6174
|
-
color: 'inherit',
|
|
6175
|
-
cursor: 'pointer',
|
|
6176
|
-
}, children: t('ide.chat.autoFixCancel', undefined, { defaultValue: 'Cancel' }) })] })), _jsxs("div", { className: cm.shrink0, style: { position: 'relative' }, children: [relevantSkill && (_jsx(RelevantSkillSuggestion, { skill: relevantSkill, onLoad: loadSkill, onOpen: (s) => onFileOpen?.(s.path, { focus: true }), onDismiss: dismissRelevantSkill })), attachmentError && (_jsx("div", { className: cm.cn(cm.textSize('xs'), cm.textError), style: { padding: '4px 10px' }, children: attachmentError })), voiceError && (_jsx("div", { className: cm.cn(cm.textSize('xs'), cm.textError), style: { padding: '4px 10px' }, children: voiceError })), voiceNotice && (_jsx("div", { className: cm.cn(cm.textSize('xs'), cm.textMuted), style: { padding: '4px 10px' }, children: voiceNotice })), attachedFiles.length > 0 && (_jsx("div", { style: { display: 'flex', flexWrap: 'wrap', gap: '4px', padding: '6px 10px 0' }, children: attachedFiles.map((f) => {
|
|
6149
|
+
}) }), _jsx("button", { type: "button", "data-mol-id": "chat-retry-cancel", onClick: cancelRetry,
|
|
6150
|
+
// The same button as the auto-fix strip's Cancel directly above it —
|
|
6151
|
+
// the two strips mirror each other, and DESIGN.md's rule is that one
|
|
6152
|
+
// action keeps one colour on every surface.
|
|
6153
|
+
className: cm.cn(cm.button({ variant: 'solid', color: 'secondary', size: 'xs' }), cm.touchTargetCompact), children: t('ide.chat.autoFixCancel', undefined, { defaultValue: 'Cancel' }) })] })), _jsxs("div", { className: cm.shrink0, style: { position: 'relative' }, children: [relevantSkill && (_jsx(RelevantSkillSuggestion, { skill: relevantSkill, onLoad: loadSkill, onOpen: (s) => onFileOpen?.(s.path, { focus: true }), onDismiss: dismissRelevantSkill })), attachmentError && (_jsx("div", { className: cm.cn(cm.textSize('xs'), cm.textError), style: { padding: '4px 10px' }, children: attachmentError })), voiceError && (_jsx("div", { className: cm.cn(cm.textSize('xs'), cm.textError), style: { padding: '4px 10px' }, children: voiceError })), voiceNotice && (_jsx("div", { className: cm.cn(cm.textSize('xs'), cm.textMuted), style: { padding: '4px 10px' }, children: voiceNotice })), attachedFiles.length > 0 && (_jsx("div", { style: { display: 'flex', flexWrap: 'wrap', gap: '4px', padding: '6px 10px 0' }, children: attachedFiles.map((f) => {
|
|
6177
6154
|
const key = f.path ?? f.filename;
|
|
6178
6155
|
return (_jsxs("span", { className: cm.cn(cm.surfaceSecondary, cm.textSize('xs')), style: {
|
|
6179
6156
|
display: 'inline-flex',
|
|
@@ -6181,7 +6158,9 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
|
|
|
6181
6158
|
gap: '4px',
|
|
6182
6159
|
borderRadius: '4px',
|
|
6183
6160
|
padding: '2px 6px',
|
|
6184
|
-
}, children: [f.previewUrl && (_jsx("img", { src: f.previewUrl, alt: f.filename, style: { width: 18, height: 18, objectFit: 'cover', borderRadius: 2 } })), _jsx("span", { style: { fontFamily: 'monospace', opacity: 0.85 }, children: f.path ? f.path.split('/').pop() : f.filename }), f.size > 0 && (_jsx("span", { className: cm.textMuted, style: { fontSize: 10 }, children: formatSize(f.size) })), _jsx("button", {
|
|
6161
|
+
}, children: [f.previewUrl && (_jsx("img", { src: f.previewUrl, alt: f.filename, style: { width: 18, height: 18, objectFit: 'cover', borderRadius: 2 } })), _jsx("span", { style: { fontFamily: 'monospace', opacity: 0.85 }, children: f.path ? f.path.split('/').pop() : f.filename }), f.size > 0 && (_jsx("span", { className: cm.textMuted, style: { fontSize: 10 }, children: formatSize(f.size) })), _jsx("button", {
|
|
6162
|
+
/* mol-bespoke-button: attachment chip remove — icon-only x inside a 2px-padded chip, 32px coarse hit box */
|
|
6163
|
+
type: "button", onClick: () => removeAttachment(key), style: {
|
|
6185
6164
|
background: 'none',
|
|
6186
6165
|
border: 'none',
|
|
6187
6166
|
cursor: 'pointer',
|
|
@@ -6507,7 +6486,9 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
|
|
|
6507
6486
|
textOverflow: 'ellipsis',
|
|
6508
6487
|
}, children: [_jsx("option", { value: "name", children: t('ide.chat.models.colName', undefined, { defaultValue: 'Model' }) }), _jsx("option", { value: "context", children: t('ide.chat.models.colContext', undefined, { defaultValue: 'Context' }) }), _jsx("option", { value: "cost", children: t('ide.chat.models.colUsageRate', undefined, { defaultValue: 'Usage rate' }) }), _jsx("option", { value: "cutoff", children: t('ide.chat.models.colCutoff', undefined, { defaultValue: 'Cutoff' }) }), _jsx("option", { value: "free", children: t('ide.chat.models.colFree', undefined, { defaultValue: 'Free' }) }), _jsx("option", { value: "region", children: t('ide.chat.models.colRegion', undefined, { defaultValue: 'Region' }) })] }), _jsx(Tooltip, { content: t('ide.chat.modelSortDirection', undefined, {
|
|
6509
6488
|
defaultValue: 'Toggle sort direction',
|
|
6510
|
-
}), placement: "top", children: _jsx("button", {
|
|
6489
|
+
}), placement: "top", children: _jsx("button", {
|
|
6490
|
+
/* mol-bespoke-button: icon-only sort-direction toggle — 24px square matched to the adjacent selects' height */
|
|
6491
|
+
type: "button", "data-mol-id": "model-sort-direction", "aria-label": t('ide.chat.modelSortDirection', undefined, {
|
|
6511
6492
|
defaultValue: 'Toggle sort direction',
|
|
6512
6493
|
}), onClick: () => setModelSort((s) => ({
|
|
6513
6494
|
...s,
|
|
@@ -6623,14 +6604,18 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
|
|
|
6623
6604
|
: isLight
|
|
6624
6605
|
? 'rgb(220,38,38)'
|
|
6625
6606
|
: 'rgb(248,113,113)';
|
|
6626
|
-
return (_jsxs(Fragment, { children: [dividerBefore && (_jsx("button", {
|
|
6607
|
+
return (_jsxs(Fragment, { children: [dividerBefore && (_jsx("button", {
|
|
6608
|
+
/* mol-bespoke-button: older-models collapse row — full-width disclosure row inside the model list */
|
|
6609
|
+
type: "button", onClick: () => setShowDeprecated((s) => !s), className: cm.cn(cm.textSize('xs'), cm.textMuted, cm.w('full')), style: {
|
|
6627
6610
|
padding: '6px 12px',
|
|
6628
6611
|
border: 'none',
|
|
6629
6612
|
borderTop: '1px solid rgba(128,128,128,0.12)',
|
|
6630
6613
|
background: 'rgba(128,128,128,0.04)',
|
|
6631
6614
|
cursor: 'pointer',
|
|
6632
6615
|
textAlign: 'left',
|
|
6633
|
-
}, children: t('ide.chat.olderModelsCollapse', { count: deprecatedModels.length }, { defaultValue: 'Older models ⌃ ({{count}})' }) })), _jsxs("button", {
|
|
6616
|
+
}, children: t('ide.chat.olderModelsCollapse', { count: deprecatedModels.length }, { defaultValue: 'Older models ⌃ ({{count}})' }) })), _jsxs("button", {
|
|
6617
|
+
/* mol-bespoke-button: model row — full-width list item in the model picker */
|
|
6618
|
+
type: "button", onClick: () => {
|
|
6634
6619
|
if (lockReason === 'paid') {
|
|
6635
6620
|
setModelPicker(null);
|
|
6636
6621
|
setInputValue('');
|
|
@@ -6882,14 +6867,18 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
|
|
|
6882
6867
|
}, children: [_jsx(RegionFlag, { code: rMeta?.flagCode ?? r, height: 12 }), _jsx("span", { children: rLabel }), _jsxs("span", { className: active ? undefined : cm.textMuted, style: { fontSize: '10px' }, children: ["(", t('ide.chat.models.usageRateValue', { rate: rRate }, { defaultValue: '×{{rate}}' }), ")"] })] }, r));
|
|
6883
6868
|
}) }))] }));
|
|
6884
6869
|
})()] }))] })] }, model.id));
|
|
6885
|
-
}), !showDeprecated && deprecatedModels.length > 0 && (_jsx("button", {
|
|
6870
|
+
}), !showDeprecated && deprecatedModels.length > 0 && (_jsx("button", {
|
|
6871
|
+
/* mol-bespoke-button: older-models expand row — full-width disclosure row inside the model list */
|
|
6872
|
+
type: "button", onClick: () => setShowDeprecated(true), className: cm.cn(cm.textSize('xs'), cm.textMuted, cm.w('full')), style: {
|
|
6886
6873
|
padding: '6px 12px',
|
|
6887
6874
|
border: 'none',
|
|
6888
6875
|
borderTop: '1px solid rgba(128,128,128,0.12)',
|
|
6889
6876
|
background: 'rgba(128,128,128,0.04)',
|
|
6890
6877
|
cursor: 'pointer',
|
|
6891
6878
|
textAlign: 'left',
|
|
6892
|
-
}, children: t('ide.chat.olderModelsExpand', { count: deprecatedModels.length }, { defaultValue: 'Older models ⌄ ({{count}})' }) }))] })), onManageCustomModels && (_jsx("button", {
|
|
6879
|
+
}, children: t('ide.chat.olderModelsExpand', { count: deprecatedModels.length }, { defaultValue: 'Older models ⌄ ({{count}})' }) }))] })), onManageCustomModels && (_jsx("button", {
|
|
6880
|
+
/* mol-bespoke-button: manage-custom-models footer — anchored full-width footer row of the model list, keyboard-indexed with the rows */
|
|
6881
|
+
type: "button", "data-mol-id": "chat-model-manage-custom", onClick: () => {
|
|
6893
6882
|
const manageMode = modelPicker.mode === 'plan' || modelPicker.mode === 'execute'
|
|
6894
6883
|
? modelPicker.mode
|
|
6895
6884
|
: liveModelMode;
|
|
@@ -6966,7 +6955,9 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
|
|
|
6966
6955
|
overflow: 'hidden',
|
|
6967
6956
|
whiteSpace: 'nowrap',
|
|
6968
6957
|
textOverflow: 'ellipsis',
|
|
6969
|
-
}, children: effortPickerModeOptions.map((o) => (_jsx("option", { value: o.value, children: o.label }, o.value))) })] }), _jsx("button", {
|
|
6958
|
+
}, children: effortPickerModeOptions.map((o) => (_jsx("option", { value: o.value, children: o.label }, o.value))) })] }), _jsx("button", {
|
|
6959
|
+
/* mol-bespoke-button: icon-only picker close — header x, no label */
|
|
6960
|
+
type: "button", "data-mol-id": "chat-effort-picker-close", onClick: () => setEffortPicker(null), style: {
|
|
6970
6961
|
background: 'none',
|
|
6971
6962
|
border: 'none',
|
|
6972
6963
|
cursor: 'pointer',
|
|
@@ -7041,7 +7032,9 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
|
|
|
7041
7032
|
alignItems: 'center',
|
|
7042
7033
|
}, children: [_jsx("span", { children: t('ide.chat.notificationSounds', undefined, {
|
|
7043
7034
|
defaultValue: 'Notification sounds',
|
|
7044
|
-
}) }), _jsx("button", {
|
|
7035
|
+
}) }), _jsx("button", {
|
|
7036
|
+
/* mol-bespoke-button: icon-only picker close — header x, no label */
|
|
7037
|
+
type: "button", onClick: () => setSoundsPicker(null), style: {
|
|
7045
7038
|
background: 'none',
|
|
7046
7039
|
border: 'none',
|
|
7047
7040
|
cursor: 'pointer',
|
|
@@ -7075,7 +7068,9 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
|
|
|
7075
7068
|
defaultValue: SOUND_MODE_LABELS[allModes[0]],
|
|
7076
7069
|
})
|
|
7077
7070
|
: t('ide.chat.soundMode.mixed', undefined, { defaultValue: 'mixed' });
|
|
7078
|
-
return (_jsxs("button", {
|
|
7071
|
+
return (_jsxs("button", {
|
|
7072
|
+
/* mol-bespoke-button: sounds "All" row — full-width list item in the /sounds popup */
|
|
7073
|
+
type: "button", onClick: () => void cycleSoundMode('all'), onMouseEnter: (e) => {
|
|
7079
7074
|
;
|
|
7080
7075
|
e.currentTarget.style.background = 'rgba(128,128,128,0.15)';
|
|
7081
7076
|
}, onMouseLeave: (e) => {
|
|
@@ -7185,7 +7180,9 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
|
|
|
7185
7180
|
? t('ide.chat.scripts.heading', undefined, { defaultValue: 'Scripts' })
|
|
7186
7181
|
: panelOverlay === 'tests'
|
|
7187
7182
|
? t('ide.tests.heading', undefined, { defaultValue: 'Tests' })
|
|
7188
|
-
: t('ide.chat.settings.heading', undefined, { defaultValue: 'Settings' }) }), _jsx("button", {
|
|
7183
|
+
: t('ide.chat.settings.heading', undefined, { defaultValue: 'Settings' }) }), _jsx("button", {
|
|
7184
|
+
/* mol-bespoke-button: icon-only overlay close — header x, no label */
|
|
7185
|
+
type: "button", "data-mol-id": "panel-overlay-close", "aria-label": t('ide.chat.closeOverlay', undefined, { defaultValue: 'Close' }), onClick: () => setPanelOverlay(null), style: {
|
|
7189
7186
|
background: 'none',
|
|
7190
7187
|
border: 'none',
|
|
7191
7188
|
cursor: 'pointer',
|
|
@@ -7306,37 +7303,23 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
|
|
|
7306
7303
|
resize: 'vertical',
|
|
7307
7304
|
color: 'inherit',
|
|
7308
7305
|
fontFamily: 'inherit',
|
|
7309
|
-
} }), _jsxs("div", { style: { display: 'flex', gap: 6, justifyContent: 'flex-end' }, children: [_jsx("button", { type: "button", onClick: () => setEditingQueuedId(null), className: cm.
|
|
7310
|
-
padding: '4px 12px',
|
|
7311
|
-
border: `1px solid ${isLight ? '#d1d9e0' : 'rgba(255,255,255,0.1)'}`,
|
|
7312
|
-
borderRadius: '4px',
|
|
7313
|
-
background: 'transparent',
|
|
7314
|
-
color: 'inherit',
|
|
7315
|
-
cursor: 'pointer',
|
|
7316
|
-
...(isCoarse ? { minHeight: 32 } : {}),
|
|
7317
|
-
}, children: t('common.cancel', undefined, { defaultValue: 'Cancel' }) }), _jsx("button", { type: "button", onClick: () => {
|
|
7306
|
+
} }), _jsxs("div", { style: { display: 'flex', gap: 6, justifyContent: 'flex-end' }, children: [_jsx("button", { type: "button", "data-mol-id": "chat-queued-edit-cancel", onClick: () => setEditingQueuedId(null), className: cm.cn(cm.button({ variant: 'solid', color: 'secondary', size: 'xs' }), cm.touchTargetCompact), children: t('common.cancel', undefined, { defaultValue: 'Cancel' }) }), _jsx("button", { type: "button", "data-mol-id": "chat-queued-edit-save", onClick: () => {
|
|
7318
7307
|
const trimmed = editingQueuedText.trim();
|
|
7319
7308
|
if (trimmed)
|
|
7320
7309
|
editQueuedMessage(qm.id, trimmed);
|
|
7321
7310
|
else
|
|
7322
7311
|
deleteQueuedMessage(qm.id);
|
|
7323
7312
|
setEditingQueuedId(null);
|
|
7324
|
-
}, className: cm.
|
|
7325
|
-
padding: '4px 12px',
|
|
7326
|
-
border: `1px solid ${isLight ? '#d1d9e0' : 'rgba(255,255,255,0.1)'}`,
|
|
7327
|
-
borderRadius: '4px',
|
|
7328
|
-
background: 'rgba(128,128,128,0.1)',
|
|
7329
|
-
color: 'inherit',
|
|
7330
|
-
cursor: 'pointer',
|
|
7331
|
-
...(isCoarse ? { minHeight: 32 } : {}),
|
|
7332
|
-
}, children: t('common.save', undefined, { defaultValue: 'Save' }) })] })] }, qm.id)) : (_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 6, minWidth: 0 }, children: [_jsx("span", { title: qm.content, className: cm.textSize('sm'), style: {
|
|
7313
|
+
}, className: cm.cn(cm.button({ variant: 'solid', color: 'primary', size: 'xs' }), cm.touchTargetCompact), children: t('common.save', undefined, { defaultValue: 'Save' }) })] })] }, qm.id)) : (_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 6, minWidth: 0 }, children: [_jsx("span", { title: qm.content, className: cm.textSize('sm'), style: {
|
|
7333
7314
|
flex: 1,
|
|
7334
7315
|
minWidth: 0,
|
|
7335
7316
|
overflow: 'hidden',
|
|
7336
7317
|
textOverflow: 'ellipsis',
|
|
7337
7318
|
whiteSpace: 'nowrap',
|
|
7338
7319
|
opacity: 0.8,
|
|
7339
|
-
}, children: qm.content }), _jsx("button", {
|
|
7320
|
+
}, children: qm.content }), _jsx("button", {
|
|
7321
|
+
/* mol-bespoke-button: icon-only edit affordance — 22px (32px coarse) pencil on a dense queued-message row */
|
|
7322
|
+
type: "button", title: t('ide.chat.editQueued', undefined, { defaultValue: 'Edit' }), onClick: () => {
|
|
7340
7323
|
setEditingQueuedId(qm.id);
|
|
7341
7324
|
setEditingQueuedText(qm.content);
|
|
7342
7325
|
}, style: {
|
|
@@ -7360,7 +7343,9 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
|
|
|
7360
7343
|
}, onMouseLeave: (e) => {
|
|
7361
7344
|
e.currentTarget.style.opacity = '0.5';
|
|
7362
7345
|
e.currentTarget.style.background = 'none';
|
|
7363
|
-
}, children: _jsx(Icon, { name: "pencil", size: 13, "aria-hidden": "true" }) }), _jsx("button", {
|
|
7346
|
+
}, children: _jsx(Icon, { name: "pencil", size: 13, "aria-hidden": "true" }) }), _jsx("button", {
|
|
7347
|
+
/* mol-bespoke-button: icon-only delete affordance — 22px (32px coarse) trash on a dense queued-message row, theme error token */
|
|
7348
|
+
type: "button", title: t('ide.chat.deleteQueued', undefined, { defaultValue: 'Delete' }), onClick: () => deleteQueuedMessage(qm.id), style: {
|
|
7364
7349
|
display: 'inline-flex',
|
|
7365
7350
|
alignItems: 'center',
|
|
7366
7351
|
justifyContent: 'center',
|
|
@@ -7370,18 +7355,23 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
|
|
|
7370
7355
|
border: 'none',
|
|
7371
7356
|
borderRadius: 4,
|
|
7372
7357
|
background: 'none',
|
|
7373
|
-
|
|
7358
|
+
// Theme ERROR token, not a per-theme literal — the token
|
|
7359
|
+
// already resolves per theme.
|
|
7360
|
+
color: 'var(--mol-color-error, #dc2626)',
|
|
7374
7361
|
opacity: 0.6,
|
|
7375
7362
|
cursor: 'pointer',
|
|
7376
7363
|
padding: 0,
|
|
7377
7364
|
transition: 'opacity 100ms, background 100ms',
|
|
7378
7365
|
}, onMouseEnter: (e) => {
|
|
7379
7366
|
e.currentTarget.style.opacity = '1';
|
|
7380
|
-
e.currentTarget.style.background =
|
|
7367
|
+
e.currentTarget.style.background =
|
|
7368
|
+
'color-mix(in srgb, var(--mol-color-error, #dc2626) 12%, transparent)';
|
|
7381
7369
|
}, onMouseLeave: (e) => {
|
|
7382
7370
|
e.currentTarget.style.opacity = '0.6';
|
|
7383
7371
|
e.currentTarget.style.background = 'none';
|
|
7384
|
-
}, children: _jsx(Icon, { name: "trash", size: 13, "aria-hidden": "true" }) }), !isLoading && (_jsx("button", {
|
|
7372
|
+
}, children: _jsx(Icon, { name: "trash", size: 13, "aria-hidden": "true" }) }), !isLoading && (_jsx("button", {
|
|
7373
|
+
/* mol-bespoke-button: icon-only send affordance — 22px (32px coarse) arrow on a dense queued-message row, theme success token */
|
|
7374
|
+
type: "button", title: t('ide.chat.sendQueued', undefined, { defaultValue: 'Send' }), onClick: () => {
|
|
7385
7375
|
const content = qm.content;
|
|
7386
7376
|
deleteQueuedMessage(qm.id);
|
|
7387
7377
|
sendMessage(content);
|
|
@@ -7395,14 +7385,16 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
|
|
|
7395
7385
|
border: 'none',
|
|
7396
7386
|
borderRadius: 4,
|
|
7397
7387
|
background: 'none',
|
|
7398
|
-
|
|
7388
|
+
// Theme SUCCESS token, not a per-theme literal.
|
|
7389
|
+
color: 'var(--mol-color-success, #16a34a)',
|
|
7399
7390
|
opacity: 0.7,
|
|
7400
7391
|
cursor: 'pointer',
|
|
7401
7392
|
padding: 0,
|
|
7402
7393
|
transition: 'opacity 100ms, background 100ms',
|
|
7403
7394
|
}, onMouseEnter: (e) => {
|
|
7404
7395
|
e.currentTarget.style.opacity = '1';
|
|
7405
|
-
e.currentTarget.style.background =
|
|
7396
|
+
e.currentTarget.style.background =
|
|
7397
|
+
'color-mix(in srgb, var(--mol-color-success, #16a34a) 14%, transparent)';
|
|
7406
7398
|
}, onMouseLeave: (e) => {
|
|
7407
7399
|
e.currentTarget.style.opacity = '0.7';
|
|
7408
7400
|
e.currentTarget.style.background = 'none';
|
|
@@ -7456,39 +7448,27 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
|
|
|
7456
7448
|
const commitBusy = commitState?.status === 'committing' ||
|
|
7457
7449
|
commitState?.status === 'committed' ||
|
|
7458
7450
|
autoCommitHeld;
|
|
7459
|
-
return (_jsx("button", { type: "button", onClick: (e) => {
|
|
7451
|
+
return (_jsx("button", { type: "button", "data-mol-id": "chat-commit-button", onClick: (e) => {
|
|
7460
7452
|
e.stopPropagation();
|
|
7461
7453
|
if (commitBusy)
|
|
7462
7454
|
return;
|
|
7463
7455
|
handleCommit();
|
|
7464
|
-
}, disabled: commitBusy,
|
|
7465
|
-
|
|
7466
|
-
|
|
7467
|
-
|
|
7468
|
-
|
|
7469
|
-
|
|
7470
|
-
|
|
7471
|
-
|
|
7472
|
-
|
|
7473
|
-
|
|
7474
|
-
}, style: {
|
|
7475
|
-
fontSize: 12,
|
|
7476
|
-
padding: '4px 10px',
|
|
7477
|
-
// Touch floor for this inline bar action (36px, matching
|
|
7478
|
-
// the notice-card buttons).
|
|
7479
|
-
...(isCoarse ? { minHeight: 36 } : {}),
|
|
7480
|
-
borderRadius: 6,
|
|
7481
|
-
border: '1px solid rgba(64,112,224,0.4)',
|
|
7482
|
-
background: 'rgba(64,112,224,0.2)',
|
|
7483
|
-
color: '#4070e0',
|
|
7484
|
-
cursor: commitBusy ? 'not-allowed' : 'pointer',
|
|
7485
|
-
opacity: commitBusy ? 0.5 : 1,
|
|
7486
|
-
transition: 'background 100ms, border-color 100ms, color 100ms',
|
|
7487
|
-
}, children: commitState?.status === 'committing'
|
|
7456
|
+
}, disabled: commitBusy,
|
|
7457
|
+
// The SAME design-system button as the tests bar's action
|
|
7458
|
+
// one strip above (and as the green AutoCommitBadge that
|
|
7459
|
+
// replaces this one when auto-commit is on) — only the
|
|
7460
|
+
// semantic colour differs. The CVA owns hover/active/focus
|
|
7461
|
+
// and the disabled look, so there is nothing to hand-roll:
|
|
7462
|
+
// this used to be an inline 12px/6px-radius button with
|
|
7463
|
+
// hardcoded rgba(64,112,224,*) and hand-written hover, and
|
|
7464
|
+
// it visibly mismatched the 13px/3px tests-bar button.
|
|
7465
|
+
className: cm.cn(cm.button({ variant: 'solid', color: 'primary', size: 'xs' }), cm.touchTargetCompact), children: commitState?.status === 'committing'
|
|
7488
7466
|
? t('ide.chat.committing')
|
|
7489
7467
|
: t('ide.chat.commit') }));
|
|
7490
7468
|
})())] }), commitBarExpanded && (_jsx("div", { style: { marginTop: 4, paddingLeft: 16, maxHeight: 200, overflowY: 'auto' }, children: pendingFiles.map((f) => (_jsxs("button", { type: "button", onClick: () => onFileDiff?.(f.path), onMouseEnter: (e) => {
|
|
7491
|
-
|
|
7469
|
+
// Theme PRIMARY token, not a literal blue — the row sits in
|
|
7470
|
+
// the same bar as the commit button, which is now primary.
|
|
7471
|
+
e.currentTarget.style.color = 'var(--mol-color-primary, #4070e0)';
|
|
7492
7472
|
}, onMouseLeave: (e) => {
|
|
7493
7473
|
e.currentTarget.style.color = '';
|
|
7494
7474
|
}, style: {
|
|
@@ -7510,7 +7490,9 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
|
|
|
7510
7490
|
width: '100%',
|
|
7511
7491
|
overflow: 'hidden',
|
|
7512
7492
|
whiteSpace: 'nowrap',
|
|
7513
|
-
}, className: cm.textMuted, children: [_jsx("span", { style: { overflow: 'hidden', textOverflow: 'ellipsis' }, children: f.path }), (!!f.additions || !!f.deletions) && (_jsxs("span", { style: { marginLeft: 'auto', flexShrink: 0, fontSize: 10, opacity: 0.8 }, children: [!!f.additions && (_jsxs("span", { style: { color: '#3fb950' }, children: ["+", f.additions] })), !!f.additions && !!f.deletions && ' ', !!f.deletions && (_jsxs("span", { style: { color: '#f85149' }, children: ["-", f.deletions] }))] })), onFileRevert && (_jsx("span", {
|
|
7493
|
+
}, className: cm.textMuted, children: [_jsx("span", { style: { overflow: 'hidden', textOverflow: 'ellipsis' }, children: f.path }), (!!f.additions || !!f.deletions) && (_jsxs("span", { style: { marginLeft: 'auto', flexShrink: 0, fontSize: 10, opacity: 0.8 }, children: [!!f.additions && (_jsxs("span", { style: { color: '#3fb950' }, children: ["+", f.additions] })), !!f.additions && !!f.deletions && ' ', !!f.deletions && (_jsxs("span", { style: { color: '#f85149' }, children: ["-", f.deletions] }))] })), onFileRevert && (_jsx("span", {
|
|
7494
|
+
/* mol-bespoke-button: icon-only per-file revert affordance — 18px (32px coarse) hit box on a dense file row */
|
|
7495
|
+
role: "button", tabIndex: 0, title: t('ide.chat.revertFile', undefined, {
|
|
7514
7496
|
defaultValue: 'Revert to last commit',
|
|
7515
7497
|
}), onClick: (e) => {
|
|
7516
7498
|
e.stopPropagation();
|
|
@@ -7605,7 +7587,9 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
|
|
|
7605
7587
|
alignItems: 'center',
|
|
7606
7588
|
marginTop: '6px',
|
|
7607
7589
|
gap: '4px',
|
|
7608
|
-
}, children: [canEdit !== false && (_jsx("button", {
|
|
7590
|
+
}, children: [canEdit !== false && (_jsx("button", {
|
|
7591
|
+
/* mol-bespoke-button: icon-only composer toggle — shares the composer row's 24px / 40x32-coarse icon box model */
|
|
7592
|
+
type: "button", onClick: () => {
|
|
7609
7593
|
const newMode = mode === 'plan' ? 'execute' : 'plan';
|
|
7610
7594
|
setMode(newMode);
|
|
7611
7595
|
http
|
|
@@ -7650,7 +7634,9 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
|
|
|
7650
7634
|
}, onMouseLeave: (e) => {
|
|
7651
7635
|
if (mode !== 'plan')
|
|
7652
7636
|
e.currentTarget.style.opacity = '0.4';
|
|
7653
|
-
}, children: _jsx("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "currentColor", children: _jsx("path", { d: "M8 1.5c-2.363 0-4 1.69-4 3.75 0 .984.424 1.625.984 2.304l.214.253c.223.264.47.556.673.848.284.411.537.896.621 1.49a.75.75 0 0 1-1.484.211c-.04-.282-.163-.547-.37-.847a8.456 8.456 0 0 0-.542-.68c-.084-.1-.173-.205-.268-.32C3.201 7.75 2.5 6.766 2.5 5.25 2.5 2.31 4.863 0 8 0s5.5 2.31 5.5 5.25c0 1.516-.701 2.5-1.328 3.259-.095.115-.184.22-.268.319-.207.245-.383.453-.541.681-.208.3-.33.565-.37.847a.751.751 0 0 1-1.485-.212c.084-.593.337-1.078.621-1.489.203-.292.45-.584.673-.848.075-.088.147-.173.213-.253.561-.679.985-1.32.985-2.304 0-2.06-1.637-3.75-4-3.75ZM5.75 12h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1 0-1.5ZM6 15.25a.75.75 0 0 1 .75-.75h2.5a.75.75 0 0 1 0 1.5h-2.5a.75.75 0 0 1-.75-.75Z" }) }) })), fastModeAvailable && canEdit !== false && (_jsx("button", {
|
|
7637
|
+
}, children: _jsx("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "currentColor", children: _jsx("path", { d: "M8 1.5c-2.363 0-4 1.69-4 3.75 0 .984.424 1.625.984 2.304l.214.253c.223.264.47.556.673.848.284.411.537.896.621 1.49a.75.75 0 0 1-1.484.211c-.04-.282-.163-.547-.37-.847a8.456 8.456 0 0 0-.542-.68c-.084-.1-.173-.205-.268-.32C3.201 7.75 2.5 6.766 2.5 5.25 2.5 2.31 4.863 0 8 0s5.5 2.31 5.5 5.25c0 1.516-.701 2.5-1.328 3.259-.095.115-.184.22-.268.319-.207.245-.383.453-.541.681-.208.3-.33.565-.37.847a.751.751 0 0 1-1.485-.212c.084-.593.337-1.078.621-1.489.203-.292.45-.584.673-.848.075-.088.147-.173.213-.253.561-.679.985-1.32.985-2.304 0-2.06-1.637-3.75-4-3.75ZM5.75 12h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1 0-1.5ZM6 15.25a.75.75 0 0 1 .75-.75h2.5a.75.75 0 0 1 0 1.5h-2.5a.75.75 0 0 1-.75-.75Z" }) }) })), fastModeAvailable && canEdit !== false && (_jsx("button", {
|
|
7638
|
+
/* mol-bespoke-button: icon-only composer toggle — shares the composer row's 24px / 40x32-coarse icon box model */
|
|
7639
|
+
type: "button", "data-mol-id": "chat-fast-mode-toggle", disabled: !canEdit, onClick: () => {
|
|
7654
7640
|
const next = !fastMode;
|
|
7655
7641
|
setFastMode(next);
|
|
7656
7642
|
http
|
|
@@ -7693,7 +7679,9 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
|
|
|
7693
7679
|
}, onMouseLeave: (e) => {
|
|
7694
7680
|
if (!fastMode)
|
|
7695
7681
|
e.currentTarget.style.opacity = '0.4';
|
|
7696
|
-
}, children: _jsx("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "currentColor", children: _jsx("path", { d: "M9.504.43a.75.75 0 0 1 .584.859l-.828 4.211h4.49a.75.75 0 0 1 .573 1.234l-7.25 8.5a.75.75 0 0 1-1.32-.658l.828-4.211H2.09a.75.75 0 0 1-.573-1.234l7.25-8.5a.75.75 0 0 1 .737-.201Z" }) }) })), _jsx("button", {
|
|
7682
|
+
}, children: _jsx("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "currentColor", children: _jsx("path", { d: "M9.504.43a.75.75 0 0 1 .584.859l-.828 4.211h4.49a.75.75 0 0 1 .573 1.234l-7.25 8.5a.75.75 0 0 1-1.32-.658l.828-4.211H2.09a.75.75 0 0 1-.573-1.234l7.25-8.5a.75.75 0 0 1 .737-.201Z" }) }) })), _jsx("button", {
|
|
7683
|
+
/* mol-bespoke-button: icon-only composer toggle — shares the composer row's 24px / 40x32-coarse icon box model */
|
|
7684
|
+
type: "button", "data-mol-id": "chat-mic-button", onClick: toggleVoice, title: t('ide.chat.voice', undefined, {
|
|
7697
7685
|
defaultValue: isListening ? 'Stop dictation' : 'Dictate',
|
|
7698
7686
|
}), style: {
|
|
7699
7687
|
display: 'inline-flex',
|
|
@@ -7715,7 +7703,9 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
|
|
|
7715
7703
|
}, onMouseLeave: (e) => {
|
|
7716
7704
|
if (!isListening)
|
|
7717
7705
|
e.currentTarget.style.opacity = '0.4';
|
|
7718
|
-
}, children: _jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 16 16", width: "16", height: "16", style: { display: 'block' }, children: [_jsx("rect", { x: "6", y: "1", width: "4", height: "8", rx: "2", fill: isListening ? 'currentColor' : 'none', stroke: "currentColor", strokeWidth: "1.25" }), _jsx("path", { d: "M4 7v1a4 4 0 008 0V7", fill: "none", stroke: "currentColor", strokeWidth: "1.25", strokeLinecap: "round" }), _jsx("line", { x1: "8", y1: "12", x2: "8", y2: "15", stroke: "currentColor", strokeWidth: "1.25", strokeLinecap: "round" }), _jsx("line", { x1: "6", y1: "15", x2: "10", y2: "15", stroke: "currentColor", strokeWidth: "1.25", strokeLinecap: "round" })] }) }), canEdit !== false && (_jsx("button", {
|
|
7706
|
+
}, children: _jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 16 16", width: "16", height: "16", style: { display: 'block' }, children: [_jsx("rect", { x: "6", y: "1", width: "4", height: "8", rx: "2", fill: isListening ? 'currentColor' : 'none', stroke: "currentColor", strokeWidth: "1.25" }), _jsx("path", { d: "M4 7v1a4 4 0 008 0V7", fill: "none", stroke: "currentColor", strokeWidth: "1.25", strokeLinecap: "round" }), _jsx("line", { x1: "8", y1: "12", x2: "8", y2: "15", stroke: "currentColor", strokeWidth: "1.25", strokeLinecap: "round" }), _jsx("line", { x1: "6", y1: "15", x2: "10", y2: "15", stroke: "currentColor", strokeWidth: "1.25", strokeLinecap: "round" })] }) }), canEdit !== false && (_jsx("button", {
|
|
7707
|
+
/* mol-bespoke-button: icon-only composer affordance — shares the composer row's 24px / 40x32-coarse icon box model */
|
|
7708
|
+
type: "button", onClick: () => fileInputRef.current?.click(), title: t('ide.chat.attachFile', undefined, { defaultValue: 'Attach file' }), style: {
|
|
7719
7709
|
display: 'inline-flex',
|
|
7720
7710
|
alignItems: 'center',
|
|
7721
7711
|
justifyContent: 'center',
|
|
@@ -7892,46 +7882,27 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
|
|
|
7892
7882
|
display: 'flex',
|
|
7893
7883
|
gap: '4px',
|
|
7894
7884
|
alignItems: 'center',
|
|
7895
|
-
}, children: [canEdit !== false && (isLoading || isRemoteStreaming) && (_jsx("button", { type: "button", onClick: handleAbort, title: t('ide.chat.stop', undefined, { defaultValue: 'Stop' }),
|
|
7896
|
-
|
|
7897
|
-
|
|
7898
|
-
|
|
7899
|
-
|
|
7900
|
-
|
|
7901
|
-
}, style: {
|
|
7902
|
-
|
|
7903
|
-
|
|
7904
|
-
|
|
7905
|
-
|
|
7906
|
-
|
|
7907
|
-
cursor: 'pointer',
|
|
7908
|
-
transition: 'background 100ms, border-color 100ms',
|
|
7909
|
-
display: 'flex',
|
|
7910
|
-
alignItems: 'center',
|
|
7911
|
-
justifyContent: 'center',
|
|
7912
|
-
// Touch hit-area floor for the composer's action buttons.
|
|
7885
|
+
}, children: [canEdit !== false && (isLoading || isRemoteStreaming) && (_jsx("button", { type: "button", "data-mol-id": "chat-stop-button", onClick: handleAbort, title: t('ide.chat.stop', undefined, { defaultValue: 'Stop' }),
|
|
7886
|
+
// The composer's two action buttons (Stop, Send) are design-system
|
|
7887
|
+
// buttons in the ERROR and PRIMARY semantics — same radius, height
|
|
7888
|
+
// and states as every other action button in the panel. They were a
|
|
7889
|
+
// matched pair of hand-rolled 6px-radius frames with hardcoded
|
|
7890
|
+
// rgba(248,81,73,*) / rgba(96,160,240,*) and hand-written hover.
|
|
7891
|
+
className: cm.button({ variant: 'solid', color: 'error', size: 'xs' }), style: {
|
|
7892
|
+
// The composer's documented touch box: wide for hit spacing but
|
|
7893
|
+
// deliberately flat (40×32) so the row doesn't balloon. This is the
|
|
7894
|
+
// one thing the ClassMap can't express here, and the reason this is
|
|
7895
|
+
// NOT cm.touchTargetCompact — a 36px floor would out-grow the
|
|
7896
|
+
// neighbouring icon buttons.
|
|
7913
7897
|
...(isCoarse ? { minWidth: 40, minHeight: 32 } : {}),
|
|
7914
|
-
}, children: _jsx("svg", { width: "12", height: "12", viewBox: "0 0 12 12", style: { display: 'block' }, children: _jsx("rect", { x: "2", y: "2", width: "8", height: "8", rx: "1.5", fill: "currentColor" }) }) })), _jsx("button", { type: "button", onClick: () => void handleSubmit(), title: t('ide.chat.send', undefined, { defaultValue: 'Send' }), disabled: !hasInput && attachedFiles.length === 0,
|
|
7915
|
-
|
|
7916
|
-
|
|
7917
|
-
|
|
7918
|
-
|
|
7919
|
-
|
|
7920
|
-
|
|
7921
|
-
|
|
7922
|
-
}, style: {
|
|
7923
|
-
padding: '5px 10px',
|
|
7924
|
-
borderRadius: 6,
|
|
7925
|
-
border: '1px solid rgba(96,160,240,0.5)',
|
|
7926
|
-
background: 'rgba(96,160,240,0.2)',
|
|
7927
|
-
color: '#6aa3f0',
|
|
7928
|
-
cursor: !hasInput && attachedFiles.length === 0 ? 'not-allowed' : 'pointer',
|
|
7929
|
-
opacity: !hasInput && attachedFiles.length === 0 ? 0.5 : 1,
|
|
7930
|
-
transition: 'background 100ms, border-color 100ms, color 100ms',
|
|
7931
|
-
display: 'flex',
|
|
7932
|
-
alignItems: 'center',
|
|
7933
|
-
justifyContent: 'center',
|
|
7934
|
-
// Touch hit-area floor for the composer's action buttons.
|
|
7898
|
+
}, children: _jsx("svg", { width: "12", height: "12", viewBox: "0 0 12 12", style: { display: 'block' }, children: _jsx("rect", { x: "2", y: "2", width: "8", height: "8", rx: "1.5", fill: "currentColor" }) }) })), _jsx("button", { type: "button", "data-mol-id": "chat-send-button", onClick: () => void handleSubmit(), title: t('ide.chat.send', undefined, { defaultValue: 'Send' }), disabled: !hasInput && attachedFiles.length === 0,
|
|
7899
|
+
// Stop's twin in the PRIMARY semantic. The real `disabled`
|
|
7900
|
+
// attribute above carries the muted/inert look via the CVA
|
|
7901
|
+
// (`disabled:opacity-50 disabled:pointer-events-none`), so the
|
|
7902
|
+
// hand-rolled cursor/opacity pair is gone with the rest.
|
|
7903
|
+
className: cm.button({ variant: 'solid', color: 'primary', size: 'xs' }), style: {
|
|
7904
|
+
// See the Stop button: the composer's documented flat 40×32 touch
|
|
7905
|
+
// box, which the ClassMap can't express.
|
|
7935
7906
|
...(isCoarse ? { minWidth: 40, minHeight: 32 } : {}),
|
|
7936
7907
|
}, children: _jsx("svg", { width: "12", height: "12", viewBox: "0 0 12 12", style: { display: 'block' }, children: _jsx("path", { d: "M 2.5,6.5 L 6,3 L 9.5,6.5 M 6,3.5 L 6,10", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round" }) }) })] })] })] })] }), reportModal && (_jsx(ReportModal, { projectId: projectId, conversationId: conversationId, initialTitle: reportModal.title, productName: productName, appVersion: version || APP_VERSION, onClose: () => setReportModal(null), onSubmitted: (result) => {
|
|
7937
7908
|
setReportModal(null);
|
|
@@ -8091,7 +8062,9 @@ export function ChatPanel({ projectId, endpoint, initialMessage, onInitialMessag
|
|
|
8091
8062
|
height: isCoarse ? undefined : '33px',
|
|
8092
8063
|
minHeight: '33px',
|
|
8093
8064
|
zIndex: 10,
|
|
8094
|
-
}, children: [_jsxs("button", {
|
|
8065
|
+
}, children: [_jsxs("button", {
|
|
8066
|
+
/* mol-bespoke-button: conversation picker — the header title row, a full-width disclosure for the history dropdown */
|
|
8067
|
+
type: "button", onClick: handleToggleDropdown, className: cm.cn(cm.textSize('xs'), cm.textMuted), onMouseEnter: (e) => {
|
|
8095
8068
|
const s = e.currentTarget.querySelector('span');
|
|
8096
8069
|
if (s)
|
|
8097
8070
|
s.style.opacity = '1';
|