Skip to content
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

KBHBIB-24 Share buttons on material #1587

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
4 changes: 4 additions & 0 deletions src/apps/material/material.entry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,10 @@ interface MaterialEntryTextProps {
shiftText: string;
subjectNumberText: string;
tryAginButtonText: string;
shareOnFacebookText: string;
shareOnFacebookAriaLabelText: string;
copyLinkText: string;
copyLinkAriaLabelText: string;
}

interface MaterialEntryConfigProps {
Expand Down
22 changes: 21 additions & 1 deletion src/apps/material/material.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,22 @@ const meta: Meta<typeof MaterialEntry> = {
openOrderErrorMissingPincodeText: {
description: "Open order error missing pincode text",
control: { type: "text" }
},
shareOnFacebookText: {
description: "Share on Facebook",
control: { type: "text" }
},
shareOnFacebookAriaLabelText: {
description: "Share this page on Facebook",
control: { type: "text" }
},
copyLinkText: {
description: "Copy link",
control: { type: "text" }
},
copyLinkAriaLabelText: {
description: "Copy this page URL to clipboard",
control: { type: "text" }
}
},
args: {
Expand Down Expand Up @@ -901,7 +917,11 @@ const meta: Meta<typeof MaterialEntry> = {
openOrderUnknownErrorText: "An unknown error occurred",
openOrderUnknownPickupagencyText: "Specified pickup agency not found",
openOrderUnknownUserText: "User not found",
openOrderErrorMissingPincodeText: "Missing pincode"
openOrderErrorMissingPincodeText: "Missing pincode",
shareOnFacebookText: "Share on Facebook",
shareOnFacebookAriaLabelText: "Share this page on Facebook",
copyLinkText: "Copy link",
copyLinkAriaLabelText: "Copy this page URL to clipboard"
}
};

Expand Down
101 changes: 101 additions & 0 deletions src/components/button-share/button-share.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import React, { useEffect, useRef, useState } from "react";
import clsx from "clsx";
import FacebookIcon from "./facebook-icon";
import LinkIcon from "./link-icon";
import { useText } from "../../core/utils/text";

type ButtonShareProps = {
className?: string;
};

const ButtonShare: React.FC<ButtonShareProps> = ({ className }) => {
const t = useText();
const { href } = window.location;
const facebookShareUrl = "https://www.facebook.com/sharer/sharer.php";
const shareUrl = `${facebookShareUrl}?u=${href}`;

const shareButtonAreaLabel = t("shareOnFacebookAriaLabelText");
const copyButtonAreaLabel = t("copyLinkAriaLabelText");

const [showFixedButtons, setShowFixedButtons] = useState(true);
const shareButtonRef = useRef<HTMLAnchorElement>(null);

const onShareButtonClick = () => {
navigator.clipboard.writeText(href);
};

// Hide fixed buttons when share button is in view or above viewport
useEffect(() => {
const shareButton = shareButtonRef.current;
const observer = new IntersectionObserver(
(entries) => {
const isIntersecting = entries.some((entry) => entry.isIntersecting);
const isAboveViewport = entries.some((entry) => {
// return true if the share button is above the viewport
return entry.boundingClientRect.top < 0;
});
setShowFixedButtons(!isIntersecting && !isAboveViewport);
},
{ threshold: 1 }
);

if (shareButton) {
observer.observe(shareButton);

return () => {
// Clean up observer on unmount
observer.disconnect();
};
}

return () => {};
}, []);

return (
<div className={clsx("button-share", className)}>
{showFixedButtons && (
<div className="button-share button-share--fixed">
<a
href={shareUrl}
JacobArrow marked this conversation as resolved.
Show resolved Hide resolved
target="_blank"
rel="noreferrer"
aria-label={shareButtonAreaLabel}
className="button-share__button button-share__button--fixed"
>
<FacebookIcon />
</a>
<button
type="button"
onClick={onShareButtonClick}
aria-label={copyButtonAreaLabel}
className="button-share__button button-share__button--fixed"
>
<LinkIcon />
</button>
</div>
)}
<a
ref={shareButtonRef}
href={shareUrl}
target="_blank"
rel="noreferrer"
aria-label={shareButtonAreaLabel}
className="button-share__button"
>
<FacebookIcon />
{t("shareOnFacebookText")}
</a>
<button
type="button"
onClick={onShareButtonClick}
aria-label={copyButtonAreaLabel}
className="button-share__button"
>
<LinkIcon />
{t("copyLinkText")}
</button>
</div>
);
};

export default ButtonShare;
22 changes: 22 additions & 0 deletions src/components/button-share/facebook-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from "react";
JacobArrow marked this conversation as resolved.
Show resolved Hide resolved

const FacebookIcon = () => {
return (
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g clipPath="url(#clip0)">
<path
d="M9.9375 9.25H7.875V12H9.9375V20.25H13.375V12H15.8789L16.125 9.25H13.375V8.10394C13.375 7.44738 13.507 7.1875 14.1416 7.1875H16.125V3.75H13.507C11.0348 3.75 9.9375 4.83831 9.9375 6.92281V9.25Z"
fill="currentColor"
/>
</g>
</svg>
);
};

export default FacebookIcon;
23 changes: 23 additions & 0 deletions src/components/button-share/link-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from "react";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Icons should live in the design system and be used like this:
import ExpandMoreIcon from "@danskernesdigitalebibliotek/dpl-design-system/build/icons/collection/ExpandMore.svg";

Copy link
Contributor Author

@JacobArrow JacobArrow Dec 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would you go around rendering an SVG without an img tag this way?


const LinkIcon = () => {
return (
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M10.0002 13C10.4297 13.5742 10.9776 14.0492 11.6067 14.393C12.2359 14.7367 12.9317 14.9411 13.6468 14.9924C14.362 15.0436 15.0798 14.9404 15.7515 14.6898C16.4233 14.4392 17.0333 14.0471 17.5402 13.54L20.5402 10.54C21.451 9.59702 21.955 8.334 21.9436 7.02302C21.9322 5.71204 21.4063 4.45797 20.4793 3.53093C19.5523 2.60389 18.2982 2.07805 16.9872 2.06666C15.6762 2.05526 14.4132 2.55924 13.4702 3.47003L11.7502 5.18003M14.0002 11C13.5707 10.4259 13.0228 9.95084 12.3936 9.60709C11.7645 9.26333 11.0687 9.05891 10.3535 9.00769C9.63841 8.95648 8.92061 9.05966 8.24885 9.31025C7.5771 9.56083 6.96709 9.95296 6.4602 10.46L3.4602 13.46C2.54941 14.403 2.04544 15.666 2.05683 16.977C2.06822 18.288 2.59407 19.5421 3.52111 20.4691C4.44815 21.3962 5.70221 21.922 7.01319 21.9334C8.32418 21.9448 9.58719 21.4408 10.5302 20.53L12.2402 18.82"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
};

export default LinkIcon;
2 changes: 2 additions & 0 deletions src/components/material/MaterialDescription.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { useUrls } from "../../core/utils/url";
import HorizontalTermLine from "../horizontal-term-line/HorizontalTermLine";
import { materialIsFiction } from "../../core/utils/helpers/general";
import SeriesList from "../card-item-list/card-list-item/series-list";
import ButtonShare from "../button-share/button-share";

export interface MaterialDescriptionProps {
pid: Pid;
Expand Down Expand Up @@ -120,6 +121,7 @@ const MaterialDescription: React.FC<MaterialDescriptionProps> = ({ work }) => {
dataCy="material-description-film-adaptations"
/>
</div>
<ButtonShare className="mt-64" />
</>
)}
</section>
Expand Down
Loading