Coffee journaling on ATProto (alpha) alpha.arabica.social
coffee

fix: flickering of community feed on filter/sort mode change

authored by pdewey.com and committed by tangled.org 2a8774c7 5af38816

+16 -19
+16 -19
internal/web/pages/feed.templ
··· 99 100 // FeedFilterBar renders the type filter tabs and sort selector 101 templ FeedFilterBar(qs FeedQueryState) { 102 - <div class="flex flex-wrap items-center justify-between gap-2 mb-4"> 103 <!-- Type filter tabs --> 104 <div class="flex flex-wrap gap-1"> 105 for _, tab := range feedFilterTabs() { 106 <button 107 - class={ "px-3 py-1.5 text-sm rounded-full transition-colors", 108 - templ.KV("bg-brown-800 text-brown-50 font-medium", qs.TypeFilter == tab.Value), 109 - templ.KV("bg-brown-100 text-brown-700 hover:bg-brown-200", qs.TypeFilter != tab.Value) } 110 - hx-get={ buildFeedURL(tab.Value, qs.Sort) } 111 - hx-target="#feed-container" 112 - hx-swap="outerHTML" 113 > 114 { tab.Label } 115 </button> ··· 118 <!-- Sort selector --> 119 <div class="flex items-center gap-1"> 120 <button 121 - class={ "px-3 py-1.5 text-sm rounded-full transition-colors", 122 - templ.KV("bg-brown-800 text-brown-50 font-medium", qs.Sort == "" || qs.Sort == "recent"), 123 - templ.KV("bg-brown-100 text-brown-700 hover:bg-brown-200", qs.Sort != "" && qs.Sort != "recent") } 124 - hx-get={ buildFeedURL(qs.TypeFilter, "recent") } 125 - hx-target="#feed-container" 126 - hx-swap="outerHTML" 127 > 128 New 129 </button> 130 <button 131 - class={ "px-3 py-1.5 text-sm rounded-full transition-colors", 132 - templ.KV("bg-brown-800 text-brown-50 font-medium", qs.Sort == "popular"), 133 - templ.KV("bg-brown-100 text-brown-700 hover:bg-brown-200", qs.Sort != "popular") } 134 - hx-get={ buildFeedURL(qs.TypeFilter, "popular") } 135 - hx-target="#feed-container" 136 - hx-swap="outerHTML" 137 > 138 Popular 139 </button>
··· 99 100 // FeedFilterBar renders the type filter tabs and sort selector 101 templ FeedFilterBar(qs FeedQueryState) { 102 + <div 103 + class="flex flex-wrap items-center justify-between gap-2 mb-4" 104 + data-type-filter={ qs.TypeFilter } 105 + data-sort={ qs.Sort } 106 + x-data="{ typeFilter: $el.dataset.typeFilter, sort: $el.dataset.sort, feedURL(t, s) { let u = '/api/feed', sep = '?'; if (t) { u += sep + 'type=' + t; sep = '&'; } if (s) { if (s !== 'recent') { u += sep + 'sort=' + s; } } return u; }, changeFilter(t) { this.typeFilter = t; htmx.ajax('GET', this.feedURL(t, this.sort), {target: '#feed-items', swap: 'outerHTML', select: '#feed-items'}); }, changeSort(s) { this.sort = s; htmx.ajax('GET', this.feedURL(this.typeFilter, s), {target: '#feed-items', swap: 'outerHTML', select: '#feed-items'}); } }" 107 + > 108 <!-- Type filter tabs --> 109 <div class="flex flex-wrap gap-1"> 110 for _, tab := range feedFilterTabs() { 111 <button 112 + class="px-3 py-1.5 text-sm rounded-full transition-colors" 113 + :class="typeFilter === $el.dataset.tab ? 'bg-brown-800 text-brown-50 font-medium' : 'bg-brown-100 text-brown-700 hover:bg-brown-200'" 114 + data-tab={ tab.Value } 115 + @click="changeFilter($el.dataset.tab)" 116 > 117 { tab.Label } 118 </button> ··· 121 <!-- Sort selector --> 122 <div class="flex items-center gap-1"> 123 <button 124 + class="px-3 py-1.5 text-sm rounded-full transition-colors" 125 + :class="(sort === '' || sort === 'recent') ? 'bg-brown-800 text-brown-50 font-medium' : 'bg-brown-100 text-brown-700 hover:bg-brown-200'" 126 + @click="changeSort('recent')" 127 > 128 New 129 </button> 130 <button 131 + class="px-3 py-1.5 text-sm rounded-full transition-colors" 132 + :class="sort === 'popular' ? 'bg-brown-800 text-brown-50 font-medium' : 'bg-brown-100 text-brown-700 hover:bg-brown-200'" 133 + @click="changeSort('popular')" 134 > 135 Popular 136 </button>