From 69f07dbdf3a94eeb134fd75f9129610757c53d40 Mon Sep 17 00:00:00 2001 From: Ken Date: Tue, 6 May 2025 19:55:25 +0200 Subject: [PATCH 1/9] =?UTF-8?q?=E2=9C=A8=20Introduce=20ImageAsThemedSvg=20?= =?UTF-8?q?for=20SVG=20handling=20in=20ImageAsSvg.tsx?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../_ui/image-as-svg/ImageAsSvg.module.css | 5 ++ .../app/_ui/image-as-svg/ImageAsSvg.tsx | 73 +++++++++++++++++++ .../_ui/overview/DesignsystemetOverview.tsx | 47 +----------- 3 files changed, 80 insertions(+), 45 deletions(-) create mode 100644 aksel.nav.no/website/app/_ui/image-as-svg/ImageAsSvg.module.css create mode 100644 aksel.nav.no/website/app/_ui/image-as-svg/ImageAsSvg.tsx diff --git a/aksel.nav.no/website/app/_ui/image-as-svg/ImageAsSvg.module.css b/aksel.nav.no/website/app/_ui/image-as-svg/ImageAsSvg.module.css new file mode 100644 index 0000000000..18c61d0853 --- /dev/null +++ b/aksel.nav.no/website/app/_ui/image-as-svg/ImageAsSvg.module.css @@ -0,0 +1,5 @@ +/* stylelint-disable csstools/value-no-unknown-custom-properties */ +.imageAsModule { + width: var(--website-svg-size); + height: var(--website-svg-size); +} diff --git a/aksel.nav.no/website/app/_ui/image-as-svg/ImageAsSvg.tsx b/aksel.nav.no/website/app/_ui/image-as-svg/ImageAsSvg.tsx new file mode 100644 index 0000000000..2ba9997c28 --- /dev/null +++ b/aksel.nav.no/website/app/_ui/image-as-svg/ImageAsSvg.tsx @@ -0,0 +1,73 @@ +import DOMPurify from "isomorphic-dompurify"; +import styles from "./ImageAsSvg.module.css"; + +/** + * Utility function to fetch and format a image as SVG with recoloring. + */ +async function ImageAsThemedSvg({ url, size }: { url?: string; size: number }) { + if (!url) { + return null; + } + + const svgString = await fetch(url) + .then((res) => res.text()) + .catch(() => null); + + if (!svgString) { + return null; + } + + const formattedSvgString = formatSvgString(svgString); + + const cleanedSvg = DOMPurify.sanitize(formattedSvgString, { + USE_PROFILES: { svg: true }, + }); + + return ( +
+ dangerouslySetInnerHTML={{ __html: cleanedSvg }} + aria-hidden + style={{ "--website-svg-size": `${size}px` }} + /> + ); +} + +const colorReplacements = { + "#99F6E4": "var(--ax-bg-moderate-hoverA)", + "#AEF4E4": "var(--ax-bg-moderate-hoverA)", + "#003453": "var(--ax-text-subtle)", + "#262626": "var(--ax-text-subtle)", + "#23262A": "var(--ax-text-subtle)", + white: "var(--ax-bg-default)", + "#417DA0": "var(--ax-bg-strong)", + "#D7E6F0": "var(--ax-bg-moderate-hover)", + "#C0D6E4": "var(--ax-bg-moderate-pressed)", + "#E3EFF7": "var(--ax-bg-moderate)", + "#005A92": "var(--ax-bg-strong)", +}; + +/** + * Formats the SVG string by replacing colors and adding classes. + */ +function formatSvgString(svgString: string) { + let formattedSvgString = svgString; + + formattedSvgString = formattedSvgString.replace( + " { + const replacement = colorReplacements[color]; + + formattedSvgString = formattedSvgString.replace( + new RegExp(color, "g"), + replacement, + ); + }); + + return formattedSvgString; +} + +export { ImageAsThemedSvg }; diff --git a/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.tsx b/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.tsx index 7748e3f179..8946c42359 100644 --- a/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.tsx +++ b/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.tsx @@ -1,4 +1,3 @@ -import NextImage from "next/image"; import type { Image } from "sanity"; import { Bleed, @@ -11,6 +10,7 @@ import { } from "@navikt/ds-react"; import { DESIGNSYSTEM_OVERVIEW_BY_CATEGORY_QUERYResult } from "@/app/_sanity/query-types"; import { urlForImage } from "@/app/_sanity/utils"; +import { ImageAsThemedSvg } from "@/app/_ui/image-as-svg/ImageAsSvg"; import { getStatusTag } from "@/app/_ui/theming/theme-config"; import { MarkdownText } from "@/app/_ui/typography/MarkdownText"; import { @@ -81,17 +81,7 @@ function DesignsystemetOverviewCard({ - {imageUrl ? ( - - ) : ( - - )} + @@ -117,39 +107,6 @@ function DesignsystemetOverviewCard({ ); } -function FallbackSvg() { - return ( - - - - - - - ); -} - function sortDesignsystemetOverviewList( list: DESIGNSYSTEM_OVERVIEW_BY_CATEGORY_QUERYResult, ) { From 95f22ea9e4760bd5f31d98f136515b5a4f28faba Mon Sep 17 00:00:00 2001 From: Ken Date: Tue, 6 May 2025 20:34:09 +0200 Subject: [PATCH 2/9] =?UTF-8?q?=F0=9F=92=84=20Update=20background=20color?= =?UTF-8?q?=20for=20dark=20mode=20in=20DesignsystemetOverview.module.css?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/_ui/image-as-svg/ImageAsSvg.tsx | 2 +- .../DesignsystemetOverview.module.css | 5 ++++ .../_ui/overview/DesignsystemetOverview.tsx | 29 +++++++++---------- yarn.lock | 1 + 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/aksel.nav.no/website/app/_ui/image-as-svg/ImageAsSvg.tsx b/aksel.nav.no/website/app/_ui/image-as-svg/ImageAsSvg.tsx index 2ba9997c28..7c1de06aef 100644 --- a/aksel.nav.no/website/app/_ui/image-as-svg/ImageAsSvg.tsx +++ b/aksel.nav.no/website/app/_ui/image-as-svg/ImageAsSvg.tsx @@ -25,7 +25,7 @@ async function ImageAsThemedSvg({ url, size }: { url?: string; size: number }) { return (
+ // biome-ignore lint/security/noDangerouslySetInnerHtml: We purify the SVG string, so its safer to use locally here. dangerouslySetInnerHTML={{ __html: cleanedSvg }} aria-hidden style={{ "--website-svg-size": `${size}px` }} diff --git a/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.module.css b/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.module.css index b740b036e1..a4da817279 100644 --- a/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.module.css +++ b/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.module.css @@ -33,6 +33,11 @@ background: var(--ax-bg-moderate); } +/* stylelint-disable-next-line selector-pseudo-class-no-unknown */ +:global(.dark) .overviewImageWrapper { + background: var(--ax-bg-soft); +} + .overviewCardHeading { display: flex; align-items: center; diff --git a/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.tsx b/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.tsx index 8946c42359..6409d1ace4 100644 --- a/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.tsx +++ b/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.tsx @@ -86,21 +86,20 @@ function DesignsystemetOverviewCard({ - - - {page?.heading} - {statusTagWithoutStable && ( - - {/* TODO: Remove underline from tag */} - {statusTagWithoutStable.text} - - )} - - + + + {page?.heading} + + {statusTagWithoutStable && ( + + {statusTagWithoutStable.text} + + )} + diff --git a/yarn.lock b/yarn.lock index 3da2383b57..fceabfb07b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -29882,6 +29882,7 @@ __metadata: "@sanity/table": "npm:1.1.3" "@sanity/vision": "npm:3.78.0" "@slack/web-api": "npm:^7.8.0" + "@svgr/core": "npm:^8.1.0" "@types/jscodeshift": "npm:^0.11.11" "@types/lodash": "npm:4.17.16" "@types/react": "npm:^18.3.11" From 6146d1bc3fc5944ced0ca1007eea3268b1a7f437 Mon Sep 17 00:00:00 2001 From: Ken Date: Tue, 6 May 2025 20:47:39 +0200 Subject: [PATCH 3/9] :tada: Use 'themed' thumbnails for ds-pages --- .../app/_ui/image-as-svg/ImageAsSvg.tsx | 11 ++- .../_ui/Designsystemet.module.css | 7 +- .../_ui/Designsystemet.thumbnail.tsx | 91 +++---------------- .../_ui/DesignsystemetPage.tsx | 8 +- 4 files changed, 29 insertions(+), 88 deletions(-) diff --git a/aksel.nav.no/website/app/_ui/image-as-svg/ImageAsSvg.tsx b/aksel.nav.no/website/app/_ui/image-as-svg/ImageAsSvg.tsx index 7c1de06aef..44c5b32313 100644 --- a/aksel.nav.no/website/app/_ui/image-as-svg/ImageAsSvg.tsx +++ b/aksel.nav.no/website/app/_ui/image-as-svg/ImageAsSvg.tsx @@ -4,7 +4,15 @@ import styles from "./ImageAsSvg.module.css"; /** * Utility function to fetch and format a image as SVG with recoloring. */ -async function ImageAsThemedSvg({ url, size }: { url?: string; size: number }) { +async function ImageAsThemedSvg({ + url, + size, + className, +}: { + url?: string; + size: number; + className?: string; +}) { if (!url) { return null; } @@ -29,6 +37,7 @@ async function ImageAsThemedSvg({ url, size }: { url?: string; size: number }) { dangerouslySetInnerHTML={{ __html: cleanedSvg }} aria-hidden style={{ "--website-svg-size": `${size}px` }} + className={className} /> ); } diff --git a/aksel.nav.no/website/app/dev/(designsystemet)/_ui/Designsystemet.module.css b/aksel.nav.no/website/app/dev/(designsystemet)/_ui/Designsystemet.module.css index f5fb4b50df..0278b903b0 100644 --- a/aksel.nav.no/website/app/dev/(designsystemet)/_ui/Designsystemet.module.css +++ b/aksel.nav.no/website/app/dev/(designsystemet)/_ui/Designsystemet.module.css @@ -72,16 +72,13 @@ align-items: center; aspect-ratio: 24 / 9; border-radius: 16px; - background-color: var(--ax-bg-brand-blue-moderate); + background-color: var(--ax-bg-moderate); margin-block-start: var(--ax-space-28); overflow: hidden; } .thumbnailImage { - position: absolute; - inset: 0; - width: 100%; - height: 100%; + z-index: 10; } .thumbnailCube { diff --git a/aksel.nav.no/website/app/dev/(designsystemet)/_ui/Designsystemet.thumbnail.tsx b/aksel.nav.no/website/app/dev/(designsystemet)/_ui/Designsystemet.thumbnail.tsx index 7dda1ecba9..59c080bc4c 100644 --- a/aksel.nav.no/website/app/dev/(designsystemet)/_ui/Designsystemet.thumbnail.tsx +++ b/aksel.nav.no/website/app/dev/(designsystemet)/_ui/Designsystemet.thumbnail.tsx @@ -1,89 +1,20 @@ +import { ImageAsThemedSvg } from "@/app/_ui/image-as-svg/ImageAsSvg"; import styles from "./Designsystemet.module.css"; -function DesignsystemetThumbnail() { +function DesignsystemetThumbnail({ thumbnailUrl }: { thumbnailUrl?: string }) { + if (!thumbnailUrl) { + return null; + } + return (
- -
- ); -} - -function Thumbnail() { - return ( - - - - - - - - - - - - - - - - - +
); } diff --git a/aksel.nav.no/website/app/dev/(designsystemet)/_ui/DesignsystemetPage.tsx b/aksel.nav.no/website/app/dev/(designsystemet)/_ui/DesignsystemetPage.tsx index ad017637ae..10bcbb033d 100644 --- a/aksel.nav.no/website/app/dev/(designsystemet)/_ui/DesignsystemetPage.tsx +++ b/aksel.nav.no/website/app/dev/(designsystemet)/_ui/DesignsystemetPage.tsx @@ -1,10 +1,12 @@ import { PortableTextBlock } from "next-sanity"; +import { Image } from "sanity"; import { BodyShort, Box, HStack, Heading, Tag } from "@navikt/ds-react"; import { GRUNNLEGGENDE_BY_SLUG_QUERYResult, KOMPONENT_BY_SLUG_QUERYResult, MONSTER_MALER_BY_SLUG_QUERYResult, } from "@/app/_sanity/query-types"; +import { urlForImage } from "@/app/_sanity/utils"; import { CustomPortableText } from "@/app/_ui/portable-text/CustomPortableText"; import { getStatusTag } from "@/app/_ui/theming/theme-config"; import { DesignsystemetEyebrow } from "@/app/dev/(designsystemet)/_ui/Designsystemet.eyebrow"; @@ -51,8 +53,10 @@ async function DesignsystemetPageHeader({ data }: DesignsystemetPageT) { const isComponentPage = data?._type === "komponent_artikkel"; + const imageUrl = urlForImage(data?.status?.bilde as Image)?.url(); + return ( - + @@ -87,7 +91,7 @@ async function DesignsystemetPageHeader({ data }: DesignsystemetPageT) { {isComponentPage && } - + ); } From 6cc3a3745a18f9c6fa63020adefc977d8b07256a Mon Sep 17 00:00:00 2001 From: Ken Date: Wed, 7 May 2025 14:13:51 +0200 Subject: [PATCH 4/9] =?UTF-8?q?=F0=9F=92=84=20Change=20background=20color?= =?UTF-8?q?=20to=20var(--ax-bg-neutral-soft)=20in=20DesignsystemetOverview?= =?UTF-8?q?.module.css?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dev/(designsystemet)/_ui/Designsystemet.thumbnail.tsx | 6 +++--- .../_ui/overview/DesignsystemetOverview.module.css | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/aksel.nav.no/website/app/dev/(designsystemet)/_ui/Designsystemet.thumbnail.tsx b/aksel.nav.no/website/app/dev/(designsystemet)/_ui/Designsystemet.thumbnail.tsx index 59c080bc4c..17ddb5661d 100644 --- a/aksel.nav.no/website/app/dev/(designsystemet)/_ui/Designsystemet.thumbnail.tsx +++ b/aksel.nav.no/website/app/dev/(designsystemet)/_ui/Designsystemet.thumbnail.tsx @@ -33,19 +33,19 @@ function CubeShape() { fillRule="evenodd" clipRule="evenodd" d="M778.342 -296.311C776.611 -298.043 773.803 -298.043 772.071 -296.311L533.962 -58.2022C532.231 -56.4706 532.231 -53.663 533.962 -51.9313L772.071 186.178C773.803 187.909 776.611 187.909 778.342 186.178L1016.45 -51.9313C1018.18 -53.6629 1018.18 -56.4705 1016.45 -58.2022L778.342 -296.311ZM775.207 -286.905L1007.04 -55.0667L775.207 176.771L543.369 -55.0668L775.207 -286.905Z" - fill="#EEF6FC" + fill="var(--ax-bg-brand-blue-soft)" /> ); diff --git a/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.module.css b/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.module.css index a4da817279..fa33da9060 100644 --- a/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.module.css +++ b/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.module.css @@ -35,7 +35,7 @@ /* stylelint-disable-next-line selector-pseudo-class-no-unknown */ :global(.dark) .overviewImageWrapper { - background: var(--ax-bg-soft); + background: var(--ax-bg-neutral-soft); } .overviewCardHeading { From e2ece1d11e8e8542d7337715b5085990f1166d1a Mon Sep 17 00:00:00 2001 From: Ken Date: Wed, 7 May 2025 14:18:17 +0200 Subject: [PATCH 5/9] :lipstick: Move tag to top of overview-card --- .../_ui/overview/DesignsystemetOverview.tsx | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.tsx b/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.tsx index 6409d1ace4..f1d041cf84 100644 --- a/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.tsx +++ b/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.tsx @@ -79,26 +79,30 @@ function DesignsystemetOverviewCard({ return ( - - - - - + + + + + + {statusTagWithoutStable && ( + + + {statusTagWithoutStable.text} + + + )} + + {page?.heading} - {statusTagWithoutStable && ( - - {statusTagWithoutStable.text} - - )} From 9c2c00eb230acf6946a83078438ed97b1474c488 Mon Sep 17 00:00:00 2001 From: Ken Date: Wed, 7 May 2025 14:20:00 +0200 Subject: [PATCH 6/9] :memo: yarn lock sync --- yarn.lock | 1 - 1 file changed, 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index fceabfb07b..3da2383b57 100644 --- a/yarn.lock +++ b/yarn.lock @@ -29882,7 +29882,6 @@ __metadata: "@sanity/table": "npm:1.1.3" "@sanity/vision": "npm:3.78.0" "@slack/web-api": "npm:^7.8.0" - "@svgr/core": "npm:^8.1.0" "@types/jscodeshift": "npm:^0.11.11" "@types/lodash": "npm:4.17.16" "@types/react": "npm:^18.3.11" From 73f99e7a85f8f111c881d17a0a71d1426d46513f Mon Sep 17 00:00:00 2001 From: Ken Date: Wed, 7 May 2025 15:34:22 +0200 Subject: [PATCH 7/9] :lipstick: Tone down overview thumbnail preview --- .../_ui/overview/DesignsystemetOverview.module.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.module.css b/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.module.css index fa33da9060..ba3871d1a4 100644 --- a/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.module.css +++ b/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.module.css @@ -30,7 +30,7 @@ aspect-ratio: 16 / 10; border-start-start-radius: calc(var(--ax-border-radius-xlarge) - 1px); border-start-end-radius: calc(var(--ax-border-radius-xlarge) - 1px); - background: var(--ax-bg-moderate); + background: var(--ax-bg-soft); } /* stylelint-disable-next-line selector-pseudo-class-no-unknown */ From 1d580d289dcfc1503f79dcdaeb0ef809b68eb0ef Mon Sep 17 00:00:00 2001 From: Ken Date: Thu, 8 May 2025 14:19:32 +0200 Subject: [PATCH 8/9] :fire: Remove arrow from overview cards --- .../_ui/overview/DesignsystemetOverview.tsx | 2 +- .../app/dev/(god-praksis)/_ui/link-card/LinkCard.tsx | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.tsx b/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.tsx index f1d041cf84..aa2c2ce716 100644 --- a/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.tsx +++ b/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.tsx @@ -98,7 +98,7 @@ function DesignsystemetOverviewCard({ - + {page?.heading} diff --git a/aksel.nav.no/website/app/dev/(god-praksis)/_ui/link-card/LinkCard.tsx b/aksel.nav.no/website/app/dev/(god-praksis)/_ui/link-card/LinkCard.tsx index b8bda2aaa5..a99f4c9c06 100644 --- a/aksel.nav.no/website/app/dev/(god-praksis)/_ui/link-card/LinkCard.tsx +++ b/aksel.nav.no/website/app/dev/(god-praksis)/_ui/link-card/LinkCard.tsx @@ -75,6 +75,11 @@ type LinkCardTitleProps = HTMLAttributes & { * @default "default" */ variant?: "default" | "subtle"; + /** + * Whether to show animated arrow icon + * @default true + */ + showArrow?: boolean; }; const LinkCardTitle = forwardRef( @@ -85,6 +90,7 @@ const LinkCardTitle = forwardRef( size = "small", weight = "semibold", variant = "default", + showArrow = true, }: LinkCardTitleProps, forwardedRef, ) => { @@ -100,7 +106,7 @@ const LinkCardTitle = forwardRef( )} > {children} - + {showArrow && } ); }, @@ -292,7 +298,7 @@ export { LinkCardArrow, LinkCardDescription, LinkCardFooter, - LinkCardTitle, LinkCardIcon, LinkCardImage, + LinkCardTitle, }; From 9df11c54fc86f27fe07d528af5065faaab1eb75f Mon Sep 17 00:00:00 2001 From: Ken Date: Thu, 8 May 2025 14:25:43 +0200 Subject: [PATCH 9/9] :recycle: Show arrow on LinkCard --- .../(designsystemet)/_ui/overview/DesignsystemetOverview.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.tsx b/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.tsx index aa2c2ce716..f1d041cf84 100644 --- a/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.tsx +++ b/aksel.nav.no/website/app/dev/(designsystemet)/_ui/overview/DesignsystemetOverview.tsx @@ -98,7 +98,7 @@ function DesignsystemetOverviewCard({ - + {page?.heading}