mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
Refactor zap popovers and more menus
This commit is contained in:
1 parent
fe006a59b0
commit
badcfc6944
9 files changed
+282
-176
No files matched your search
+92
-67
@@ -47,7 +47,7 @@
|
||||
class="h-5 w-5"
|
||||
/>
|
||||
</button>
|
||||
<div class="relative" data-modal-zap-wrapper>
|
||||
<div class="popover" data-modal-zap-wrapper>
|
||||
<button
|
||||
id="modalZapBtn"
|
||||
type="button"
|
||||
@@ -65,13 +65,14 @@
|
||||
</button>
|
||||
<div
|
||||
id="modalZapDialog"
|
||||
class="zap-popover hidden"
|
||||
class="popover__panel card w-72 max-w-[calc(100vw-2rem)] px-5 py-4"
|
||||
data-variant="zap"
|
||||
role="dialog"
|
||||
aria-hidden="true"
|
||||
data-state="closed"
|
||||
hidden
|
||||
>
|
||||
<div
|
||||
class="zap-popover__content card w-72 max-w-[calc(100vw-2rem)] px-5 py-4"
|
||||
>
|
||||
<div class="grid gap-4">
|
||||
<div class="mb-4 flex items-center justify-between gap-4">
|
||||
<h3
|
||||
class="text-xs font-semibold uppercase tracking-wide text-muted"
|
||||
@@ -89,8 +90,9 @@
|
||||
</div>
|
||||
<p
|
||||
id="modalZapWalletPrompt"
|
||||
class="mb-3 hidden text-sm text-muted"
|
||||
class="mb-3 text-sm text-muted"
|
||||
aria-hidden="true"
|
||||
hidden
|
||||
>
|
||||
Connect a wallet in
|
||||
<button
|
||||
@@ -191,71 +193,94 @@
|
||||
</button>
|
||||
<div
|
||||
id="moreDropdown-modal"
|
||||
class="absolute right-0 top-14 hidden w-48 rounded-lg border border-border bg-surface-alt py-2 text-left text-sm text-text shadow-lg"
|
||||
class="popover__panel w-48"
|
||||
role="menu"
|
||||
data-more-menu="true"
|
||||
data-state="closed"
|
||||
aria-hidden="true"
|
||||
hidden
|
||||
>
|
||||
<button
|
||||
class="focus-ring block w-full px-4 py-2 text-left transition hover:bg-panel-hover"
|
||||
data-action="open-channel"
|
||||
data-context="modal"
|
||||
>
|
||||
Open channel
|
||||
</button>
|
||||
<button
|
||||
class="focus-ring block w-full px-4 py-2 text-left transition hover:bg-panel-hover"
|
||||
data-action="copy-link"
|
||||
data-context="modal"
|
||||
>
|
||||
Copy link
|
||||
</button>
|
||||
<div class="px-4 pb-1 pt-3 text-xs font-semibold uppercase tracking-wide text-muted">
|
||||
Boost on Nostr…
|
||||
<div class="menu" role="none">
|
||||
<button
|
||||
type="button"
|
||||
class="menu__item justify-start"
|
||||
role="menuitem"
|
||||
data-action="open-channel"
|
||||
data-context="modal"
|
||||
>
|
||||
Open channel
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="menu__item justify-start"
|
||||
role="menuitem"
|
||||
data-action="copy-link"
|
||||
data-context="modal"
|
||||
>
|
||||
Copy link
|
||||
</button>
|
||||
<p class="menu__heading" role="presentation">
|
||||
Boost on Nostr…
|
||||
</p>
|
||||
<button
|
||||
type="button"
|
||||
class="menu__item justify-start"
|
||||
role="menuitem"
|
||||
data-action="repost-event"
|
||||
data-context="modal"
|
||||
>
|
||||
Repost (kind 6)
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="menu__item justify-start"
|
||||
role="menuitem"
|
||||
data-action="mirror-video"
|
||||
data-context="modal"
|
||||
>
|
||||
Mirror (kind 1063)
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="menu__item justify-start"
|
||||
role="menuitem"
|
||||
data-action="ensure-presence"
|
||||
data-context="modal"
|
||||
>
|
||||
Rebroadcast
|
||||
</button>
|
||||
<div class="menu__separator" role="separator"></div>
|
||||
<button
|
||||
type="button"
|
||||
class="menu__item justify-start"
|
||||
role="menuitem"
|
||||
data-action="blacklist-author"
|
||||
data-context="modal"
|
||||
data-blacklist-menu="true"
|
||||
data-variant="critical"
|
||||
>
|
||||
Blacklist creator
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="menu__item justify-start"
|
||||
role="menuitem"
|
||||
data-action="block-author"
|
||||
data-context="modal"
|
||||
data-variant="critical"
|
||||
>
|
||||
Block creator
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="menu__item justify-start"
|
||||
role="menuitem"
|
||||
data-action="report"
|
||||
data-context="modal"
|
||||
>
|
||||
Report
|
||||
</button>
|
||||
</div>
|
||||
<button
|
||||
class="focus-ring block w-full px-4 py-2 text-left transition hover:bg-panel-hover"
|
||||
data-action="repost-event"
|
||||
data-context="modal"
|
||||
>
|
||||
Repost (kind 6)
|
||||
</button>
|
||||
<button
|
||||
class="focus-ring block w-full px-4 py-2 text-left transition hover:bg-panel-hover"
|
||||
data-action="mirror-video"
|
||||
data-context="modal"
|
||||
>
|
||||
Mirror (kind 1063)
|
||||
</button>
|
||||
<button
|
||||
class="focus-ring block w-full px-4 py-2 text-left transition hover:bg-panel-hover"
|
||||
data-action="ensure-presence"
|
||||
data-context="modal"
|
||||
>
|
||||
Rebroadcast
|
||||
</button>
|
||||
<div class="my-2 border-t border-border/40"></div>
|
||||
<button
|
||||
class="focus-ring block w-full px-4 py-2 text-left font-semibold text-critical transition hover:bg-critical hover:text-text"
|
||||
data-action="blacklist-author"
|
||||
data-context="modal"
|
||||
data-blacklist-menu="true"
|
||||
>
|
||||
Blacklist creator
|
||||
</button>
|
||||
<button
|
||||
class="focus-ring block w-full px-4 py-2 text-left font-semibold text-critical transition hover:bg-critical hover:text-text"
|
||||
data-action="block-author"
|
||||
data-context="modal"
|
||||
>
|
||||
Block creator
|
||||
</button>
|
||||
<button
|
||||
class="focus-ring block w-full px-4 py-2 text-left transition hover:bg-panel-hover"
|
||||
data-action="report"
|
||||
data-context="modal"
|
||||
>
|
||||
Report
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+9
-20
@@ -510,26 +510,6 @@ body.modal-open #sidebarOverlay {
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
[data-modal-zap-wrapper] .zap-popover,
|
||||
.zap-popover {
|
||||
position: absolute;
|
||||
top: calc(100% + 0.5rem);
|
||||
right: 0;
|
||||
z-index: 80;
|
||||
width: max-content;
|
||||
}
|
||||
|
||||
.zap-popover__content {
|
||||
width: 18rem;
|
||||
max-width: calc(100vw - 2rem);
|
||||
background: var(--color-overlay-veil);
|
||||
color: var(--color-subtle);
|
||||
border: 1px solid var(--color-border-translucent-stronger);
|
||||
box-shadow: 0 22px 48px -18px var(--color-shadow-intense);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
backdrop-filter: blur(12px);
|
||||
}
|
||||
|
||||
.modal-actions__overflow {
|
||||
position: relative;
|
||||
}
|
||||
@@ -543,6 +523,15 @@ body.modal-open #sidebarOverlay {
|
||||
z-index: 70;
|
||||
}
|
||||
|
||||
.popover__panel[data-variant="zap"] {
|
||||
background: var(--color-overlay-veil);
|
||||
color: var(--color-subtle);
|
||||
border: 1px solid var(--color-border-translucent-stronger);
|
||||
box-shadow: 0 22px 48px -18px var(--color-shadow-intense);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
backdrop-filter: blur(12px);
|
||||
}
|
||||
|
||||
/* Mobile-specific styles */
|
||||
@media (max-width: 767px) {
|
||||
#playerModal {
|
||||
|
||||
@@ -157,6 +157,38 @@ Mix utilities such as `right-0` or `translate-x-1/2` on `.popover__panel` when y
|
||||
|
||||
The helpers rely on layout utilities (`flex`, `gap-*`) so you can safely inject icons, shortcuts, or nested badges without restyling the base tokens.
|
||||
|
||||
### Zap Popover
|
||||
|
||||
Compose `.popover` with a zap-specific panel variant when you need to surface the tipping form inline. Toggle `data-state="open"` on the `.popover__panel` and remove its `hidden` attribute when the dialog is visible. The `data-variant="zap"` hook reuses the frosted-glass styling defined in `css/style.css`.
|
||||
|
||||
```html
|
||||
<div class="popover">
|
||||
<button class="btn-ghost h-10 w-10 rounded-full p-0" type="button" aria-haspopup="dialog" aria-expanded="false">
|
||||
<img src="assets/svg/lightning-bolt.svg" alt="Zap" class="h-5 w-5" />
|
||||
</button>
|
||||
<div
|
||||
class="popover__panel card w-72 max-w-[calc(100vw-2rem)] space-y-4"
|
||||
role="dialog"
|
||||
aria-hidden="true"
|
||||
data-variant="zap"
|
||||
data-state="closed"
|
||||
hidden
|
||||
>
|
||||
<div class="flex items-center justify-between gap-4">
|
||||
<h3 class="text-xs font-semibold uppercase tracking-wide text-muted">Send a zap</h3>
|
||||
<button class="btn-ghost h-8 w-8 rounded-full p-0" type="button" aria-label="Close zap dialog">✕</button>
|
||||
</div>
|
||||
<form class="space-y-4">
|
||||
<label class="block text-xs font-semibold uppercase tracking-wide text-muted" for="zapAmountExample">
|
||||
Zap amount (sats)
|
||||
</label>
|
||||
<input id="zapAmountExample" class="input" type="number" min="1" step="1" inputmode="numeric" />
|
||||
<button class="btn w-full" type="submit">Send</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
### Grid Stack
|
||||
|
||||
`.grid-stack` offers gap tokens for dense layouts. Add `data-variant="cards"` for responsive card grids (`grid-cols-1` → `sm:grid-cols-2` → `xl:grid-cols-3`). Switch to `data-orientation="vertical"` for stacked flex columns that reuse the same spacing tokens.
|
||||
|
||||
+27
-11
@@ -154,7 +154,7 @@ function setChannelZapVisibility(visible) {
|
||||
? app.isUserLoggedIn()
|
||||
: Boolean(app?.normalizeHexPubkey?.(app?.pubkey));
|
||||
const shouldShow = !!visible && isLoggedIn;
|
||||
zapButton.classList.toggle("hidden", !shouldShow);
|
||||
zapButton.toggleAttribute("hidden", !shouldShow);
|
||||
zapButton.disabled = !shouldShow;
|
||||
zapButton.setAttribute("aria-disabled", (!shouldShow).toString());
|
||||
zapButton.setAttribute("aria-hidden", (!shouldShow).toString());
|
||||
@@ -171,6 +171,7 @@ function setChannelZapVisibility(visible) {
|
||||
closeZapControls();
|
||||
if (controls) {
|
||||
controls.setAttribute("aria-hidden", "true");
|
||||
controls.hidden = true;
|
||||
}
|
||||
if (amountInput) {
|
||||
amountInput.disabled = !shouldShow;
|
||||
@@ -233,6 +234,18 @@ function getZapControlsContainer() {
|
||||
if (!cachedZapControls) {
|
||||
cachedZapControls = document.getElementById("zapControls");
|
||||
}
|
||||
if (cachedZapControls) {
|
||||
if (!cachedZapControls.dataset.state) {
|
||||
const isHidden =
|
||||
cachedZapControls.hasAttribute("hidden") ||
|
||||
cachedZapControls.getAttribute("aria-hidden") === "true";
|
||||
cachedZapControls.dataset.state = isHidden ? "closed" : "open";
|
||||
}
|
||||
if (cachedZapControls.dataset.state !== "open") {
|
||||
cachedZapControls.hidden = true;
|
||||
cachedZapControls.setAttribute("aria-hidden", "true");
|
||||
}
|
||||
}
|
||||
return cachedZapControls;
|
||||
}
|
||||
|
||||
@@ -332,7 +345,7 @@ function setZapWalletPromptVisible(visible) {
|
||||
return;
|
||||
}
|
||||
const shouldShow = !!visible;
|
||||
prompt.classList.toggle("hidden", !shouldShow);
|
||||
prompt.toggleAttribute("hidden", !shouldShow);
|
||||
prompt.setAttribute("aria-hidden", (!shouldShow).toString());
|
||||
}
|
||||
|
||||
@@ -376,7 +389,8 @@ function openZapControls({ focus = false } = {}) {
|
||||
return false;
|
||||
}
|
||||
if (!zapControlsOpen) {
|
||||
controls.classList.remove("hidden");
|
||||
controls.hidden = false;
|
||||
controls.dataset.state = "open";
|
||||
controls.setAttribute("aria-hidden", "false");
|
||||
zapButton.setAttribute("aria-expanded", "true");
|
||||
zapControlsOpen = true;
|
||||
@@ -391,8 +405,9 @@ function closeZapControls({ focusButton = false } = {}) {
|
||||
const controls = getZapControlsContainer();
|
||||
const zapButton = getChannelZapButton();
|
||||
if (controls) {
|
||||
controls.classList.add("hidden");
|
||||
controls.dataset.state = "closed";
|
||||
controls.setAttribute("aria-hidden", "true");
|
||||
controls.hidden = true;
|
||||
}
|
||||
if (zapButton) {
|
||||
zapButton.setAttribute("aria-expanded", "false");
|
||||
@@ -1274,12 +1289,12 @@ async function updateChannelMenuState() {
|
||||
if (action === "copy-npub") {
|
||||
if (currentChannelNpub) {
|
||||
button.dataset.npub = currentChannelNpub;
|
||||
button.classList.remove("hidden");
|
||||
button.removeAttribute("hidden");
|
||||
button.setAttribute("aria-hidden", "false");
|
||||
} else {
|
||||
delete button.dataset.npub;
|
||||
button.classList.add("hidden");
|
||||
button.setAttribute("aria-hidden", "true");
|
||||
button.setAttribute("hidden", "");
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1287,12 +1302,12 @@ async function updateChannelMenuState() {
|
||||
if (action === "block-author") {
|
||||
if (currentChannelHex) {
|
||||
button.dataset.author = currentChannelHex;
|
||||
button.classList.remove("hidden");
|
||||
button.removeAttribute("hidden");
|
||||
button.setAttribute("aria-hidden", "false");
|
||||
} else {
|
||||
delete button.dataset.author;
|
||||
button.classList.add("hidden");
|
||||
button.setAttribute("aria-hidden", "true");
|
||||
button.setAttribute("hidden", "");
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1305,13 +1320,13 @@ async function updateChannelMenuState() {
|
||||
} else {
|
||||
delete button.dataset.npub;
|
||||
}
|
||||
button.classList.remove("hidden");
|
||||
button.removeAttribute("hidden");
|
||||
button.setAttribute("aria-hidden", "false");
|
||||
} else {
|
||||
delete button.dataset.author;
|
||||
delete button.dataset.npub;
|
||||
button.classList.add("hidden");
|
||||
button.setAttribute("aria-hidden", "true");
|
||||
button.setAttribute("hidden", "");
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1421,7 +1436,8 @@ function setupZapButton() {
|
||||
}
|
||||
|
||||
setChannelZapVisibility(false);
|
||||
controls.classList.add("hidden");
|
||||
controls.dataset.state = "closed";
|
||||
controls.hidden = true;
|
||||
controls.setAttribute("aria-hidden", "true");
|
||||
zapButton.setAttribute("aria-expanded", "false");
|
||||
setupZapWalletLink();
|
||||
|
||||
@@ -194,7 +194,9 @@ export class VideoCard {
|
||||
|
||||
closeMoreMenu() {
|
||||
if (this.moreMenu) {
|
||||
this.moreMenu.classList.add("hidden");
|
||||
this.moreMenu.dataset.state = "closed";
|
||||
this.moreMenu.setAttribute("aria-hidden", "true");
|
||||
this.moreMenu.hidden = true;
|
||||
}
|
||||
if (this.moreMenuButton) {
|
||||
this.moreMenuButton.setAttribute("aria-expanded", "false");
|
||||
@@ -661,7 +663,7 @@ export class VideoCard {
|
||||
|
||||
buildMoreMenu() {
|
||||
const wrapper = this.createElement("div", {
|
||||
classNames: ["relative", "inline-block", "ml-1", "overflow-visible"],
|
||||
classNames: ["popover", "ml-1"],
|
||||
});
|
||||
wrapper.dataset.moreMenuWrapper = "true";
|
||||
|
||||
@@ -698,43 +700,38 @@ export class VideoCard {
|
||||
button.appendChild(icon);
|
||||
|
||||
const dropdown = this.createElement("div", {
|
||||
classNames: [
|
||||
"hidden",
|
||||
"absolute",
|
||||
"right-0",
|
||||
"bottom-full",
|
||||
"mb-2",
|
||||
"w-40",
|
||||
"rounded-md",
|
||||
"shadow-lg",
|
||||
"bg-gray-800",
|
||||
"ring-1",
|
||||
"ring-black",
|
||||
"ring-opacity-5",
|
||||
"z-50",
|
||||
],
|
||||
classNames: ["popover__panel", "w-40", "p-0"],
|
||||
attrs: {
|
||||
hidden: "",
|
||||
"data-state": "closed",
|
||||
"aria-hidden": "true",
|
||||
},
|
||||
});
|
||||
dropdown.id = `moreDropdown-${this.index}`;
|
||||
dropdown.dataset.moreMenu = "true";
|
||||
dropdown.setAttribute("role", "menu");
|
||||
|
||||
const list = this.createElement("div", {
|
||||
classNames: ["py-1"],
|
||||
classNames: ["menu"],
|
||||
attrs: { role: "none" },
|
||||
});
|
||||
|
||||
const addActionButton = (text, action, extraDataset = {}, classes = []) => {
|
||||
const addActionButton = (text, action, extraDataset = {}, options = {}) => {
|
||||
const { variant = null } = options || {};
|
||||
const btn = this.createElement("button", {
|
||||
classNames: [
|
||||
"block",
|
||||
"w-full",
|
||||
"text-left",
|
||||
"px-4",
|
||||
"py-2",
|
||||
"text-sm",
|
||||
...classes,
|
||||
"menu__item",
|
||||
"justify-start",
|
||||
],
|
||||
textContent: text,
|
||||
attrs: {
|
||||
type: "button",
|
||||
role: "menuitem",
|
||||
},
|
||||
});
|
||||
if (variant) {
|
||||
btn.dataset.variant = variant;
|
||||
}
|
||||
btn.dataset.action = action;
|
||||
Object.entries(extraDataset || {}).forEach(([key, value]) => {
|
||||
if (value === undefined || value === null) {
|
||||
@@ -748,11 +745,11 @@ export class VideoCard {
|
||||
|
||||
addActionButton("Open channel", "open-channel", {
|
||||
author: this.video.pubkey || "",
|
||||
}, ["text-gray-100", "hover:bg-gray-700"]);
|
||||
});
|
||||
|
||||
addActionButton("Copy link", "copy-link", {
|
||||
eventId: this.video.id || "",
|
||||
}, ["text-gray-100", "hover:bg-gray-700"]);
|
||||
});
|
||||
|
||||
const pointer = Array.isArray(this.pointerInfo?.pointer)
|
||||
? this.pointerInfo.pointer
|
||||
@@ -782,16 +779,7 @@ export class VideoCard {
|
||||
}
|
||||
|
||||
const boostLabel = this.createElement("div", {
|
||||
classNames: [
|
||||
"px-4",
|
||||
"pt-2",
|
||||
"pb-1",
|
||||
"text-xs",
|
||||
"font-semibold",
|
||||
"uppercase",
|
||||
"tracking-wide",
|
||||
"text-gray-400",
|
||||
],
|
||||
classNames: ["menu__heading"],
|
||||
textContent: "Boost on Nostr…",
|
||||
});
|
||||
list.appendChild(boostLabel);
|
||||
@@ -800,7 +788,6 @@ export class VideoCard {
|
||||
"Repost (kind 6)",
|
||||
"repost-event",
|
||||
baseBoostDataset,
|
||||
["text-gray-100", "hover:bg-gray-700"],
|
||||
);
|
||||
|
||||
if (this.playbackUrl && this.video.isPrivate !== true) {
|
||||
@@ -819,7 +806,6 @@ export class VideoCard {
|
||||
"Mirror (kind 1063)",
|
||||
"mirror-video",
|
||||
mirrorDataset,
|
||||
["text-gray-100", "hover:bg-gray-700"],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -832,12 +818,12 @@ export class VideoCard {
|
||||
"Rebroadcast",
|
||||
"ensure-presence",
|
||||
ensureDataset,
|
||||
["text-gray-100", "hover:bg-gray-700"],
|
||||
);
|
||||
|
||||
list.appendChild(
|
||||
this.createElement("div", {
|
||||
classNames: ["my-1", "border-t", "border-gray-700", "opacity-70"],
|
||||
classNames: ["menu__separator"],
|
||||
attrs: { role: "separator" },
|
||||
})
|
||||
);
|
||||
|
||||
@@ -855,7 +841,6 @@ export class VideoCard {
|
||||
pointerRelay: historyPointerRelay || "",
|
||||
reason: "remove-item",
|
||||
},
|
||||
["text-gray-100", "hover:bg-gray-700"]
|
||||
);
|
||||
removeButton.setAttribute(
|
||||
"title",
|
||||
@@ -873,7 +858,7 @@ export class VideoCard {
|
||||
"Blacklist creator",
|
||||
"blacklist-author",
|
||||
{ author: this.video.pubkey || "" },
|
||||
["text-red-400", "hover:bg-red-700", "hover:text-white"]
|
||||
{ variant: "critical" }
|
||||
);
|
||||
}
|
||||
|
||||
@@ -881,14 +866,13 @@ export class VideoCard {
|
||||
"Block creator",
|
||||
"block-author",
|
||||
{ author: this.video.pubkey || "" },
|
||||
["text-red-400", "hover:bg-red-700", "hover:text-white"]
|
||||
{ variant: "critical" }
|
||||
);
|
||||
|
||||
addActionButton(
|
||||
"Report",
|
||||
"report",
|
||||
{ eventId: this.video.id || "" },
|
||||
["text-gray-100", "hover:bg-gray-700"]
|
||||
);
|
||||
|
||||
dropdown.appendChild(list);
|
||||
@@ -1563,12 +1547,14 @@ export class VideoCard {
|
||||
this.moreMenuButton.addEventListener("click", (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
const willOpen = this.moreMenu.classList.contains("hidden");
|
||||
const willOpen = this.moreMenu.dataset.state !== "open";
|
||||
if (this.onRequestCloseAllMenus) {
|
||||
this.onRequestCloseAllMenus(this);
|
||||
}
|
||||
if (willOpen) {
|
||||
this.moreMenu.classList.remove("hidden");
|
||||
this.moreMenu.hidden = false;
|
||||
this.moreMenu.dataset.state = "open";
|
||||
this.moreMenu.setAttribute("aria-hidden", "false");
|
||||
this.moreMenuButton.setAttribute("aria-expanded", "true");
|
||||
}
|
||||
});
|
||||
|
||||
@@ -264,6 +264,32 @@ export class VideoModal {
|
||||
this.modalZapWalletLink =
|
||||
playerModal.querySelector("#modalZapWalletLink") || null;
|
||||
|
||||
if (this.modalZapDialog) {
|
||||
if (!this.modalZapDialog.dataset.state) {
|
||||
const isHidden =
|
||||
this.modalZapDialog.hasAttribute("hidden") ||
|
||||
this.modalZapDialog.getAttribute("aria-hidden") === "true";
|
||||
this.modalZapDialog.dataset.state = isHidden ? "closed" : "open";
|
||||
}
|
||||
if (this.modalZapDialog.dataset.state !== "open") {
|
||||
this.modalZapDialog.hidden = true;
|
||||
this.modalZapDialog.setAttribute("aria-hidden", "true");
|
||||
}
|
||||
}
|
||||
|
||||
if (this.modalMoreMenu) {
|
||||
if (!this.modalMoreMenu.dataset.state) {
|
||||
const isHidden =
|
||||
this.modalMoreMenu.hasAttribute("hidden") ||
|
||||
this.modalMoreMenu.getAttribute("aria-hidden") === "true";
|
||||
this.modalMoreMenu.dataset.state = isHidden ? "closed" : "open";
|
||||
}
|
||||
if (this.modalMoreMenu.dataset.state !== "open") {
|
||||
this.modalMoreMenu.hidden = true;
|
||||
this.modalMoreMenu.setAttribute("aria-hidden", "true");
|
||||
}
|
||||
}
|
||||
|
||||
const closeButton = playerModal.querySelector("#closeModal");
|
||||
if (closeButton) {
|
||||
closeButton.addEventListener("click", () => {
|
||||
@@ -626,7 +652,7 @@ export class VideoModal {
|
||||
setZapVisibility(visible) {
|
||||
const shouldShow = !!visible;
|
||||
if (this.modalZapBtn) {
|
||||
this.modalZapBtn.classList.toggle("hidden", !shouldShow);
|
||||
this.modalZapBtn.toggleAttribute("hidden", !shouldShow);
|
||||
const disableButton = !shouldShow || this.modalZapPending;
|
||||
this.modalZapBtn.disabled = disableButton;
|
||||
this.modalZapBtn.setAttribute("aria-disabled", (!shouldShow).toString());
|
||||
@@ -656,7 +682,7 @@ export class VideoModal {
|
||||
return;
|
||||
}
|
||||
const shouldShow = !!visible;
|
||||
this.modalZapWalletPrompt.classList.toggle("hidden", !shouldShow);
|
||||
this.modalZapWalletPrompt.toggleAttribute("hidden", !shouldShow);
|
||||
this.modalZapWalletPrompt.setAttribute(
|
||||
"aria-hidden",
|
||||
(!shouldShow).toString()
|
||||
@@ -667,7 +693,8 @@ export class VideoModal {
|
||||
if (!this.modalZapDialog) {
|
||||
return;
|
||||
}
|
||||
this.modalZapDialog.classList.remove("hidden");
|
||||
this.modalZapDialog.hidden = false;
|
||||
this.modalZapDialog.dataset.state = "open";
|
||||
this.modalZapDialogOpen = true;
|
||||
this.modalZapDialog.setAttribute("aria-hidden", "false");
|
||||
if (this.modalZapBtn) {
|
||||
@@ -681,8 +708,9 @@ export class VideoModal {
|
||||
return;
|
||||
}
|
||||
if (this.modalZapDialogOpen) {
|
||||
this.modalZapDialog.classList.add("hidden");
|
||||
this.modalZapDialog.dataset.state = "closed";
|
||||
this.modalZapDialog.setAttribute("aria-hidden", "true");
|
||||
this.modalZapDialog.hidden = true;
|
||||
this.modalZapDialogOpen = false;
|
||||
if (this.modalZapBtn) {
|
||||
this.modalZapBtn.setAttribute("aria-expanded", "false");
|
||||
@@ -918,7 +946,7 @@ export class VideoModal {
|
||||
this.modalZapBtn.disabled = true;
|
||||
this.modalZapBtn.setAttribute("aria-busy", "true");
|
||||
this.modalZapBtn.classList.add("opacity-50", "pointer-events-none");
|
||||
} else if (!this.modalZapBtn.classList.contains("hidden")) {
|
||||
} else if (!this.modalZapBtn.hasAttribute("hidden")) {
|
||||
this.modalZapBtn.disabled = false;
|
||||
this.modalZapBtn.removeAttribute("aria-busy");
|
||||
this.modalZapBtn.classList.remove("opacity-50", "pointer-events-none");
|
||||
@@ -1106,12 +1134,12 @@ export class VideoModal {
|
||||
if (action === "blacklist-author") {
|
||||
if (canManageBlacklist && currentVideo?.pubkey) {
|
||||
button.dataset.author = currentVideo.pubkey;
|
||||
button.classList.remove("hidden");
|
||||
button.removeAttribute("hidden");
|
||||
button.setAttribute("aria-hidden", "false");
|
||||
} else {
|
||||
delete button.dataset.author;
|
||||
button.classList.add("hidden");
|
||||
button.setAttribute("aria-hidden", "true");
|
||||
button.setAttribute("hidden", "");
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1161,7 +1189,7 @@ export class VideoModal {
|
||||
const isPrivate = currentVideo?.isPrivate === true;
|
||||
|
||||
if (hasUrl && !isPrivate) {
|
||||
button.classList.remove("hidden");
|
||||
button.removeAttribute("hidden");
|
||||
button.setAttribute("aria-hidden", "false");
|
||||
button.dataset.eventId = currentVideo.id || "";
|
||||
button.dataset.author = currentVideo.pubkey || "";
|
||||
@@ -1181,8 +1209,8 @@ export class VideoModal {
|
||||
delete button.dataset.description;
|
||||
delete button.dataset.title;
|
||||
button.dataset.isPrivate = "true";
|
||||
button.classList.add("hidden");
|
||||
button.setAttribute("aria-hidden", "true");
|
||||
button.setAttribute("hidden", "");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -226,7 +226,9 @@ export default class MoreMenuController {
|
||||
const menus = this.document.querySelectorAll("[data-more-menu]");
|
||||
menus.forEach((menu) => {
|
||||
if (!HTMLElementCtor || menu instanceof HTMLElementCtor) {
|
||||
menu.classList.add("hidden");
|
||||
menu.dataset.state = "closed";
|
||||
menu.setAttribute("aria-hidden", "true");
|
||||
menu.hidden = true;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -278,11 +280,25 @@ export default class MoreMenuController {
|
||||
return;
|
||||
}
|
||||
|
||||
const willOpen = dropdown.classList.contains("hidden");
|
||||
if (dropdown && !dropdown.dataset.state) {
|
||||
const isHidden =
|
||||
dropdown.hasAttribute("hidden") ||
|
||||
dropdown.getAttribute("aria-hidden") === "true";
|
||||
dropdown.dataset.state = isHidden ? "closed" : "open";
|
||||
}
|
||||
|
||||
if (dropdown && dropdown.dataset.state !== "open") {
|
||||
dropdown.hidden = true;
|
||||
dropdown.setAttribute("aria-hidden", "true");
|
||||
}
|
||||
|
||||
const willOpen = dropdown?.dataset.state !== "open";
|
||||
this.closeAllMoreMenus();
|
||||
|
||||
if (willOpen) {
|
||||
dropdown.classList.remove("hidden");
|
||||
dropdown.hidden = false;
|
||||
dropdown.dataset.state = "open";
|
||||
dropdown.setAttribute("aria-hidden", "false");
|
||||
button.setAttribute("aria-expanded", "true");
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1001,7 +1001,9 @@ export class VideoListView {
|
||||
const menus = this.document.querySelectorAll("[data-more-menu]");
|
||||
menus.forEach((menu) => {
|
||||
if (menu instanceof HTMLElement) {
|
||||
menu.classList.add("hidden");
|
||||
menu.dataset.state = "closed";
|
||||
menu.setAttribute("aria-hidden", "true");
|
||||
menu.hidden = true;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
+29
-17
@@ -29,7 +29,7 @@
|
||||
</div>
|
||||
<div class="flex flex-col items-end gap-3 self-start sm:self-end">
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="relative" data-channel-zap-wrapper>
|
||||
<div class="popover" data-channel-zap-wrapper>
|
||||
<button
|
||||
id="zapButton"
|
||||
type="button"
|
||||
@@ -47,15 +47,16 @@
|
||||
</button>
|
||||
<div
|
||||
id="zapControls"
|
||||
class="zap-popover hidden"
|
||||
class="popover__panel card w-72 max-w-[calc(100vw-2rem)] p-4"
|
||||
data-variant="zap"
|
||||
role="dialog"
|
||||
aria-hidden="true"
|
||||
aria-label="Channel zap dialog"
|
||||
data-state="closed"
|
||||
hidden
|
||||
>
|
||||
<div
|
||||
class="zap-popover__content card w-72 max-w-[calc(100vw-2rem)] p-4"
|
||||
>
|
||||
<div class="mb-3 flex items-center justify-between gap-4">
|
||||
<div class="grid gap-4">
|
||||
<div class="flex items-center justify-between gap-4">
|
||||
<h3
|
||||
class="text-xs font-semibold uppercase tracking-wide text-muted-strong"
|
||||
>
|
||||
@@ -72,8 +73,9 @@
|
||||
</div>
|
||||
<p
|
||||
id="zapWalletPrompt"
|
||||
class="mb-3 hidden text-sm text-muted"
|
||||
class="text-sm text-muted"
|
||||
aria-hidden="true"
|
||||
hidden
|
||||
>
|
||||
Connect a wallet in
|
||||
<button
|
||||
@@ -145,10 +147,7 @@
|
||||
class="icon-image"
|
||||
/>
|
||||
</button>
|
||||
<div
|
||||
class="relative inline-block overflow-visible"
|
||||
data-more-menu-wrapper="true"
|
||||
>
|
||||
<div class="popover" data-more-menu-wrapper="true">
|
||||
<button
|
||||
id="channelMoreBtn"
|
||||
type="button"
|
||||
@@ -162,35 +161,48 @@
|
||||
</button>
|
||||
<div
|
||||
id="moreDropdown-channel-profile"
|
||||
class="hidden absolute right-0 top-12 w-48 rounded-md shadow-lg bg-gray-800 ring-1 ring-black ring-opacity-5 z-50"
|
||||
class="popover__panel w-48"
|
||||
role="menu"
|
||||
data-more-menu="true"
|
||||
data-state="closed"
|
||||
aria-hidden="true"
|
||||
hidden
|
||||
>
|
||||
<div class="py-1">
|
||||
<div class="menu" role="none">
|
||||
<button
|
||||
class="block w-full text-left px-4 py-2 text-sm text-gray-100 hover:bg-gray-700"
|
||||
type="button"
|
||||
class="menu__item justify-start"
|
||||
role="menuitem"
|
||||
data-action="copy-npub"
|
||||
data-context="channel-profile"
|
||||
>
|
||||
Copy npub
|
||||
</button>
|
||||
<button
|
||||
class="block w-full text-left px-4 py-2 text-sm text-red-400 hover:bg-red-700 hover:text-white"
|
||||
type="button"
|
||||
class="menu__item justify-start"
|
||||
role="menuitem"
|
||||
data-action="blacklist-author"
|
||||
data-context="channel-profile"
|
||||
data-blacklist-menu="true"
|
||||
data-variant="critical"
|
||||
>
|
||||
Blacklist channel
|
||||
</button>
|
||||
<button
|
||||
class="block w-full text-left px-4 py-2 text-sm text-red-400 hover:bg-red-700 hover:text-white"
|
||||
type="button"
|
||||
class="menu__item justify-start"
|
||||
role="menuitem"
|
||||
data-action="block-author"
|
||||
data-context="channel-profile"
|
||||
data-variant="critical"
|
||||
>
|
||||
Block channel
|
||||
</button>
|
||||
<button
|
||||
class="block w-full text-left px-4 py-2 text-sm text-gray-100 hover:bg-gray-700"
|
||||
type="button"
|
||||
class="menu__item justify-start"
|
||||
role="menuitem"
|
||||
data-action="report"
|
||||
data-context="channel-profile"
|
||||
>
|
||||
|
||||
Reference in new issue
Block a user