Merge pull request #406 from basecamp/closing-soon-badge

Closing soon badge
This commit is contained in:
Andy Smith
2025-05-07 11:13:35 -05:00
committed by GitHub
6 changed files with 109 additions and 1 deletions
+9
View File
@@ -26,4 +26,13 @@
50% { transform: translateX(-1rem); }
75% { transform: translateX(1rem); }
}
@keyframes wobble {
0% { transform: rotate(calc(var(--bubble-rotate) + 30deg)); }
15% { border-radius: 66% 34% 72% 28% / 39% 63% 37% 61%; }
25% { border-radius: 55% 47% 62% 40% / 58% 50% 52% 44%; }
33% { border-radius: 46% 54% 61% 39% / 50% 51% 49% 50%; }
50% { border-radius: 54% 46% 61% 39% / 57% 49% 51% 43%; }
75% { border-radius: 53% 45% 60% 38% / 56% 48% 50% 42%; }
}
}
+58 -1
View File
@@ -59,7 +59,7 @@
transition: opacity 0.2s ease-in-out;
}
@media (hover: hover) {
@media (any-hover: hover) {
.card:hover & {
img:not([src=""]) {
opacity: 1;
@@ -286,4 +286,61 @@
-2px 2px 0 var(--card-color),
2px 2px 0 var(--card-color);
}
.card__bubble {
--bubble-color: radial-gradient(oklch(var(--lch-blue-medium) / 10%) 50%, oklch(var(--lch-blue-medium) / 50%) 100%);
--bubble-shape: 54% 46% 61% 39% / 57% 49% 51% 43%;
--bubble-rotate: 0deg;
--size: 5cqi;
block-size: var(--size);
container-type: inline-size;
font-size: 1.75rem;
font-weight: bold;
inline-size: var(--size);
inset: 50% auto auto -0.5ch;
padding: 0.5cqi;
position: absolute;
translate: -100% -50%;
&:before {
background: var(--bubble-color);
border-radius: var(--bubble-shape);
content: "";
inset: 0;
position: absolute;
transform: rotate(var(--bubble-rotate));
}
@media (any-hover: hover) {
&:hover:before {
animation: wobble 1200ms;
}
}
span {
display: grid;
font-size: 40cqi;
font-weight: 900;
inset: 0;
place-content: center;
position: absolute;
text-align: center;
}
svg {
display: block;
letter-spacing: 0.125ch;
text-transform: uppercase;
}
.card:nth-child(2n+1) & { --bubble-rotate: -90deg; }
.card:nth-child(3n+1) & { --bubble-rotate: 45deg; }
}
.card__bubble--today {
span {
font-size: 30cqi;
}
}
}
+4
View File
@@ -79,5 +79,9 @@
inset: 0 0 auto auto;
position: absolute;
}
.card__bubble {
display: none;
}
}
}
+11
View File
@@ -1,6 +1,9 @@
module Card::Closeable
extend ActiveSupport::Concern
AUTO_CLOSE_AFTER = 30.days
AUTO_CLOSE_REMINDER_BEFORE = 30.days
included do
has_one :closure, dependent: :destroy
@@ -26,6 +29,14 @@ module Card::Closeable
last_active_at + auto_close_period if auto_closing? && last_active_at
end
def days_until_close
(auto_close_at.to_date - Date.current).to_i if auto_close_at
end
def closing_soon?
considering? && Time.current >= auto_close_at - AUTO_CLOSE_REMINDER_BEFORE
end
def closed?
closure.present?
end
@@ -28,5 +28,9 @@
</footer>
<%= render "cards/display/common/background", card: card %>
<% if card.closing_soon? %>
<%= render "cards/display/preview/bubble", label: "Closes in", days: card.days_until_close %>
<% end %>
<% end %>
<% end %>
@@ -0,0 +1,23 @@
<div class="card__bubble">
<svg viewBox="0 0 200 100">
<path id="top-half" fill="transparent" d="M 20,100 A 80,80 0 0,1 180,100" />
<text text-anchor="middle" fill="currentColor">
<textPath href="#top-half" startOffset="50%" dominant-baseline="middle">
<%= label %>
</textPath>
</text>
</svg>
<span class="circle-bubble__number">
<%= days %>
</span>
<svg viewBox="0 0 200 100">
<path id="bottom-half" d="M 20,0 A 80,80 0 0,0 180,0" fill="transparent" />
<text text-anchor="middle" fill="currentColor">
<textPath href="#bottom-half" startOffset="50%" dominant-baseline="middle">
<%= "Day".pluralize(days) %>
</textPath>
</text>
</svg>
</div>