mirror of
https://github.com/yattee/yattee.git
synced 2026-07-20 14:22:02 +00:00
Fix macOS native styling for search toolbar pickers and view options
The content type segmented picker rendered as a Liquid-Glass pill instead of a native macOS segmented control. Wrapping a `.segmented` Picker in `.opacity`/`.disabled`/`.accessibilityHidden`/`.fixedSize` (used to keep toolbar items mounted-but-invisible for stable layout) inserts a hosting layer that makes the toolbar fall back to the pill rendering. - SearchView: filters button and content type picker are now always visible on macOS, rendered bare so `.segmented` keeps native styling. - SearchView: don't reset the content type to .video on submit on macOS, so a pre-selected type (e.g. Playlists) is preserved (iOS unchanged). - InstanceBrowseView: same pill fix, rendering the tab / content type pickers bare via conditional `if` instead of opacity-masking. - ViewOptionsSheet / MediaBrowserViewOptionsSheet: use `.formStyle(.grouped)` for native macOS form styling in the options popover.
This commit is contained in:
@@ -156,7 +156,7 @@ struct ViewOptionsSheet: View {
|
|||||||
.presentationDragIndicator(.visible)
|
.presentationDragIndicator(.visible)
|
||||||
#endif
|
#endif
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
.padding()
|
.formStyle(.grouped)
|
||||||
.frame(width: 300)
|
.frame(width: 300)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -357,30 +357,26 @@ struct InstanceBrowseView: View {
|
|||||||
}
|
}
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
if #available(macOS 26, *) {
|
if #available(macOS 26, *) {
|
||||||
// Search filters button appears only while showing search results.
|
// Render the items bare (conditional `if`, no opacity/disabled
|
||||||
// Items stay mounted (invisible/inert) otherwise so the toolbar layout is stable.
|
// wrappers): wrapping a `.segmented` Picker inserts a hosting layer
|
||||||
ToolbarItem(placement: .navigation) {
|
// that makes the toolbar fall back to a Liquid-Glass pill instead of
|
||||||
searchFiltersToolbarButton
|
// the native segmented control. The search filters button shows only
|
||||||
.opacity(showsSearchFiltersInToolbar ? 1 : 0)
|
// while displaying search results; the principal picker swaps between
|
||||||
.disabled(!showsSearchFiltersInToolbar)
|
// the browse tab picker and the search content type picker.
|
||||||
.accessibilityHidden(!showsSearchFiltersInToolbar)
|
if showsSearchFiltersInToolbar {
|
||||||
|
ToolbarItem(placement: .navigation) {
|
||||||
|
searchFiltersToolbarButton
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.sharedBackgroundVisibility(showsSearchFiltersInToolbar ? .automatic : .hidden)
|
if isToolbarPickerVisible {
|
||||||
// Search content type picker while showing results, browse tab picker otherwise
|
ToolbarItem(placement: .principal) {
|
||||||
ToolbarItem(placement: .principal) {
|
|
||||||
Group {
|
|
||||||
if showsSearchFiltersInToolbar {
|
if showsSearchFiltersInToolbar {
|
||||||
searchContentTypePicker
|
searchContentTypePicker
|
||||||
} else {
|
} else {
|
||||||
tabPicker
|
tabPicker
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.fixedSize()
|
|
||||||
.opacity(isToolbarPickerVisible ? 1 : 0)
|
|
||||||
.disabled(!isToolbarPickerVisible)
|
|
||||||
.accessibilityHidden(!isToolbarPickerVisible)
|
|
||||||
}
|
}
|
||||||
.sharedBackgroundVisibility(isToolbarPickerVisible ? .automatic : .hidden)
|
|
||||||
} else if showsSearchFiltersInToolbar {
|
} else if showsSearchFiltersInToolbar {
|
||||||
ToolbarItem(placement: .navigation) {
|
ToolbarItem(placement: .navigation) {
|
||||||
searchFiltersToolbarButton
|
searchFiltersToolbarButton
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ struct MediaBrowserViewOptionsSheet: View {
|
|||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
// Popover content: no navigation chrome, click-outside dismisses.
|
// Popover content: no navigation chrome, click-outside dismisses.
|
||||||
formContent
|
formContent
|
||||||
.padding()
|
.formStyle(.grouped)
|
||||||
.frame(width: 300)
|
.frame(width: 300)
|
||||||
.onAppear {
|
.onAppear {
|
||||||
// Reset sort order if current selection is not available for this source type
|
// Reset sort order if current selection is not available for this source type
|
||||||
|
|||||||
@@ -291,29 +291,18 @@ struct SearchView: View {
|
|||||||
}
|
}
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
if searchInstance?.supportsSearchFilters == true {
|
if searchInstance?.supportsSearchFilters == true {
|
||||||
if #available(macOS 26, *) {
|
// Filters button + content type picker are always visible on macOS.
|
||||||
// Items stay in the toolbar even before a search is submitted
|
// The picker is rendered bare (no opacity/disabled/fixedSize wrappers):
|
||||||
// (invisible and inert) so the search field keeps a stable size.
|
// wrapping a `.segmented` Picker in those modifiers inserts a hosting
|
||||||
ToolbarItem(placement: .navigation) {
|
// layer that makes the toolbar fall back to a Liquid-Glass pill instead
|
||||||
searchFiltersToolbarButton
|
// of the native segmented control.
|
||||||
.opacity(hasSearched ? 1 : 0)
|
ToolbarItem(placement: .navigation) {
|
||||||
.disabled(!hasSearched)
|
searchFiltersToolbarButton
|
||||||
.accessibilityHidden(!hasSearched)
|
}
|
||||||
}
|
ToolbarItem(placement: .principal) {
|
||||||
.sharedBackgroundVisibility(hasSearched ? .automatic : .hidden)
|
if #available(macOS 26, *) {
|
||||||
ToolbarItem(placement: .principal) {
|
|
||||||
contentTypePicker
|
contentTypePicker
|
||||||
.fixedSize()
|
} else {
|
||||||
.opacity(hasSearched ? 1 : 0)
|
|
||||||
.disabled(!hasSearched)
|
|
||||||
.accessibilityHidden(!hasSearched)
|
|
||||||
}
|
|
||||||
.sharedBackgroundVisibility(hasSearched ? .automatic : .hidden)
|
|
||||||
} else if hasSearched {
|
|
||||||
ToolbarItem(placement: .navigation) {
|
|
||||||
searchFiltersToolbarButton
|
|
||||||
}
|
|
||||||
ToolbarItem(placement: .principal) {
|
|
||||||
contentTypePicker
|
contentTypePicker
|
||||||
.fixedSize()
|
.fixedSize()
|
||||||
}
|
}
|
||||||
@@ -331,7 +320,11 @@ struct SearchView: View {
|
|||||||
.searchable(text: searchTextBinding, prompt: Text(String(localized: "search.placeholder")))
|
.searchable(text: searchTextBinding, prompt: Text(String(localized: "search.placeholder")))
|
||||||
.onSubmit(of: .search) {
|
.onSubmit(of: .search) {
|
||||||
searchViewModel?.cancelSuggestions()
|
searchViewModel?.cancelSuggestions()
|
||||||
|
#if !os(macOS)
|
||||||
|
// On macOS the content type picker is always visible, so preserve the
|
||||||
|
// user's chosen type instead of resetting it to .video on each submit.
|
||||||
searchViewModel?.filters.type = .video
|
searchViewModel?.filters.type = .video
|
||||||
|
#endif
|
||||||
if let filters = searchViewModel?.filters {
|
if let filters = searchViewModel?.filters {
|
||||||
saveFilters(filters)
|
saveFilters(filters)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user