Files
openclaw/ui/src/styles/layout.mobile.css
Val Alexander 36c6d44eca feat(ui): add multi-session selection and deletion (#51924)
* feat(sessions): implement multi-session deletion and selection functionality

- Added `deleteSessionsAndRefresh` function to handle deletion of multiple sessions.
- Updated session state management to track selected session keys.
- Enhanced UI to support bulk actions for selected sessions, including delete and unselect options.
- Refactored related tests to accommodate new multi-session deletion logic.
- Improved responsiveness of sessions table with new CSS rules for mobile layouts.

* feat(sessions): add page deselection functionality and enhance error handling

- Implemented `onDeselectPage` method to allow deselecting specific pages in the session view.
- Updated `deleteSessionsAndRefresh` to handle multiple deletion errors, storing them in an array and displaying a consolidated error message.
- Enhanced tests to verify the new deselection behavior and updated error handling for session deletions.
2026-03-21 18:33:05 -05:00

764 lines
14 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* ===========================================
Mobile Layout
=========================================== */
/* Tablet and smaller: switch the left nav to a slide-over drawer. */
@media (max-width: 1100px) {
.shell,
.shell--nav-collapsed {
grid-template-columns: minmax(0, 1fr);
grid-template-rows: var(--shell-topbar-height) minmax(0, 1fr);
grid-template-areas:
"topbar"
"content";
}
.shell--chat-focus {
grid-template-rows: var(--shell-topbar-height) minmax(0, 1fr);
}
.shell-nav,
.shell--nav-collapsed .shell-nav {
position: fixed;
top: 0;
bottom: 0;
left: 0;
z-index: 70;
width: min(86vw, 320px);
min-width: 0;
border-right: none;
box-shadow: 0 30px 80px color-mix(in srgb, black 40%, transparent);
transform: translateX(-100%);
opacity: 0;
pointer-events: none;
transition:
transform var(--shell-focus-duration) var(--shell-focus-ease),
opacity var(--shell-focus-duration) var(--shell-focus-ease);
}
.shell--nav-collapsed:not(.shell--nav-drawer-open) .shell-nav {
width: var(--shell-nav-rail-width);
transform: translateX(0);
opacity: 1;
pointer-events: auto;
box-shadow: none;
}
.shell--nav-drawer-open .shell-nav,
.shell--nav-collapsed.shell--nav-drawer-open .shell-nav {
transform: translateX(0);
opacity: 1;
pointer-events: auto;
}
.shell-nav-backdrop {
display: block;
position: fixed;
inset: 0;
z-index: 65;
border: 0;
background: color-mix(in srgb, black 52%, transparent);
opacity: 0;
pointer-events: none;
transition: opacity var(--shell-focus-duration) var(--shell-focus-ease);
}
.shell--nav-drawer-open .shell-nav-backdrop {
opacity: 1;
pointer-events: auto;
}
/* Show the hamburger toggle at the same breakpoint where the drawer takes over. */
.topbar-nav-toggle {
display: inline-flex;
align-items: center;
justify-content: center;
width: 38px;
height: 38px;
padding: 0;
border: 1px solid color-mix(in srgb, var(--border) 84%, transparent);
border-radius: 999px;
background: color-mix(in srgb, var(--bg-elevated) 80%, transparent);
color: var(--muted);
box-shadow: inset 0 1px 0 color-mix(in srgb, white 8%, transparent);
}
.sidebar,
.sidebar--collapsed {
width: 100%;
min-width: 0;
flex: 1 1 auto;
flex-direction: column;
align-items: stretch;
border-right: none;
}
.sidebar-shell,
.sidebar--collapsed .sidebar-shell {
padding: 18px 16px 14px;
border-radius: 0;
}
.shell--nav-collapsed:not(.shell--nav-drawer-open) .sidebar-shell,
.shell--nav-collapsed:not(.shell--nav-drawer-open) .sidebar--collapsed .sidebar-shell {
padding: 12px 8px 10px;
}
.sidebar-shell__header {
min-height: 0;
padding: 0 4px 16px;
}
.sidebar-shell__header .nav-collapse-toggle {
display: none;
}
.shell--nav-collapsed:not(.shell--nav-drawer-open) .sidebar-shell__header {
justify-content: center;
align-items: center;
gap: 0;
padding: 0 2px 16px;
}
.sidebar-nav,
.sidebar--collapsed .sidebar-nav {
flex: 1 1 auto;
display: block;
padding: 0;
overflow-x: hidden;
overflow-y: auto;
scrollbar-width: none;
}
.sidebar-nav::-webkit-scrollbar,
.sidebar--collapsed .sidebar-nav::-webkit-scrollbar {
display: none;
}
.nav-section,
.sidebar--collapsed .nav-section {
display: grid;
margin-bottom: 16px;
}
.sidebar-nav .nav-section__label,
.sidebar--collapsed .nav-section__label {
display: flex;
}
.nav-item,
.sidebar--collapsed .nav-item {
margin: 0;
min-height: 40px;
padding: 0 12px;
font-size: 13px;
border-radius: 12px;
white-space: nowrap;
flex: 0 0 auto;
width: auto;
}
.shell--nav-collapsed:not(.shell--nav-drawer-open) .sidebar--collapsed .nav-item {
justify-content: center;
width: 44px;
min-height: 44px;
padding: 0;
margin: 0 auto;
border-radius: 16px;
}
.sidebar--collapsed .nav-item--active::before,
.sidebar--collapsed .nav-item.active::before {
content: none;
}
.sidebar--collapsed .nav-item__text,
.sidebar--collapsed .nav-item__external-icon {
display: inline-flex;
}
.shell--nav-collapsed:not(.shell--nav-drawer-open) .sidebar--collapsed .nav-item__text,
.shell--nav-collapsed:not(.shell--nav-drawer-open) .sidebar--collapsed .nav-item__external-icon {
display: none;
}
.shell--nav-collapsed:not(.shell--nav-drawer-open) .sidebar--collapsed .nav-item--active::before,
.shell--nav-collapsed:not(.shell--nav-drawer-open) .sidebar--collapsed .nav-item.active::before {
content: "";
position: absolute;
left: 8px;
top: 10px;
bottom: 10px;
width: 3px;
border-radius: 999px;
background: color-mix(in srgb, var(--accent) 86%, transparent);
box-shadow: 0 0 14px color-mix(in srgb, var(--accent) 34%, transparent);
}
.sidebar--collapsed .sidebar-shell__footer {
padding: 12px 8px 0;
}
.sidebar--collapsed .sidebar-version {
width: auto;
min-height: 40px;
padding: 0 12px;
}
.shell--nav-collapsed:not(.shell--nav-drawer-open) .sidebar--collapsed .sidebar-shell__footer {
padding: 8px 0 2px;
}
.shell--nav-collapsed:not(.shell--nav-drawer-open) .sidebar--collapsed .sidebar-version {
width: 44px;
min-height: 44px;
padding: 0;
justify-content: center;
}
.shell--nav-collapsed:not(.shell--nav-drawer-open) .sidebar-mode-switch {
display: none;
}
}
/* Mobile-specific styles */
@media (max-width: 768px) {
.shell {
--shell-pad: 8px;
--shell-gap: 8px;
}
/* Topbar */
.topbar {
padding: 10px 12px;
min-height: auto;
}
.topnav-shell {
flex-wrap: wrap;
gap: 10px;
}
.topnav-shell__actions {
min-width: 0;
flex: 1 1 auto;
justify-content: space-between;
gap: 10px;
align-items: stretch;
}
.topnav-shell__content {
display: none;
width: 100%;
}
.topbar-nav-toggle {
display: inline-flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
width: 38px;
height: 38px;
padding: 0;
border: 1px solid color-mix(in srgb, var(--border) 84%, transparent);
border-radius: 999px;
background: color-mix(in srgb, var(--bg-elevated) 80%, transparent);
color: var(--muted);
box-shadow: inset 0 1px 0 color-mix(in srgb, white 8%, transparent);
}
.topbar-status {
gap: 6px;
width: auto;
flex-wrap: nowrap;
}
.topbar-search {
min-width: 0;
flex: 1;
}
.topbar-theme-mode {
display: none;
}
.sidebar-mode-switch {
display: block;
}
.sidebar-mode-switch .topbar-theme-mode {
display: inline-flex;
width: 100%;
justify-content: center;
}
.topbar-status .pill {
padding: 4px 8px;
font-size: 11px;
gap: 4px;
}
.topbar-status .pill .mono {
display: none;
}
.topbar-status .pill span:nth-child(2) {
display: none;
}
.shell-nav,
.shell--nav-collapsed .shell-nav {
width: min(92vw, 320px);
}
.shell--nav-collapsed:not(.shell--nav-drawer-open) .shell-nav {
width: 78px;
}
.sidebar-shell,
.sidebar--collapsed .sidebar-shell {
padding: 16px 14px 12px;
}
.nav-item,
.sidebar--collapsed .nav-item {
font-size: 12px;
}
/* Content */
.content-header {
display: none;
}
/* Hide the entire content-header on mobile chat — controls are in mobile gear menu */
.content--chat .content-header {
display: none;
}
.content--chat {
gap: 2px;
}
/* Show the mobile gear toggle (lives in topbar now) */
.chat-mobile-controls-wrapper {
display: flex;
position: relative;
}
.chat-mobile-controls-wrapper .chat-controls-mobile-toggle {
display: flex;
}
/* The dropdown panel — anchored below the gear in topbar */
.chat-mobile-controls-wrapper .chat-controls-dropdown {
display: none;
position: absolute;
top: 100%;
right: 0;
z-index: 100;
background: var(--card, #161b22);
border: 1px solid var(--border, #30363d);
border-radius: 10px;
padding: 8px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
flex-direction: column;
gap: 4px;
min-width: 220px;
}
.chat-mobile-controls-wrapper .chat-controls-dropdown.open {
display: flex;
}
.chat-mobile-controls-wrapper .chat-controls-dropdown .chat-controls {
display: flex;
flex-direction: column;
gap: 4px;
width: 100%;
}
.chat-mobile-controls-wrapper .chat-controls-dropdown .chat-controls__session {
min-width: unset;
max-width: unset;
width: 100%;
}
.chat-mobile-controls-wrapper .chat-controls-dropdown .chat-controls__session select {
width: 100%;
font-size: 14px;
padding: 10px 12px;
}
.chat-mobile-controls-wrapper .chat-controls-dropdown .chat-controls__thinking {
display: flex;
flex-direction: row;
gap: 6px;
padding: 4px 0;
justify-content: center;
}
.chat-mobile-controls-wrapper .chat-controls-dropdown .btn--icon {
min-width: 44px;
height: 44px;
}
.content {
padding: 4px 4px 16px;
gap: 12px;
}
/* Cards */
.card {
padding: 12px;
border-radius: var(--radius-md);
}
.card-title {
font-size: 13px;
}
/* Stats */
.stat-grid {
gap: 8px;
grid-template-columns: repeat(2, 1fr);
}
.stat {
padding: 10px;
border-radius: var(--radius-md);
}
.stat-label {
font-size: 11px;
}
.stat-value {
font-size: 18px;
}
/* Notes */
.note-grid {
grid-template-columns: 1fr;
gap: 8px;
}
/* Forms */
.form-grid {
grid-template-columns: 1fr;
gap: 10px;
}
.field input,
.field textarea,
.field select {
padding: 8px 10px;
border-radius: var(--radius-md);
font-size: 14px;
}
/* Buttons */
.btn {
padding: 8px 12px;
font-size: 12px;
}
/* Pills */
.pill {
padding: 4px 10px;
font-size: 12px;
}
/* Chat */
.chat-header {
flex-direction: column;
align-items: stretch;
gap: 8px;
}
.chat-header__left {
flex-direction: column;
align-items: stretch;
}
.chat-header__right {
justify-content: space-between;
}
.chat-session {
min-width: unset;
width: 100%;
}
.chat-thread {
margin-top: 0;
padding: 0 8px 12px;
}
.chat-msg {
max-width: 90%;
}
.chat-bubble {
padding: 8px 12px;
border-radius: var(--radius-md);
}
.chat-compose {
gap: 8px;
}
.chat-compose__field textarea {
min-height: 60px;
padding: 8px 10px;
border-radius: var(--radius-md);
font-size: 14px;
}
.agent-chat__input {
margin: 0 8px 10px;
}
.agent-chat__toolbar {
padding: 4px 8px;
}
.agent-chat__input-btn,
.agent-chat__toolbar .btn-ghost {
width: 28px;
height: 28px;
}
.agent-chat__input-btn svg,
.agent-chat__toolbar .btn-ghost svg {
width: 14px;
height: 14px;
}
/* Log stream */
.log-stream {
border-radius: var(--radius-md);
max-height: 380px;
}
.log-row {
grid-template-columns: 1fr;
gap: 4px;
padding: 8px;
}
.log-time {
font-size: 10px;
}
.log-level {
font-size: 9px;
}
.log-subsystem {
font-size: 11px;
}
.log-message {
font-size: 12px;
}
/* Lists */
.list-item {
padding: 10px;
border-radius: var(--radius-md);
}
.list-title {
font-size: 13px;
}
.list-sub {
font-size: 11px;
}
/* Code blocks */
.code-block {
padding: 8px;
border-radius: var(--radius-md);
font-size: 11px;
}
.theme-orb__trigger {
width: 26px;
height: 26px;
font-size: 13px;
}
}
/* Small mobile */
@media (max-width: 400px) {
.shell {
--shell-pad: 4px;
}
.topbar {
padding: 8px 10px;
}
.brand-title {
font-size: 13px;
}
.nav-item {
padding: 6px 8px;
font-size: 11px;
}
.content {
padding: 4px 4px 12px;
gap: 10px;
}
.card {
padding: 10px;
}
.stat {
padding: 8px;
}
.stat-value {
font-size: 16px;
}
.chat-bubble {
padding: 8px 10px;
}
.chat-compose__field textarea {
min-height: 52px;
padding: 8px 10px;
font-size: 13px;
}
.btn {
padding: 6px 10px;
font-size: 11px;
}
.topbar-status .pill {
padding: 3px 6px;
font-size: 10px;
}
.theme-orb__trigger {
width: 24px;
height: 24px;
font-size: 12px;
}
}
/* ===========================================
Sessions table responsive column hiding
=========================================== */
/* nth-child is 1-based and includes the checkbox column (col 1). */
/* ≤1400px: hide Verbose (col 9) and Reasoning (col 10) */
@media (max-width: 1400px) {
.data-table th:nth-child(9),
.data-table td:nth-child(9),
.data-table th:nth-child(10),
.data-table td:nth-child(10) {
display: none;
}
}
/* ≤1100px: also hide Fast (col 8) and Kind (col 4) */
@media (max-width: 1100px) {
.data-table th:nth-child(4),
.data-table td:nth-child(4),
.data-table th:nth-child(8),
.data-table td:nth-child(8) {
display: none;
}
.data-table th,
.data-table td {
padding: 8px 10px;
}
}
/* ≤900px: also hide Thinking (col 7) and Label (col 3) */
@media (max-width: 900px) {
.data-table th:nth-child(3),
.data-table td:nth-child(3),
.data-table th:nth-child(7),
.data-table td:nth-child(7) {
display: none;
}
}
/* ≤768px: also hide Tokens (col 6); tighten padding; stack pagination */
@media (max-width: 768px) {
.data-table th:nth-child(6),
.data-table td:nth-child(6) {
display: none;
}
.data-table th,
.data-table td {
padding: 8px 6px;
font-size: 12px;
}
.data-table-pagination {
flex-direction: column;
align-items: stretch;
gap: 8px;
padding: 10px 8px;
}
.data-table-pagination__info {
text-align: center;
}
.data-table-pagination__controls {
justify-content: center;
}
.data-table-search input {
font-size: 14px;
padding: 8px 10px;
}
.data-table-wrapper {
border-radius: var(--radius-sm);
}
.session-key-cell {
max-width: 200px;
}
.session-key-cell .session-link,
.session-key-cell .session-key-display-name {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
overflow-wrap: normal;
word-break: normal;
}
.filters {
flex-wrap: wrap;
gap: 8px;
}
}
/* ≤500px: tighten further, truncate key column */
@media (max-width: 500px) {
.data-table th,
.data-table td {
padding: 6px 4px;
font-size: 11px;
}
.session-key-cell {
max-width: 140px;
}
}