Desktop: More tools gets a command search across groups and a compact list layout
This commit is contained in:
parent
e32d0772e9
commit
78b1b599a5
4 changed files with 41 additions and 5 deletions
|
|
@ -9,8 +9,8 @@ import { api, errorText, type MethodDescriptor, newJob, type Project, type ToolR
|
|||
import { type Key, t } from '../../i18n';
|
||||
import { useData, useWrite } from '../../store';
|
||||
import { Icon } from '../../ui/icons';
|
||||
import { ErrorNotice, Skeleton } from '../../ui/kit';
|
||||
import { Section, StatusPill } from '../../ui/ds';
|
||||
import { ErrorNotice, Seg, Skeleton } from '../../ui/kit';
|
||||
import { Section, StatusPill, Toolbar } from '../../ui/ds';
|
||||
import '../../styles/tools.css';
|
||||
import { WriteButton } from '../../ui/WriteButton';
|
||||
|
||||
|
|
@ -111,6 +111,9 @@ export function ToolsTab({ project }: { project: Project }) {
|
|||
const [methods, setMethods] = useState<MethodDescriptor[] | null>(null);
|
||||
const [err, setErr] = useState<string | null>(null);
|
||||
const [open, setOpen] = useState<string>(TOOLBOX[0]!.id);
|
||||
const [q, setQ] = useState('');
|
||||
const [dense, setDenseState] = useState<boolean>(() => { try { return localStorage.getItem('sb.tools.dense') === '1'; } catch { return false; } });
|
||||
const setDense = (v: boolean) => { setDenseState(v); try { localStorage.setItem('sb.tools.dense', v ? '1' : '0'); } catch { /* private mode */ } };
|
||||
useEffect(() => {
|
||||
api.call<{ methods: MethodDescriptor[] }>('system.methods').then(r => setMethods(r.methods), e => setErr(errorText(e)));
|
||||
}, []);
|
||||
|
|
@ -118,12 +121,26 @@ export function ToolsTab({ project }: { project: Project }) {
|
|||
const copy = (c: string) => { navigator.clipboard?.writeText(c).then(() => d.toast({ kind: 'ok', title: t('tools.copied') }), () => {}); };
|
||||
const groups = TOOLBOX.map(g => ({ g, ms: g.methods.map(x => by.get(x)).filter((x): x is MethodDescriptor => !!x) }));
|
||||
const cur = groups.find(x => x.g.id === open);
|
||||
const needle = q.trim().toLowerCase();
|
||||
const hits = needle ? groups.flatMap(x => x.ms).filter(m => [m.method, m.title, m.description ?? ''].some(x => x.toLowerCase().includes(needle))) : [];
|
||||
return (
|
||||
<div className="scr-tools">
|
||||
<div className={`scr-tools${dense ? ' dense' : ''}`}>
|
||||
<p className="tl-lead"><Icon name="info" />{t('tools.lead')}</p>
|
||||
{methods && (
|
||||
<Toolbar label={t('tools.filter')}>
|
||||
<div className="search-input"><Icon name="search" /><input className="input" value={q} onChange={e => setQ(e.target.value)} placeholder={t('tools.search', { count: groups.reduce((a, x) => a + x.ms.length, 0) })} aria-label={t('tools.searchAria')} onKeyDown={e => { if (e.key === 'Escape') setQ(''); }} /></div>
|
||||
<span className="grow" />
|
||||
<Seg value={dense ? 'list' : 'cards'} onChange={v => setDense(v === 'list')} label={t('tools.density')} options={[['cards', t('pf.cards'), 'grid'], ['list', t('tools.list'), 'layers']]} />
|
||||
</Toolbar>
|
||||
)}
|
||||
{needle && (
|
||||
<Section title={t('tools.results', { count: hits.length })} icon="search">
|
||||
{hits.length ? <div className="tl-cmds">{hits.map(m => <Tool key={m.method} m={m} project={project} />)}</div> : <p className="muted">{t('tools.noHits')}</p>}
|
||||
</Section>
|
||||
)}
|
||||
{err && <ErrorNotice error={err} />}
|
||||
{!methods && !err && <Skeleton lines={4} />}
|
||||
{methods && (
|
||||
{methods && !needle && (
|
||||
<div className="tl-groups" role="group" aria-label={t('tab.tools')}>
|
||||
{groups.map(({ g, ms }) => {
|
||||
const isOpen = open === g.id;
|
||||
|
|
@ -138,7 +155,7 @@ export function ToolsTab({ project }: { project: Project }) {
|
|||
})}
|
||||
</div>
|
||||
)}
|
||||
{methods && cur && (
|
||||
{methods && cur && !needle && (
|
||||
<Section id="tools-open" title={t(`tools.g.${cur.g.id}` as Key)} icon="sliders" sub={t('tools.count', { count: cur.ms.length })}>
|
||||
<div className="tl-cmds">{cur.ms.map(m => <Tool key={m.method} m={m} project={project} />)}</div>
|
||||
</Section>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue