Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions frontend/editor/public/locales/en-US/translation.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5788,6 +5788,7 @@ routing = "Routing"
security = "Security"

[policies.detail]
close = "Close"
editSettings = "Edit Settings"
enforces = "Enforces"
managedByOrg = "Managed by your organization. Contact a team leader to change this policy."
Expand Down Expand Up @@ -5841,6 +5842,7 @@ allDocTypesTitle = "All document types"
back = "Back"
builderDesc = "Build the sequence of tools this policy runs on each document."
clear = "Clear"
close = "Close"
continue = "Continue"
docTypesLabel = "Document types"
edit = "Edit"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ export function usePoliciesEnabled(): boolean {
return false;
}

/** Whether the Policies list should appear for the current user. False in core. */
export function usePoliciesVisible(): boolean {
return false;
}

/**
* Whether a policy is open (its detail should take over the rail). Always false
* in core; proprietary bridges to the policy-selection store.
Expand Down
130 changes: 70 additions & 60 deletions frontend/editor/src/core/components/tools/RightSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ import {
PoliciesSection,
PolicyDetailTakeover,
usePoliciesEnabled,
usePoliciesVisible,
usePolicyDetailActive,
} from "@app/components/policies/PoliciesSidebar";
import { PolicyAutoRunController } from "@app/components/policies/PolicyAutoRunController";
import { useFavoriteToolItems } from "@app/hooks/tools/useFavoriteToolItems";
import { useToolSections } from "@app/hooks/useToolSections";
import type { SubcategoryGroup } from "@app/hooks/useToolSections";
import { ToolIcon } from "@app/components/shared/ToolIcon";
import { PanelHeader } from "@shared/components/PanelHeader";
import { Tooltip as AppTooltip } from "@app/components/shared/Tooltip";
import { withViewTransition } from "@app/utils/viewTransition";
import ChevronLeftIcon from "@mui/icons-material/ChevronLeft";
Expand Down Expand Up @@ -67,6 +69,7 @@ export default function RightSidebar() {
} = useToolWorkflow();

const policiesEnabled = usePoliciesEnabled();
const policiesVisible = usePoliciesVisible();
const rawPolicyDetailActive = usePolicyDetailActive();
const fullscreenExpanded = useIsFullscreenExpanded();
const fullscreenGeometry = useToolPanelGeometry({
Expand Down Expand Up @@ -118,9 +121,14 @@ export default function RightSidebar() {
const inToolView = leftPanelView !== "toolPicker";
// Show X (close) button only when there's somewhere to go back to.
const showCloseButton = inToolView || allToolsView;
// Policies sit above the tool list in the default tool-picker view.
// Policies sit above the tool list in the default tool-picker view — but only
// when the current user actually has policies to see (see usePoliciesVisible),
// so regular users with none get the plain tool picker with no empty block.
const showPolicies =
policiesEnabled && !allToolsView && leftPanelView === "toolPicker";
policiesEnabled &&
policiesVisible &&
!allToolsView &&
leftPanelView === "toolPicker";
// When Policies are shown, the search moves OUT of the header to sit between
// the Policies and Tools sections (separating them); otherwise it stays in the
// header. Show the header search when there's a close button, or in the
Expand Down Expand Up @@ -286,65 +294,67 @@ export default function RightSidebar() {
</div>
) : (
<>
{!showPolicies && (
<div className="tool-panel__compact-header">
{activeTool ? (
<div
className="tool-panel__active-tool-pill"
aria-label={activeTool.name}
>
<span className="tool-panel__active-tool-pill-icon">
<ToolIcon
icon={activeTool.icon}
marginRight="0"
color="var(--mantine-color-blue-filled)"
/>
</span>
<span className="tool-panel__active-tool-pill-label">
{activeTool.name}
</span>
</div>
) : showHeaderSearch ? (
<div className="tool-panel__compact-header-search">
<ToolSearch
value={searchQuery}
onChange={handleHeaderSearchChange}
toolRegistry={toolRegistry}
mode="filter"
autoFocus={allToolsView && !inToolView}
{!showPolicies &&
(activeTool ? (
<PanelHeader
icon={
<ToolIcon
icon={activeTool.icon}
marginRight="0"
color="currentColor"
/>
</div>
) : null}
{showCloseButton ? (
<ActionIcon
variant="subtle"
color="gray"
radius="xl"
size="md"
onClick={handleHeaderBack}
aria-label={
inToolView
? t("toolPanel.backToAllTools", "Back to all tools")
: t("toolPanel.goBack", "Go back")
}
className="tool-panel__expand-btn"
>
<CloseIcon sx={{ fontSize: "1.1rem" }} />
</ActionIcon>
) : (
<ActionIcon
variant="outline"
radius="xl"
size="md"
onClick={handleCollapse}
aria-label={t("toolPanel.collapse", "Collapse panel")}
className="tool-panel__expand-btn tool-panel__toggle-vt"
>
<ChevronRightIcon sx={{ fontSize: "1.1rem" }} />
</ActionIcon>
)}
</div>
)}
}
title={activeTool.name}
onClose={handleHeaderBack}
closeLabel={
inToolView
? t("toolPanel.backToAllTools", "Back to all tools")
: t("toolPanel.goBack", "Go back")
}
/>
) : (
<div className="tool-panel__compact-header">
{showHeaderSearch ? (
<div className="tool-panel__compact-header-search">
<ToolSearch
value={searchQuery}
onChange={handleHeaderSearchChange}
toolRegistry={toolRegistry}
mode="filter"
autoFocus={allToolsView && !inToolView}
/>
</div>
) : null}
{showCloseButton ? (
<ActionIcon
variant="subtle"
color="gray"
radius="xl"
size="md"
onClick={handleHeaderBack}
aria-label={
inToolView
? t("toolPanel.backToAllTools", "Back to all tools")
: t("toolPanel.goBack", "Go back")
}
className="tool-panel__expand-btn"
>
<CloseIcon sx={{ fontSize: "1.1rem" }} />
</ActionIcon>
) : (
<ActionIcon
variant="outline"
radius="xl"
size="md"
onClick={handleCollapse}
aria-label={t("toolPanel.collapse", "Collapse panel")}
className="tool-panel__expand-btn tool-panel__toggle-vt"
>
<ChevronRightIcon sx={{ fontSize: "1.1rem" }} />
</ActionIcon>
)}
</div>
))}

{showPolicies && (
<PoliciesSection
Expand Down
61 changes: 0 additions & 61 deletions frontend/editor/src/core/components/tools/ToolPanel.css
Original file line number Diff line number Diff line change
Expand Up @@ -294,67 +294,6 @@
background-color: var(--bg-muted);
}

.tool-panel__active-tool-pill {
display: inline-flex;
align-items: center;
gap: 0.5rem;
flex: 1 1 auto;
min-width: 0;
padding: 0.35rem 0.75rem 0.35rem 0.4rem;
border: 1px solid var(--border-subtle);
border-radius: 9999px;
background: var(--mantine-color-body);
}

.tool-panel__active-tool-pill-icon {
display: inline-flex;
align-items: center;
justify-content: center;
width: 1.75rem;
height: 1.75rem;
border-radius: 9999px;
background: var(--mantine-color-blue-light);
color: var(--mantine-color-blue-filled);
flex-shrink: 0;
}

[data-mantine-color-scheme="dark"] .tool-panel__active-tool-pill-icon {
background: color-mix(
in srgb,
var(--mantine-color-blue-filled) 18%,
transparent
);
color: var(--mantine-color-blue-3, var(--mantine-color-blue-filled));
}

/* The inner .tool-button-icon wrapper carries its own transform/margin; reset
them so the icon glyph sits dead-centre in the circular background. */
.tool-panel__active-tool-pill-icon .tool-button-icon {
margin: 0 !important;
transform: none !important;
display: inline-flex;
align-items: center;
justify-content: center;
line-height: 1;
}

