style(usage): tighten filter menus and match the analysis toggle
Size usage filter menus to their content and use the home protocol selection style for the Token and request toggle.
This commit is contained in:
1 parent
ed988f7998
commit
9e5ed4d2d3
4 files changed
+74
-24
No files matched your search
@@ -53,8 +53,11 @@
|
||||
position: fixed;
|
||||
z-index: 45;
|
||||
display: grid;
|
||||
min-width: 180px;
|
||||
padding: 6px;
|
||||
box-sizing: border-box;
|
||||
width: max-content;
|
||||
min-width: 0;
|
||||
max-width: min(320px, calc(100vw - 24px));
|
||||
padding: 4px;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 10px;
|
||||
background: var(--bg-card);
|
||||
@@ -69,12 +72,12 @@
|
||||
|
||||
.select-menu-option {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) 16px;
|
||||
grid-template-columns: minmax(0, max-content) 16px;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
min-height: 36px;
|
||||
padding: 6px 10px;
|
||||
min-height: 32px;
|
||||
padding: 4px 8px;
|
||||
border: 0;
|
||||
border-radius: 6px;
|
||||
background: transparent;
|
||||
|
||||
@@ -21,6 +21,31 @@ type MenuLayout = {
|
||||
height: number;
|
||||
};
|
||||
|
||||
const measureMenu = (menu: HTMLDivElement) => {
|
||||
const menuStyle = menu.getAttribute('style');
|
||||
const optionButtons = [...menu.querySelectorAll<HTMLButtonElement>('.select-menu-option')];
|
||||
const optionStyles = optionButtons.map((option) => option.getAttribute('style'));
|
||||
menu.style.width = 'max-content';
|
||||
menu.style.maxWidth = 'none';
|
||||
menu.style.height = 'auto';
|
||||
menu.style.maxHeight = 'none';
|
||||
menu.style.visibility = 'hidden';
|
||||
optionButtons.forEach((option) => {
|
||||
option.style.width = 'max-content';
|
||||
option.style.maxWidth = 'none';
|
||||
option.style.gridTemplateColumns = 'max-content 16px';
|
||||
});
|
||||
const rect = menu.getBoundingClientRect();
|
||||
if (menuStyle === null) menu.removeAttribute('style');
|
||||
else menu.setAttribute('style', menuStyle);
|
||||
optionButtons.forEach((option, index) => {
|
||||
const style = optionStyles[index];
|
||||
if (style === null) option.removeAttribute('style');
|
||||
else option.setAttribute('style', style);
|
||||
});
|
||||
return { width: Math.ceil(rect.width), height: Math.ceil(rect.height) };
|
||||
};
|
||||
|
||||
export function SelectMenu({
|
||||
value,
|
||||
options,
|
||||
@@ -44,18 +69,23 @@ export function SelectMenu({
|
||||
|
||||
const updateLayout = useCallback(() => {
|
||||
const root = rootRef.current;
|
||||
const menu = menuRef.current;
|
||||
if (!root) return;
|
||||
const rect = root.getBoundingClientRect();
|
||||
const edgeGap = 12;
|
||||
const triggerGap = 6;
|
||||
const preferredHeight = Math.min(282, Math.max(options.length, 1) * 42 + 18);
|
||||
const minimumHeight = 88;
|
||||
const measured = menu ? measureMenu(menu) : null;
|
||||
const contentWidth = measured && measured.width > 0 ? measured.width : rect.width;
|
||||
const contentHeight = measured && measured.height > 0
|
||||
? measured.height
|
||||
: Math.max(options.length, 1) * 36 + 12;
|
||||
const spaceBelow = Math.max(0, window.innerHeight - edgeGap - rect.bottom - triggerGap);
|
||||
const spaceAbove = Math.max(0, rect.top - triggerGap - edgeGap);
|
||||
const placeAbove = spaceBelow < minimumHeight && spaceAbove > spaceBelow;
|
||||
const placeAbove = spaceBelow < contentHeight && spaceAbove > spaceBelow;
|
||||
const available = placeAbove ? spaceAbove : spaceBelow;
|
||||
const height = Math.min(preferredHeight, Math.max(Math.min(minimumHeight, available), available));
|
||||
const width = Math.min(320, Math.max(rect.width, 180));
|
||||
const maxWidth = Math.max(edgeGap, window.innerWidth - edgeGap * 2);
|
||||
const width = Math.min(320, maxWidth, contentWidth);
|
||||
const height = Math.min(contentHeight, Math.max(available, Math.min(contentHeight, 36)));
|
||||
const maxLeft = Math.max(edgeGap, window.innerWidth - edgeGap - width);
|
||||
const left = Math.min(Math.max(edgeGap, rect.left), maxLeft);
|
||||
const desiredTop = placeAbove ? rect.top - triggerGap - height : rect.bottom + triggerGap;
|
||||
|
||||
@@ -57,26 +57,36 @@
|
||||
.usage-analysis-metric {
|
||||
display: flex;
|
||||
flex: none;
|
||||
gap: 2px;
|
||||
padding: 3px;
|
||||
border-radius: 8px;
|
||||
background: var(--bg-secondary);
|
||||
gap: 8px;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.usage-analysis-metric button {
|
||||
padding: 5px 9px;
|
||||
border: 0;
|
||||
border-radius: 5px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 8px;
|
||||
background: transparent;
|
||||
color: var(--text-secondary);
|
||||
color: var(--text-tertiary);
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.usage-analysis-metric button[aria-pressed='true'] {
|
||||
background: var(--bg-primary);
|
||||
color: var(--text-primary);
|
||||
box-shadow: 0 1px 3px rgb(0 0 0 / 9%);
|
||||
.usage-analysis-metric button:hover {
|
||||
color: var(--ui-accent);
|
||||
background: color-mix(in srgb, var(--ui-accent) 5%, var(--bg-card));
|
||||
}
|
||||
|
||||
.usage-analysis-metric button[aria-pressed='true'],
|
||||
.usage-analysis-metric button[aria-pressed='true']:hover {
|
||||
border-color: transparent;
|
||||
background: color-mix(in srgb, var(--ui-accent) 10%, var(--bg-card));
|
||||
color: var(--ui-accent);
|
||||
font-weight: 600;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.usage-model-comparison {
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
|
||||
:root:not([data-theme='dark']) .workspace :is(
|
||||
.agent-model-section, .agent-auth-segmented, .routing-segmented,
|
||||
.plugin-tabs, .usage-analysis-metric,
|
||||
.plugin-tabs,
|
||||
.credential-quota, .usage-collector-state
|
||||
) {
|
||||
background: #fff;
|
||||
@@ -73,8 +73,7 @@
|
||||
|
||||
:root:not([data-theme='dark']) .workspace :is(
|
||||
.agent-list-items button.active,
|
||||
.routing-segmented button.active, .plugin-tabs button.active,
|
||||
.usage-analysis-metric button[aria-pressed='true']
|
||||
.routing-segmented button.active, .plugin-tabs button.active
|
||||
) {
|
||||
background: #fff;
|
||||
border: 1px solid var(--ui-accent);
|
||||
@@ -111,6 +110,14 @@
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
:root:not([data-theme='dark']) .workspace .usage-analysis-metric button[aria-pressed='true'],
|
||||
:root:not([data-theme='dark']) .workspace .usage-analysis-metric button[aria-pressed='true']:hover {
|
||||
background: color-mix(in srgb, var(--ui-accent) 10%, var(--bg-card));
|
||||
border-color: transparent;
|
||||
color: var(--ui-accent);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/* Do not let local subpage palettes bring the neutral fills back. */
|
||||
:root:not([data-theme='dark']) .workspace .usage-tab-panel {
|
||||
--usage-page-soft: #fff;
|
||||
|
||||
Reference in new issue
Block a user