@rathnasgala2/template 3.2.0 → 3.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -671,7 +671,6 @@ export const GALA_BASE_COMPONENT_CSS = `
|
|
|
671
671
|
}
|
|
672
672
|
.g-reaction:hover:not(:disabled) { border-color: var(--gala-color-text); color: var(--gala-color-text); }
|
|
673
673
|
.g-reaction:active:not(:disabled) { transform: scale(.96); }
|
|
674
|
-
.g-reaction:disabled { opacity: .55; cursor: default; }
|
|
675
674
|
.g-reaction__icon { display: inline-grid; place-items: center; font-size: 1.1rem; line-height: 1; }
|
|
676
675
|
.g-reaction__icon .g-icon { width: 1.15rem; height: 1.15rem; }
|
|
677
676
|
.g-reaction__label { overflow-wrap: anywhere; }
|
|
@@ -706,12 +705,41 @@ export const GALA_BASE_COMPONENT_CSS = `
|
|
|
706
705
|
}
|
|
707
706
|
.g-composer__submit:hover:not(:disabled), .g-composer__signin:hover, .g-report button[type="submit"]:hover { filter: brightness(1.07) saturate(1.05); }
|
|
708
707
|
.g-composer__submit:active:not(:disabled), .g-composer__signin:active { transform: scale(.97); }
|
|
709
|
-
.g-composer__submit:disabled { opacity: .55; cursor: default; box-shadow: none; }
|
|
710
708
|
.g-composer__cancel, .g-report button[type="button"] {
|
|
711
709
|
min-height: 2.75rem; padding: .6rem 1rem; border-radius: var(--gala-radius-pill); border: var(--gala-border-width) solid var(--gala-color-border); background: transparent; color: var(--gala-color-text);
|
|
712
710
|
font-family: var(--gala-font-ui); font-weight: var(--gala-weight-ui); font-size: .9rem; cursor: pointer;
|
|
713
711
|
}
|
|
714
712
|
.g-composer__cancel:hover, .g-report button[type="button"]:hover { border-color: var(--gala-color-text); }
|
|
713
|
+
/* Interaction-button states. Enabled: full-strength tokens and a pointer.
|
|
714
|
+
Disabled (native or aria-disabled): muted surface and border tokens,
|
|
715
|
+
faint text, reduced opacity, a dashed border and not-allowed. Working
|
|
716
|
+
(aria-busy): enabled colours, a progress cursor and a spinner, never the
|
|
717
|
+
muted look. Themes may tint these tokens, never remove the rule. */
|
|
718
|
+
.g-reaction:is(:disabled, [aria-disabled="true"]):not([aria-busy="true"]),
|
|
719
|
+
.g-comments__more:is(:disabled, [aria-disabled="true"]):not([aria-busy="true"]),
|
|
720
|
+
.g-composer__cancel:is(:disabled, [aria-disabled="true"]):not([aria-busy="true"]),
|
|
721
|
+
.g-report button[type="button"]:is(:disabled, [aria-disabled="true"]):not([aria-busy="true"]),
|
|
722
|
+
.g-comment__action:is(:disabled, [aria-disabled="true"]):not([aria-busy="true"]),
|
|
723
|
+
.g-composer__submit:is(:disabled, [aria-disabled="true"]):not([aria-busy="true"]),
|
|
724
|
+
.g-composer__signin:is(:disabled, [aria-disabled="true"]):not([aria-busy="true"]),
|
|
725
|
+
.g-report button[type="submit"]:is(:disabled, [aria-disabled="true"]):not([aria-busy="true"]) {
|
|
726
|
+
background: var(--gala-color-surface-raised); background-image: none; color: var(--gala-color-text-faint);
|
|
727
|
+
border: var(--gala-border-width) dashed var(--gala-color-border); box-shadow: none; filter: none; transform: none;
|
|
728
|
+
opacity: .6; cursor: not-allowed;
|
|
729
|
+
}
|
|
730
|
+
.g-interactions__signout:is(:disabled, [aria-disabled="true"]):not([aria-busy="true"]) { color: var(--gala-color-text-faint); text-decoration-style: dashed; opacity: .6; cursor: not-allowed; }
|
|
731
|
+
.g-reaction[aria-busy="true"], .g-comments__more[aria-busy="true"], .g-composer__cancel[aria-busy="true"], .g-comment__action[aria-busy="true"],
|
|
732
|
+
.g-composer__submit[aria-busy="true"], .g-composer__signin[aria-busy="true"], .g-report button[aria-busy="true"] { cursor: progress; }
|
|
733
|
+
.g-reaction[aria-busy="true"]::after, .g-comments__more[aria-busy="true"]::after, .g-comment__action[aria-busy="true"]::after,
|
|
734
|
+
.g-composer__submit[aria-busy="true"]::after, .g-report button[aria-busy="true"]::after {
|
|
735
|
+
content: ""; display: inline-block; flex: none; width: .9em; height: .9em; margin-left: .5em; border-radius: 50%;
|
|
736
|
+
border: 2px solid currentColor; border-right-color: transparent; vertical-align: -.1em; animation: g-busy-spin .8s linear infinite;
|
|
737
|
+
}
|
|
738
|
+
@keyframes g-busy-spin { to { transform: rotate(360deg); } }
|
|
739
|
+
@media (prefers-reduced-motion: reduce) {
|
|
740
|
+
.g-reaction[aria-busy="true"]::after, .g-comments__more[aria-busy="true"]::after, .g-comment__action[aria-busy="true"]::after,
|
|
741
|
+
.g-composer__submit[aria-busy="true"]::after, .g-report button[aria-busy="true"]::after { animation: none; border-right-color: currentColor; border-style: dotted; }
|
|
742
|
+
}
|
|
715
743
|
.g-comment-list { display: grid; gap: var(--gala-space-4); min-width: 0; }
|
|
716
744
|
.g-comment { display: grid; gap: var(--gala-space-2); min-width: 0; }
|
|
717
745
|
.g-comment__head { display: flex; align-items: center; gap: var(--gala-space-3); min-width: 0; }
|
|
@@ -253,9 +253,10 @@
|
|
|
253
253
|
};
|
|
254
254
|
const composers = new Set();
|
|
255
255
|
let rootComposer = /** @type {Composer | null} */ (null);
|
|
256
|
-
let inline =
|
|
257
|
-
null
|
|
258
|
-
|
|
256
|
+
let inline =
|
|
257
|
+
/** @type {{composer: Composer, item: CommentItem, trigger: HTMLElement | null} | null} */ (
|
|
258
|
+
null
|
|
259
|
+
);
|
|
259
260
|
let loadToken = 0;
|
|
260
261
|
|
|
261
262
|
// ------------------------------------------------------------------- helpers
|
|
@@ -295,6 +296,47 @@
|
|
|
295
296
|
return node;
|
|
296
297
|
}
|
|
297
298
|
|
|
299
|
+
/**
|
|
300
|
+
* One place for the disabled state: the native attribute (which blocks
|
|
301
|
+
* activation and focus) and `aria-disabled` together, so the base layer's
|
|
302
|
+
* `:disabled` / `[aria-disabled="true"]` rule and assistive technology agree.
|
|
303
|
+
*
|
|
304
|
+
* @param {HTMLElement} node
|
|
305
|
+
* @param {boolean} on
|
|
306
|
+
*/
|
|
307
|
+
function setDisabled(node, on) {
|
|
308
|
+
/** @type {HTMLButtonElement} */ (node).disabled = on;
|
|
309
|
+
if (on) node.setAttribute('aria-disabled', 'true');
|
|
310
|
+
else node.removeAttribute('aria-disabled');
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* The working (pending) state: disabled for activation, but marked
|
|
315
|
+
* `aria-busy` so the base layer draws a spinner instead of the muted
|
|
316
|
+
* disabled look.
|
|
317
|
+
*
|
|
318
|
+
* @param {HTMLElement} node
|
|
319
|
+
* @param {boolean} on
|
|
320
|
+
*/
|
|
321
|
+
function setBusy(node, on) {
|
|
322
|
+
setDisabled(node, on);
|
|
323
|
+
if (on) node.setAttribute('aria-busy', 'true');
|
|
324
|
+
else node.removeAttribute('aria-busy');
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* A trigger whose action is already in progress (its inline composer is
|
|
329
|
+
* open) stays focusable, so it is `aria-disabled` only, and ignores clicks.
|
|
330
|
+
*
|
|
331
|
+
* @param {HTMLElement | null} trigger
|
|
332
|
+
* @param {boolean} on
|
|
333
|
+
*/
|
|
334
|
+
function holdTrigger(trigger, on) {
|
|
335
|
+
if (!trigger) return;
|
|
336
|
+
if (on) trigger.setAttribute('aria-disabled', 'true');
|
|
337
|
+
else trigger.removeAttribute('aria-disabled');
|
|
338
|
+
}
|
|
339
|
+
|
|
298
340
|
let idCounter = 0;
|
|
299
341
|
/**
|
|
300
342
|
* @param {string} prefix
|
|
@@ -867,7 +909,7 @@
|
|
|
867
909
|
continue;
|
|
868
910
|
}
|
|
869
911
|
node.hidden = false;
|
|
870
|
-
node
|
|
912
|
+
setDisabled(node, false);
|
|
871
913
|
setPressed(node, !!item.viewerActive);
|
|
872
914
|
setCount(node, item.count, 'reactions');
|
|
873
915
|
}
|
|
@@ -1267,7 +1309,7 @@
|
|
|
1267
1309
|
let cursor = /** @type {string | null} */ (null);
|
|
1268
1310
|
let first = true;
|
|
1269
1311
|
more.addEventListener('click', async () => {
|
|
1270
|
-
more
|
|
1312
|
+
setBusy(more, true);
|
|
1271
1313
|
try {
|
|
1272
1314
|
const query = new URLSearchParams({ parentId: comment.id });
|
|
1273
1315
|
if (cursor) query.set('cursor', cursor);
|
|
@@ -1284,9 +1326,9 @@
|
|
|
1284
1326
|
list.appendChild(renderComment(reply));
|
|
1285
1327
|
cursor = page.nextCursor || null;
|
|
1286
1328
|
if (!cursor) more.remove();
|
|
1287
|
-
else more
|
|
1329
|
+
else setBusy(more, false);
|
|
1288
1330
|
} catch (error) {
|
|
1289
|
-
more
|
|
1331
|
+
setBusy(more, false);
|
|
1290
1332
|
announce(failureMessage(error));
|
|
1291
1333
|
}
|
|
1292
1334
|
});
|
|
@@ -1307,9 +1349,10 @@
|
|
|
1307
1349
|
MESSAGES.reply,
|
|
1308
1350
|
MESSAGES.reply + ' to ' + name,
|
|
1309
1351
|
);
|
|
1310
|
-
reply.addEventListener('click', () =>
|
|
1311
|
-
|
|
1312
|
-
|
|
1352
|
+
reply.addEventListener('click', () => {
|
|
1353
|
+
if (reply.getAttribute('aria-disabled') === 'true') return;
|
|
1354
|
+
openInlineComposer(item, 'reply', reply);
|
|
1355
|
+
});
|
|
1313
1356
|
actions.appendChild(reply);
|
|
1314
1357
|
}
|
|
1315
1358
|
if (comment.viewer && comment.viewer.canEdit) {
|
|
@@ -1318,9 +1361,10 @@
|
|
|
1318
1361
|
MESSAGES.edit,
|
|
1319
1362
|
MESSAGES.edit + ' your comment',
|
|
1320
1363
|
);
|
|
1321
|
-
edit.addEventListener('click', () =>
|
|
1322
|
-
|
|
1323
|
-
|
|
1364
|
+
edit.addEventListener('click', () => {
|
|
1365
|
+
if (edit.getAttribute('aria-disabled') === 'true') return;
|
|
1366
|
+
openInlineComposer(item, 'edit', edit);
|
|
1367
|
+
});
|
|
1324
1368
|
actions.appendChild(edit);
|
|
1325
1369
|
}
|
|
1326
1370
|
if (comment.viewer && comment.viewer.canDelete) {
|
|
@@ -1376,8 +1420,8 @@
|
|
|
1376
1420
|
}
|
|
1377
1421
|
});
|
|
1378
1422
|
yes.addEventListener('click', async () => {
|
|
1379
|
-
yes
|
|
1380
|
-
no
|
|
1423
|
+
setBusy(yes, true);
|
|
1424
|
+
setDisabled(no, true);
|
|
1381
1425
|
try {
|
|
1382
1426
|
await api(
|
|
1383
1427
|
'DELETE',
|
|
@@ -1386,8 +1430,8 @@
|
|
|
1386
1430
|
applyDeleted(item);
|
|
1387
1431
|
announce(MESSAGES.deleted);
|
|
1388
1432
|
} catch (error) {
|
|
1389
|
-
yes
|
|
1390
|
-
no
|
|
1433
|
+
setBusy(yes, false);
|
|
1434
|
+
setDisabled(no, false);
|
|
1391
1435
|
announce(failureMessage(error));
|
|
1392
1436
|
}
|
|
1393
1437
|
});
|
|
@@ -1599,7 +1643,7 @@
|
|
|
1599
1643
|
return;
|
|
1600
1644
|
}
|
|
1601
1645
|
composer.busy = true;
|
|
1602
|
-
submit
|
|
1646
|
+
setDisabled(submit, true);
|
|
1603
1647
|
submit.setAttribute('aria-busy', 'true');
|
|
1604
1648
|
showError('');
|
|
1605
1649
|
try {
|
|
@@ -1626,7 +1670,7 @@
|
|
|
1626
1670
|
showError(failureMessage(failure));
|
|
1627
1671
|
} finally {
|
|
1628
1672
|
composer.busy = false;
|
|
1629
|
-
submit
|
|
1673
|
+
setDisabled(submit, false);
|
|
1630
1674
|
submit.removeAttribute('aria-busy');
|
|
1631
1675
|
}
|
|
1632
1676
|
});
|
|
@@ -1682,6 +1726,7 @@
|
|
|
1682
1726
|
function closeInline() {
|
|
1683
1727
|
if (inline) {
|
|
1684
1728
|
inline.composer.close();
|
|
1729
|
+
holdTrigger(inline.trigger, false);
|
|
1685
1730
|
inline = null;
|
|
1686
1731
|
}
|
|
1687
1732
|
}
|
|
@@ -1697,6 +1742,7 @@
|
|
|
1697
1742
|
const comment = item._comment;
|
|
1698
1743
|
const done = (/** @type {any} */ result) => {
|
|
1699
1744
|
/** @type {{composer: Composer}} */ (inline).composer.close();
|
|
1745
|
+
holdTrigger(trigger, false);
|
|
1700
1746
|
inline = null;
|
|
1701
1747
|
if (mode === 'edit') {
|
|
1702
1748
|
fillComment(item, result);
|
|
@@ -1713,12 +1759,14 @@
|
|
|
1713
1759
|
body: mode === 'edit' ? comment.body || '' : presetBody || '',
|
|
1714
1760
|
onDone: done,
|
|
1715
1761
|
onCancel: () => {
|
|
1762
|
+
holdTrigger(trigger, false);
|
|
1716
1763
|
inline = null;
|
|
1717
1764
|
if (trigger && trigger.isConnected) focusNode(trigger);
|
|
1718
1765
|
else focusNode(item);
|
|
1719
1766
|
},
|
|
1720
1767
|
});
|
|
1721
|
-
|
|
1768
|
+
holdTrigger(trigger, true);
|
|
1769
|
+
inline = { composer, item, trigger };
|
|
1722
1770
|
const replies = item.querySelector(':scope > .g-comment__replies');
|
|
1723
1771
|
if (replies) item.insertBefore(composer.element, replies);
|
|
1724
1772
|
else item.appendChild(composer.element);
|
|
@@ -1805,7 +1853,7 @@
|
|
|
1805
1853
|
});
|
|
1806
1854
|
cancel.addEventListener('click', finish);
|
|
1807
1855
|
send.addEventListener('click', async () => {
|
|
1808
|
-
send
|
|
1856
|
+
setBusy(send, true);
|
|
1809
1857
|
error.hidden = true;
|
|
1810
1858
|
/** @type {{reasonCode: string, note?: string}} */
|
|
1811
1859
|
const payload = { reasonCode: select.value };
|
|
@@ -1822,7 +1870,7 @@
|
|
|
1822
1870
|
finish();
|
|
1823
1871
|
announce(MESSAGES.reported);
|
|
1824
1872
|
} catch (failure) {
|
|
1825
|
-
send
|
|
1873
|
+
setBusy(send, false);
|
|
1826
1874
|
error.textContent = failureMessage(failure);
|
|
1827
1875
|
error.hidden = false;
|
|
1828
1876
|
}
|
|
@@ -1959,7 +2007,7 @@
|
|
|
1959
2007
|
showError(MESSAGES.appealTooLong);
|
|
1960
2008
|
return;
|
|
1961
2009
|
}
|
|
1962
|
-
send
|
|
2010
|
+
setDisabled(send, true);
|
|
1963
2011
|
send.setAttribute('aria-busy', 'true');
|
|
1964
2012
|
showError('');
|
|
1965
2013
|
try {
|
|
@@ -1991,7 +2039,7 @@
|
|
|
1991
2039
|
);
|
|
1992
2040
|
announce(message);
|
|
1993
2041
|
} else {
|
|
1994
|
-
send
|
|
2042
|
+
setDisabled(send, false);
|
|
1995
2043
|
showError(message);
|
|
1996
2044
|
}
|
|
1997
2045
|
} finally {
|
|
@@ -2088,7 +2136,7 @@
|
|
|
2088
2136
|
|
|
2089
2137
|
async function loadMore() {
|
|
2090
2138
|
if (!live.nextCursor || !moreEl) return;
|
|
2091
|
-
moreEl
|
|
2139
|
+
setBusy(moreEl, true);
|
|
2092
2140
|
try {
|
|
2093
2141
|
const query = new URLSearchParams({ cursor: live.nextCursor });
|
|
2094
2142
|
const page = await api(
|
|
@@ -2099,7 +2147,7 @@
|
|
|
2099
2147
|
} catch (error) {
|
|
2100
2148
|
announce(failureMessage(error));
|
|
2101
2149
|
} finally {
|
|
2102
|
-
moreEl
|
|
2150
|
+
setBusy(moreEl, false);
|
|
2103
2151
|
}
|
|
2104
2152
|
}
|
|
2105
2153
|
|