From 8927e7345f8a06ca59323b620ce3cf87e51fbacf Mon Sep 17 00:00:00 2001 From: Mat Jordan Date: Tue, 5 Nov 2024 09:33:31 -0500 Subject: [PATCH] Add common IIIF share component. --- components/Clover/ViewerWrapper.styled.ts | 10 + components/Clover/ViewerWrapper.tsx | 39 ++-- components/Figure/Figure.styled.ts | 1 + components/Heading/Heading.styled.ts | 3 +- components/Hero/Hero.styled.ts | 4 +- components/Hero/Hero.tsx | 2 +- components/Homepage/Collections.styled.ts | 3 - components/Homepage/Overview.styled.ts | 10 +- components/Search/Results.tsx | 11 +- components/Search/Search.styled.ts | 10 +- components/Shared/CopyText.styled.ts | 17 +- components/Shared/DefinitionList.styled.ts | 6 +- components/Shared/IIIF/Share.tsx | 196 ++++++++++++++++++ components/Shared/Icon.tsx | 31 ++- components/Shared/SVG/Icons.tsx | 8 + .../DownloadAndShare/IIIFManifest.tsx | 23 +- components/Work/TopInfo.styled.ts | 17 +- components/Work/TopInfo.tsx | 19 +- hooks/useCopyToClipboard.ts | 24 ++- lib/dc-api.ts | 27 +++ pages/collections/[id].tsx | 22 ++ 21 files changed, 399 insertions(+), 84 deletions(-) create mode 100644 components/Shared/IIIF/Share.tsx diff --git a/components/Clover/ViewerWrapper.styled.ts b/components/Clover/ViewerWrapper.styled.ts index 2d580346..f1d1c560 100644 --- a/components/Clover/ViewerWrapper.styled.ts +++ b/components/Clover/ViewerWrapper.styled.ts @@ -10,6 +10,16 @@ const ViewerWrapperStyled = styled("section", { background: "#f0f0f0", }, + ".clover-viewer-header": { + display: "none", + }, + + ".clover-viewer-media-wrapper": { + "div[role='radiogroup']": { + paddingBottom: "0", + }, + }, + "& label[for='information-toggle']": { boxShadow: "none", }, diff --git a/components/Clover/ViewerWrapper.tsx b/components/Clover/ViewerWrapper.tsx index 24076213..4a6cf573 100644 --- a/components/Clover/ViewerWrapper.tsx +++ b/components/Clover/ViewerWrapper.tsx @@ -8,6 +8,7 @@ import type { } from "@samvera/clover-iiif"; import Announcement from "@/components/Shared/Announcement"; +import Container from "../Shared/Container"; import { IconInfo } from "@/components/Shared/SVG/Icons"; import React from "react"; import { UserContext } from "@/context/user-context"; @@ -76,24 +77,26 @@ const WorkViewerWrapper: React.FC = ({ }; return ( - - {manifestId && ( - - )} - {isWorkRestricted && userAuth?.user?.isReadingRoom && ( - - - -

You have access to Work because you are in the reading room

-
-
- )} -
+ + + {manifestId && ( + + )} + {isWorkRestricted && userAuth?.user?.isReadingRoom && ( + + + +

You have access to Work because you are in the reading room

+
+
+ )} +
+
); }; diff --git a/components/Figure/Figure.styled.ts b/components/Figure/Figure.styled.ts index 1d2e8c54..7c11f9fd 100644 --- a/components/Figure/Figure.styled.ts +++ b/components/Figure/Figure.styled.ts @@ -93,6 +93,7 @@ const FigureTitle = styled("span", { color: "$purple", display: "flex", alignItems: "flex-start", + lineHeight: "1.25em", }); const FigureText = styled("div", { diff --git a/components/Heading/Heading.styled.ts b/components/Heading/Heading.styled.ts index 2cac8d43..123e4b7c 100644 --- a/components/Heading/Heading.styled.ts +++ b/components/Heading/Heading.styled.ts @@ -35,9 +35,10 @@ const StyledHeading = styled("h2", { }, "&[data-level=h2]": { - color: "$purple", fontFamily: "$northwesternDisplayBold", + color: "$black80", fontSize: "$gr7", + letterSpacing: "-0.015em", fontWeight: "400", marginBottom: "$gr5", }, diff --git a/components/Hero/Hero.styled.ts b/components/Hero/Hero.styled.ts index 4eb41ff1..fc3f454f 100644 --- a/components/Hero/Hero.styled.ts +++ b/components/Hero/Hero.styled.ts @@ -37,6 +37,7 @@ const HeroStyled = styled("div", { width: "100%", height: "100%", position: "relative", + zIndex: "1", ".swiper-wrapper": { "&::before": { @@ -135,10 +136,11 @@ const HeroStyled = styled("div", { ".slide-label": { fontFamily: "$northwesternDisplayBold", - fontSize: "$gr8", + fontSize: "$gr7", display: "block", margin: "0 0 $gr2", lineHeight: "1em", + letterSpacing: "-0.015em", "@sm": { fontSize: "$gr7", diff --git a/components/Hero/Hero.tsx b/components/Hero/Hero.tsx index a1bacaea..029bad32 100644 --- a/components/Hero/Hero.tsx +++ b/components/Hero/Hero.tsx @@ -30,7 +30,7 @@ const Hero: React.FC = ({ collection }) => { clickable: true, }} slidesPerView={1} - speed={1000} + speed={300} > {collection.items.map((item) => ( diff --git a/components/Homepage/Collections.styled.ts b/components/Homepage/Collections.styled.ts index f82e32bf..c60e9229 100644 --- a/components/Homepage/Collections.styled.ts +++ b/components/Homepage/Collections.styled.ts @@ -4,9 +4,6 @@ import { FigureTitle } from "@/components/Figure/Figure.styled"; import { styled } from "@/stitches.config"; const HomepageCollectionsStyled = styled("section", { - backgroundColor: "$purple10", - padding: "$gr5 0", - [`${FigureTitle}`]: { lineHeight: "1.25em", fontSize: "$gr4", diff --git a/components/Homepage/Overview.styled.ts b/components/Homepage/Overview.styled.ts index 02d0e450..a635d4f0 100644 --- a/components/Homepage/Overview.styled.ts +++ b/components/Homepage/Overview.styled.ts @@ -12,19 +12,21 @@ const Content = styled("div", { }, h2: { - fontFamily: "$northwesternDisplayBold", - margin: "0 0 $gr2", + fontFamily: "$northwesternDisplayBook", + margin: "0 0 $gr3", fontSize: "$gr6", fontWeight: "400", lineHeight: "1.15", + letterSpacing: "-0.015em", }, p: { - fontFamily: "$northwesternSansLight", - fontSize: "$4", + fontFamily: "$northwesternSansRegular", + fontSize: "$gr4", lineHeight: "1.55em", margin: "0 0 $gr4", padding: "0", + color: "$black50", }, }); diff --git a/components/Search/Results.tsx b/components/Search/Results.tsx index f3753075..a8763326 100644 --- a/components/Search/Results.tsx +++ b/components/Search/Results.tsx @@ -2,9 +2,11 @@ import { NoResultsMessage, ResultsMessage, ResultsWrapper, + ResultsWrapperHeader, } from "@/components/Search/Search.styled"; import Grid from "@/components/Grid/Grid"; +import IIIFShare from "../Shared/IIIF/Share"; import PaginationAltCounts from "@/components/Search/PaginationAltCounts"; import { SearchResultsState } from "@/types/components/search"; import { pluralize } from "@/lib/utils/count-helpers"; @@ -27,9 +29,12 @@ const SearchResults: React.FC = ({ <> {!isAI && (totalResults ? ( - - {pluralize("result", totalResults)} - + + + {pluralize("result", totalResults)} + + + ) : ( Your search did not match any results. Please diff --git a/components/Search/Search.styled.ts b/components/Search/Search.styled.ts index 113bbd14..12187f81 100644 --- a/components/Search/Search.styled.ts +++ b/components/Search/Search.styled.ts @@ -87,7 +87,6 @@ const Button = styled("button", { const ResultsMessage = styled("span", { color: "$black50", - padding: "0 $gr4 $gr4", fontSize: "$gr3", "@lg": { @@ -126,6 +125,14 @@ const ResultsWrapper = styled("div", { minHeight: "80vh", }); +const ResultsWrapperHeader = styled("header", { + display: "flex", + flexDirection: "row", + justifyContent: "space-between", + alignItems: "center", + padding: "0 $gr4 $gr4", +}); + const StyledResponseWrapper = styled("div", { padding: "0 0 $gr6", }); @@ -135,6 +142,7 @@ export { NoResultsMessage, ResultsMessage, ResultsWrapper, + ResultsWrapperHeader, SearchStyled, StyledResponseWrapper, }; diff --git a/components/Shared/CopyText.styled.ts b/components/Shared/CopyText.styled.ts index d4aee8aa..64237fca 100644 --- a/components/Shared/CopyText.styled.ts +++ b/components/Shared/CopyText.styled.ts @@ -6,13 +6,12 @@ const StyledStatus = styled("span", { display: "flex", alignContent: "center", alignItems: "center", - padding: "0 $gr1", - marginLeft: "$gr1", - backgroundColor: "$darkBlueA", - color: "$white", + color: "$darkBlueA", borderRadius: "3px", fontSize: "$gr1", textTransform: "uppercase", + position: "absolute", + right: "-1.25em", }); const StyledCopyText = styled("button", { @@ -26,15 +25,17 @@ const StyledCopyText = styled("button", { fontFamily: "$northwesternSans", fontSize: "$gr3", whiteSpace: "nowrap", + textDecoration: "underline", + textDecorationThickness: "min(2px,max(1px,.05em))", + textUnderlineOffset: "calc(.05em + 2px)", + textDecorationColor: "$purple10", + position: "relative", + zIndex: "0", svg: { height: "calc($gr3 - 3px)", marginRight: "$gr1", }, - - "&:hover": { - textDecoration: "underline", - }, }); export { StyledCopyText, StyledStatus }; diff --git a/components/Shared/DefinitionList.styled.ts b/components/Shared/DefinitionList.styled.ts index 808b8923..0dfa6b36 100644 --- a/components/Shared/DefinitionList.styled.ts +++ b/components/Shared/DefinitionList.styled.ts @@ -4,15 +4,15 @@ import { styled } from "@/stitches.config"; const DefinitionListWrapper = styled("div", { lineHeight: "1.47em", + fontSize: "$gr3", "& dt": { - fontSize: "$gr3", color: "$black", - fontFamily: "$northwesternDisplayBold", + fontFamily: "$northwesternSansBold", }, "& dd": { marginInlineStart: "0", - paddingBottom: "$gr2", + paddingBottom: "$gr3", }, }); diff --git a/components/Shared/IIIF/Share.tsx b/components/Shared/IIIF/Share.tsx new file mode 100644 index 00000000..ca5c5071 --- /dev/null +++ b/components/Shared/IIIF/Share.tsx @@ -0,0 +1,196 @@ +import * as Dropdown from "@radix-ui/react-dropdown-menu"; + +import Icon, { IconStyled } from "../Icon"; +import { IconChevronDown, IconExternalLink } from "../SVG/Icons"; + +import CopyText from "../CopyText"; +import IIIFLogo from "../SVG/IIIF"; +import { styled } from "@/stitches.config"; + +const IIIFShare = ({ uri }: { uri: string }) => { + return ( + + + + + + + View as IIIF + + + + + + View in... + + + Clover IIIF + + + + + Mirador + + + + + Theseus + + + + + + View Raw JSON + + + + + + + + + What is IIIF? + + + + + + + + + ); +}; + +const StyledIIIFShare = styled("div", { + position: "relative", + zIndex: 1, + + "> button": { + backgroundColor: "transparent", + color: "$black50", + fontFamily: "$northwesternSansRegular", + fontSize: "$gr3", + borderRadius: "38px", + border: "none", + display: "flex", + alignItems: "center", + justifyContent: "space-between", + cursor: "pointer", + gap: "$gr1", + padding: "0 $gr1", + margin: "0", + + "> span": { + svg: { + padding: "7px", + path: { + fill: "$purple !important", + }, + }, + + "&:last-child": { + display: "inline-flex", + alignItems: "center", + gap: "$gr1", + + "svg path": { + stroke: "$black50 !important", + fill: "none !important", + }, + }, + }, + + em: { + fontStyle: "normal", + display: "inline-flex", + marginBottom: "-3px", + }, + + "&:hover, &:active ": { + color: "$purple", + fill: "$black", + backgroundColor: "$purple10", + + "> span:last-child svg path": { + stroke: "$purple !important", + }, + }, + }, +}); + +const StyledIIIFShareContent = styled(Dropdown.Content, { + zIndex: 1, + backgroundColor: "$white", + padding: "$gr3", + borderRadius: "3px", + boxShadow: "5px 5px 19px 0 #0002", + display: "flex", + flexDirection: "column", + fontSize: "$gr2 ", + minWidth: "160px", + gap: "$gr2", + + a: { + color: "$purple", + display: "flex", + + svg: { + color: "$purple", + fill: "$purple", + }, + }, + + button: { + fontSize: "$gr2", + margin: "0 !important", + padding: "0 !important", + fontWeight: "400", + lineHeight: "inherit !important", + textDecoration: "none", + color: "$purple", + }, +}); + +const StyledDropdownLabel = styled(Dropdown.Separator, { + fontSize: "$gr2 ", + color: "$black50", +}); + +const StyledDropdownSeparator = styled(Dropdown.Separator, { + height: "1px", + backgroundColor: "$gray6", +}); + +export default IIIFShare; diff --git a/components/Shared/Icon.tsx b/components/Shared/Icon.tsx index fbd94278..794f8a61 100644 --- a/components/Shared/Icon.tsx +++ b/components/Shared/Icon.tsx @@ -1,12 +1,23 @@ +import { CSS } from "@stitches/react"; import { ReactNode } from "react"; import { styled } from "@/stitches.config"; interface IconProps { children: ReactNode; + style?: CSS; + hasSVGPadding?: boolean; } -const Icon: React.FC = ({ children }) => { - return {children}; +const Icon: React.FC = ({ + children, + style, + hasSVGPadding = true, +}) => { + return ( + + {children} + + ); }; /* eslint sort-keys: 0 */ @@ -32,7 +43,21 @@ export const IconStyled = styled("span", { color: "inherit", fill: "inherit", stroke: "inherit", - padding: "8px", + }, + + variants: { + hasSVGPadding: { + true: { + svg: { + padding: "0.5em", + }, + }, + false: { + svg: { + padding: "0", + }, + }, + }, }, }); diff --git a/components/Shared/SVG/Icons.tsx b/components/Shared/SVG/Icons.tsx index 7e5344b6..0df72d2e 100644 --- a/components/Shared/SVG/Icons.tsx +++ b/components/Shared/SVG/Icons.tsx @@ -79,6 +79,13 @@ const IconClear: React.FC = () => ( ); +const IconExternalLink: React.FC = () => ( + + + + +); + const IconFilter: React.FC = () => ( Filter @@ -228,6 +235,7 @@ export { IconCheck, IconChevronDown, IconClear, + IconExternalLink, IconFilter, IconImage, IconInfo, diff --git a/components/Work/ActionsDialog/DownloadAndShare/IIIFManifest.tsx b/components/Work/ActionsDialog/DownloadAndShare/IIIFManifest.tsx index cd84a852..ad8a9bcc 100644 --- a/components/Work/ActionsDialog/DownloadAndShare/IIIFManifest.tsx +++ b/components/Work/ActionsDialog/DownloadAndShare/IIIFManifest.tsx @@ -48,18 +48,19 @@ const IIIFManifest: React.FC = ({ manifest, work }) => { manifestId={manifest.id} /> - {(isWorkInstitution || isWorkPrivate) && ( - - Opening in external tools like Mirador is not supported for works - that require authentication. - - )} + + {(isWorkInstitution || isWorkPrivate) && ( + + Opening in external tools like Mirador is not supported for works that + require authentication. + + )} ); }; diff --git a/components/Work/TopInfo.styled.ts b/components/Work/TopInfo.styled.ts index 44586359..7acff104 100644 --- a/components/Work/TopInfo.styled.ts +++ b/components/Work/TopInfo.styled.ts @@ -11,7 +11,6 @@ const ActionButtons = styled("div", { button: { marginRight: "$gr3", - fontFamily: "$northwesternSansLight", paddingTop: "$gr3", "&:last-child": { @@ -53,25 +52,17 @@ const TopInfoWrapper = styled("section", { h1: { lineHeight: "1em", + fontWeight: "400", fontFamily: "$northwesternDisplayBold", - fontSize: "$8", - letterSpacing: "-0.015em", + fontSize: "$gr7", + letterSpacing: "-0.025em", margin: "0", - - "@sm": { - fontSize: "$gr7", - }, }, p: { - fontSize: "$gr5", + fontSize: "$gr4", color: "$black50", - fontFamily: "$northwesternSansLight", lineHeight: "1.47em", - - "@sm": { - fontSize: "$gr4", - }, }, }, }); diff --git a/components/Work/TopInfo.tsx b/components/Work/TopInfo.tsx index e4962656..ff4705c8 100644 --- a/components/Work/TopInfo.tsx +++ b/components/Work/TopInfo.tsx @@ -15,6 +15,7 @@ import { Button } from "@nulib/design-system"; import Card from "@/components/Shared/Card"; import { DefinitionListWrapper } from "@/components/Shared/DefinitionList.styled"; import Expand from "@/components/Shared/Expand/Expand"; +import IIIFShare from "../Shared/IIIF/Share"; import { Manifest } from "@iiif/presentation-3"; import type { Work } from "@nulib/dcapi-types"; import WorkActionsDialog from "@/components/Work/ActionsDialog/ActionsDialog"; @@ -71,10 +72,20 @@ const WorkTopInfo: React.FC = ({ return (
- - {manifest?.summary && ( - - )} +
+
+
+ +
+