mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-07-09 16:00:59 +00:00
Surface saved views in the FilterBar mobile expanded body
Mobile users could not save, apply, or set default views on any savedViewsKey surface because SavedViewsMenu only rendered in the desktop controls row. Render it in the mobile chip row, show that row when a surface has saved views even with zero menu filters, drop the duplicate Reset the wider chip row introduced, and left-anchor the dropdown below the sm breakpoint so it stays on screen at 375px.
This commit is contained in:
parent
9923e4b04f
commit
545087d614
3 changed files with 62 additions and 3 deletions
|
|
@ -1,8 +1,19 @@
|
|||
import { Route, Router } from '@solidjs/router';
|
||||
import { cleanup, fireEvent, render, screen, within } from '@solidjs/testing-library';
|
||||
import type { JSX } from 'solid-js';
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||
import { FilterBar } from './FilterBar';
|
||||
import type { FilterDef } from './filterCatalog';
|
||||
|
||||
// SavedViewsMenu URL-backs view application (useNavigate/useLocation), so
|
||||
// savedViewsKey renders must sit inside a Router context.
|
||||
const renderInRouter = (component: () => JSX.Element) =>
|
||||
render(() => (
|
||||
<Router>
|
||||
<Route path="/" component={component} />
|
||||
</Router>
|
||||
));
|
||||
|
||||
const search = {
|
||||
value: () => '',
|
||||
setValue: vi.fn(),
|
||||
|
|
@ -93,4 +104,49 @@ describe('FilterBar', () => {
|
|||
fireEvent.click(screen.getByRole('button', { name: 'Clear all' }));
|
||||
expect(onClearAll).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('shows saved views in the expanded mobile body when savedViewsKey is set', () => {
|
||||
renderInRouter(() => (
|
||||
<FilterBar
|
||||
search={search}
|
||||
filters={[inlineTypeFilter(), menuNodeFilter()]}
|
||||
isMobile={() => true}
|
||||
savedViewsKey="test-surface"
|
||||
/>
|
||||
));
|
||||
|
||||
expect(screen.queryByRole('button', { name: 'Saved views' })).not.toBeInTheDocument();
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Filters' }));
|
||||
expect(screen.getByRole('button', { name: 'Saved views' })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows saved views on mobile even when every filter is inline', () => {
|
||||
renderInRouter(() => (
|
||||
<FilterBar
|
||||
search={search}
|
||||
filters={[inlineTypeFilter()]}
|
||||
isMobile={() => true}
|
||||
savedViewsKey="test-surface"
|
||||
/>
|
||||
));
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Filters' }));
|
||||
expect(screen.getByRole('button', { name: 'Saved views' })).toBeInTheDocument();
|
||||
expect(screen.queryByRole('combobox', { name: 'Filter' })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders a single clear-all on mobile when the saved-views row is shown', () => {
|
||||
renderInRouter(() => (
|
||||
<FilterBar
|
||||
search={search}
|
||||
filters={[inlineTypeFilter(vi.fn(), 'vm')]}
|
||||
isMobile={() => true}
|
||||
savedViewsKey="test-surface"
|
||||
/>
|
||||
));
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: /^Filters/ }));
|
||||
expect(screen.getAllByRole('button', { name: 'Clear all' })).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ export const FilterBar: Component<FilterBarProps> = (props) => {
|
|||
const showMobileBody = () => props.isMobile() && mobileExpanded();
|
||||
const showChipRow = () =>
|
||||
showDesktopChipRow() ||
|
||||
(showMobileBody() && (activeMenuFilters().length > 0 || hasMenuFilters()));
|
||||
(showMobileBody() && (activeMenuFilters().length > 0 || hasMenuFilters() || hasSavedViews()));
|
||||
|
||||
const searchHistory = () => {
|
||||
const key = props.search.historyKey;
|
||||
|
|
@ -169,7 +169,7 @@ export const FilterBar: Component<FilterBarProps> = (props) => {
|
|||
<Show when={showInlineRow()}>
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<For each={inlineFilters()}>{(filter) => <InlineFilterControl filter={filter} />}</For>
|
||||
<Show when={hasClearableState() && activeMenuFilters().length === 0}>
|
||||
<Show when={hasClearableState() && !showChipRow()}>
|
||||
<FilterBarClearAllButton onClick={clearAll} />
|
||||
</Show>
|
||||
</div>
|
||||
|
|
@ -182,6 +182,9 @@ export const FilterBar: Component<FilterBarProps> = (props) => {
|
|||
<Show when={hasMenuFilters()}>
|
||||
<AddFilterMenu filters={menuFilters()} />
|
||||
</Show>
|
||||
<Show when={props.savedViewsKey}>
|
||||
{(key) => <SavedViewsMenu storageKey={key()} />}
|
||||
</Show>
|
||||
</Show>
|
||||
<Show when={hasClearableState() && showMobileBody()}>
|
||||
<FilterBarClearAllButton onClick={clearAll} />
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ export const SavedViewsMenu: Component<SavedViewsMenuProps> = (props) => {
|
|||
<Show when={open()}>
|
||||
<div
|
||||
role="menu"
|
||||
class="absolute right-0 top-[calc(100%+0.25rem)] z-50 w-64 max-w-[calc(100vw-2rem)] rounded-md border border-border bg-surface shadow-lg"
|
||||
class="absolute left-0 top-[calc(100%+0.25rem)] z-50 w-64 max-w-[calc(100vw-2rem)] rounded-md border border-border bg-surface shadow-lg sm:left-auto sm:right-0"
|
||||
>
|
||||
<Show
|
||||
when={savePromptOpen()}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue