diff --git a/apps/compliance-portal/src/pages/documents/_components/DocumentEntry.tsx b/apps/compliance-portal/src/pages/documents/_components/DocumentEntry.tsx index 7f69d0cff..0fa6a01d1 100644 --- a/apps/compliance-portal/src/pages/documents/_components/DocumentEntry.tsx +++ b/apps/compliance-portal/src/pages/documents/_components/DocumentEntry.tsx @@ -18,7 +18,10 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +import { Toast } from "@base-ui/react/toast"; +import { LinkSimpleIcon } from "@phosphor-icons/react"; import { Checkbox } from "@probo/ui/src/v2/Checkbox/Checkbox"; +import { IconButton } from "@probo/ui/src/v2/IconButton/IconButton"; import { ListItem } from "@probo/ui/src/v2/List/ListItem"; import { ListItemContent } from "@probo/ui/src/v2/List/ListItemContent"; import { Text } from "@probo/ui/src/v2/typography/Text"; @@ -27,6 +30,7 @@ import { useTranslation } from "react-i18next"; import { Link as RouterLink } from "react-router"; import { DocumentAccessAction } from "./DocumentAccessAction"; +import { documentEntry } from "./variants"; interface DocumentEntryProps { // Primary line (document title, file name, or framework name). @@ -51,8 +55,9 @@ interface DocumentEntryProps { } // Presentational row shared by the document / file / report list items: a title -// with accent metadata and the trailing access action. On small screens the -// whole row is the hit target (the trailing icon is a status affordance only). +// with accent metadata, a copy-link control, and the trailing access action. On +// small screens the whole row is the hit target (the trailing icon is a status +// affordance only). export function DocumentEntry({ title, meta, @@ -65,6 +70,8 @@ export function DocumentEntry({ onSelectedChange, }: DocumentEntryProps) { const { t } = useTranslation("documents"); + const toast = Toast.useToastManager(); + const slots = documentEntry(); // Only locked rows (not yet authorized, no pending request) can be requested, // so only they are selectable — the checkbox is disabled otherwise to avoid a @@ -77,6 +84,14 @@ export function DocumentEntry({ ? t("actions.view") : t("actions.getAccess"); + const handleCopyLink = () => { + const url = new URL(viewHref, window.location.origin); + navigator.clipboard.writeText(url.href).then( + () => toast.add({ title: t("viewer.linkCopied"), type: "success" }), + () => {}, + ); + }; + return ( - {/* Desktop: labeled interactive control. */} -
- -
+
+ + + - {/* Mobile: status icon only; the row overlay handles activation. - Pending (`requested`) rows keep the icon in the a11y tree as status. */} -
- + {/* Desktop: labeled interactive control. */} +
+ +
+ + {/* Mobile: status icon only; the row overlay handles activation. + Pending (`requested`) rows keep the icon in the a11y tree as status. */} +
+ +
{/* Sit above the row content so title / icon areas are part of the hit target. */} diff --git a/apps/compliance-portal/src/pages/documents/_components/DocumentViewer.tsx b/apps/compliance-portal/src/pages/documents/_components/DocumentViewer.tsx index 73bb3145d..3eb59ec32 100644 --- a/apps/compliance-portal/src/pages/documents/_components/DocumentViewer.tsx +++ b/apps/compliance-portal/src/pages/documents/_components/DocumentViewer.tsx @@ -23,9 +23,9 @@ import { CaretLeftIcon, CaretRightIcon, DownloadSimpleIcon, + LinkSimpleIcon, MagnifyingGlassMinusIcon, MagnifyingGlassPlusIcon, - ShareNetworkIcon, SpinnerGapIcon, } from "@phosphor-icons/react"; import { Button } from "@probo/ui/src/v2/Button/Button"; @@ -64,8 +64,8 @@ interface DocumentViewerProps { } // Full-page document viewer: a header band with the title and a toolbar -// (page navigation + zoom for PDFs, share, download) above the scrollable body. -// PDFs render with react-pdf, images inline, and anything else offers a +// (page navigation + zoom for PDFs, copy link, download) above the scrollable +// body. PDFs render with react-pdf, images inline, and anything else offers a // download. export function DocumentViewer({ title, dataUri, downloadName }: DocumentViewerProps) { const { t } = useTranslation("documents"); @@ -87,7 +87,7 @@ export function DocumentViewer({ title, dataUri, downloadName }: DocumentViewerP setCurrentPage(next); }; - const handleShare = () => { + const handleCopyLink = () => { navigator.clipboard.writeText(window.location.href).then( () => toast.add({ title: t("viewer.linkCopied"), type: "success" }), () => {}, @@ -168,11 +168,11 @@ export function DocumentViewer({ title, dataUri, downloadName }: DocumentViewerP