mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-07-17 18:06:06 +00:00
style(web): keep market tag filter on a single horizontal-scroll row
With many category tags the quick-filter row used `sm:flex-wrap` on desktop, so once tags overflowed the available width they wrapped onto a second, center-aligned line — leaving an orphan tag floating under the row (looked broken and only gets worse as more tags are added). Make the row a single, never-wrapping line that scrolls horizontally at every breakpoint, left-aligned, with the scrollbar hidden and a subtle right-edge fade to signal there's more to scroll. Adds a reusable `.scrollbar-hide` utility to global.css.
This commit is contained in:
@@ -74,6 +74,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Hide scrollbar while keeping scroll behaviour (horizontal tag/filter rows). */
|
||||||
|
.scrollbar-hide {
|
||||||
|
-ms-overflow-style: none; /* IE / Edge */
|
||||||
|
scrollbar-width: none; /* Firefox */
|
||||||
|
}
|
||||||
|
.scrollbar-hide::-webkit-scrollbar {
|
||||||
|
display: none; /* Chrome / Safari / WebKit */
|
||||||
|
}
|
||||||
|
|
||||||
@custom-variant dark (&:is(.dark *));
|
@custom-variant dark (&:is(.dark *));
|
||||||
|
|
||||||
@theme inline {
|
@theme inline {
|
||||||
|
|||||||
@@ -787,38 +787,42 @@ function MarketPageContent({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 用真实标签做快速筛选 */}
|
{/* 用真实标签做快速筛选 —— 始终单行横向滚动,避免标签变多时换行错位 */}
|
||||||
<div className="mx-auto flex w-full max-w-4xl items-center gap-2 overflow-x-auto pb-1 sm:flex-wrap sm:justify-center sm:overflow-visible">
|
<div className="relative mx-auto w-full max-w-4xl">
|
||||||
<Button
|
<div className="scrollbar-hide flex items-center gap-2 overflow-x-auto pb-1 pr-6">
|
||||||
type="button"
|
<Button
|
||||||
variant={selectedTags.length === 0 ? 'secondary' : 'ghost'}
|
type="button"
|
||||||
size="sm"
|
variant={selectedTags.length === 0 ? 'secondary' : 'ghost'}
|
||||||
className="h-8 shrink-0"
|
size="sm"
|
||||||
onClick={() => handleTagsChange([])}
|
className="h-8 shrink-0"
|
||||||
>
|
onClick={() => handleTagsChange([])}
|
||||||
{t('market.allExtensions')}
|
>
|
||||||
</Button>
|
{t('market.allExtensions')}
|
||||||
{availableTags.map((tag) => {
|
</Button>
|
||||||
const selected = selectedTags.includes(tag.tag);
|
{availableTags.map((tag) => {
|
||||||
return (
|
const selected = selectedTags.includes(tag.tag);
|
||||||
<Button
|
return (
|
||||||
key={tag.tag}
|
<Button
|
||||||
type="button"
|
key={tag.tag}
|
||||||
variant={selected ? 'secondary' : 'ghost'}
|
type="button"
|
||||||
size="sm"
|
variant={selected ? 'secondary' : 'ghost'}
|
||||||
className="h-8 shrink-0"
|
size="sm"
|
||||||
onClick={() => {
|
className="h-8 shrink-0"
|
||||||
const newTags = selected
|
onClick={() => {
|
||||||
? selectedTags.filter((t) => t !== tag.tag)
|
const newTags = selected
|
||||||
: [...selectedTags, tag.tag];
|
? selectedTags.filter((t) => t !== tag.tag)
|
||||||
handleTagsChange(newTags);
|
: [...selectedTags, tag.tag];
|
||||||
}}
|
handleTagsChange(newTags);
|
||||||
>
|
}}
|
||||||
{tagNames[tag.tag] || tag.tag}
|
>
|
||||||
{selected && <X className="h-3.5 w-3.5" />}
|
{tagNames[tag.tag] || tag.tag}
|
||||||
</Button>
|
{selected && <X className="h-3.5 w-3.5" />}
|
||||||
);
|
</Button>
|
||||||
})}
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
{/* 右侧渐隐,提示还有更多标签可横向滚动查看 */}
|
||||||
|
<div className="pointer-events-none absolute right-0 top-0 bottom-1 w-8 bg-gradient-to-l from-background to-transparent" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user