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..44c5b32313 --- /dev/null +++ b/aksel.nav.no/website/app/_ui/image-as-svg/ImageAsSvg.tsx @@ -0,0 +1,82 @@ +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, + className, +}: { + url?: string; + size: number; + className?: string; +}) { + 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 ( +
+ ); +} + +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/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..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 @@ -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 ( - - - - - - - - - - - - - - - - - +
); } @@ -102,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/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 && } - + ); } 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..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,12 @@ 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 */ +:global(.dark) .overviewImageWrapper { + background: var(--ax-bg-neutral-soft); } .overviewCardHeading { 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..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 @@ -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 { @@ -79,77 +79,37 @@ function DesignsystemetOverviewCard({ return ( - - - {imageUrl ? ( - - ) : ( - - )} - - - - - - - {page?.heading} - {statusTagWithoutStable && ( + + + + + + {statusTagWithoutStable && ( + - {/* TODO: Remove underline from tag */} {statusTagWithoutStable.text} - )} - - + + )} + + + + + + + {page?.heading} + + ); } -function FallbackSvg() { - return ( - - - - - - - ); -} - function sortDesignsystemetOverviewList( list: DESIGNSYSTEM_OVERVIEW_BY_CATEGORY_QUERYResult, ) { 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, };