Merge pull request #2676 from basecamp/mobile/bridge-done-stamp

Mobile / Bridge "Done" stamp
This commit is contained in:
Jay Ohms
2026-03-17 12:24:49 -04:00
committed by GitHub
6 changed files with 99 additions and 37 deletions
+1 -12
View File
@@ -34,16 +34,6 @@
}
}
@media (max-width: 639px) {
&:has(.card__closed) {
padding-block-start: 4.5rem;
.card-perma__bg {
box-shadow: 0 -2rem 0 0 var(--color-container);
}
}
}
@media (max-width: 799px) {
--half-btn-height: 1.25rem;
--padding-inline: 1.5ch;
@@ -262,8 +252,7 @@
.card__closed {
@media (max-width: 639px) {
inset: auto 0 100% auto;
translate: 0 30%;
inset: auto 0 3rem auto;
scale: 75%;
}
}
+20 -15
View File
@@ -59,16 +59,26 @@
/* ------------------------------------------------------------------------ */
.card-perma {
margin-block-start: 0;
margin-block-start: var(--block-space-half);
&:not(:has(.card-perma__notch-new-card-buttons)) .card-perma__bg {
padding-block: clamp(0.25rem, 2vw, var(--padding-block));
padding-block-end: clamp(0.25rem, 2vw, var(--padding-block));
}
.card {
background: linear-gradient(to bottom, var(--color-canvas), var(--card-bg-color));
box-shadow: unset;
}
.card__board {
border-radius: 0 var(--border-radius) var(--border-radius) 0;
}
}
.card-perma__bg {
border-start-start-radius: calc(0.2em + clamp(0.25rem, 2vw, var(--padding-block)));
border-start-end-radius: calc(0.2em + clamp(0.25rem, 2vw, var(--padding-block)));
padding-inline: 0;
padding-block-start: 0;
background-color: unset;
}
.card-perma__closure-message {
@@ -77,21 +87,10 @@
}
.card-perma--draft {
.card-perma__bg {
padding-inline: 0;
padding-block-start: 0;
background-color: unset;
}
.card {
background: linear-gradient(to bottom, var(--color-canvas), var(--card-bg-color));
box-shadow: 0 101vh 0 100vh var(--card-bg-color);
}
.card__board {
border-radius: 0 var(--border-radius) var(--border-radius) 0;
}
.card-perma__notch--bottom {
z-index: 1;
}
@@ -131,3 +130,9 @@
display: none;
}
}
[data-bridge-components~=stamp] {
[data-controller~=bridge--stamp] {
display: none;
}
}
@@ -0,0 +1,44 @@
import { BridgeComponent } from "@hotwired/hotwire-native-bridge"
export default class extends BridgeComponent {
static component = "stamp"
static values = { scopeSelector: { type: String, default: "body" } }
connect() {
super.connect()
if (this.element.closest(this.scopeSelectorValue)) {
this.notifyBridgeOfConnect()
this.#observeStamp()
}
}
disconnect() {
super.disconnect()
this.notifyBridgeOfDisconnect()
this.stampObserver?.disconnect()
}
notifyBridgeOfConnect() {
const bridgeElement = this.bridgeElement
this.send("connect", {
title: bridgeElement.title,
description: bridgeElement.bridgeAttribute("description")
})
}
notifyBridgeOfDisconnect() {
this.send("disconnect")
}
#observeStamp() {
this.stampObserver = new MutationObserver(() => {
this.notifyBridgeOfConnect()
})
this.stampObserver.observe(this.element, {
attributes: true
})
}
}
@@ -10,7 +10,7 @@ BridgeElement.prototype.getButton = function() {
}
BridgeElement.prototype.getIcon = function() {
const url = this.bridgeAttribute(`icon-url`)
const url = this.bridgeAttribute("icon-url")
if (url) {
return { url }
@@ -20,9 +20,9 @@ BridgeElement.prototype.getIcon = function() {
}
BridgeElement.prototype.getDisplayTitle = function() {
return !!this.bridgeAttribute(`display-title`)
return !!this.bridgeAttribute("display-title")
}
BridgeElement.prototype.getDisplayAsPrimaryAction = function() {
return !!this.bridgeAttribute(`display-as-primary-action`)
return !!this.bridgeAttribute("display-as-primary-action")
}
@@ -1,13 +1,27 @@
<div class="flex gap-half">
<%= link_to edit_card_path(card), class: "btn btn--circle-mobile borderless",
data: { controller: "hotkey", action: "keydown.e@document->hotkey#click", bridge__overflow_menu_target: "item", bridge_title: "Edit", turbo_frame: dom_id(card, :edit) } do %>
data: {
controller: "hotkey",
action: "keydown.e@document->hotkey#click",
bridge__overflow_menu_target: "item",
bridge_title: "Edit",
turbo_frame: dom_id(card, :edit)
} do %>
<%= icon_tag "pencil", class: "icon--mobile-only" %>
<span>Edit</span>
<kbd class="txt-x-small hide-on-touch">e</kbd>
<% end %>
<%= button_to card_closure_path(card), class: "btn btn--circle-mobile borderless",
data: { controller: "hotkey", form_target: "submit", bridge__buttons_target: "button", bridge_title: "Mark done", bridge_display_as_primary_action: true, bridge_display_title: true, bridge_icon_url: bridge_icon("check"), action: "keydown.d@document->hotkey#click" },
<%= button_to card_closure_path(card), class: "btn btn--circle-mobile borderless hide-on-native",
data: {
controller: "hotkey",
form_target: "submit",
bridge__buttons_target: ("button" unless card.postponed?),
bridge_title: "Mark done",
bridge_display_as_primary_action: true,
bridge_display_title: true, bridge_icon_url: bridge_icon("check"),
action: "keydown.d@document->hotkey#click"
},
form: { data: { controller: "form" } } do %>
<%= icon_tag "check", class: "icon--mobile-only" %>
<span class="overflow-ellipsis">Mark as Done</span>
+14 -4
View File
@@ -1,15 +1,25 @@
<% if card.postponed? %>
<div class="card__closed <%= "card__closed--system" if card.postponed_by&.system? %>">
<%= tag.div class: token_list("card__closed", "card__closed--system": card.postponed_by&.system?), data: {
controller: "bridge--stamp",
bridge__stamp_scope_selector_value: ".card-perma",
bridge_title: "Not Now",
bridge_description: card.postponed_at.strftime("%b %d, %Y")
} do %>
<span class="card__closed-title" data-text="Not Now">Not Now</span>
<strong class="card__closed-date"><%= card.postponed_at.strftime("%b %d, %Y") %></strong>
<span class="card__closed-by-line">by <span class="card__closed-by"><%= card.postponed_by&.familiar_name %></span></span>
</div>
<% end %>
<% end %>
<% if card.closed? %>
<div class="card__closed">
<%= tag.div class: "card__closed", data: {
controller: "bridge--stamp",
bridge__stamp_scope_selector_value: ".card-perma",
bridge_title: "Done",
bridge_description: card.closed_at.strftime("%b %d, %Y")
} do %>
<span class="card__closed-title" data-text="Done">Done</span>
<strong class="card__closed-date"><%= card.closed_at.strftime("%b %d, %Y") %></strong>
<span class="card__closed-by-line">by <span class="card__closed-by"><%= card.closed_by.familiar_name %></span></span>
</div>
<% end %>
<% end %>