mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-26 14:01:12 +00:00
* feat(chat): switch between session transcript branches from the chat header * fix(chat): type fixes and protocol regen for branch switcher CI
383 lines
9.5 KiB
CSS
383 lines
9.5 KiB
CSS
openclaw-chat-pane {
|
|
display: flex;
|
|
flex-direction: column;
|
|
flex: 1 1 0;
|
|
min-width: 0;
|
|
min-height: 0;
|
|
}
|
|
|
|
.chat-split-view__drop-container {
|
|
position: relative;
|
|
display: flex;
|
|
flex: 1 1 0;
|
|
width: 100%;
|
|
min-width: 0;
|
|
min-height: 0;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.chat-split-view {
|
|
display: flex;
|
|
flex: 1 1 0;
|
|
width: 100%;
|
|
min-width: 0;
|
|
min-height: 0;
|
|
overflow: auto;
|
|
}
|
|
|
|
.chat-split-view__column {
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-width: 320px;
|
|
min-height: 0;
|
|
}
|
|
|
|
/* One cell = pane header + pane; the header lives in-flow with its pane, so
|
|
split geometry needs no mirrored toolbar layer. */
|
|
.chat-split-view__cell {
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-width: 0;
|
|
min-height: 200px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.chat-split-view__cell--active {
|
|
box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 60%, transparent);
|
|
}
|
|
|
|
.chat-split-view__pane {
|
|
flex: 1 1 0;
|
|
min-width: 0;
|
|
min-height: 0;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.chat-split-view--narrow .chat-split-view__cell {
|
|
min-height: 0;
|
|
}
|
|
|
|
/* Narrow mode shows only the active pane; a focus ring is pure noise there. */
|
|
.chat-split-view--narrow .chat-split-view__cell--active {
|
|
box-shadow: none;
|
|
}
|
|
|
|
.chat-split-view__drop-indicator {
|
|
position: absolute;
|
|
z-index: 20;
|
|
box-sizing: border-box;
|
|
pointer-events: none;
|
|
border: 1px solid color-mix(in srgb, var(--accent) 65%, transparent);
|
|
border-radius: var(--radius-sm);
|
|
background: color-mix(in srgb, var(--accent) 14%, transparent);
|
|
}
|
|
|
|
.chat-split-view__drop-indicator--center {
|
|
border-color: transparent;
|
|
background: transparent;
|
|
box-shadow: inset 0 0 0 2px var(--accent);
|
|
}
|
|
|
|
.chat-split-view__drop-indicator-label {
|
|
position: absolute;
|
|
top: 50%;
|
|
left: 50%;
|
|
transform: translate(-50%, -50%);
|
|
padding: 3px 10px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 999px;
|
|
background: var(--panel);
|
|
color: var(--text);
|
|
font-size: 11px;
|
|
font-weight: 500;
|
|
white-space: nowrap;
|
|
pointer-events: none;
|
|
}
|
|
|
|
@media (prefers-reduced-motion: no-preference) {
|
|
.chat-split-view__drop-indicator {
|
|
animation: chat-drop-indicator-in 0.12s ease;
|
|
transition:
|
|
left 0.14s ease,
|
|
top 0.14s ease,
|
|
width 0.14s ease,
|
|
height 0.14s ease,
|
|
opacity 0.12s ease;
|
|
}
|
|
|
|
@keyframes chat-drop-indicator-in {
|
|
from {
|
|
opacity: 0;
|
|
}
|
|
|
|
to {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
.chat-pane__header {
|
|
display: flex;
|
|
flex: 0 0 auto;
|
|
align-items: center;
|
|
gap: 8px;
|
|
/* 48px centers the 28px actions on the app's shared 24px chrome
|
|
centerline (sidebar brand row, floating toggles), so split headers
|
|
line up with the sidebar across the top of the shell. */
|
|
min-height: 48px;
|
|
padding: 0 6px 0 12px;
|
|
border-bottom: 1px solid color-mix(in srgb, var(--border) 74%, transparent);
|
|
background: color-mix(in srgb, var(--panel) 62%, transparent);
|
|
/* Chrome row, not content: a selectable title would fight the native
|
|
window drag the macOS app starts from this row. */
|
|
user-select: none;
|
|
-webkit-user-select: none;
|
|
}
|
|
|
|
/* The title hugs its text so the workspace chip sits right after it (the
|
|
header's shared 8px gap provides the spacing); it may shrink with ellipsis
|
|
when space runs out, and the action row pushes itself to the right edge. */
|
|
.chat-pane__session-title {
|
|
flex: 0 1 auto;
|
|
min-width: 0;
|
|
overflow: hidden;
|
|
color: var(--text);
|
|
font-size: 12px;
|
|
white-space: nowrap;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.chat-pane__session-title-button {
|
|
display: block;
|
|
padding: 3px 5px;
|
|
border: 0;
|
|
border-radius: var(--radius-sm);
|
|
background: transparent;
|
|
text-align: left;
|
|
cursor: text;
|
|
}
|
|
|
|
.chat-pane__session-title-button:hover,
|
|
.chat-pane__session-title-button:focus-visible {
|
|
background: color-mix(in srgb, var(--text) 7%, transparent);
|
|
outline: none;
|
|
}
|
|
|
|
.chat-pane__session-title-input {
|
|
flex: 1 1 auto;
|
|
min-width: 60px;
|
|
height: 28px;
|
|
padding: 0 7px;
|
|
border: 1px solid var(--accent);
|
|
border-radius: var(--radius-sm);
|
|
background: var(--panel);
|
|
color: var(--text);
|
|
font: inherit;
|
|
font-size: 12px;
|
|
outline: none;
|
|
user-select: text;
|
|
-webkit-user-select: text;
|
|
}
|
|
|
|
/* Where supported, the rename input hugs its text too, so the workspace chip
|
|
tracks the title while typing; elsewhere editing falls back to full width. */
|
|
@supports (field-sizing: content) {
|
|
.chat-pane__session-title-input {
|
|
flex: 0 1 auto;
|
|
field-sizing: content;
|
|
max-width: min(60ch, 100%);
|
|
}
|
|
}
|
|
|
|
.chat-pane__cloud {
|
|
display: inline-flex;
|
|
flex: 0 0 auto;
|
|
align-items: center;
|
|
color: var(--muted);
|
|
}
|
|
|
|
.chat-pane__cloud svg,
|
|
.chat-pane__workspace-chip svg {
|
|
width: 14px;
|
|
height: 14px;
|
|
/* Lucide outline icons: without this the paths render browser-default
|
|
black fill, which reads as a solid dark blob on the chip. */
|
|
fill: none;
|
|
stroke: currentColor;
|
|
stroke-width: 1.5px;
|
|
stroke-linecap: round;
|
|
stroke-linejoin: round;
|
|
}
|
|
|
|
.chat-pane__workspace-menu {
|
|
flex: 0 1 auto;
|
|
min-width: 0;
|
|
}
|
|
|
|
.chat-pane__branches-menu {
|
|
flex: 0 0 auto;
|
|
}
|
|
|
|
.chat-pane__branches-trigger svg,
|
|
.chat-pane__branch-active svg {
|
|
width: 14px;
|
|
height: 14px;
|
|
}
|
|
|
|
.chat-pane__branch-item {
|
|
min-width: 260px;
|
|
max-width: 360px;
|
|
}
|
|
|
|
.chat-pane__branch-copy {
|
|
display: grid;
|
|
min-width: 0;
|
|
gap: 2px;
|
|
}
|
|
|
|
.chat-pane__branch-headline {
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.chat-pane__branch-meta {
|
|
color: var(--muted);
|
|
font-size: 11px;
|
|
}
|
|
|
|
.chat-pane__branch-active {
|
|
display: inline-flex;
|
|
margin-left: auto;
|
|
color: var(--accent);
|
|
}
|
|
|
|
.chat-pane__workspace-chip {
|
|
display: inline-flex;
|
|
max-width: 180px;
|
|
height: 26px;
|
|
align-items: center;
|
|
gap: 5px;
|
|
padding: 0 8px;
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-full);
|
|
background: var(--panel);
|
|
color: var(--muted);
|
|
font-size: 11px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.chat-pane__workspace-chip:hover,
|
|
.chat-pane__workspace-chip:focus-visible {
|
|
border-color: var(--muted-strong);
|
|
color: var(--text);
|
|
outline: none;
|
|
}
|
|
|
|
.chat-pane__workspace-chip span {
|
|
min-width: 0;
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.chat-pane__actions {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 2px;
|
|
flex: 0 0 auto;
|
|
/* With the title text-hugging, this claims the leftover width so the
|
|
action cluster stays pinned to the right edge (and doubles as the
|
|
native window-drag surface between chip and actions). */
|
|
margin-left: auto;
|
|
}
|
|
|
|
@media (max-width: 480px) {
|
|
.chat-pane__workspace-chip {
|
|
width: 28px;
|
|
padding: 0 6px;
|
|
justify-content: center;
|
|
}
|
|
|
|
.chat-pane__workspace-chip span {
|
|
display: none;
|
|
}
|
|
}
|
|
|
|
/* Plain web with the nav collapsed: the floating sidebar-expand pill
|
|
(.shell-nav-expand, fixed 10px/10px, 32px wide) overlays the first pane
|
|
header's left edge; 52px clears it so the session title stays readable.
|
|
Native shells below reserve larger insets for their own window chrome. */
|
|
html:not(.openclaw-native-macos):not(.openclaw-native-nav):not(.openclaw-native-web-chrome)
|
|
.shell--nav-collapsed:not(.shell--mobile-nav)
|
|
.chat-split-view__column:first-child
|
|
> .chat-split-view__cell:first-child
|
|
.chat-pane__header {
|
|
padding-left: 52px;
|
|
}
|
|
|
|
/* Native macOS desktop shells: the pane header is the window's top surface,
|
|
so it adopts the app titlebar height (52px injected by
|
|
DashboardWindowController; the 50px fallback mirrors
|
|
.macos-titlebar-controls for older app builds). The web 48px default would
|
|
center the session title/actions 2px above the traffic-light/hosted-button
|
|
centerline. Drawer layouts instead fold titlebar clearance into their 58px
|
|
topbar row (layout.mobile.css). */
|
|
html.openclaw-native-macos .shell:not(.shell--mobile-nav) .chat-pane__header {
|
|
min-height: var(--openclaw-native-titlebar-height, 50px);
|
|
}
|
|
|
|
/* Native macOS: with the nav column collapsed the top-left pane header is the
|
|
window's top surface, so its content shifts right of the floating window
|
|
chrome (Safari-style) instead of hiding under it. Traffic lights end at
|
|
x=78; newer apps (openclaw-native-nav) also float the titlebar accessory
|
|
(sidebar toggle + back/forward, DashboardWindowController) ending ~x=194.
|
|
Drawer layouts reserve a 58px topbar row instead (layout.mobile.css). The
|
|
first column's min-width grows by the extra inset
|
|
(90/204 minus the 12px base padding): the header's action row cannot
|
|
shrink, and the cell's overflow:hidden would clip the close/split buttons
|
|
at the 320px column minimum otherwise. */
|
|
html.openclaw-native-macos
|
|
.shell--nav-collapsed:not(.shell--mobile-nav)
|
|
.chat-split-view__column:first-child {
|
|
min-width: 398px;
|
|
}
|
|
|
|
html.openclaw-native-macos
|
|
.shell--nav-collapsed:not(.shell--mobile-nav)
|
|
.chat-split-view__column:first-child
|
|
> .chat-split-view__cell:first-child
|
|
.chat-pane__header {
|
|
padding-left: 90px;
|
|
}
|
|
|
|
html.openclaw-native-nav
|
|
.shell--nav-collapsed:not(.shell--mobile-nav)
|
|
.chat-split-view__column:first-child {
|
|
min-width: 512px;
|
|
}
|
|
|
|
html.openclaw-native-nav
|
|
.shell--nav-collapsed:not(.shell--mobile-nav)
|
|
.chat-split-view__column:first-child
|
|
> .chat-split-view__cell:first-child
|
|
.chat-pane__header {
|
|
padding-left: 204px;
|
|
}
|
|
|
|
/* 246px = 78px traffic lights + (5 * 28px buttons + 4 * 4px gaps) + 12px.
|
|
The 554px minimum adds the 234px inset delta to the 320px base column. */
|
|
html.openclaw-native-web-chrome
|
|
.shell--nav-collapsed:not(.shell--mobile-nav)
|
|
.chat-split-view__column:first-child {
|
|
min-width: 554px;
|
|
}
|
|
|
|
html.openclaw-native-web-chrome
|
|
.shell--nav-collapsed:not(.shell--mobile-nav)
|
|
.chat-split-view__column:first-child
|
|
> .chat-split-view__cell:first-child
|
|
.chat-pane__header {
|
|
padding-left: 246px;
|
|
}
|