swarm ui: the agents page is separate cards, not one big agents card
The filter bar is a card of its own, holding the + agent button and the refresh picker; the hives card and each agent card sit beside it.
This commit is contained in:
parent
70901115a2
commit
6e5dc3dd30
2 changed files with 78 additions and 44 deletions
|
|
@ -24,3 +24,19 @@
|
|||
flex-direction: column;
|
||||
gap: 0.5em;
|
||||
}
|
||||
/* A filter bar that is a card of its own (`standalone`), the same border and
|
||||
fill as a row card. */
|
||||
.ui-filterable-view-filter-card {
|
||||
padding: 0.75em 1em;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 0.5em;
|
||||
background: var(--bg-elev);
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
/* The caller's buttons, at the bar's trailing edge. */
|
||||
.ui-filterable-view-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5em;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,11 @@ function FilterBar<T>({
|
|||
resetFilters,
|
||||
activeFilters,
|
||||
multiselectOptionsFor,
|
||||
actions,
|
||||
standalone,
|
||||
}: {
|
||||
actions?: ComponentChildren;
|
||||
standalone?: boolean;
|
||||
columns: FilterColumn<T>[];
|
||||
getFilter: (key: string) => MultiselectFilterState & { value: string };
|
||||
updateFilter: (
|
||||
|
|
@ -65,7 +69,13 @@ function FilterBar<T>({
|
|||
const filterable = columns.filter(isFilterable);
|
||||
if (filterable.length === 0) return null;
|
||||
return (
|
||||
<div class="ui-filterable-view-filter-bar">
|
||||
<div
|
||||
class={
|
||||
standalone
|
||||
? "ui-filterable-view-filter-bar ui-filterable-view-filter-card"
|
||||
: "ui-filterable-view-filter-bar"
|
||||
}
|
||||
>
|
||||
{filterable.map((c) => {
|
||||
const label = columnLabel(c);
|
||||
if (c.filterMode === "multiselect") {
|
||||
|
|
@ -105,6 +115,7 @@ function FilterBar<T>({
|
|||
reset filters
|
||||
</button>
|
||||
) : null}
|
||||
{actions ? <div class="ui-filterable-view-actions">{actions}</div> : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -130,9 +141,15 @@ export function FilterableView<T>(
|
|||
// (same as `Table`'s own "no rows match the current filter") — the
|
||||
// two cases mean different things, same as `Table`'s own split.
|
||||
emptyMessage?: ComponentChildren;
|
||||
// Cards view only. The filter bar becomes a card of its own, so the caller
|
||||
// can lay it out beside the row cards instead of inside a panel, and
|
||||
// `barActions` (buttons, a refresh picker) sit at its trailing edge.
|
||||
standalone?: boolean;
|
||||
barActions?: ComponentChildren;
|
||||
},
|
||||
) {
|
||||
const { columns, rows, rowKey, storageKey, renderCard, emptyMessage } = props;
|
||||
const { standalone, barActions } = props;
|
||||
const {
|
||||
visibleRows,
|
||||
activeFilters,
|
||||
|
|
@ -165,6 +182,8 @@ export function FilterableView<T>(
|
|||
resetFilters={resetFilters}
|
||||
activeFilters={activeFilters}
|
||||
multiselectOptionsFor={multiselectOptionsFor}
|
||||
actions={barActions}
|
||||
standalone={standalone}
|
||||
/>
|
||||
{rows.length === 0 && emptyMessage ? (
|
||||
<p class="ui-filterable-view-empty">{emptyMessage}</p>
|
||||
|
|
|
|||
Loading…
Reference in a new issue