patx/miadruck
Implement share link button and copy feature
Commit af1b6c8 · Harrison Erd · 2026-01-15T23:20:07-05:00
Implement share link button and copy feature Added share link button and copy functionality with toast notification.
Comments
No comments yet.
Diff
diff --git a/index.html b/index.html
index ca76b3a..e3690f1 100644
--- a/index.html
+++ b/index.html
@@ -299,6 +299,52 @@
color:rgba(11,18,32,.92);
}
+ /* --- Share link icon (bottom-left on listing cards) --- */
+ .card-actions{
+ position:relative; /* needed so the share button can anchor */
+ }
+ .link-btn{
+ position:absolute;
+ left:0;
+ bottom:0;
+ width:38px;
+ height:38px;
+ border-radius:999px;
+ border:1px solid rgba(0,0,0,.10);
+ background:rgba(255,255,255,.92);
+ display:inline-flex;
+ align-items:center;
+ justify-content:center;
+ cursor:pointer;
+ box-shadow:0 14px 34px rgba(0,0,0,.10);
+ transition:transform .12s ease, filter .12s ease, background .12s ease;
+ }
+ .link-btn:hover{ filter:brightness(1.03); transform:translateY(-1px); }
+ .link-btn:active{ transform:scale(.985); }
+ .link-btn svg{ width:18px; height:18px; }
+
+ /* Optional “Copied!” toast */
+ .copy-toast{
+ position:fixed;
+ left:50%;
+ bottom:22px;
+ transform:translateX(-50%);
+ padding:10px 14px;
+ border-radius:999px;
+ background:rgba(11,18,32,.88);
+ color:#fff;
+ font-weight:800;
+ font-size:13px;
+ z-index:999;
+ opacity:0;
+ pointer-events:none;
+ transition:opacity .18s ease, transform .18s ease;
+ }
+ .copy-toast.show{
+ opacity:1;
+ transform:translateX(-50%) translateY(-4px);
+ }
+
.form{ display:grid; gap:12px; }
.row2{ display:grid; grid-template-columns:1fr 1fr; gap:12px; }
@media (max-width:560px){ .row2{ grid-template-columns:1fr; } }
@@ -953,9 +999,9 @@
</footer>
<script>
- // ---------------------------
- // EDITABLE DATA (no JSON files needed)
- // ---------------------------
+ // --------------
+ // EDITABLE DATA
+ // --------------
const FEATURED = [
{
id: "boca-600-nw-12",
@@ -989,13 +1035,13 @@
},
{
id: "lighthouse-29-ave",
- title: "Beach Side Cottage",
+ title: "Beach Side Cottage • Great Area",
price: "$2,800/month",
meta: "2 bd • 2 ba • 980 sqft",
area: "2730 NE 29th Ave, Lighthouse Point, FL 33064",
image: "https://i.postimg.cc/50ncVsLB/image.png",
link: "sms:9545527330",
- tags: ["Updated", "East of US1"],
+ tags: ["Off Market", "Updated", "East of US1"],
}
];
@@ -1046,6 +1092,21 @@
<div class="meta">${esc(x.area || "")}</div>
<div class="tags">${tags}</div>
<div class="card-actions">
+
+ <!-- bottom-left share link icon -->
+ <button class="link-btn"
+ type="button"
+ aria-label="Copy listing link"
+ title="Copy link"
+ onclick="copyListingLink('${esc(x.id || x.title)}')">
+ <svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
+ <path d="M10 13a5 5 0 0 0 7.07 0l2.12-2.12a5 5 0 0 0-7.07-7.07L10.9 4.99"
+ stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+ <path d="M14 11a5 5 0 0 0-7.07 0L4.81 13.12a5 5 0 0 0 7.07 7.07L13.1 19.01"
+ stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+ </svg>
+ </button>
+
<div class="btn-split">
<a href="${esc(link)}" ${newTab}>More Details</a>
<a href="#contact" onclick="prefillListing('${esc(x.id || x.title)}'); switchToContact();">Contact</a>
@@ -1121,6 +1182,53 @@
if (b) b.value = v;
}
+ // ---------------------------
+ // Share URL + copy helper (for link icon)
+ // ---------------------------
+ function listingShareUrl(id){
+ const u = new URL(location.href);
+ u.searchParams.set("listing", String(id || ""));
+ return u.toString();
+ }
+
+ async function copyListingLink(id){
+ const url = listingShareUrl(id);
+
+ try{
+ if (navigator.clipboard && window.isSecureContext){
+ await navigator.clipboard.writeText(url);
+ } else {
+ // fallback for non-HTTPS or older browsers
+ const ta = document.createElement("textarea");
+ ta.value = url;
+ ta.style.position = "fixed";
+ ta.style.opacity = "0";
+ document.body.appendChild(ta);
+ ta.select();
+ document.execCommand("copy");
+ ta.remove();
+ }
+ showToast("Link copied");
+ } catch (e){
+ // last resort: prompt
+ window.prompt("Copy this link:", url);
+ }
+ }
+
+ function showToast(msg){
+ let t = document.getElementById("copyToast");
+ if (!t){
+ t = document.createElement("div");
+ t.id = "copyToast";
+ t.className = "copy-toast";
+ document.body.appendChild(t);
+ }
+ t.textContent = msg || "Copied!";
+ t.classList.add("show");
+ clearTimeout(showToast._timer);
+ showToast._timer = setTimeout(() => t.classList.remove("show"), 1400);
+ }
+
// ---------------------------
// Formspree AJAX submit -> replace form with success (deters duplicates)
// ---------------------------
@@ -1196,6 +1304,7 @@
// expose for inline onclick
window.switchToContact = switchToContact;
window.prefillListing = prefillListing;
+ window.copyListingLink = copyListingLink;
render();
</script>