.tool-panel__active-tool-pill-icon svg {
font-size: 1rem;
width: 1rem;
height: 1rem;
}

.tool-panel__active-tool-pill-label {
font-size: 0.9rem;
font-weight: 600;
flex: 1;
min-width: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: var(--text-primary);
}

::view-transition-old(tool-rail) {
animation: vt-rail-fade-out 180ms ease-out forwards;
}
Expand Down
98 changes: 1 addition & 97 deletions frontend/editor/src/proprietary/components/chat/ChatPanel.css
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,7 @@
flex-shrink: 0;
}

.chat-panel__agent-pill {
display: inline-flex;
align-items: center;
gap: 0.5rem;
flex: 1;
min-width: 0;
padding: 0.4rem 0.75rem 0.4rem 0.4rem;
border: 1px solid var(--border-subtle);
border-radius: 9999px;
background: var(--mantine-color-body);
cursor: pointer;
transition:
background 120ms ease-out,
border-color 120ms ease-out;
.chat-panel__agent-pill-vt {
view-transition-name: stirling-agent;
}

Expand All @@ -50,89 +37,6 @@
animation-timing-function: cubic-bezier(0.32, 0.72, 0, 1);
}

.chat-panel__agent-pill:hover {
background: var(--mantine-color-default-hover);
}

.chat-panel__agent-pill-icon {
display: inline-flex;
align-items: center;
justify-content: center;
width: 1.75rem;
height: 1.75rem;
border-radius: 9999px;
background: var(--mantine-color-blue-light);
color: var(--mantine-color-blue-filled);
flex-shrink: 0;
position: relative;
}

/* Running / in-progress status dot, anchored to the agent pill icon. */
.agent-status-dot {
position: absolute;
bottom: 0;
right: 0;
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--mantine-color-blue-5);
border: 1.5px solid var(--mantine-color-body);
animation: agent-dot-pulse 2.4s ease-in-out infinite;
pointer-events: none;
}

@keyframes agent-dot-pulse {
0%,
100% {
opacity: 1;
}
50% {
opacity: 0.45;
}
}

@media (prefers-reduced-motion: reduce) {
.agent-status-dot {
animation: none;
}
}

.chat-panel__agent-pill--loading {
border-color: color-mix(
in srgb,
var(--mantine-color-blue-5) 60%,
var(--border-subtle)
);
}

[data-mantine-color-scheme="dark"] .chat-panel__agent-pill--loading {
border-color: color-mix(
in srgb,
var(--mantine-color-blue-4) 55%,
var(--border-subtle)
);
}

/* Dark-mode: let the pill blend into the rail. Just a thin border, no fill —
so it doesn't read as a clashing lighter card on the dark toolbar. */
[data-mantine-color-scheme="dark"] .chat-panel__agent-pill {
background: transparent;
border-color: var(--border-subtle);
}

[data-mantine-color-scheme="dark"] .chat-panel__agent-pill:hover {
background: rgba(255, 255, 255, 0.04);
}

[data-mantine-color-scheme="dark"] .chat-panel__agent-pill-icon {
background: color-mix(
in srgb,
var(--mantine-color-blue-filled) 18%,
transparent
);
color: var(--mantine-color-blue-3, var(--mantine-color-blue-filled));
}

/* Same treatment for the input pill and quick-action cards. */
[data-mantine-color-scheme="dark"] .chat-panel-input {
background: transparent;
Expand Down
Loading
Loading