-
-
Notifications
You must be signed in to change notification settings - Fork 439
feat: add citation popup for blog posts (fixes #3322) #3332
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
d787d86
9d480c2
7569110
0445d05
596f038
a5c53b0
51bf89c
6d23c0f
1ce793d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,135 @@ | ||
| /* | ||
| * SPDX-FileCopyrightText: 2026 The Matrix.org Foundation C.I.C. | ||
| * SPDX-FileContributor: Syed Ishmum Ahnaf <syedishmum15@gmail.com> | ||
| * | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| .citation { | ||
| display: inline-block; | ||
| margin-top: 0.5rem; | ||
| } | ||
|
|
||
| .cite-btn { | ||
| display: inline-block; | ||
| font-size: 0.78rem; | ||
| font-weight: 600; | ||
| color: var(--color-text); | ||
| background-color: #f0f0f0; | ||
| border: 1px solid #d2d2d2; | ||
| border-radius: 9999px; | ||
| padding: 0.3rem 0.9rem; | ||
| text-decoration: none; | ||
| cursor: pointer; | ||
| transition: background-color 0.15s ease, border-color 0.15s ease; | ||
|
|
||
| &:hover { | ||
| background-color: #e4e4e4; | ||
| border-color: #aaa; | ||
| } | ||
| } | ||
|
|
||
|
SyedIshmumAhnaf marked this conversation as resolved.
|
||
| .cite-modal { | ||
| inset: 50% auto auto 50%; | ||
| width: min(90vw, 640px); | ||
| max-height: min(90vh, 44rem); | ||
| margin: 0; | ||
| padding: 0; | ||
| color: var(--color-text); | ||
| background: transparent; | ||
| border: 0; | ||
| overflow: visible; | ||
| transform: translate(-50%, -50%); | ||
|
|
||
| &::backdrop { | ||
| background: rgba(0, 0, 0, 0.5); | ||
| } | ||
| } | ||
|
|
||
| .cite-modal__box { | ||
| position: relative; | ||
| max-height: min(90vh, 44rem); | ||
| overflow-y: auto; | ||
| background: #fff; | ||
| border: 1px solid var(--borders-color); | ||
| border-radius: 8px; | ||
| padding: 1.5rem; | ||
| box-shadow: 0 4px 24px rgba(0, 0, 0, 0.15); | ||
|
|
||
| h3 { | ||
| margin-top: 0; | ||
| } | ||
| } | ||
|
|
||
| .cite-modal__close { | ||
| position: absolute; | ||
| top: 0.75rem; | ||
| right: 1rem; | ||
| padding: 0; | ||
| color: var(--color-text-light); | ||
| background: transparent; | ||
| border: 0; | ||
| font: inherit; | ||
| font-size: 1.25rem; | ||
| line-height: 1; | ||
| cursor: pointer; | ||
|
|
||
| &:hover { | ||
| color: var(--color-text); | ||
| } | ||
| } | ||
|
|
||
| .cite-formats { | ||
| display: grid; | ||
| gap: 1rem; | ||
| margin-top: 1rem; | ||
| } | ||
|
|
||
| .cite-panel { | ||
| display: grid; | ||
| gap: 0.5rem; | ||
| } | ||
|
|
||
| .cite-panel__heading { | ||
| margin: 0; | ||
| color: var(--color-text); | ||
| font-size: 0.78rem; | ||
| font-weight: 700; | ||
| line-height: 1.3; | ||
| } | ||
|
|
||
| .cite-copy-controls { | ||
| display: none; | ||
| align-items: center; | ||
| gap: 0.5rem; | ||
| flex-wrap: wrap; | ||
| } | ||
|
|
||
| .citation.cite-copy-enabled .cite-copy-controls { | ||
| display: flex; | ||
| } | ||
|
|
||
| .cite-copy-btn { | ||
| font-size: 0.78rem; | ||
| cursor: pointer; | ||
| } | ||
|
|
||
| .cite-copy-status { | ||
| color: var(--color-text-light); | ||
| font-size: 0.78rem; | ||
| min-height: 1em; | ||
| } | ||
|
|
||
| .cite-text { | ||
| font-family: monospace; | ||
| font-size: 0.82rem; | ||
| line-height: 1.5; | ||
| padding: 0.5rem; | ||
| margin: 0; | ||
| border: 1px solid var(--borders-color); | ||
| border-radius: 4px; | ||
| background: #f9f9f9; | ||
| white-space: pre-wrap; | ||
| word-break: break-word; | ||
| color: var(--color-text); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,3 +27,4 @@ | |
| @import '_working-groups'; | ||
| @import '_governing-board'; | ||
| @import '_branding'; | ||
| @import '_citation'; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| /* | ||
| * SPDX-FileCopyrightText: 2026 The Matrix.org Foundation C.I.C. | ||
| * SPDX-FileContributor: Syed Ishmum Ahnaf <syedishmum15@gmail.com> | ||
| * | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| const RESET_DELAY_MS = 2000; | ||
|
|
||
| function resetCopyFeedback(status, timeoutId) { | ||
| status.textContent = ""; | ||
| if (timeoutId !== undefined) { | ||
| window.clearTimeout(timeoutId); | ||
| } | ||
| } | ||
|
|
||
| function scheduleReset(button, status) { | ||
| const existingTimeoutId = button.dataset.resetTimeoutId; | ||
| if (existingTimeoutId !== undefined) { | ||
| window.clearTimeout(Number(existingTimeoutId)); | ||
| } | ||
|
|
||
| const timeoutId = window.setTimeout(() => { | ||
| resetCopyFeedback(status); | ||
| delete button.dataset.resetTimeoutId; | ||
| }, RESET_DELAY_MS); | ||
|
|
||
| button.dataset.resetTimeoutId = String(timeoutId); | ||
| } | ||
|
|
||
| function enableCitationCopy(citation) { | ||
| const buttons = citation.querySelectorAll("[data-cite-copy]"); | ||
|
|
||
| if (buttons.length === 0) { | ||
| return; | ||
| } | ||
|
|
||
| citation.classList.add("cite-copy-enabled"); | ||
|
|
||
| for (const button of buttons) { | ||
| button.addEventListener("click", async () => { | ||
| const panel = button.closest("[data-cite-panel]"); | ||
| const text = panel?.querySelector(".cite-text"); | ||
| const status = panel?.querySelector(".cite-copy-status"); | ||
|
|
||
| if (!text || !status) { | ||
| return; | ||
| } | ||
|
|
||
| try { | ||
| await navigator.clipboard.writeText(text.textContent.trim()); | ||
| status.textContent = "Copied"; | ||
| } catch (error) { | ||
| status.textContent = "Copy failed"; | ||
| } | ||
|
|
||
| scheduleReset(button, status); | ||
| }); | ||
| } | ||
| } | ||
|
|
||
| if (window.isSecureContext && navigator.clipboard?.writeText) { | ||
| for (const citation of document.querySelectorAll(".citation")) { | ||
| enableCitationCopy(citation); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
| @@ -0,0 +1,147 @@ | ||||
| {# citation popup — {% import "macros/citation.html" as citation %} #} | ||||
|
|
||||
| {% macro render(page) %} | ||||
|
|
||||
| {# unique id #} | ||||
| {% set cb_id = "cite-popover-" ~ page.slug %} | ||||
| {% set formats = ["apa", "mla", "chicago", "harvard", "bibtex"] %} | ||||
|
|
||||
| <div class="citation"> | ||||
|
|
||||
| <button type="button" class="cite-btn" popovertarget="{{ cb_id }}"> | ||||
| Cite | ||||
| </button> | ||||
|
|
||||
| <div id="{{ cb_id }}" class="cite-modal" popover role="dialog" aria-labelledby="{{ cb_id }}-title"> | ||||
| <div class="cite-modal__box"> | ||||
|
|
||||
| <button | ||||
| type="button" | ||||
| class="cite-modal__close" | ||||
| popovertarget="{{ cb_id }}" | ||||
| popovertargetaction="hide" | ||||
| aria-label="Close citation dialog" | ||||
| > | ||||
| × | ||||
| </button> | ||||
|
|
||||
| <h3 id="{{ cb_id }}-title">Cite this post</h3> | ||||
|
|
||||
| <div class="cite-formats"> | ||||
|
|
||||
| {% for fmt in formats %} | ||||
| <div class="cite-panel cite-panel--{{ fmt }}" data-cite-panel="{{ fmt }}"> | ||||
| <h4 class="cite-panel__heading">{{ fmt | upper }}</h4> | ||||
| <pre class="cite-text"> | ||||
| {%- if fmt == "apa" -%} | ||||
| {{ self::cite_apa(page=page) }} | ||||
| {%- elif fmt == "mla" -%} | ||||
| {{ self::cite_mla(page=page) }} | ||||
| {%- elif fmt == "chicago" -%} | ||||
| {{ self::cite_chicago(page=page) }} | ||||
| {%- elif fmt == "harvard" -%} | ||||
| {{ self::cite_harvard(page=page) }} | ||||
| {%- elif fmt == "bibtex" -%} | ||||
| {{ self::cite_bibtex(page=page) }} | ||||
| {%- endif -%} | ||||
| </pre> | ||||
|
|
||||
| <div class="cite-copy-controls"> | ||||
| <button type="button" class="call-to-action cite-copy-btn" data-cite-copy>Copy</button> | ||||
| <span class="cite-copy-status" role="status" aria-live="polite"></span> | ||||
| </div> | ||||
| </div> | ||||
| {% endfor %} | ||||
|
|
||||
| </div> | ||||
|
|
||||
| </div> | ||||
| </div> | ||||
|
|
||||
| </div> | ||||
|
|
||||
| {% endmacro render %} | ||||
|
|
||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||
|
|
||||
| {% macro cite_apa(page) %} | ||||
| {%- if page.taxonomies.author is defined and page.taxonomies.author | length > 0 -%} | ||||
| {%- set authors = page.taxonomies.author | join(sep=", ") -%} | ||||
| {%- else -%} | ||||
| {%- set authors = "Matrix.org" -%} | ||||
| {%- endif -%} | ||||
| {%- if page.date -%} | ||||
| {%- set year = page.date | date(format="%Y") -%} | ||||
| {%- else -%} | ||||
| {%- set year = "n.d." -%} | ||||
| {%- endif -%} | ||||
| {{ authors }}. ({{ year }}). {{ page.title }}. Matrix.org. {{ page.permalink }} | ||||
| {%- endmacro cite_apa %} | ||||
|
|
||||
|
|
||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||
| {% macro cite_mla(page) %} | ||||
| {%- if page.taxonomies.author is defined and page.taxonomies.author | length > 0 -%} | ||||
| {%- set authors = page.taxonomies.author | join(sep=", ") -%} | ||||
| {%- else -%} | ||||
| {%- set authors = "Matrix.org" -%} | ||||
| {%- endif -%} | ||||
| {%- if page.date -%} | ||||
| {%- set date_fmt = page.date | date(format="%d %b. %Y") -%} | ||||
| {%- else -%} | ||||
| {%- set date_fmt = "n.d." -%} | ||||
| {%- endif -%} | ||||
| {{ authors }}. "{{ page.title }}." Matrix.org, {{ date_fmt }}, {{ page.permalink }}. | ||||
| {%- endmacro cite_mla %} | ||||
|
|
||||
|
|
||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||
| {% macro cite_chicago(page) %} | ||||
| {%- if page.taxonomies.author is defined and page.taxonomies.author | length > 0 -%} | ||||
| {%- set authors = page.taxonomies.author | join(sep=", ") -%} | ||||
| {%- else -%} | ||||
| {%- set authors = "Matrix.org" -%} | ||||
| {%- endif -%} | ||||
| {%- if page.date -%} | ||||
| {%- set date_fmt = page.date | date(format="%B %d, %Y") -%} | ||||
| {%- else -%} | ||||
| {%- set date_fmt = "n.d." -%} | ||||
| {%- endif -%} | ||||
| {{ authors }}. "{{ page.title }}." Matrix.org. {{ date_fmt }}. {{ page.permalink }}. | ||||
| {%- endmacro cite_chicago %} | ||||
|
|
||||
|
|
||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||
| {% macro cite_harvard(page) %} | ||||
| {%- if page.taxonomies.author is defined and page.taxonomies.author | length > 0 -%} | ||||
| {%- set authors = page.taxonomies.author | join(sep=", ") -%} | ||||
| {%- else -%} | ||||
| {%- set authors = "Matrix.org" -%} | ||||
| {%- endif -%} | ||||
| {%- if page.date -%} | ||||
| {%- set year = page.date | date(format="%Y") -%} | ||||
| {%- set date_fmt = page.date | date(format="%d %B %Y") -%} | ||||
| {%- else -%} | ||||
| {%- set year = "n.d." -%} | ||||
| {%- set date_fmt = "n.d." -%} | ||||
| {%- endif -%} | ||||
| {{ authors }} ({{ year }}) '{{ page.title }}', Matrix.org, viewed {{ date_fmt }}, <{{ page.permalink }}>. | ||||
| {%- endmacro cite_harvard %} | ||||
|
|
||||
|
|
||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||
| {% macro cite_bibtex(page) %} | ||||
| {%- if page.taxonomies.author is defined and page.taxonomies.author | length > 0 -%} | ||||
| {%- set authors = page.taxonomies.author | join(sep=" and ") -%} | ||||
| {%- else -%} | ||||
| {%- set authors = "Matrix.org" -%} | ||||
| {%- endif -%} | ||||
| {%- if page.date -%} | ||||
| {%- set year = page.date | date(format="%Y") -%} | ||||
| {%- else -%} | ||||
| {%- set year = "n.d." -%} | ||||
| {%- endif -%} | ||||
| {%- set slug = page.slug -%} | ||||
| @misc{ {{ authors | lower | replace(from=" ", to="") }}{{ year }}, | ||||
| author = { {{ authors }} }, | ||||
| title = { {{ page.title }} }, | ||||
| year = { {{ year }} }, | ||||
| url = { {{ page.permalink }} }, | ||||
| note = {Matrix.org} | ||||
| } | ||||
| {%- endmacro cite_bibtex %} | ||||
Uh oh!
There was an error while loading. Please reload this page.