Skip to content

Commit e369a78

Browse files
Add page-level share button with referral ID (#1050)
Section anchor links already append `?rid=<referralId>` when copied, but there was no way to share the page URL itself with a referral ID attached. ## Changes - **`useSiteShell.js`** - Extracted `addReferralIdToUrl(url)` helper — eliminates duplicated referral ID injection logic - Extracted `writeToClipboard(url, successMessage?)` helper — shared by both copy functions - Added `shareCurrentPage()` — copies current page URL (no hash) with referral ID as `?rid=...` if available; exposed in composable return - **`PageNavigation.vue`** - Added a centered `fa-solid fa-share-from-square` button between prev/next arrows - Rendered only on content pages (`v-if="shell.isContentPage"`) - Calls `shareCurrentPage()` on click with a "Share Page" tooltip - **`styles.css`** - Added `.tooltip-center` for the share button tooltip positioning - Added `border`/`padding` reset for `<button>.arrow-btn` to match `<a>` sibling appearance --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: BenjaminMichaelis <22186029+BenjaminMichaelis@users.noreply.github.com>
1 parent 2eaf7db commit e369a78

3 files changed

Lines changed: 56 additions & 19 deletions

File tree

EssentialCSharp.Web/src/components/PageNavigation.vue

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@ const shell = inject("shell");
1616
( or use the <i class="fa-solid fa-square-caret-left" /> key)
1717
</span>
1818
</div>
19+
<div v-if="shell.isContentPage" class="turn-page-tooltip">
20+
<button id="share-btn" type="button" class="arrow-btn" aria-label="Share this page" @click="shell.shareCurrentPage()">
21+
<i class="fa-solid fa-share-from-square arrow-icon" />
22+
</button>
23+
<span class="turn-page-tooltip-text tooltip-center">
24+
<b>Share Page</b>
25+
<br />
26+
Copies a link to this page
27+
</span>
28+
</div>
1929
<div class="turn-page-tooltip">
2030
<a v-if="shell.nextPageUrl" id="next-btn" :href="shell.nextPageUrl" class="arrow-btn">
2131
<i class="fa fa-solid fa-arrow-right icon-light arrow-icon" />

EssentialCSharp.Web/src/composables/useSiteShell.js

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -89,44 +89,59 @@ export function useSiteShell() {
8989
return urlObject.toString();
9090
}
9191

92-
function copyToClipboard(copyText) {
93-
let url;
94-
95-
if (copyText.includes("#")) {
96-
url = `${window.location.origin}/${copyText}`;
97-
}
98-
else {
99-
const currentUrl = window.location.href.split("#")[0];
100-
url = `${currentUrl}#${copyText}`;
101-
}
102-
92+
function addReferralIdToUrl(url) {
10393
const referralId = window.REFERRAL_ID;
10494
if (typeof referralId === "string" && referralId.trim().length > 0) {
105-
url = addQueryParam(url, "rid", referralId);
95+
return addQueryParam(url, "rid", referralId);
10696
}
97+
return url;
98+
}
10799

100+
function writeToClipboard(url, successMessage = "Copied to clipboard!") {
108101
navigator.clipboard
109102
.writeText(url)
110103
.then(
111104
() => {
112105
snackbarColor.value = "white";
113-
snackbarMessage.value = "Copied url to clipboard!";
106+
snackbarMessage.value = successMessage;
107+
if (snackbarTimeoutId !== null) {
108+
clearTimeout(snackbarTimeoutId);
109+
}
110+
snackbarTimeoutId = setTimeout(() => {
111+
snackbarMessage.value = null;
112+
}, 3000);
114113
},
115114
(error) => {
116115
console.error("Could not copy text to clipboard: ", error);
117116
snackbarColor.value = "red";
118117
snackbarMessage.value = `Error: Could not copy text to clipboard: ${error}`;
118+
if (snackbarTimeoutId !== null) {
119+
clearTimeout(snackbarTimeoutId);
120+
}
121+
snackbarTimeoutId = setTimeout(() => {
122+
snackbarMessage.value = null;
123+
}, 3000);
119124
}
120125
);
126+
}
121127

122-
if (snackbarTimeoutId !== null) {
123-
clearTimeout(snackbarTimeoutId);
124-
snackbarMessage.value = null;
128+
function copyToClipboard(copyText) {
129+
let url;
130+
131+
if (copyText.includes("#")) {
132+
url = `${window.location.origin}/${copyText}`;
125133
}
134+
else {
135+
const currentUrl = window.location.href.split("#")[0];
136+
url = `${currentUrl}#${copyText}`;
137+
}
138+
139+
writeToClipboard(addReferralIdToUrl(url), "Copied url to clipboard!");
140+
}
126141

127-
snackbarTimeoutId = setTimeout(() => {
128-
snackbarMessage.value = null;
129-
}, 3000);
142+
function shareCurrentPage() {
143+
const url = window.location.href.split("#")[0];
144+
writeToClipboard(addReferralIdToUrl(url), "Copied page url to clipboard!");
130145
}
131146

132147
function goToPrevious() {
@@ -276,6 +291,7 @@ export function useSiteShell() {
276291
isContentPage,
277292
filteredTocData,
278293
copyToClipboard,
294+
shareCurrentPage,
279295
goToPrevious,
280296
goToNext,
281297
openSearch,

EssentialCSharp.Web/wwwroot/css/styles.css

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,17 @@ a:hover {
437437
right: 3rem;
438438
}
439439

440+
.turn-page-tooltip .tooltip-center {
441+
left: 50%;
442+
transform: translateX(-50%);
443+
}
444+
445+
/* Share button reset */
446+
.turn-page button.arrow-btn {
447+
border: none;
448+
padding: 0;
449+
}
450+
440451
/* Chapter Navigation Sidebar Styles */
441452

442453
.sidebar {

0 commit comments

Comments
 (0)