Skip to content

Commit 6881ed0

Browse files
committed
clean fab
1 parent 88baefa commit 6881ed0

1 file changed

Lines changed: 49 additions & 3 deletions

File tree

frontend/src/lib/components/ArticleCard.svelte

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,26 @@
396396
397397
let overflowTriggerRef = $state<HTMLButtonElement | null>(null);
398398
399+
// Sticky detection: track whether the action bar is floating (stuck) vs at its natural position
400+
let actionBarSentinelRef = $state<HTMLDivElement | null>(null);
401+
let isActionBarFloating = $state(false);
402+
403+
$effect(() => {
404+
if (!expanded || !actionBarSentinelRef) {
405+
isActionBarFloating = false;
406+
return;
407+
}
408+
const observer = new IntersectionObserver(
409+
([entry]) => {
410+
// When the sentinel is visible, the action bar is at its natural position (not floating)
411+
isActionBarFloating = !entry.isIntersecting;
412+
},
413+
{ threshold: 0 }
414+
);
415+
observer.observe(actionBarSentinelRef);
416+
return () => observer.disconnect();
417+
});
418+
399419
function handleOverflowTag(e: MouseEvent) {
400420
e.stopPropagation();
401421
overflowMenuOpen = false;
@@ -635,6 +655,7 @@
635655
<div
636656
class="article-actions-container"
637657
class:scroll-hidden={expanded && !feedViewStore.mobileControlsVisible}
658+
class:floating={isActionBarFloating}
638659
>
639660
<div class="article-actions">
640661
{#if isShareMode}
@@ -785,6 +806,7 @@
785806
{/if}
786807
</div>
787808
</div>
809+
{#if expanded}<div class="action-bar-sentinel" bind:this={actionBarSentinelRef}></div>{/if}
788810

789811
{#if tagMenuOpen}
790812
<TagMenu
@@ -1190,14 +1212,20 @@
11901212
}
11911213
}
11921214
1193-
/* Expanded: pop out into floating pill, sticky at bottom */
1215+
/* Expanded: sticky at bottom, ready to float */
11941216
.article-item.expanded .article-actions-container {
11951217
justify-content: center;
11961218
position: sticky;
11971219
bottom: 0;
11981220
padding: 1rem 0;
11991221
}
12001222
1223+
/* Sentinel element for sticky detection */
1224+
.action-bar-sentinel {
1225+
height: 1px;
1226+
margin-top: -1px;
1227+
}
1228+
12011229
/* On mobile, position above the MobileBottomBar and hide on scroll */
12021230
@media (max-width: 1000px) {
12031231
.article-item.expanded .article-actions-container {
@@ -1214,7 +1242,8 @@
12141242
}
12151243
}
12161244
1217-
.article-item.expanded .article-actions {
1245+
/* Floating pill styles only when action bar is stuck */
1246+
.article-item.expanded .article-actions-container.floating .article-actions {
12181247
justify-content: space-between;
12191248
width: auto;
12201249
gap: 0.875rem;
@@ -1223,15 +1252,32 @@
12231252
backdrop-filter: blur(8px);
12241253
border-radius: 9999px;
12251254
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
1255+
transition:
1256+
background 0.2s ease,
1257+
box-shadow 0.2s ease,
1258+
border-radius 0.2s ease,
1259+
padding 0.2s ease;
12261260
}
12271261
12281262
@media (prefers-color-scheme: dark) {
1229-
.article-item.expanded .article-actions {
1263+
.article-item.expanded .article-actions-container.floating .article-actions {
12301264
background: rgba(40, 40, 40, 0.95);
12311265
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
12321266
}
12331267
}
12341268
1269+
/* Non-floating expanded state: normal inline look */
1270+
.article-item.expanded .article-actions-container:not(.floating) .article-actions {
1271+
justify-content: space-between;
1272+
width: auto;
1273+
gap: 0.875rem;
1274+
transition:
1275+
background 0.2s ease,
1276+
box-shadow 0.2s ease,
1277+
border-radius 0.2s ease,
1278+
padding 0.2s ease;
1279+
}
1280+
12351281
.action-btn {
12361282
display: flex;
12371283
align-items: center;

0 commit comments

Comments
 (0)