diff --git a/cmd/server/tests/filter_builder_test.go b/cmd/server/tests/filter_builder_test.go index f08943a1..24a641de 100644 --- a/cmd/server/tests/filter_builder_test.go +++ b/cmd/server/tests/filter_builder_test.go @@ -526,6 +526,16 @@ func TestFilterSuggestionsUnderRules(t *testing.T) { assert.NotContains(t, valuesOf(results), "spacewestern", "zero-match values never offered") assert.NotContains(t, valuesOf(results), "history", "values outside the rules never offered") + // Browse with NO other rules in place: the blank query still lists + // the field's values (the static similarity path would answer a + // single space with nothing). Regression for the empty-browse bug. + status, results = suggest("genre", " ", "") + require.Equal(t, http.StatusOK, status) + assert.Contains(t, valuesOf(results), "fantasy", "browse with no rules lists the field's values") + status, results = suggest("author", " ", "") + require.Equal(t, http.StatusOK, status) + assert.Contains(t, valuesOf(results), "Amara Voss", "author browse with no rules") + // Library field menu: visibility-scoped, id values + name display // (this test's fixture libraries are named "Test Builder Sug …"). status, results = suggest("library", "Test Builder", "") diff --git a/internal/handlers/media.go b/internal/handlers/media.go index 42b78347..6a1631d7 100644 --- a/internal/handlers/media.go +++ b/internal/handlers/media.go @@ -2648,9 +2648,14 @@ func (mh *MediaHandler) handleFieldValuesSearch(c *echo.Context, userID pgtype.U tree = t } - // Static path: the classic six with no rule tree (unchanged - // contract — the tag-dropdown island and deep links still ride it). - staticSix := tree == nil + // Static path: the classic six with a REAL typed query and no rule + // tree (unchanged contract — the tag-dropdown island and deep links + // still ride it). A BLANK typed query is BROWSE (the builder's + // click-the-box top-values list): the static queries would + // similarity-match a single space into nothing, so browse rides the + // composed engine, which trims the query and answers the top values + // under the rules. + staticSix := tree == nil && strings.TrimSpace(searchQuery) != "" if staticSix { switch fieldType { case "author", "genre", "tags", "narrator", "series", "language": diff --git a/web/static/input.css b/web/static/input.css index 8180b732..71c44f46 100644 --- a/web/static/input.css +++ b/web/static/input.css @@ -1962,6 +1962,8 @@ .fb-menu-value { width: 16rem; left: 0; + top: 100%; + margin-top: 0.25rem; } .fb-menu-group { font-size: 0.65rem; @@ -1974,9 +1976,6 @@ background-color: color-mix(in srgb, var(--text-primary) 5%, transparent); border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); - position: sticky; - top: 0; - z-index: 1; } .fb-menu-filter-wrap { padding: 0.4rem 0.5rem;