Files
openclaw/ui/src/styles/layout.css
Val Alexander da5b7ff0af style(ui): polish agent file preview and usage popovers (#53382)
* feat: make workspace links clickable in agent context card and files list

Updated the agent context card and files list to render workspace names as clickable links, allowing users to easily access the corresponding workspace files. This enhances usability by providing direct navigation to the workspace location.

* style(ui): polish markdown preview dialog

* style(ui): reduce markdown preview list indentation

* style(ui): update markdown preview dialog width and alignment

* fix(ui): open usage filter popovers toward the right

* style(ui): adjust positioning of usage filter and export popovers

* style(ui): update sidebar footer padding and modify usage header z-index

* style(ui): adjust positioning of usage filter popover to the left and export popover to the right

* style(ui): simplify workspace link rendering in agent context card

* UI: make workspace paths interactive buttons or plain text

Agent Context card workspace (Channels/Cron panels): replace non-interactive
<div> with a real <button> wired to onSelectPanel('files'), matching the
Overview panel pattern.

Core Files footer workspace: drop workspace-link class since the user is
already on the Files panel — keep as plain text.
2026-03-23 23:55:25 -05:00

1052 lines
21 KiB
CSS

/* ===========================================
Shell Layout
=========================================== */
.shell {
--shell-pad: 16px;
--shell-gap: 16px;
--shell-nav-width: 258px;
--shell-nav-rail-width: 78px;
--shell-topbar-height: 52px;
--shell-focus-duration: 200ms;
--shell-focus-ease: var(--ease-out);
height: 100vh;
display: grid;
grid-template-columns: var(--shell-nav-width) minmax(0, 1fr);
grid-template-rows: var(--shell-topbar-height) 1fr;
grid-template-areas:
"nav topbar"
"nav content";
gap: 0;
animation: dashboard-enter 0.3s var(--ease-out);
transition: grid-template-columns var(--shell-focus-duration) var(--shell-focus-ease);
overflow: hidden;
}
@supports (height: 100dvh) {
.shell {
height: 100dvh;
}
}
.shell--chat {
min-height: 100vh;
height: 100vh;
overflow: hidden;
}
@supports (height: 100dvh) {
.shell--chat {
height: 100dvh;
}
}
.shell--nav-collapsed {
grid-template-columns: var(--shell-nav-rail-width) minmax(0, 1fr);
}
.shell--chat-focus {
grid-template-columns: 0px minmax(0, 1fr);
}
.shell--onboarding {
grid-template-columns: 0 minmax(0, 1fr);
grid-template-rows: 0 1fr;
}
.shell--onboarding .topbar {
display: none;
}
.shell--onboarding .shell-nav {
display: none;
}
.shell--onboarding .content {
padding-top: 0;
}
.shell--chat-focus .content {
padding-top: 0;
}
.shell--chat-focus .content > * + * {
margin-top: 0;
}
/* ===========================================
Topbar
=========================================== */
.topbar {
grid-area: topbar;
position: sticky;
top: 0;
z-index: 40;
display: flex;
align-items: center;
padding: 0 24px;
min-height: 58px;
border-bottom: 1px solid color-mix(in srgb, var(--border) 74%, transparent);
background: color-mix(in srgb, var(--bg) 82%, transparent);
backdrop-filter: blur(12px) saturate(1.6);
-webkit-backdrop-filter: blur(12px) saturate(1.6);
}
.topnav-shell {
display: flex;
align-items: center;
gap: 16px;
width: 100%;
min-height: var(--shell-topbar-height);
padding: 0;
border: none;
border-radius: 0;
background: transparent;
box-shadow: none;
}
.topbar-nav-toggle {
display: none;
}
.topnav-shell__actions {
display: flex;
align-items: center;
gap: 12px;
flex-shrink: 0;
}
.topnav-shell__content {
min-width: 0;
flex: 1;
}
.topbar .nav-collapse-toggle {
width: 36px;
height: 36px;
margin-bottom: 0;
}
.topbar .nav-collapse-toggle__icon {
width: 20px;
height: 20px;
}
.topbar .nav-collapse-toggle__icon svg {
width: 20px;
height: 20px;
}
.topnav-shell .dashboard-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
min-width: 0;
}
.topnav-shell .dashboard-header__breadcrumb {
display: flex;
align-items: center;
gap: 8px;
min-width: 0;
overflow: hidden;
font-size: 13px;
}
.topnav-shell .dashboard-header__breadcrumb-link,
.topnav-shell .dashboard-header__breadcrumb-sep {
color: var(--muted);
}
.topnav-shell .dashboard-header__breadcrumb-current {
color: var(--text-strong);
font-weight: 650;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.topbar-status {
display: flex;
align-items: center;
gap: 8px;
}
.topbar-status .pill {
padding: 6px 10px;
gap: 6px;
font-size: 12px;
font-weight: 500;
height: 32px;
box-sizing: border-box;
}
.topbar-status .pill .mono {
display: flex;
align-items: center;
line-height: 1;
margin-top: 0px;
}
.topbar-status .statusDot {
width: 6px;
height: 6px;
}
.topbar-status .theme-orb__trigger {
width: 26px;
height: 26px;
font-size: 13px;
}
.topbar-search {
display: inline-flex;
align-items: center;
gap: 12px;
min-height: 38px;
padding: 0 14px;
border: 1px solid color-mix(in srgb, var(--border) 88%, transparent);
border-radius: var(--radius-full);
background: color-mix(in srgb, var(--bg-elevated) 84%, transparent);
color: var(--muted);
font-size: 13px;
cursor: pointer;
transition:
border-color var(--duration-fast) ease,
background var(--duration-fast) ease,
color var(--duration-fast) ease;
min-width: 200px;
}
.topbar-search:hover {
border-color: color-mix(in srgb, var(--border-strong) 90%, transparent);
background: color-mix(in srgb, var(--bg-hover) 84%, transparent);
color: var(--text);
}
.topbar-search:focus-visible {
outline: none;
box-shadow: var(--focus-ring);
}
.topbar-search__label {
flex: 1;
text-align: left;
}
.topbar-search__kbd {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 2px 6px;
border: 1px solid var(--border);
border-radius: var(--radius-sm);
background: var(--bg);
font-family: var(--mono);
font-size: 11px;
line-height: 1;
color: var(--muted);
}
.topbar-theme-mode {
display: inline-flex;
align-items: center;
gap: 2px;
padding: 3px;
border: 1px solid color-mix(in srgb, var(--border) 84%, transparent);
border-radius: var(--radius-full);
background: color-mix(in srgb, var(--bg-elevated) 78%, transparent);
}
.topbar-theme-mode__btn {
width: 30px;
height: 30px;
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0;
border: 1px solid transparent;
border-radius: var(--radius-full);
background: transparent;
color: var(--muted);
cursor: pointer;
transition:
color var(--duration-fast) ease,
background var(--duration-fast) ease,
border-color var(--duration-fast) ease;
}
.topbar-theme-mode__btn:hover {
color: var(--text);
background: var(--bg-hover);
}
.topbar-theme-mode__btn:focus-visible {
outline: none;
box-shadow: var(--focus-ring);
}
.topbar-theme-mode__btn--active {
color: var(--accent);
background: var(--accent-subtle);
border-color: color-mix(in srgb, var(--accent) 25%, transparent);
}
.topbar-theme-mode__btn svg {
width: 14px;
height: 14px;
stroke: currentColor;
fill: none;
stroke-width: 1.75px;
stroke-linecap: round;
stroke-linejoin: round;
}
/* ===========================================
Navigation Sidebar
=========================================== */
.shell-nav {
grid-area: nav;
display: flex;
min-height: 100%;
overflow: hidden;
border-right: 1px solid color-mix(in srgb, var(--border) 74%, transparent);
transition: width var(--shell-focus-duration) var(--shell-focus-ease);
}
.shell-nav-backdrop {
display: none;
}
.sidebar {
display: flex;
flex-direction: column;
flex: 1;
min-height: 0;
min-width: 0;
overflow: hidden;
background: color-mix(in srgb, var(--bg) 96%, var(--bg-elevated) 4%);
}
:root[data-theme-mode="light"] .sidebar {
background: color-mix(in srgb, var(--panel) 98%, white 2%);
}
.sidebar-shell {
display: flex;
flex-direction: column;
min-height: 0;
flex: 1;
padding: 14px 10px 12px;
border: none;
border-radius: 0;
background: transparent;
box-shadow: none;
}
.sidebar--collapsed {
width: var(--shell-nav-rail-width);
min-width: var(--shell-nav-rail-width);
flex: 0 0 var(--shell-nav-rail-width);
}
.sidebar-shell__header,
.sidebar-shell__footer {
flex-shrink: 0;
}
.sidebar-shell__header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
min-height: 0;
padding: 0 8px 18px;
}
.sidebar-shell__body {
min-height: 0;
flex: 1;
display: flex;
}
.sidebar-shell__footer {
padding: 12px 0 0;
border-top: 1px solid color-mix(in srgb, var(--border) 80%, transparent);
}
.sidebar-brand {
display: flex;
align-items: center;
gap: 10px;
min-width: 0;
}
.sidebar-brand__logo {
width: 32px;
height: 32px;
flex-shrink: 0;
border-radius: var(--radius-md);
box-shadow: 0 8px 18px color-mix(in srgb, black 12%, transparent);
}
.sidebar-brand__copy {
display: flex;
flex-direction: column;
gap: 2px;
min-width: 0;
}
.sidebar-brand__eyebrow {
font-size: 10px;
line-height: 1.1;
font-weight: 600;
letter-spacing: 0.08em;
color: var(--muted);
text-transform: uppercase;
}
.sidebar-brand__title {
font-size: 15px;
line-height: 1.1;
font-weight: 700;
letter-spacing: -0.03em;
color: var(--text-strong);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.sidebar-nav {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
padding: 0;
scrollbar-width: none;
}
.sidebar-nav::-webkit-scrollbar {
display: none;
}
.nav-collapse-toggle {
width: 36px;
height: 36px;
display: flex;
align-items: center;
justify-content: center;
background: color-mix(in srgb, var(--bg-elevated) 88%, transparent);
border: 1px solid color-mix(in srgb, var(--border-strong) 68%, transparent);
border-radius: var(--radius-full);
cursor: pointer;
transition:
background var(--duration-fast) ease,
border-color var(--duration-fast) ease,
color var(--duration-fast) ease,
transform var(--duration-fast) ease;
margin-bottom: 0;
color: var(--muted);
box-shadow: inset 0 1px 0 color-mix(in srgb, white 8%, transparent);
}
.nav-collapse-toggle:hover {
background: color-mix(in srgb, var(--bg-hover) 90%, transparent);
border-color: color-mix(in srgb, var(--border-strong) 88%, transparent);
color: var(--text);
transform: translateY(-1px);
}
.nav-collapse-toggle__icon {
display: flex;
align-items: center;
justify-content: center;
width: 16px;
height: 16px;
color: inherit;
}
.nav-collapse-toggle__icon svg {
width: 16px;
height: 16px;
stroke: currentColor;
fill: none;
stroke-width: 1.5px;
stroke-linecap: round;
stroke-linejoin: round;
}
.nav-section {
display: grid;
gap: 6px;
margin-bottom: 16px;
}
.nav-section:last-child {
margin-bottom: 0;
}
.nav-section__items {
display: grid;
gap: 4px;
}
.nav-section--collapsed .nav-section__items {
display: none;
}
.nav-section__label {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
width: 100%;
padding: 0 10px;
min-height: 28px;
background: transparent;
border: none;
border-radius: var(--radius-md);
color: color-mix(in srgb, var(--muted) 72%, var(--text) 28%);
cursor: pointer;
text-align: left;
transition:
color var(--duration-fast) ease,
background var(--duration-fast) ease;
}
.nav-section__label:hover {
color: var(--text);
background: color-mix(in srgb, var(--bg-hover) 72%, transparent);
}
.nav-section__label-text {
font-size: 12px;
font-weight: 700;
letter-spacing: 0.06em;
text-transform: uppercase;
}
.nav-section__chevron {
display: inline-flex;
align-items: center;
justify-content: center;
opacity: 0.5;
transition: transform var(--duration-fast) ease;
}
.nav-section__chevron svg {
width: 12px;
height: 12px;
stroke: currentColor;
fill: none;
stroke-width: 1.5px;
stroke-linecap: round;
stroke-linejoin: round;
}
.nav-section--collapsed .nav-section__chevron {
transform: rotate(-90deg);
}
.nav-item {
position: relative;
display: flex;
align-items: center;
justify-content: flex-start;
gap: 8px;
min-height: 40px;
padding: 0 9px;
border-radius: var(--radius-md);
border: 1px solid transparent;
background: transparent;
color: var(--muted);
cursor: pointer;
text-decoration: none;
transition:
border-color var(--duration-fast) ease,
background var(--duration-fast) ease,
color var(--duration-fast) ease,
transform var(--duration-fast) ease;
}
.nav-item__icon {
width: 16px;
height: 16px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
opacity: 0.72;
transition:
opacity var(--duration-fast) ease,
color var(--duration-fast) ease;
}
.nav-item__icon svg {
width: 16px;
height: 16px;
stroke: currentColor;
fill: none;
stroke-width: 1.5px;
stroke-linecap: round;
stroke-linejoin: round;
}
.nav-item__text {
font-size: 14px;
font-weight: 600;
white-space: nowrap;
}
.nav-item:hover {
color: var(--text);
background: color-mix(in srgb, var(--bg-hover) 84%, transparent);
border-color: color-mix(in srgb, var(--border) 72%, transparent);
text-decoration: none;
}
.nav-item:hover .nav-item__icon {
opacity: 1;
}
.nav-item.active,
.nav-item--active {
color: var(--text-strong);
background: color-mix(in srgb, var(--accent-subtle) 88%, var(--bg-elevated) 12%);
border-color: color-mix(in srgb, var(--accent) 18%, transparent);
box-shadow:
inset 0 1px 0 color-mix(in srgb, white 10%, transparent),
0 12px 24px color-mix(in srgb, black 10%, transparent);
}
.nav-item.active .nav-item__icon,
.nav-item--active .nav-item__icon {
opacity: 1;
color: var(--accent);
}
.sidebar--collapsed .sidebar-shell {
padding: 12px 8px 10px;
}
.sidebar--collapsed .sidebar-shell__header {
justify-content: center;
align-items: center;
gap: 0;
padding: 0 2px 16px;
}
.sidebar--collapsed .sidebar-nav {
padding: 0;
}
.sidebar--collapsed .nav-section {
gap: 6px;
margin-bottom: 16px;
}
.sidebar--collapsed .nav-item {
justify-content: center;
width: 44px;
min-height: 44px;
padding: 0;
margin: 0 auto;
border-radius: var(--radius-lg);
border-color: transparent;
box-shadow: none;
}
.sidebar--collapsed .nav-item__icon {
width: 18px;
height: 18px;
}
.sidebar--collapsed .nav-item__icon svg {
width: 18px;
height: 18px;
}
.sidebar--collapsed .nav-item__text,
.sidebar--collapsed .nav-item__external-icon {
display: none;
}
.sidebar--collapsed .nav-item--active::before,
.sidebar--collapsed .nav-item.active::before {
content: "";
position: absolute;
left: 8px;
top: 10px;
bottom: 10px;
width: 3px;
border-radius: var(--radius-full);
background: color-mix(in srgb, var(--accent) 86%, transparent);
box-shadow: 0 0 14px color-mix(in srgb, var(--accent) 34%, transparent);
}
.sidebar--collapsed .nav-item.active,
.sidebar--collapsed .nav-item--active {
background: linear-gradient(
180deg,
color-mix(in srgb, var(--accent) 14%, var(--bg-elevated) 86%) 0%,
color-mix(in srgb, var(--accent) 8%, var(--bg) 92%) 100%
);
border-color: color-mix(in srgb, var(--accent) 18%, var(--border) 82%);
box-shadow:
inset 0 1px 0 color-mix(in srgb, white 8%, transparent),
0 10px 20px color-mix(in srgb, black 18%, transparent);
}
.sidebar--collapsed .nav-collapse-toggle {
width: 42px;
height: 42px;
border-color: color-mix(in srgb, var(--border) 82%, transparent);
background: color-mix(in srgb, var(--bg-elevated) 92%, transparent);
box-shadow:
inset 0 1px 0 color-mix(in srgb, white 8%, transparent),
0 8px 18px color-mix(in srgb, black 16%, transparent);
}
.sidebar--collapsed .sidebar-brand__logo {
width: 34px;
height: 34px;
border-radius: var(--radius-md);
box-shadow:
0 10px 20px color-mix(in srgb, black 20%, transparent),
inset 0 1px 0 color-mix(in srgb, white 10%, transparent);
}
.sidebar-utility-group {
display: grid;
gap: 8px;
}
.sidebar-utility-link {
min-height: 42px;
}
.sidebar-version {
display: flex;
align-items: center;
justify-content: space-between;
gap: 10px;
min-height: 40px;
padding: 0 12px;
border-radius: var(--radius-lg);
background: color-mix(in srgb, var(--bg-elevated) 72%, transparent);
border: 1px solid color-mix(in srgb, var(--border) 72%, transparent);
}
.sidebar-version__label {
font-size: 11px;
font-weight: 600;
color: var(--muted);
text-transform: uppercase;
letter-spacing: 0.06em;
}
.sidebar-version__text {
font-size: 12px;
color: var(--text);
font-weight: 600;
}
.sidebar-version__dot {
width: 8px;
height: 8px;
border-radius: var(--radius-full);
background: color-mix(in srgb, var(--accent) 78%, white 22%);
box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 14%, transparent);
opacity: 1;
margin: 0 auto;
}
.sidebar-version__status {
width: 8px;
height: 8px;
border-radius: var(--radius-full);
flex-shrink: 0;
margin-left: auto;
}
.sidebar-version__status.sidebar-connection-status--online {
background: var(--ok);
box-shadow: 0 0 0 4px color-mix(in srgb, var(--ok) 14%, transparent);
}
.sidebar-version__status.sidebar-connection-status--offline {
background: var(--danger);
box-shadow: 0 0 0 4px color-mix(in srgb, var(--danger) 14%, transparent);
}
.sidebar--collapsed .sidebar-shell__footer {
padding: 8px 0 2px;
}
.sidebar--collapsed .sidebar-utility-group {
justify-items: center;
gap: 6px;
}
.sidebar--collapsed .sidebar-version {
width: 44px;
min-height: 44px;
padding: 0;
justify-content: center;
border-radius: var(--radius-lg);
}
.sidebar--collapsed .sidebar-version__status {
margin-left: 0;
}
/* Mode switch in sidebar — hidden on desktop, shown on mobile */
.sidebar-mode-switch {
display: none;
}
.shell--nav-collapsed .shell-nav {
width: var(--shell-nav-rail-width);
min-width: var(--shell-nav-rail-width);
}
.shell--chat-focus .shell-nav {
width: 0;
min-width: 0;
overflow: hidden;
pointer-events: none;
opacity: 0;
border-right-width: 0;
}
.nav-item__external-icon {
width: 12px;
height: 12px;
display: inline-flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
margin-left: auto;
opacity: 0;
transition: opacity var(--duration-fast) ease;
}
.nav-item__external-icon svg {
width: 12px;
height: 12px;
stroke: currentColor;
fill: none;
stroke-width: 1.5px;
stroke-linecap: round;
stroke-linejoin: round;
}
.nav-item:hover .nav-item__external-icon {
opacity: 0.5;
}
/* ===========================================
Content Area
=========================================== */
.content {
grid-area: content;
padding: 16px 20px 32px;
display: block;
min-height: 0;
overflow-y: auto;
overflow-x: hidden;
}
.content > * + * {
margin-top: 20px;
}
:root[data-theme-mode="light"] .content {
background: var(--bg-content);
}
.content--chat {
display: flex;
flex-direction: column;
gap: 2px;
overflow: hidden;
padding-bottom: 0;
}
.content--chat > * + * {
margin-top: 0;
}
/* Content header */
.content-header {
display: flex;
align-items: flex-end;
justify-content: space-between;
gap: 16px;
padding: 4px 8px;
overflow: hidden;
transform-origin: top center;
transition:
opacity var(--shell-focus-duration) var(--shell-focus-ease),
transform var(--shell-focus-duration) var(--shell-focus-ease),
max-height var(--shell-focus-duration) var(--shell-focus-ease),
padding var(--shell-focus-duration) var(--shell-focus-ease);
max-height: 80px;
}
.shell--chat-focus .content-header {
opacity: 0;
transform: translateY(-8px);
max-height: 0px;
padding: 0;
pointer-events: none;
}
.page-title {
font-size: 22px;
font-weight: 650;
letter-spacing: -0.03em;
line-height: 1.2;
color: var(--text-strong);
}
.page-sub {
color: var(--muted);
font-size: 13px;
font-weight: 400;
margin-top: 4px;
letter-spacing: -0.005em;
}
.page-meta {
display: flex;
gap: 8px;
}
/* Chat view header adjustments */
.content--chat .content-header {
flex-direction: row;
align-items: center;
justify-content: space-between;
gap: 16px;
padding-bottom: 0;
}
.content--chat .content-header > div:first-child {
text-align: left;
}
.content--chat .page-meta {
justify-content: flex-start;
}
.content--chat .chat-controls {
flex-shrink: 0;
}
/* ===========================================
Grid Utilities
=========================================== */
.grid {
display: grid;
gap: 20px;
}
.grid-cols-2 {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.grid-cols-3 {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.stat-grid {
display: grid;
gap: 14px;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}
.note-grid {
display: grid;
gap: 16px;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.row {
display: flex;
gap: 12px;
align-items: center;
}
.stack {
display: grid;
gap: 12px;
grid-template-columns: minmax(0, 1fr);
}
.filters {
display: flex;
flex-wrap: wrap;
gap: 8px;
align-items: center;
}
/* ===========================================
Responsive - Tablet
=========================================== */
@media (max-width: 1100px) {
.shell {
--shell-pad: 12px;
--shell-gap: 12px;
grid-template-columns: 1fr;
grid-template-rows: auto auto 1fr;
grid-template-areas:
"topbar"
"nav"
"content";
}
.grid-cols-2,
.grid-cols-3 {
grid-template-columns: 1fr;
}
.topbar {
position: static;
padding: 12px 14px;
gap: 10px;
}
.topbar-status {
flex-wrap: wrap;
}
.table-head,
.table-row {
grid-template-columns: 1fr;
}
.list-item {
grid-template-columns: 1fr;
}
}
/* Mobile chat controls — hidden on desktop, shown in layout.mobile.css */
.chat-mobile-controls-wrapper {
display: none;
}
.chat-controls-mobile-toggle {
display: none;
border-radius: var(--radius-full);
}
.chat-controls-dropdown {
display: none;
}