From d7434c5a98cac6f06e1b95cb73a211050fedd9f6 Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Thu, 22 Jan 2026 19:54:12 -0500 Subject: [PATCH 1/5] Add scrollable tag strip option --- css/tailwind.source.css | 6 ++++++ js/ui/components/hashtagStripHelper.js | 7 ++++++- js/ui/components/tagPillList.js | 4 ++++ js/ui/views/VideoListView.js | 1 + 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/css/tailwind.source.css b/css/tailwind.source.css index ef7af0aa..1f77eb25 100644 --- a/css/tailwind.source.css +++ b/css/tailwind.source.css @@ -2419,6 +2419,12 @@ overflow: hidden; } + .video-tag-strip--scroll { + overflow-x: auto; + overflow-y: hidden; + -webkit-overflow-scrolling: touch; + } + .video-tag-pill { @apply inline-flex items-center gap-2 rounded-full border border-status-neutral-border bg-status-neutral-surface px-3 py-1 text-2xs font-medium text-status-neutral-on; @apply relative justify-center whitespace-nowrap transition; diff --git a/js/ui/components/hashtagStripHelper.js b/js/ui/components/hashtagStripHelper.js index 8b0953e2..f011caed 100644 --- a/js/ui/components/hashtagStripHelper.js +++ b/js/ui/components/hashtagStripHelper.js @@ -12,12 +12,14 @@ export class HashtagStripHelper { window: win = null, logger, context = "", + scrollable = false, } = {}) { this.document = doc || (typeof document !== "undefined" ? document : null); this.window = win || this.document?.defaultView || (typeof window !== "undefined" ? window : null); this.logger = logger || userLogger; this.context = typeof context === "string" ? context : ""; + this.scrollable = scrollable === true; this.container = null; this._tagStrip = null; @@ -191,11 +193,14 @@ export class HashtagStripHelper { onTagActivate: (tag, detail = {}) => this._handleTagActivate(tag, detail), getTagState: (tag) => this._resolveTagState(tag), + scrollable: this.scrollable, }); root.appendChild(strip); this._tagStrip = strip; - trimTagPillStripToFit({ strip, container: root }); + if (!this.scrollable) { + trimTagPillStripToFit({ strip, container: root }); + } root.hidden = strip.childElementCount === 0; } finally { this._isApplyingTrim = false; diff --git a/js/ui/components/tagPillList.js b/js/ui/components/tagPillList.js index dc194561..ea89704e 100644 --- a/js/ui/components/tagPillList.js +++ b/js/ui/components/tagPillList.js @@ -213,12 +213,16 @@ export function renderTagPillStrip({ tags = [], onTagActivate, getTagState, + scrollable = false, } = {}) { const resolvedDocument = resolveDocument(doc); assertDocument(resolvedDocument); const root = resolvedDocument.createElement("div"); root.classList.add("video-tag-strip"); + if (scrollable) { + root.classList.add("video-tag-strip--scroll"); + } const buttons = tags.map((tag) => createTagButton({ diff --git a/js/ui/views/VideoListView.js b/js/ui/views/VideoListView.js index faa8fc77..e25d329d 100644 --- a/js/ui/views/VideoListView.js +++ b/js/ui/views/VideoListView.js @@ -180,6 +180,7 @@ export class VideoListView { document: this.document, window: this.window, logger: userLogger, + scrollable: true, }); this.popularTagHelper.setContext("popular-tags"); this.popularTagHelper.setActivateHandler((detail) => From 766bf0c872112a9c395cdc6661a5a56a55283250 Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Thu, 22 Jan 2026 19:58:12 -0500 Subject: [PATCH 2/5] Refine scrollable tag strip styling --- css/tailwind.source.css | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/css/tailwind.source.css b/css/tailwind.source.css index 1f77eb25..62da5801 100644 --- a/css/tailwind.source.css +++ b/css/tailwind.source.css @@ -2423,6 +2423,26 @@ overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch; + padding-bottom: var(--space-2xs); + scrollbar-width: thin; + scrollbar-color: var(--scrollbar-thumb) transparent; + } + + .video-tag-strip--scroll::-webkit-scrollbar { + height: var(--scrollbar-thin-width); + } + + .video-tag-strip--scroll::-webkit-scrollbar-track { + background: transparent; + } + + .video-tag-strip--scroll::-webkit-scrollbar-thumb { + background: var(--scrollbar-thumb); + border-radius: var(--radius-sm); + } + + .video-tag-strip--scroll::-webkit-scrollbar-thumb:hover { + background: var(--scrollbar-thumb-hover); } .video-tag-pill { From 711f9bd03190568a03f5f93a8665181873c9de75 Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Thu, 22 Jan 2026 20:01:49 -0500 Subject: [PATCH 3/5] Adjust scrollable tag strip scrollbar --- css/tailwind.source.css | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/css/tailwind.source.css b/css/tailwind.source.css index 62da5801..92b9f1b1 100644 --- a/css/tailwind.source.css +++ b/css/tailwind.source.css @@ -2423,26 +2423,28 @@ overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch; - padding-bottom: var(--space-2xs); + padding-bottom: var(--space-xs); scrollbar-width: thin; scrollbar-color: var(--scrollbar-thumb) transparent; } .video-tag-strip--scroll::-webkit-scrollbar { - height: var(--scrollbar-thin-width); + height: 4px; } .video-tag-strip--scroll::-webkit-scrollbar-track { - background: transparent; + background: + linear-gradient( + to bottom, + transparent calc(50% - 0.5px), + var(--scrollbar-track) calc(50% - 0.5px) calc(50% + 0.5px), + transparent calc(50% + 0.5px) + ); } .video-tag-strip--scroll::-webkit-scrollbar-thumb { background: var(--scrollbar-thumb); - border-radius: var(--radius-sm); - } - - .video-tag-strip--scroll::-webkit-scrollbar-thumb:hover { - background: var(--scrollbar-thumb-hover); + border-radius: var(--radius-pill); } .video-tag-pill { From 5dde681d089b4aaf3328a27aa56c2b83190cf92c Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Thu, 22 Jan 2026 20:06:02 -0500 Subject: [PATCH 4/5] Pass click events to tag preference handler --- js/ui/components/hashtagStripHelper.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/ui/components/hashtagStripHelper.js b/js/ui/components/hashtagStripHelper.js index f011caed..35d1a849 100644 --- a/js/ui/components/hashtagStripHelper.js +++ b/js/ui/components/hashtagStripHelper.js @@ -245,6 +245,7 @@ export class HashtagStripHelper { try { this.activateHandler({ tag, + event: detail?.event || null, trigger: detail?.button || null, context: this.context, }); From 475f6786811ef33a1ac40472554ccf87f88d1cb3 Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Thu, 22 Jan 2026 20:16:24 -0500 Subject: [PATCH 5/5] Harden tag preference activation for popular tags --- js/ui/components/hashtagStripHelper.js | 8 +++++++- js/ui/views/VideoListView.js | 9 +++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/js/ui/components/hashtagStripHelper.js b/js/ui/components/hashtagStripHelper.js index 35d1a849..6dc2dde5 100644 --- a/js/ui/components/hashtagStripHelper.js +++ b/js/ui/components/hashtagStripHelper.js @@ -243,10 +243,16 @@ export class HashtagStripHelper { } try { + const trigger = + detail?.button || + detail?.event?.currentTarget || + detail?.event?.target?.closest?.("button[data-tag]") || + null; this.activateHandler({ tag, event: detail?.event || null, - trigger: detail?.button || null, + trigger, + button: trigger, context: this.context, }); } catch (error) { diff --git a/js/ui/views/VideoListView.js b/js/ui/views/VideoListView.js index e25d329d..51871bc9 100644 --- a/js/ui/views/VideoListView.js +++ b/js/ui/views/VideoListView.js @@ -1289,8 +1289,13 @@ export class VideoListView { detail && typeof detail === "object" ? detail : { tag: detail }; const tag = candidate.tag; const event = candidate.event || options.event || null; - const trigger = - candidate.trigger || candidate.button || options.button || null; + let trigger = candidate.trigger || candidate.button || options.button || null; + if (!trigger && event && event.target) { + trigger = + event.target.closest?.("button[data-tag]") || + event.currentTarget || + null; + } const context = typeof candidate.context === "string" && candidate.context ? candidate.context