diff --git a/packages/mobile/src/screens/search-screen/SearchFilters.tsx b/packages/mobile/src/screens/search-screen/SearchFilters.tsx index 863c1591a12..e40d4760ca3 100644 --- a/packages/mobile/src/screens/search-screen/SearchFilters.tsx +++ b/packages/mobile/src/screens/search-screen/SearchFilters.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from 'react' +import { useMemo, useState, useEffect } from 'react' import type { Genre } from '@audius/common/utils' import { @@ -48,12 +48,25 @@ export const GenreFilter = () => { setGenre(value) } + const options = useMemo(() => { + // Freeform/custom genres (e.g. "Hyperpop Fusion") aren't in the predefined + // GENRES list. Without a matching option the FilterButton can't resolve a + // label and the active chip falls back to the generic "Genre" text, leaving + // no indication of what's actually being filtered. Add the current genre as + // an option so it renders as a selected chip. + if (genre && !genreOptions.some((option) => option.value === genre)) { + return [{ label: genre, value: genre }, ...genreOptions] + } + + return genreOptions + }, [genre]) + return ( ) diff --git a/packages/web/src/pages/search-page/SearchFilters.tsx b/packages/web/src/pages/search-page/SearchFilters.tsx index 4a1a4936f1c..835d7247e90 100644 --- a/packages/web/src/pages/search-page/SearchFilters.tsx +++ b/packages/web/src/pages/search-page/SearchFilters.tsx @@ -1,4 +1,4 @@ -import { ReactElement, useCallback, useState } from 'react' +import { ReactElement, useCallback, useMemo, useState } from 'react' import { GENRES, @@ -55,6 +55,24 @@ const GenreFilter = () => { updateGenreParams(value) } + const options = useMemo(() => { + const genreOptions = GENRES.map((genre) => ({ + label: genre, + value: convertGenreLabelToValue(genre) + })) + + // Freeform/custom genres (e.g. "Hyperpop Fusion") aren't in the predefined + // GENRES list. Without a matching option the FilterButton can't resolve a + // label and the active chip falls back to the generic "Genre" text, leaving + // no indication of what's actually being filtered. Add the current genre as + // an option so it renders as a selected chip. + if (genre && !genreOptions.some((option) => option.value === genre)) { + return [{ label: genre, value: genre }, ...genreOptions] + } + + return genreOptions + }, [genre]) + return ( { }} value={genre} onChange={handleGenreChange} - options={GENRES.map((genre) => ({ - label: genre, - value: convertGenreLabelToValue(genre) - }))} + options={options} showFilterInput filterInputProps={{ label: messages.genreFilterLabel }} />