Add semantic tokens and utilities for modal typography

This commit is contained in:
thePR0M3TH3AN committed 2025-10-14 14:54:01 -04:00
1 parent 5e318bfa17
commit fc095e9796
9 files changed
+106 -62

No files matched your search

+17 -17
View File
@@ -9,7 +9,7 @@
>
<div id="editVideoModalOverlay" class="bv-modal-backdrop"></div>
<div class="modal-sheet modal-content max-h-[90vh] overflow-y-auto lg:max-w-4xl" tabindex="-1">
<div class="modal-sheet modal-content max-h-modal-shell overflow-y-auto lg:max-w-4xl" tabindex="-1">
<div class="modal-header">
<h2 class="text-xl font-bold text-text">Edit Video Note</h2>
<button id="closeEditVideoModal" class="modal-close">
@@ -230,7 +230,7 @@
placeholder="video/mp4"
class="input"
/>
<p class="text-[11px] text-muted">RFC 2046 media type for this encoding.</p>
<p class="text-3xs text-muted">RFC 2046 media type for this encoding.</p>
</div>
<div class="space-y-2">
<label class="block text-xs font-medium text-muted-strong">
@@ -242,7 +242,7 @@
placeholder="1920x1080"
class="input"
/>
<p class="text-[11px] text-muted">Formatted as widthxheight.</p>
<p class="text-3xs text-muted">Formatted as widthxheight.</p>
</div>
<div class="space-y-2">
<label class="block text-xs font-medium text-muted-strong">
@@ -254,7 +254,7 @@
placeholder="https://cdn.example.com/variant.m3u8"
class="input"
/>
<p class="text-[11px] text-muted">HTTPS variant URL shared across clients.</p>
<p class="text-3xs text-muted">HTTPS variant URL shared across clients.</p>
</div>
<div class="space-y-2">
<label class="block text-xs font-medium text-muted-strong">
@@ -266,7 +266,7 @@
placeholder="magnet:?xt=urn:btih:..."
class="input"
/>
<p class="text-[11px] text-muted">Optional magnet pointer if the variant is seeded via P2P.</p>
<p class="text-3xs text-muted">Optional magnet pointer if the variant is seeded via P2P.</p>
</div>
</div>
@@ -275,7 +275,7 @@
<h4 class="text-xs font-semibold uppercase tracking-wide text-muted">Image values</h4>
<button
type="button"
class="btn-ghost focus-ring text-[11px] font-medium"
class="btn-ghost focus-ring text-3xs font-medium"
data-nip71-nested-add="image"
>
Add image URL
@@ -292,7 +292,7 @@
/>
<button
type="button"
class="btn-ghost focus-ring text-[11px] font-medium"
class="btn-ghost focus-ring text-3xs font-medium"
data-nip71-remove="nested"
aria-label="Remove image URL"
>
@@ -307,7 +307,7 @@
<h4 class="text-xs font-semibold uppercase tracking-wide text-muted">Fallback URLs</h4>
<button
type="button"
class="btn-ghost focus-ring text-[11px] font-medium"
class="btn-ghost focus-ring text-3xs font-medium"
data-nip71-nested-add="fallback"
>
Add fallback
@@ -324,7 +324,7 @@
/>
<button
type="button"
class="btn-ghost focus-ring text-[11px] font-medium"
class="btn-ghost focus-ring text-3xs font-medium"
data-nip71-remove="nested"
aria-label="Remove fallback URL"
>
@@ -339,7 +339,7 @@
<h4 class="text-xs font-semibold uppercase tracking-wide text-muted">Services</h4>
<button
type="button"
class="btn-ghost focus-ring text-[11px] font-medium"
class="btn-ghost focus-ring text-3xs font-medium"
data-nip71-nested-add="service"
>
Add service
@@ -356,7 +356,7 @@
/>
<button
type="button"
class="btn-ghost focus-ring text-[11px] font-medium"
class="btn-ghost focus-ring text-3xs font-medium"
data-nip71-remove="nested"
aria-label="Remove service entry"
>
@@ -369,7 +369,7 @@
<div class="flex justify-end">
<button
type="button"
class="btn-ghost focus-ring text-[11px] font-medium"
class="btn-ghost focus-ring text-3xs font-medium"
data-nip71-remove="imeta"
>
Remove variant
@@ -431,7 +431,7 @@
<div class="flex justify-end">
<button
type="button"
class="btn-ghost focus-ring text-[11px] font-medium"
class="btn-ghost focus-ring text-3xs font-medium"
data-nip71-remove="text-track"
>
Remove track
@@ -502,7 +502,7 @@
<div class="flex justify-end">
<button
type="button"
class="btn-ghost focus-ring text-[11px] font-medium"
class="btn-ghost focus-ring text-3xs font-medium"
data-nip71-remove="segment"
>
Remove segment
@@ -537,7 +537,7 @@
/>
<button
type="button"
class="btn-ghost focus-ring text-[11px] font-medium"
class="btn-ghost focus-ring text-3xs font-medium"
data-nip71-remove="t"
>
Remove
@@ -583,7 +583,7 @@
<div class="flex justify-end">
<button
type="button"
class="btn-ghost focus-ring text-[11px] font-medium"
class="btn-ghost focus-ring text-3xs font-medium"
data-nip71-remove="p"
>
Remove participant
@@ -615,7 +615,7 @@
/>
<button
type="button"
class="btn-ghost focus-ring text-[11px] font-medium"
class="btn-ghost focus-ring text-3xs font-medium"
data-nip71-remove="r"
>
Remove
+3 -3
View File
@@ -10,7 +10,7 @@
>
<div class="bv-modal-backdrop"></div>
<div class="modal-sheet modal-content relative flex max-h-[90vh] flex-col overflow-hidden lg:max-w-6xl" tabindex="-1">
<div class="modal-sheet modal-content relative flex max-h-modal-shell flex-col overflow-hidden lg:max-w-6xl" tabindex="-1">
<!-- Modal Header -->
<div class="modal-header">
<h2 id="profileModalTitle" class="text-xl font-bold text-text">Profile</h2>
@@ -141,7 +141,7 @@
</span>
<div class="flex min-w-0 flex-1 flex-col gap-2">
<div class="flex flex-wrap items-center gap-3">
<span class="text-[11px] font-semibold uppercase tracking-[0.2em] text-info">
<span class="text-3xs font-semibold uppercase tracking-extra-wide text-info">
Active profile
</span>
<a
@@ -461,7 +461,7 @@
>
You haven’t watched any videos yet.
</div>
<div id="profileHistoryScroll" class="relative max-h-[420px] overflow-y-auto pr-1">
<div id="profileHistoryScroll" class="relative max-h-profile-history overflow-y-auto pr-1">
<div
id="profileHistoryGrid"
class="grid-stack hidden"
+5 -5
View File
@@ -14,7 +14,7 @@
data-dismiss
></div>
<div class="modal-sheet max-h-[92vh] overflow-hidden lg:max-w-5xl" tabindex="-1">
<div class="modal-sheet max-h-modal-sheet overflow-hidden lg:max-w-5xl" tabindex="-1">
<div class="modal-header transition-transform duration-150">
<div class="flex flex-col">
<h2 id="revertModalTitle" class="text-xl font-bold text-text">
@@ -47,7 +47,7 @@
</button>
</div>
<div class="modal-body space-y-6 overflow-y-auto max-h-[calc(92vh-4rem)]">
<div class="modal-body space-y-6 overflow-y-auto max-h-modal-body">
<div
class="rounded-md border border-border/60 bg-panel/60 p-4 text-sm text-muted-strong"
>
@@ -58,12 +58,12 @@
<p class="mt-2 text-xs text-muted">
Versions are grouped by their
<code
class="rounded border border-border/60 bg-surface/60 px-1 py-0.5 text-[0.7rem]"
class="rounded border border-border/60 bg-surface/60 px-1 py-0.5 text-2xs"
>d</code
>
tag or shared
<code
class="rounded border border-border/60 bg-surface/60 px-1 py-0.5 text-[0.7rem]"
class="rounded border border-border/60 bg-surface/60 px-1 py-0.5 text-2xs"
>videoRootId</code
>. This ensures legacy clients see consistent history when multiple
edits were published, and keeps audience flags (NSFW / for kids)
@@ -84,7 +84,7 @@
</div>
<div
id="revertVersionsList"
class="space-y-2 overflow-y-auto pr-1 max-h-[48vh]"
class="space-y-2 overflow-y-auto pr-1 max-h-modal-pane"
></div>
</aside>
+31 -31
View File
@@ -11,7 +11,7 @@
<div class="bv-modal-backdrop" data-dismiss></div>
<!-- Modal Container -->
<div class="modal-sheet max-h-[90vh] overflow-y-auto" tabindex="-1">
<div class="modal-sheet max-h-modal-shell overflow-y-auto" tabindex="-1">
<!-- Top Bar (similar to video-modal) -->
<div class="modal-header transition-transform duration-150">
<h2 id="uploadModalTitle" class="text-xl font-bold text-text">
@@ -380,7 +380,7 @@
placeholder="video/mp4"
class="input"
/>
<p class="text-[11px] text-muted">
<p class="text-3xs text-muted">
RFC 2046 media type for this encoding.
</p>
</div>
@@ -394,7 +394,7 @@
placeholder="1920x1080"
class="input"
/>
<p class="text-[11px] text-muted">
<p class="text-3xs text-muted">
Formatted as widthxheight.
</p>
</div>
@@ -408,7 +408,7 @@
placeholder="https://cdn.example.com/variant.m3u8"
class="input"
/>
<p class="text-[11px] text-muted">
<p class="text-3xs text-muted">
HTTPS variant URL shared across clients.
</p>
</div>
@@ -422,7 +422,7 @@
placeholder="magnet:?xt=urn:btih:..."
class="input"
/>
<p class="text-[11px] text-muted">
<p class="text-3xs text-muted">
Optional magnet pointer if the variant is seeded via
P2P.
</p>
@@ -438,7 +438,7 @@
</h4>
<button
type="button"
class="btn-ghost px-2 py-1 text-[11px]"
class="btn-ghost px-2 py-1 text-3xs"
data-nip71-nested-add="image"
>
Add image URL
@@ -461,7 +461,7 @@
/>
<button
type="button"
class="btn-ghost px-2 py-1 text-[11px] text-muted-strong"
class="btn-ghost px-2 py-1 text-3xs text-muted-strong"
data-nip71-remove="nested"
aria-label="Remove image URL"
>
@@ -480,7 +480,7 @@
</h4>
<button
type="button"
class="btn-ghost px-2 py-1 text-[11px]"
class="btn-ghost px-2 py-1 text-3xs"
data-nip71-nested-add="fallback"
>
Add fallback
@@ -503,7 +503,7 @@
/>
<button
type="button"
class="btn-ghost px-2 py-1 text-[11px] text-muted-strong"
class="btn-ghost px-2 py-1 text-3xs text-muted-strong"
data-nip71-remove="nested"
aria-label="Remove fallback URL"
>
@@ -522,7 +522,7 @@
</h4>
<button
type="button"
class="btn-ghost px-2 py-1 text-[11px]"
class="btn-ghost px-2 py-1 text-3xs"
data-nip71-nested-add="service"
>
Add service hint
@@ -545,7 +545,7 @@
/>
<button
type="button"
class="btn-ghost px-2 py-1 text-[11px] text-muted-strong"
class="btn-ghost px-2 py-1 text-3xs text-muted-strong"
data-nip71-remove="nested"
aria-label="Remove service hint"
>
@@ -615,7 +615,7 @@
placeholder="https://cdn.example.com/captions.en.vtt"
class="input"
/>
<p class="text-[11px] text-muted">
<p class="text-3xs text-muted">
Direct link to the caption file.
</p>
</div>
@@ -629,7 +629,7 @@
placeholder="subtitles"
class="input"
/>
<p class="text-[11px] text-muted">
<p class="text-3xs text-muted">
Use values like captions, subtitles, or descriptions.
</p>
</div>
@@ -643,7 +643,7 @@
placeholder="en-US"
class="input"
/>
<p class="text-[11px] text-muted">
<p class="text-3xs text-muted">
BCP-47 locale code.
</p>
</div>
@@ -708,7 +708,7 @@
placeholder="00:00:00"
class="input"
/>
<p class="text-[11px] text-muted">HH:MM:SS</p>
<p class="text-3xs text-muted">HH:MM:SS</p>
</div>
<div class="space-y-2">
<label class="block text-xs font-medium text-muted-strong"
@@ -720,7 +720,7 @@
placeholder="00:03:30"
class="input"
/>
<p class="text-[11px] text-muted">
<p class="text-3xs text-muted">
Leave blank for open-ended segments.
</p>
</div>
@@ -745,7 +745,7 @@
placeholder="https://cdn.example.com/segment.jpg"
class="input"
/>
<p class="text-[11px] text-muted">
<p class="text-3xs text-muted">
Optional still image for this moment.
</p>
</div>
@@ -800,7 +800,7 @@
/>
<button
type="button"
class="btn-ghost px-2 py-1 text-[11px]" data-variant="critical"
class="btn-ghost px-2 py-1 text-3xs" data-variant="critical"
data-nip71-remove="t"
aria-label="Remove hashtag"
>
@@ -855,7 +855,7 @@
placeholder="npub1..."
class="input"
/>
<p class="text-[11px] text-muted">
<p class="text-3xs text-muted">
Accepts npub or hex.
</p>
</div>
@@ -869,7 +869,7 @@
placeholder="wss://relay.example.com"
class="input"
/>
<p class="text-[11px] text-muted">
<p class="text-3xs text-muted">
Relay hint for discovering the participant.
</p>
</div>
@@ -924,7 +924,7 @@
/>
<button
type="button"
class="btn-ghost px-2 py-1 text-[11px]" data-variant="critical"
class="btn-ghost px-2 py-1 text-3xs" data-variant="critical"
data-nip71-remove="r"
aria-label="Remove reference"
>
@@ -1539,7 +1539,7 @@
placeholder="Auto-filled after upload (e.g., video/mp4)"
class="input"
/>
<p class="text-[11px] text-muted">
<p class="text-3xs text-muted">
RFC 2046 media type for this encoding.
</p>
</div>
@@ -1555,7 +1555,7 @@
placeholder="Auto-filled if detected (e.g., 1920x1080)"
class="input"
/>
<p class="text-[11px] text-muted">
<p class="text-3xs text-muted">
Formatted as widthxheight.
</p>
</div>
@@ -1571,7 +1571,7 @@
placeholder="Auto-filled after upload with the public HTTPS URL"
class="input"
/>
<p class="text-[11px] text-muted">
<p class="text-3xs text-muted">
HTTPS variant URL shared across clients.
</p>
</div>
@@ -1587,7 +1587,7 @@
placeholder="Optional magnet pointer if seeding via P2P"
class="input"
/>
<p class="text-[11px] text-muted">
<p class="text-3xs text-muted">
Optional magnet pointer if the variant is seeded
via P2P.
</p>
@@ -1603,7 +1603,7 @@
</h4>
<button
type="button"
class="btn-ghost px-2 py-1 text-[11px]"
class="btn-ghost px-2 py-1 text-3xs"
data-nip71-nested-add="image"
>
Add image URL
@@ -1626,7 +1626,7 @@
/>
<button
type="button"
class="btn-ghost px-2 py-1 text-[11px] text-muted-strong"
class="btn-ghost px-2 py-1 text-3xs text-muted-strong"
data-nip71-remove="nested"
aria-label="Remove image URL"
>
@@ -1645,7 +1645,7 @@
</h4>
<button
type="button"
class="btn-ghost px-2 py-1 text-[11px]"
class="btn-ghost px-2 py-1 text-3xs"
data-nip71-nested-add="fallback"
>
Add fallback
@@ -1668,7 +1668,7 @@
/>
<button
type="button"
class="btn-ghost px-2 py-1 text-[11px] text-muted-strong"
class="btn-ghost px-2 py-1 text-3xs text-muted-strong"
data-nip71-remove="nested"
aria-label="Remove fallback URL"
>
@@ -1687,7 +1687,7 @@
</h4>
<button
type="button"
class="btn-ghost px-2 py-1 text-[11px]"
class="btn-ghost px-2 py-1 text-3xs"
data-nip71-nested-add="service"
>
Add service hint
@@ -1710,7 +1710,7 @@
/>
<button
type="button"
class="btn-ghost px-2 py-1 text-[11px] text-muted-strong"
class="btn-ghost px-2 py-1 text-3xs text-muted-strong"
data-nip71-remove="nested"
aria-label="Remove service hint"
>
+9
View File
@@ -273,6 +273,11 @@
/* Component sizing */
--menu-min-width: 12rem;
--modal-max-width: 38rem;
--modal-shell-max-height: 90vh;
--modal-sheet-max-height: 92vh;
--modal-body-max-height: calc(92vh - 4rem);
--modal-pane-max-height: 48vh;
--profile-history-max-height: 26.25rem;
--layout-player-max-width: 68.75rem;
--layout-docs-max-width: 92.5rem;
--icon-size-sm: var(--font-size-lg);
@@ -308,6 +313,9 @@
/* Typography */
--font-family-sans: "Inter", "Segoe UI", system-ui, -apple-system, sans-serif;
--font-family-mono: "Fira Code", "SFMono-Regular", ui-monospace, monospace;
--font-size-4xs: 0.65rem;
--font-size-3xs: 0.6875rem;
--font-size-2xs: 0.7rem;
--font-size-xs: 0.75rem;
--font-size-sm: 0.875rem;
--font-size-base: 1rem;
@@ -323,6 +331,7 @@
--line-height-snug: 1.25;
--line-height-base: 1.5;
--line-height-relaxed: 1.75;
--tracking-extra-wide: 0.2em;
/* Beacon UI tokens */
--grid-border-width: calc(var(--space-2xs) / 4);
+22
View File
@@ -32,6 +32,28 @@ When introducing a new runtime feature that requires dynamic styling:
3. Clean up by calling `releaseScope` when the component unmounts.
4. Prefer reusable primitives (like `.ds-metric-probe`) for offscreen measurement or layout shims so multiple components can share the same CSS.
## Typography & Layout Tokens
Small-type utilities and modal geometry are now backed by dedicated semantic tokens in `css/tokens.css`. The scale introduces
`--font-size-4xs` (0.65rem), `--font-size-3xs` (0.6875rem), `--font-size-2xs` (0.7rem), and `--tracking-extra-wide`
(0.2em) alongside modal measurements such as `--modal-shell-max-height`, `--modal-sheet-max-height`,
`--modal-body-max-height`, `--modal-pane-max-height`, and `--profile-history-max-height`. Tailwind exposes the tokens through
utility aliases including `text-4xs`, `text-3xs`, `text-2xs`, `tracking-extra-wide`, `max-h-modal-shell`, `max-h-modal-sheet`,
`max-h-modal-body`, `max-h-modal-pane`, and `max-h-profile-history`. Use these utilities instead of arbitrary values so future
scale adjustments can ship from a single source of truth.
### Migration notes
- Replace literal classes such as `text-[11px]`, `text-[0.7rem]`, and `text-[0.65rem]` with the new semantic helpers
(`text-3xs`, `text-2xs`, `text-4xs`). The controller logic for saved profiles and modal renderers has been updated to follow
the same pattern.
- Swap bespoke tracking overrides (for example, `tracking-[0.2em]`) to `tracking-extra-wide` so the widened CTA headings stay
consistent across themes.
- Move modal shells and scroll containers off arbitrary `max-h-[...]` utilities in favour of `max-h-modal-shell`,
`max-h-modal-sheet`, `max-h-modal-body`, `max-h-modal-pane`, and `max-h-profile-history`.
- Keep the legacy search strings (like `text-[11px]`) in regression checklists—repositories should no longer include those
selectors after migrating a template or controller.
## Theming
### `[data-theme]` contract
+5 -5
View File
@@ -1365,7 +1365,7 @@ export class RevertModal {
const badges = [];
if (variant.autoGenerated) {
badges.push(
'<span class="inline-flex items-center rounded-full border border-amber-600/70 bg-amber-900/30 px-2 py-0.5 text-[0.65rem] uppercase tracking-wide text-amber-200/90">Auto-generated</span>'
'<span class="inline-flex items-center rounded-full border border-amber-600/70 bg-amber-900/30 px-2 py-0.5 text-4xs uppercase tracking-wide text-amber-200/90">Auto-generated</span>'
);
}
@@ -1392,7 +1392,7 @@ export class RevertModal {
const renderNestedList = (label, values, emptyLabel) => {
if (!Array.isArray(values) || values.length === 0) {
return `<div><p class="text-[0.7rem] uppercase tracking-wide text-gray-500">${escape(
return `<div><p class="text-2xs uppercase tracking-wide text-gray-500">${escape(
label
)}</p>${this.renderListEmpty(emptyLabel)}</div>`;
}
@@ -1403,14 +1403,14 @@ export class RevertModal {
.map((markup) => `<li>${markup}</li>`);
if (!items.length) {
return `<div><p class="text-[0.7rem] uppercase tracking-wide text-gray-500">${escape(
return `<div><p class="text-2xs uppercase tracking-wide text-gray-500">${escape(
label
)}</p>${this.renderListEmpty(emptyLabel)}</div>`;
}
return `
<div>
<p class="text-[0.7rem] uppercase tracking-wide text-gray-500">${escape(
<p class="text-2xs uppercase tracking-wide text-gray-500">${escape(
label
)}</p>
<ul class="mt-1 space-y-1 text-xs text-gray-200">${items.join("")}</ul>
@@ -1476,7 +1476,7 @@ export class RevertModal {
)}</code>`
: this.renderPlaceholder();
const languageHtml = track.language
? `<span class="inline-flex items-center rounded-full border border-gray-700 bg-gray-800/70 px-2 py-0.5 text-[0.7rem] uppercase tracking-wide text-gray-200">${escape(
? `<span class="inline-flex items-center rounded-full border border-gray-700 bg-gray-800/70 px-2 py-0.5 text-2xs uppercase tracking-wide text-gray-200">${escape(
track.language
)}</span>`
: this.renderPlaceholder();
+1 -1
View File
@@ -1327,7 +1327,7 @@ export class ProfileModalController {
const label = document.createElement("span");
label.className =
"text-[11px] font-semibold uppercase tracking-[0.2em] text-blue-200";
"text-3xs font-semibold uppercase tracking-extra-wide text-blue-200";
label.textContent =
entry.authType === "nsec" ? "Direct key" : "Saved profile";
+13
View File
@@ -223,6 +223,9 @@ module.exports = {
mono: ["var(--font-family-mono)"]
},
fontSize: {
"4xs": ["var(--font-size-4xs)", { lineHeight: "var(--line-height-tight)" }],
"3xs": ["var(--font-size-3xs)", { lineHeight: "var(--line-height-tight)" }],
"2xs": ["var(--font-size-2xs)", { lineHeight: "var(--line-height-tight)" }],
xs: ["var(--font-size-xs)", { lineHeight: "var(--line-height-tight)" }],
sm: ["var(--font-size-sm)", { lineHeight: "var(--line-height-snug)" }],
base: [
@@ -244,6 +247,16 @@ module.exports = {
base: "var(--motion-duration-base)",
slow: "var(--motion-duration-slow)"
},
letterSpacing: {
"extra-wide": "var(--tracking-extra-wide)"
},
maxHeight: {
"modal-shell": "var(--modal-shell-max-height)",
"modal-sheet": "var(--modal-sheet-max-height)",
"modal-body": "var(--modal-body-max-height)",
"modal-pane": "var(--modal-pane-max-height)",
"profile-history": "var(--profile-history-max-height)"
},
transitionTimingFunction: {
"ease-out": "var(--motion-ease-out)",
"ease-in-out": "var(--motion-ease-in-out)"