mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-26 02:06:49 +00:00
feat: UI polish sprint — 7 items + logs toolbar redesign (#365)
* feat: UI polish sprint — tag filters, toast tokens, logs toolbar, billing portal, editor UX - Fleet: replace inline tag pills with multi-select combobox dropdown - Toast: remap all notification colors to oklch design tokens - Logs: convert floating hover toolbar to permanent pinned toolbar, replace all hardcoded colors with design tokens for theme support - Audit: fix dropdown scroll-lock (modal=false), light theme button contrast - Resources: remove redundant inner border/bg on tab wrapper - Editor: add ⌘K/Ctrl+K shortcut hint and handler, standardize button heights - Billing: signed Lemon Squeezy portal URLs via sencho.io proxy for all tiers - New MultiSelectCombobox UI component * feat(editor): replace button row with split-button dropdown Replace three separate editor buttons (Discard, Save Only, Save & Deploy) with a compact split-button dropdown. Primary action is "Save & Deploy"; chevron opens dropdown with "Save Only" and "Discard Changes" options.
This commit is contained in:
@@ -26,7 +26,8 @@ import { useLicense } from '@/context/LicenseContext';
|
||||
import { ProGate } from './ProGate';
|
||||
import FleetSnapshots from './FleetSnapshots';
|
||||
import { toast } from '@/components/ui/toast-store';
|
||||
import { LabelPill, LabelDot, type Label as StackLabel } from './LabelPill';
|
||||
import { LabelDot, type Label as StackLabel } from './LabelPill';
|
||||
import { MultiSelectCombobox } from '@/components/ui/multi-select-combobox';
|
||||
|
||||
// --- Types ---
|
||||
|
||||
@@ -1022,24 +1023,18 @@ export function FleetView({ onNavigateToNode }: FleetViewProps) {
|
||||
{fleetLabels.length > 0 && (
|
||||
<>
|
||||
<div className="w-px h-5 bg-border mx-1" />
|
||||
<div className="flex items-center gap-1.5 flex-wrap">
|
||||
{fleetLabels.map(label => (
|
||||
<LabelPill
|
||||
key={label.id}
|
||||
label={label}
|
||||
size="sm"
|
||||
active={labelFilters.has(label.id)}
|
||||
onClick={() => {
|
||||
setLabelFilters(prev => {
|
||||
const next = new Set(prev);
|
||||
if (next.has(label.id)) next.delete(label.id);
|
||||
else next.add(label.id);
|
||||
return next;
|
||||
});
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<MultiSelectCombobox
|
||||
options={fleetLabels.map(l => ({ value: String(l.id), label: l.name, color: l.color }))}
|
||||
selected={new Set(Array.from(labelFilters).map(String))}
|
||||
onSelectionChange={(sel) => setLabelFilters(new Set(Array.from(sel).map(Number)))}
|
||||
placeholder="Tags"
|
||||
renderOption={(option) => (
|
||||
<span className="flex items-center gap-1.5">
|
||||
<LabelDot color={option.color as StackLabel['color'] ?? 'slate'} />
|
||||
{option.label}
|
||||
</span>
|
||||
)}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user