From 20b8fae0a663bf9a6f0050beda381a0129837965 Mon Sep 17 00:00:00 2001 From: Brandon Oxendine Date: Mon, 5 Jan 2026 13:47:23 +0100 Subject: [PATCH 01/15] changed button filters to toggles --- .../filter-config/filter-config.svelte | 72 ++++++++----------- .../components/filter-config/types.ts | 9 ++- .../wave/issues-page/issues-page.svelte | 11 ++- 3 files changed, 47 insertions(+), 45 deletions(-) diff --git a/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte b/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte index 398695f52..d4448a8fc 100644 --- a/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte +++ b/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte @@ -39,18 +39,9 @@ ...(mode === 'maintainer' || mode === 'wave' ? { applicantAssigned: { - type: 'single-select', + type: 'toggle', label: 'Applicant assignment', - options: [ - { - label: 'Assigned to an applicant', - value: 'true', - }, - { - label: 'Not assigned', - value: 'false', - }, - ], + toggleLabel: 'Assigned to an applicant', }, } : {}), @@ -58,35 +49,17 @@ ...(mode === 'maintainer' || mode === 'wave' ? { hasApplications: { - type: 'single-select', + type: 'toggle', label: 'Applications', - options: [ - { - label: 'Has applications', - value: 'true', - }, - { - label: 'No applications', - value: 'false', - }, - ], + toggleLabel: 'Has applications', }, } : {}), hasPr: { - type: 'single-select', + type: 'toggle', label: 'Pull Requests', - options: [ - { - label: 'Has linked PR', - value: 'true', - }, - { - label: 'No linked PR', - value: 'false', - }, - ], + toggleLabel: 'Has linked PR', }, ...(mode === 'maintainer' || mode === 'wave' @@ -131,14 +104,9 @@ ...(mode === 'maintainer' ? { isInWaveProgram: { - type: 'single-select', + type: 'toggle', label: 'Wave Membership', - options: [ - { - label: 'Part of a Wave', - value: 'true', - }, - ], + toggleLabel: 'Part of a Wave', }, } : {}), @@ -151,6 +119,7 @@ import { getOwnWaveProgramRepos, getWaveProgramRepos } from '$lib/utils/wave/wavePrograms'; import DropdownFilterItem from './components/dropdown-filter-item.svelte'; import SingleSelectFilterItem from './components/single-select-filter-item.svelte'; + import Toggle from '$lib/components/toggle/toggle.svelte'; import type { FilterConfig } from './types'; let { @@ -180,6 +149,10 @@ } } + function handleToggleFilter(filterKey: K, checked: boolean) { + handleSelectFilter(filterKey, checked ? 'true' : 'false'); + } + function handleApply() { onapply(filters); } @@ -202,15 +175,22 @@
{#each Object.entries(AVAILABLE_FILTERS(ownUserId, mode, currentWaveProgramId)) as [filterKey, filterConfig], i (filterKey)}
-
{filterConfig.label}
{#if filterConfig.type === 'single-select'} +
{filterConfig.label}
handleSelectFilter(filterKey as keyof IssueFilters, value)} /> + {:else if filterConfig.type === 'toggle'} + handleToggleFilter(filterKey as keyof IssueFilters, checked)} + /> {:else if filterConfig.type === 'dropdown'} +
{filterConfig.label}
= { optionsPromise: Promise; }; +export type ToggleConfig = { + type: 'toggle'; + label: string; + toggleLabel: string; +}; + export type FilterConfig = | SingleSelectConfig<{ label: string; value: string }[]> - | DropdownConfig<{ label: string; value: string }[]>; + | DropdownConfig<{ label: string; value: string }[]> + | ToggleConfig; diff --git a/src/lib/components/wave/issues-page/issues-page.svelte b/src/lib/components/wave/issues-page/issues-page.svelte index 41bd03457..c49779c3a 100644 --- a/src/lib/components/wave/issues-page/issues-page.svelte +++ b/src/lib/components/wave/issues-page/issues-page.svelte @@ -337,7 +337,7 @@ > Filter {#if noOfFilters > 0} -
+
{noOfFilters}
{/if} @@ -518,8 +518,13 @@ width: 1.25rem; font-size: 0.75rem; border-radius: 50%; - background-color: var(--color-primary-level-1); - color: var(--color-primary-level-6); + background-color: var(--color-primary); + color: var(--color-background); + font-weight: 700; + } + + .filter-count.filter-count-open { + background-color: var(--color-primary); } .spinner { From abce9d3256b169d40ab6660b6c8a295717a4d87b Mon Sep 17 00:00:00 2001 From: Brandon Oxendine Date: Mon, 5 Jan 2026 13:51:41 +0100 Subject: [PATCH 02/15] move repo selector down and make it full width --- .../filter-config/filter-config.svelte | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte b/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte index d4448a8fc..1f4ace043 100644 --- a/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte +++ b/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte @@ -62,6 +62,16 @@ toggleLabel: 'Has linked PR', }, + ...(mode === 'maintainer' + ? { + isInWaveProgram: { + type: 'toggle', + label: 'Wave Membership', + toggleLabel: 'Part of a Wave', + }, + } + : {}), + ...(mode === 'maintainer' || mode === 'wave' ? { repoId: { @@ -100,16 +110,6 @@ }, } : {}), - - ...(mode === 'maintainer' - ? { - isInWaveProgram: { - type: 'toggle', - label: 'Wave Membership', - toggleLabel: 'Part of a Wave', - }, - } - : {}), }) as const; @@ -237,6 +237,11 @@ font-family: var(--typeface-regular); } + .filter-config-item :global(.dropdown-trigger) { + width: 100%; + max-width: none; + } + .actions { position: sticky; bottom: 0.25rem; From 8200fe8e8af9a23efd3870aca080594aab352a58 Mon Sep 17 00:00:00 2001 From: Brandon Oxendine Date: Mon, 5 Jan 2026 14:10:11 +0100 Subject: [PATCH 03/15] Adjust repo selector corner radius --- .../filter-config/components/dropdown-filter-item.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/components/wave/issues-page/components/filter-config/components/dropdown-filter-item.svelte b/src/lib/components/wave/issues-page/components/filter-config/components/dropdown-filter-item.svelte index f080aca59..df0fbad12 100644 --- a/src/lib/components/wave/issues-page/components/filter-config/components/dropdown-filter-item.svelte +++ b/src/lib/components/wave/issues-page/components/filter-config/components/dropdown-filter-item.svelte @@ -142,7 +142,7 @@ .dropdown-trigger { cursor: pointer; padding: 0.25rem 0.5rem; - border-radius: 0.5rem; + border-radius: 0.5rem 0 0.5rem 0.5rem; border: 1px solid var(--color-foreground-level-3); user-select: none; display: flex; From e4da93f968418eb1a1a7c18e9cd159989705adb3 Mon Sep 17 00:00:00 2001 From: Brandon Oxendine Date: Mon, 5 Jan 2026 14:13:38 +0100 Subject: [PATCH 04/15] Update spacing on filter list items --- .../filter-config/components/dropdown-filter-item.svelte | 8 +++++--- .../components/filter-config/filter-config.svelte | 1 - 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/lib/components/wave/issues-page/components/filter-config/components/dropdown-filter-item.svelte b/src/lib/components/wave/issues-page/components/filter-config/components/dropdown-filter-item.svelte index df0fbad12..610a4c6c6 100644 --- a/src/lib/components/wave/issues-page/components/filter-config/components/dropdown-filter-item.svelte +++ b/src/lib/components/wave/issues-page/components/filter-config/components/dropdown-filter-item.svelte @@ -78,7 +78,7 @@ > {#if !selectedOption} - Any + All repositories {:else} {#await optionsPromise} Loading... @@ -124,7 +124,9 @@
- + {#each options.filter((option) => option.label .toLowerCase() @@ -231,7 +233,7 @@ .dropdown-options button { min-width: 0; - padding: 0.5rem 0.5rem; + padding: 0.4rem 0.6rem; background: none; border: none; text-align: left; diff --git a/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte b/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte index 1f4ace043..c38018fad 100644 --- a/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte +++ b/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte @@ -190,7 +190,6 @@ onchange={(checked) => handleToggleFilter(filterKey as keyof IssueFilters, checked)} /> {:else if filterConfig.type === 'dropdown'} -
{filterConfig.label}
Date: Mon, 5 Jan 2026 15:47:17 +0100 Subject: [PATCH 05/15] use segmented control for status, update text in repo selector --- .../components/dropdown-filter-item.svelte | 6 +- .../filter-config/filter-config.svelte | 69 ++++++++++++++++--- 2 files changed, 61 insertions(+), 14 deletions(-) diff --git a/src/lib/components/wave/issues-page/components/filter-config/components/dropdown-filter-item.svelte b/src/lib/components/wave/issues-page/components/filter-config/components/dropdown-filter-item.svelte index 610a4c6c6..e1d1e99e3 100644 --- a/src/lib/components/wave/issues-page/components/filter-config/components/dropdown-filter-item.svelte +++ b/src/lib/components/wave/issues-page/components/filter-config/components/dropdown-filter-item.svelte @@ -78,7 +78,7 @@ > {#if !selectedOption} - All repositories + In any repo {:else} {#await optionsPromise} Loading... @@ -125,7 +125,7 @@
{#each options.filter((option) => option.label @@ -233,7 +233,7 @@ .dropdown-options button { min-width: 0; - padding: 0.4rem 0.6rem; + padding: 0.3rem 0.7rem; background: none; border: none; text-align: left; diff --git a/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte b/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte index c38018fad..731f58d76 100644 --- a/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte +++ b/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte @@ -115,6 +115,7 @@
@@ -176,13 +182,28 @@ {#each Object.entries(AVAILABLE_FILTERS(ownUserId, mode, currentWaveProgramId)) as [filterKey, filterConfig], i (filterKey)}
{#if filterConfig.type === 'single-select'} -
{filterConfig.label}
- handleSelectFilter(filterKey as keyof IssueFilters, value)} - /> + {#if filterKey === 'state'} +
+ Status +
+ ({ + title: option.label, + value: option.value, + }))} + bind:active={statusValue} + onTabChange={(value) => handleSelectFilter(filterKey as keyof IssueFilters, value)} + /> +
+
+ {:else} +
{filterConfig.label}
+ handleSelectFilter(filterKey as keyof IssueFilters, value)} + /> + {/if} {:else if filterConfig.type === 'toggle'} Date: Mon, 5 Jan 2026 16:22:39 +0100 Subject: [PATCH 06/15] Fix filter config toggle typing --- .../components/filter-config/filter-config.svelte | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte b/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte index 731f58d76..c5cd4a6c2 100644 --- a/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte +++ b/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte @@ -150,7 +150,9 @@ } } - function handleToggleFilter(filterKey: K, checked: boolean) { + type ToggleFilterKey = 'applicantAssigned' | 'hasApplications' | 'hasPr' | 'isInWaveProgram'; + + function handleToggleFilter(filterKey: ToggleFilterKey, checked: boolean) { handleSelectFilter(filterKey, checked ? 'true' : null); } @@ -168,13 +170,6 @@ filters = appliedFilters; } - let statusValue = $state((filters.state ?? 'open') as IssueFilters['state']); - $effect(() => { - const nextValue = (filters.state ?? 'open') as IssueFilters['state']; - if (statusValue !== nextValue) { - statusValue = nextValue; - } - });
@@ -191,7 +186,7 @@ title: option.label, value: option.value, }))} - bind:active={statusValue} + active={(filters.state ?? 'open') as IssueFilters['state']} onTabChange={(value) => handleSelectFilter(filterKey as keyof IssueFilters, value)} />
From 45f5b96009d8c9c0196c093784537586b3a43d67 Mon Sep 17 00:00:00 2001 From: Brandon Oxendine Date: Mon, 5 Jan 2026 16:32:09 +0100 Subject: [PATCH 07/15] try to fix errors again --- .../filter-config/filter-config.svelte | 39 +++++++++++++------ 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte b/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte index c5cd4a6c2..414e4bcea 100644 --- a/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte +++ b/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte @@ -151,11 +151,28 @@ } type ToggleFilterKey = 'applicantAssigned' | 'hasApplications' | 'hasPr' | 'isInWaveProgram'; + type StatusValue = 'open' | 'closed'; function handleToggleFilter(filterKey: ToggleFilterKey, checked: boolean) { handleSelectFilter(filterKey, checked ? 'true' : null); } + function isToggleFilterKey(filterKey: keyof IssueFilters): filterKey is ToggleFilterKey { + return ( + filterKey === 'applicantAssigned' || + filterKey === 'hasApplications' || + filterKey === 'hasPr' || + filterKey === 'isInWaveProgram' + ); + } + + const statusOptions: { title: string; value: StatusValue }[] = [ + { title: 'Open', value: 'open' }, + { title: 'Closed', value: 'closed' }, + ]; + + let statusActive = $derived((filters.state ?? 'open') as StatusValue); + function handleApply() { onapply(filters); } @@ -182,12 +199,9 @@ Status
({ - title: option.label, - value: option.value, - }))} - active={(filters.state ?? 'open') as IssueFilters['state']} - onTabChange={(value) => handleSelectFilter(filterKey as keyof IssueFilters, value)} + options={statusOptions} + active={statusActive} + onTabChange={(value) => handleSelectFilter('state', value as StatusValue)} />
@@ -200,11 +214,14 @@ /> {/if} {:else if filterConfig.type === 'toggle'} - handleToggleFilter(filterKey as keyof IssueFilters, checked)} - /> + {#if isToggleFilterKey(filterKey)} + {@const toggleKey = filterKey} + handleToggleFilter(toggleKey, checked)} + /> + {/if} {:else if filterConfig.type === 'dropdown'} Date: Mon, 5 Jan 2026 16:53:16 +0100 Subject: [PATCH 08/15] Fix filter config typing for toggles and status segmented control --- .../components/filter-config/filter-config.svelte | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte b/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte index 414e4bcea..fe66355c9 100644 --- a/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte +++ b/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte @@ -187,11 +187,18 @@ filters = appliedFilters; } + let filterEntries = $derived( + Object.entries(AVAILABLE_FILTERS(ownUserId, mode, currentWaveProgramId)) as [ + keyof IssueFilters, + FilterConfig, + ][], + ); +
- {#each Object.entries(AVAILABLE_FILTERS(ownUserId, mode, currentWaveProgramId)) as [filterKey, filterConfig], i (filterKey)} + {#each filterEntries as [filterKey, filterConfig], i (filterKey)}
{#if filterConfig.type === 'single-select'} {#if filterKey === 'state'} From 803ba12a4c39dbb5e54cd1d3bcdd9dac693f726b Mon Sep 17 00:00:00 2001 From: Brandon Oxendine Date: Tue, 6 Jan 2026 11:55:57 +0100 Subject: [PATCH 09/15] update copy, fix assigned to me filter --- .../components/dropdown-filter-item.svelte | 1 + .../filter-config/filter-config.svelte | 161 ++++++++++-------- .../components/filter-config/types.ts | 2 +- 3 files changed, 95 insertions(+), 69 deletions(-) diff --git a/src/lib/components/wave/issues-page/components/filter-config/components/dropdown-filter-item.svelte b/src/lib/components/wave/issues-page/components/filter-config/components/dropdown-filter-item.svelte index e1d1e99e3..b0539f83f 100644 --- a/src/lib/components/wave/issues-page/components/filter-config/components/dropdown-filter-item.svelte +++ b/src/lib/components/wave/issues-page/components/filter-config/components/dropdown-filter-item.svelte @@ -144,6 +144,7 @@ .dropdown-trigger { cursor: pointer; padding: 0.25rem 0.5rem; + min-height: 42px; border-radius: 0.5rem 0 0.5rem 0.5rem; border: 1px solid var(--color-foreground-level-3); user-select: none; diff --git a/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte b/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte index fe66355c9..065328f44 100644 --- a/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte +++ b/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte @@ -21,16 +21,15 @@ ], }, - ...(ownUserId && mode === 'contributor' + ...(mode === 'maintainer' || mode === 'wave' ? { - assignedToUser: { + applicantAssigned: { type: 'single-select', - label: 'Assignment', + label: 'Assigned', options: [ - { - label: 'Assigned to me', - value: ownUserId, - }, + { label: 'All', value: 'all' }, + { label: 'Yes', value: 'true' }, + { label: 'No', value: 'false' }, ], }, } @@ -38,36 +37,48 @@ ...(mode === 'maintainer' || mode === 'wave' ? { - applicantAssigned: { - type: 'toggle', - label: 'Applicant assignment', - toggleLabel: 'Assigned to an applicant', + hasApplications: { + type: 'single-select', + label: 'Applications', + options: [ + { label: 'All', value: 'all' }, + { label: 'Has', value: 'true' }, + { label: 'None', value: 'false' }, + ], }, } : {}), - ...(mode === 'maintainer' || mode === 'wave' + hasPr: { + type: 'single-select', + label: 'Linked PR', + options: [ + { label: 'All', value: 'all' }, + { label: 'Linked', value: 'true' }, + { label: 'None', value: 'false' }, + ], + }, + + ...(ownUserId && mode === 'contributor' ? { - hasApplications: { + assignedToUser: { type: 'toggle', - label: 'Applications', - toggleLabel: 'Has applications', + label: 'Assigned to me', + onValue: ownUserId, }, } : {}), - hasPr: { - type: 'toggle', - label: 'Pull Requests', - toggleLabel: 'Has linked PR', - }, - ...(mode === 'maintainer' ? { isInWaveProgram: { - type: 'toggle', - label: 'Wave Membership', - toggleLabel: 'Part of a Wave', + type: 'single-select', + label: 'Part of Wave', + options: [ + { label: 'All', value: 'all' }, + { label: 'Yes', value: 'true' }, + { label: 'No', value: 'false' }, + ], }, } : {}), @@ -116,11 +127,11 @@ -
+
{#each options as option (option.value)} @@ -196,4 +203,12 @@ opacity: 0.5; pointer-events: none; } + + .segmented-control.default-active .selector { + background-color: var(--color-foreground-level-5); + } + + .segmented-control.default-active .option.selected { + color: var(--color-background); + } diff --git a/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte b/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte index 065328f44..6c0f0a7db 100644 --- a/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte +++ b/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte @@ -169,7 +169,9 @@ { title: 'Closed', value: 'closed' }, ]; - let statusActive = $derived((filters.state ?? 'all') as StatusValue); + const statusDefault: StatusValue = mode === 'maintainer' ? 'open' : 'all'; + + let statusActive = $derived((filters.state ?? statusDefault) as StatusValue); function getSegmentedValue(value: string | boolean | undefined | null) { if (value === undefined || value === null) return 'all'; @@ -188,6 +190,34 @@ onapply(filters); } + function normalizedFilterEntries(value: IssueFilters) { + return Object.entries(value).filter(([key, entryValue]) => { + if (entryValue === undefined) return false; + if (key === 'state' && entryValue === 'open' && (mode === 'maintainer' || mode === 'wave')) { + return false; + } + if (mode === 'maintainer' && key === 'mine' && entryValue === true) return false; + if (mode === 'maintainer' && key === 'eligibleForWave' && entryValue === true) return false; + if (mode === 'contributor' && key === 'isInWaveProgram' && entryValue === true) return false; + if (mode === 'contributor' && key === 'appliedToByUser' && entryValue === ownUserId) + return false; + if (mode === 'wave' && key === 'waveProgramId') return false; + return true; + }); + } + + function isSameFilters(a: IssueFilters, b: IssueFilters) { + const aEntries = normalizedFilterEntries(a); + const bEntries = normalizedFilterEntries(b); + + if (aEntries.length !== bEntries.length) return false; + + return aEntries.every(([key, value]) => b[key as keyof IssueFilters] === value); + } + + let hasChanges = $derived(!isSameFilters(filters, appliedFilters)); + let hasAppliedFilters = $derived(normalizedFilterEntries(appliedFilters).length > 0); + export function reset() { filters = appliedFilters; } @@ -213,6 +243,7 @@ handleSelectFilter( 'state', @@ -231,6 +262,7 @@ value: option.value, }))} active={getSegmentedValue(filters[filterKey as keyof IssueFilters])} + defaultValue="all" onTabChange={(value) => handleSelectFilter( filterKey as keyof IssueFilters, @@ -271,8 +303,8 @@
- - + +
diff --git a/src/lib/components/wave/issues-page/issues-page.svelte b/src/lib/components/wave/issues-page/issues-page.svelte index c49779c3a..d4d43f304 100644 --- a/src/lib/components/wave/issues-page/issues-page.svelte +++ b/src/lib/components/wave/issues-page/issues-page.svelte @@ -222,9 +222,16 @@ } }); - let noOfFilters = $derived( - Object.keys(appliedFilters).filter((key) => key !== 'search').length - noOfPreappliedFilters, - ); + let noOfFilters = $derived(() => { + const filterKeys = Object.keys(appliedFilters).filter((key) => key !== 'search'); + let count = filterKeys.length - noOfPreappliedFilters; + + if (filtersMode === 'maintainer' && appliedFilters.state === 'open') { + count -= 1; + } + + return Math.max(0, count); + }); let searchOpen = $state(false); From 7c141e8e56119e6da77b82d8cf46c153f1cbe84e Mon Sep 17 00:00:00 2001 From: Brandon Oxendine Date: Tue, 6 Jan 2026 12:43:56 +0100 Subject: [PATCH 11/15] fix linked pr filter in contributor filters. and move repo selector down --- .../filter-config/filter-config.svelte | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte b/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte index 6c0f0a7db..194773426 100644 --- a/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte +++ b/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte @@ -21,6 +21,16 @@ ], }, + hasPr: { + type: 'single-select', + label: 'Linked PR', + options: [ + { label: 'All', value: 'all' }, + { label: 'Linked', value: 'true' }, + { label: 'None', value: 'false' }, + ], + }, + ...(mode === 'maintainer' || mode === 'wave' ? { applicantAssigned: { @@ -49,16 +59,6 @@ } : {}), - hasPr: { - type: 'single-select', - label: 'Linked PR', - options: [ - { label: 'All', value: 'all' }, - { label: 'Linked', value: 'true' }, - { label: 'None', value: 'false' }, - ], - }, - ...(ownUserId && mode === 'contributor' ? { assignedToUser: { From e6196b6b14be40730b209bb37bb22729e09b9688 Mon Sep 17 00:00:00 2001 From: Brandon Oxendine Date: Tue, 6 Jan 2026 13:21:21 +0100 Subject: [PATCH 12/15] fix flash when filters unapplied. change repository to repo. --- .../filter-config/filter-config.svelte | 35 +++++--- .../wave/issues-page/issues-page.svelte | 84 +++++++++++++++---- 2 files changed, 93 insertions(+), 26 deletions(-) diff --git a/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte b/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte index 194773426..8e84830e2 100644 --- a/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte +++ b/src/lib/components/wave/issues-page/components/filter-config/filter-config.svelte @@ -33,13 +33,13 @@ ...(mode === 'maintainer' || mode === 'wave' ? { - applicantAssigned: { + hasApplications: { type: 'single-select', - label: 'Assigned', + label: 'Applications', options: [ { label: 'All', value: 'all' }, - { label: 'Yes', value: 'true' }, - { label: 'No', value: 'false' }, + { label: 'Has', value: 'true' }, + { label: 'None', value: 'false' }, ], }, } @@ -47,13 +47,13 @@ ...(mode === 'maintainer' || mode === 'wave' ? { - hasApplications: { + applicantAssigned: { type: 'single-select', - label: 'Applications', + label: 'Assigned', options: [ { label: 'All', value: 'all' }, - { label: 'Has', value: 'true' }, - { label: 'None', value: 'false' }, + { label: 'Yes', value: 'true' }, + { label: 'No', value: 'false' }, ], }, } @@ -87,7 +87,7 @@ ? { repoId: { type: 'dropdown', - label: 'Repository', + label: 'Repo', optionsPromise: (async () => { if (mode === 'wave') { if (!currentWaveProgramId) { @@ -140,12 +140,14 @@ ownUserId, mode, currentWaveProgramId, + flash = false, }: { onapply: (filters: IssueFilters) => void; appliedFilters: IssueFilters; ownUserId: string | null; mode: 'maintainer' | 'contributor' | 'wave'; currentWaveProgramId?: string; + flash?: boolean; } = $props(); let filters = $state(appliedFilters); @@ -222,6 +224,14 @@ filters = appliedFilters; } + export function hasChangesInFilters() { + return hasChanges; + } + + export function hasAppliedFiltersInView() { + return hasAppliedFilters; + } + let filterEntries = $derived( Object.entries(AVAILABLE_FILTERS(ownUserId, mode, currentWaveProgramId)) as [ keyof IssueFilters, @@ -302,7 +312,7 @@ {/each}
-
+
@@ -373,5 +383,10 @@ display: flex; justify-content: flex-end; gap: 0.5rem; + transition: background-color 0.3s; + } + + .actions.actions-flash { + background-color: var(--color-primary-level-1); } diff --git a/src/lib/components/wave/issues-page/issues-page.svelte b/src/lib/components/wave/issues-page/issues-page.svelte index d4d43f304..7f47dcdd5 100644 --- a/src/lib/components/wave/issues-page/issues-page.svelte +++ b/src/lib/components/wave/issues-page/issues-page.svelte @@ -108,6 +108,10 @@ } let filtersOpen = $state(false); + let filterFlash = $state(false); + let filterFlashTimeout: ReturnType | null = null; + let filterDropdownEl = $state(null); + let filterButtonEl = $state(null); // svelte-ignore non_reactive_update let filterConfigInstance: FilterConfig; @@ -120,6 +124,39 @@ } } + function triggerFilterFlash() { + if (filterFlashTimeout) { + clearTimeout(filterFlashTimeout); + } + + filterFlash = true; + filterFlashTimeout = setTimeout(() => { + filterFlash = false; + }, 450); + } + + function handleFilterOutsideClick(event: MouseEvent) { + if (!filtersOpen) return; + + const target = event.target as Node | null; + if (!target) return; + + if (filterDropdownEl?.contains(target) || filterButtonEl?.contains(target)) { + return; + } + + if ( + filterConfigInstance?.hasChangesInFilters() || + filterConfigInstance?.hasAppliedFiltersInView() + ) { + triggerFilterFlash(); + return; + } + + filtersOpen = false; + filterConfigInstance?.reset(); + } + let applyingFilters = $state(false); async function handleApplyFilters(filters: IssueFilters) { @@ -287,6 +324,8 @@ } + +
@@ -335,20 +374,22 @@ onclick={handleSearchOpen}>Search -
- +
+
+ +