Fix vaporwave glitch band clipping the progress pie badge
- Move overflow:hidden off the group card onto a dedicated .vw-glitch-clip overlay so the card can stay overflow-visible and the corner progress pie is no longer cropped by the card or its rounded corner. - Add overflow-x-clip to CategoryLane so badges that poke past the card's right edge are discarded instead of spawning a stray horizontal scrollbar. - Nudge TodoProgressPie to -right-2.5 and give the "N/N done" label pr-2.5 so both clear each other within the lane's 10px margin without spilling.
This commit is contained in:
parent
6f7b72c882
commit
fca66959c2
|
|
@ -1720,17 +1720,34 @@ html.theme-vaporwave .vw-palm--right-small {
|
||||||
that inline value (animations sit above inline styles in the cascade) --
|
that inline value (animations sit above inline styles in the cascade) --
|
||||||
the card stops following the pointer. opacity-50 is exactly the class the
|
the card stops following the pointer. opacity-50 is exactly the class the
|
||||||
card gets while dragging, so the hiccup stands down for the duration.
|
card gets while dragging, so the hiccup stands down for the duration.
|
||||||
(overflow: hidden keeps the tracking band clipped to the card while it
|
(The tracking band sweeps inside a .vw-glitch-clip clip box rendered by
|
||||||
sweeps; the hover lift uses the separate `translate` property, so the
|
GroupCard rather than relying on overflow: hidden on the card itself --
|
||||||
jitter doesn't fight it.) */
|
the card must stay overflow-visible so the progress pie, which pokes
|
||||||
|
outside the bottom-right corner, isn't cropped by the card or its
|
||||||
|
rounded-2xl corner. The hover lift uses the separate `translate`
|
||||||
|
property, so the jitter doesn't fight it.) */
|
||||||
html.theme-vaporwave [data-group-card]:not(.opacity-50) {
|
html.theme-vaporwave [data-group-card]:not(.opacity-50) {
|
||||||
overflow: hidden;
|
|
||||||
animation: vw-card-glitch 10s linear infinite;
|
animation: vw-card-glitch 10s linear infinite;
|
||||||
}
|
}
|
||||||
html.theme-vaporwave [data-group-card]:not(.opacity-50) > div:first-child h3 {
|
html.theme-vaporwave [data-group-card]:not(.opacity-50) > div:first-child h3 {
|
||||||
animation: vw-title-glitch 10s linear infinite;
|
animation: vw-title-glitch 10s linear infinite;
|
||||||
}
|
}
|
||||||
html.theme-vaporwave [data-group-card]:not(.opacity-50)::after {
|
/* The band's clip box: a full-card overlay (in GroupCard) that carries the
|
||||||
|
overflow clipping, so the card itself never needs it. inset-0 +
|
||||||
|
border-radius: inherit matches the card's own padding-box clip exactly,
|
||||||
|
sweep included. Hidden in every other theme. */
|
||||||
|
.vw-glitch-clip {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
html.theme-vaporwave .vw-glitch-clip {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: inherit;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
html.theme-vaporwave [data-group-card]:not(.opacity-50) .vw-glitch-clip::after {
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
|
@ -1756,14 +1773,14 @@ html.theme-vaporwave [data-group-card]:not(.opacity-50)::after {
|
||||||
first delay elapses, and under reduced motion, everything just sits still.) */
|
first delay elapses, and under reduced motion, everything just sits still.) */
|
||||||
html.theme-vaporwave [data-category-lane] .overflow-y-auto > div:nth-child(3n + 2) [data-group-card]:not(.opacity-50),
|
html.theme-vaporwave [data-category-lane] .overflow-y-auto > div:nth-child(3n + 2) [data-group-card]:not(.opacity-50),
|
||||||
html.theme-vaporwave [data-category-lane] .overflow-y-auto > div:nth-child(3n + 2) [data-group-card]:not(.opacity-50) > div:first-child h3,
|
html.theme-vaporwave [data-category-lane] .overflow-y-auto > div:nth-child(3n + 2) [data-group-card]:not(.opacity-50) > div:first-child h3,
|
||||||
html.theme-vaporwave [data-category-lane] .overflow-y-auto > div:nth-child(3n + 2) [data-group-card]:not(.opacity-50)::after {
|
html.theme-vaporwave [data-category-lane] .overflow-y-auto > div:nth-child(3n + 2) [data-group-card]:not(.opacity-50) .vw-glitch-clip::after {
|
||||||
animation-duration: 13s;
|
animation-duration: 13s;
|
||||||
animation-delay: 3s;
|
animation-delay: 3s;
|
||||||
}
|
}
|
||||||
/* Phase C: the longest period, offset furthest. */
|
/* Phase C: the longest period, offset furthest. */
|
||||||
html.theme-vaporwave [data-category-lane] .overflow-y-auto > div:nth-child(3n) [data-group-card]:not(.opacity-50),
|
html.theme-vaporwave [data-category-lane] .overflow-y-auto > div:nth-child(3n) [data-group-card]:not(.opacity-50),
|
||||||
html.theme-vaporwave [data-category-lane] .overflow-y-auto > div:nth-child(3n) [data-group-card]:not(.opacity-50) > div:first-child h3,
|
html.theme-vaporwave [data-category-lane] .overflow-y-auto > div:nth-child(3n) [data-group-card]:not(.opacity-50) > div:first-child h3,
|
||||||
html.theme-vaporwave [data-category-lane] .overflow-y-auto > div:nth-child(3n) [data-group-card]:not(.opacity-50)::after {
|
html.theme-vaporwave [data-category-lane] .overflow-y-auto > div:nth-child(3n) [data-group-card]:not(.opacity-50) .vw-glitch-clip::after {
|
||||||
animation-duration: 17s;
|
animation-duration: 17s;
|
||||||
animation-delay: 7s;
|
animation-delay: 7s;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -162,7 +162,16 @@ export function CategoryLane({ category }: { category: CategoryDTO }) {
|
||||||
// leaves enough clearance that a card's hover lift
|
// leaves enough clearance that a card's hover lift
|
||||||
// (-translate-y-0.5 in GroupCard) doesn't tuck its top stroke
|
// (-translate-y-0.5 in GroupCard) doesn't tuck its top stroke
|
||||||
// under the lane header above it.
|
// under the lane header above it.
|
||||||
"flex-1 space-y-2 overflow-y-auto rounded-t-lg px-2.5 pt-1.5 pb-2 transition-colors",
|
//
|
||||||
|
// overflow-x-clip: the lane is a fixed-width (w-72) panel whose
|
||||||
|
// cards always span it, so horizontal scrolling is never wanted.
|
||||||
|
// The only things that can spill horizontally are corner badges
|
||||||
|
// like the group card's progress pie, which deliberately poke
|
||||||
|
// past the card's right edge. `clip` (not `hidden`) keeps
|
||||||
|
// overflow-y-auto fully functional while simply discarding any
|
||||||
|
// spill, so a future badge that strays a px too far can never
|
||||||
|
// grow a stray horizontal scrollbar here.
|
||||||
|
"flex-1 space-y-2 overflow-y-auto overflow-x-clip rounded-t-lg px-2.5 pt-1.5 pb-2 transition-colors",
|
||||||
isDropTargetLane && "bg-primary/10"
|
isDropTargetLane && "bg-primary/10"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -406,7 +406,11 @@ export function GroupCard({ group }: { group: GroupDTO }) {
|
||||||
<TooltipContent side="top">Archive (all to-dos done)</TooltipContent>
|
<TooltipContent side="top">Archive (all to-dos done)</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
<span className="ml-auto text-[11px] font-medium tabular-nums text-muted-foreground">
|
{/* pr-2.5: the corner progress pie (TodoProgressPie) hugs
|
||||||
|
the card's right edge right here, so the label keeps a
|
||||||
|
little room of its own -- together the two clear each
|
||||||
|
other without either spilling past the lane's edge. */}
|
||||||
|
<span className="ml-auto pr-2.5 text-[11px] font-medium tabular-nums text-muted-foreground">
|
||||||
{completedCount}/{group.todos.length} done
|
{completedCount}/{group.todos.length} done
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -421,6 +425,14 @@ export function GroupCard({ group }: { group: GroupDTO }) {
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Vaporwave's VHS tracking band sweeps inside this clip box (see
|
||||||
|
.vw-glitch-clip in app/globals.css) instead of the card itself
|
||||||
|
using overflow: hidden -- the card must stay overflow-visible so
|
||||||
|
the progress pie can poke past the bottom-right corner without
|
||||||
|
being clipped by it or the card's rounded corner. display:none
|
||||||
|
(and thus inert) in every other theme. */}
|
||||||
|
<div className="vw-glitch-clip" aria-hidden />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{editingTodo && (
|
{editingTodo && (
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,20 @@ export function TodoProgressPie({
|
||||||
// context (see hover:-translate-y-0.5 in GroupCard), so
|
// context (see hover:-translate-y-0.5 in GroupCard), so
|
||||||
// without an explicit z-index here it paints on top and crops
|
// without an explicit z-index here it paints on top and crops
|
||||||
// the badge's overlapping edge.
|
// the badge's overlapping edge.
|
||||||
className="absolute -right-1.5 -bottom-1.5 z-10 size-7 shrink-0 cursor-default rounded-full border-2 shadow-sm outline-none transition-transform hover:scale-110 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1"
|
// -right-2.5: the badge's horizontal position is a budget, not
|
||||||
|
// a taste call. From the card's right border there are exactly
|
||||||
|
// 10px of lane (CategoryLane's px-2.5) before the lane's own
|
||||||
|
// clip edge -- or its vertical scrollbar, in classic-scrollbar
|
||||||
|
// browsers, which sits at the same 10px mark and paints over
|
||||||
|
// anything past it. So the badge may stick out at most ~7px
|
||||||
|
// (10px offset from the card's *padding* edge minus the 3px
|
||||||
|
// border) to stay clear of both. In exchange the "N/N done"
|
||||||
|
// footer text carries pr-2.5, which hands this badge the room
|
||||||
|
// it needs to clear the text (see the span in GroupCard).
|
||||||
|
// Moving it further out looks like it "fits" until it doesn't:
|
||||||
|
// past the 10px mark the lane clips the badge's edge or grows
|
||||||
|
// a stray horizontal scrollbar.
|
||||||
|
className="absolute -right-2.5 -bottom-1.5 z-10 size-7 shrink-0 cursor-default rounded-full border-2 shadow-sm outline-none transition-transform hover:scale-110 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1"
|
||||||
style={{
|
style={{
|
||||||
borderColor: accentColor,
|
borderColor: accentColor,
|
||||||
background: `conic-gradient(${accentColor} ${pct}%, ${emptyColor} ${pct}% 100%)`,
|
background: `conic-gradient(${accentColor} ${pct}%, ${emptyColor} ${pct}% 100%)`,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue