import React, { useEffect, useId, useState } from "react"; import classNames from "classnames"; import { ArcIconSocialLinkedin } from "@arc-ui/icons/ArcIconSocialLinkedin"; import { ArcIconSocialX } from "@arc-ui/icons/ArcIconSocialX"; import { BtIconLink } from "@arc-ui/icons/BtIconLink"; import { BtIconEmailUnread } from "@arc-ui/icons/BtIconEmailUnread"; import { Heading } from "@arc-ui/components/Heading"; import { Icon } from "@arc-ui/components/Icon"; import { Text } from "@arc-ui/components/Text"; import { Rule } from "@arc-ui/components/Rule"; import { Link } from "@arc-ui/components/Link"; import { Tag } from "@arc-ui/components/Tag"; import { Toast, ToastNotification } from "@arc-ui/components/Toast"; import { VerticalSpace } from "@arc-ui/components/VerticalSpace"; import { Author } from "../Author"; import { type TextSection } from "./types/text-section"; import { type LinkSection } from "./types/link-section"; import { type Topic } from "./types/topic"; import { type Share } from "./types/share"; import { type ShareButton } from "./types/share-button"; import { type SidebarAuthor } from "./types/sidebar-author"; import { filterAttrs } from "@arc-ui/community-utils/filter-attrs"; import styles from "./ArticleSidebar.module.css"; /** * Use `ArticleSidebar` to provide additional information about the article. */ export const ArticleSidebar: React.FC = ({ author, aboutSection, topics, share, additionalContent, linkSection, url: providedUrl, ...props }) => { const id = useId(); const [showToast, setShowToast] = useState(false); const [clientUrl, setClientUrl] = useState(""); useEffect(() => { if (!providedUrl) setClientUrl(window.location.href); }, [providedUrl]); const url = providedUrl ?? clientUrl; const copyTextToClipBoard = async () => { await navigator.clipboard.writeText(url); setShowToast(true); }; const shareButtons: ShareButton[] = share ? [ { isButton: true, onClick: copyTextToClipBoard, icon: BtIconLink, ariaLabel: share.clipboardAriaLabel || "Copy url to clipboard", }, { href: `mailto:?subject=${encodeURIComponent(share.articleTitle)}&body=${encodeURIComponent(url)}`, icon: BtIconEmailUnread, ariaLabel: share.emailAriaLabel || "Share by email", }, ...(share.linkedin ? [ { href: `https://www.linkedin.com/sharing/share-offsite/?url=${encodeURIComponent(url)}`, icon: ArcIconSocialLinkedin, ariaLabel: share.linkedInAriaLabel || "Share on LinkedIn", }, ] : []), ...(share.x ? [ { href: `https://twitter.com/intent/tweet?url=${encodeURIComponent(url)}`, icon: ArcIconSocialX, ariaLabel: share.xAriaLabel || "Share on x", }, ] : []), ] : []; const hasTopContent = Boolean(author || aboutSection || additionalContent); const showShare = share && url; const hasBottomContent = Boolean(linkSection || topics || showShare); return (
{author && ( <> )} {aboutSection && ( <> {author && } {aboutSection.heading} {aboutSection.content} )} {additionalContent && ( <> {(author || aboutSection) && }
{additionalContent.map(({ heading, headingLevel, content }) => (
{heading} {content}
))}
)}
{hasTopContent && hasBottomContent && (
)} {linkSection && ( <> {linkSection.heading} {linkSection.links.map(({ text, url, ariaLabel }) => (
{text}
))} )} {topics && ( <> {linkSection && } {topics.heading}
{topics.tags.map((tag) => ( ))}
)} {showShare && ( <> {(linkSection || topics) && (
)} {share.heading}
{shareButtons.map( ({ isButton, ariaLabel, href, icon, onClick }) => ( ), )}
)} setShowToast(false)} />
); }; export interface ArticleSidebarProps { /** * Props for Author component. */ author?: SidebarAuthor; /** * Content for the about section. */ aboutSection?: TextSection; /** * Array of headings and text for additional text sections. */ additionalContent?: TextSection[]; /** * Links that are relevant to the article. */ linkSection?: LinkSection; /** * Topics rendered as tags that are relevant to the article. */ topics?: Topic; /** * Sharing options for the article. */ share?: Share; /** * The article URL used by the share buttons. * If it is not provided, the component uses the current browser URL. */ url?: string; }