diff --git a/.storybook/preview.jsx b/.storybook/preview.jsx index 4e3f734fc6..878de70d71 100644 --- a/.storybook/preview.jsx +++ b/.storybook/preview.jsx @@ -2,7 +2,7 @@ import { withThemeByClassName } from "@storybook/addon-themes"; import React, { useLayoutEffect } from "react"; import darksideCss from "@navikt/ds-css/darkside/index.css?inline"; import defaultCss from "@navikt/ds-css/index.css?inline"; -import { UNSAFE_AkselTheme } from "@navikt/ds-react/Provider"; +import { UNSAFE_AkselTheme } from "../@navikt/core/react/src/provider"; import "./layout.css"; export const parameters = { diff --git a/@navikt/core/css/darkside/accordion.darkside.css b/@navikt/core/css/darkside/accordion.darkside.css index b44af6e4eb..a5c9d3f369 100644 --- a/@navikt/core/css/darkside/accordion.darkside.css +++ b/@navikt/core/css/darkside/accordion.darkside.css @@ -1,198 +1,182 @@ -.navds-accordion { - --__ac-accordion-header-shadow-color: var(--ac-accordion-header-border, var(--a-border-divider)); -} - -/************************* - * Header * - *************************/ +/* ---------------------------- Accordion header ---------------------------- */ .navds-accordion__header { - --__ac-accordion-header-shadow: inset 2px 0 0 0 var(--a-transparent), inset -2px 0 0 0 var(--a-transparent), - inset 0 2px 0 0 var(--__ac-accordion-header-shadow-color); - width: 100%; display: flex; justify-content: flex-start; align-items: flex-start; - gap: var(--a-spacing-2); - padding: var(--a-spacing-3); - margin: 0; + gap: var(--ax-spacing-3); + padding: var(--ax-spacing-3); text-align: left; - background: var(--ac-accordion-header-bg, var(--a-surface-transparent)); cursor: pointer; border: none; position: relative; - box-shadow: var(--__ac-accordion-header-shadow); - z-index: 1; -} + border-radius: var(--ax-border-radius-large); + background: transparent; + color: var(--ax-text-accent); -.navds-accordion__header:hover { - background-color: var(--ac-accordion-header-bg-hover, var(--a-surface-hover)); - text-decoration: underline; - color: var(--ac-accordion-header-text-hover, inherit); -} + > * { + font-weight: var(--ax-font-weight-regular); + } -.navds-accordion--small .navds-accordion__header { - padding: var(--a-spacing-2) var(--a-spacing-3); -} + @media (forced-colors: active) { + border: 1px solid buttonborder; + background-color: canvas; + color: canvastext; + } -.navds-accordion--medium .navds-accordion__header { - padding: var(--a-spacing-3); -} + &:hover { + background-color: var(--ax-bg-accent-hoverA); + color: var(--ax-text-accent-strong); + + &::before, + &::after { + display: none; + } + + > .navds-accordion__icon-wrapper { + background-color: var(--ax-bg-accent-strong-hover); + color: var(--ax-text-accent-contrast); + } + + @media (forced-colors: active) { + background-color: canvas; + border: 1px solid highlight; + color: highlight; + } + } -.navds-accordion--large .navds-accordion__header { - padding: var(--a-spacing-4) var(--a-spacing-3); -} + &:focus-visible { + outline: 2px solid var(--ax-border-focus); + outline-offset: 2px; + z-index: 1; -.navds-accordion__item:last-child > :where(.navds-accordion__header) { - box-shadow: - var(--__ac-accordion-header-shadow), - inset 0 -2px 0 0 var(--__ac-accordion-header-shadow-color); + &::before, + &::after { + display: none; + } + } } -.navds-accordion__item:last-child:where(.navds-accordion__item--open) :where(.navds-accordion__header) { - box-shadow: - inset 2px 0 0 0 var(--a-transparent), - inset -2px 0 0 0 var(--a-transparent), - inset 0 2px 0 0 var(--a-transparent), - inset 0 2px 0 0 var(--__ac-accordion-header-shadow-color); +.navds-accordion--small .navds-accordion__header { + padding-block: var(--a-spacing-2); } -.navds-accordion__item:last-child:where(.navds-accordion__item--open) { - box-shadow: - inset 2px 0 0 0 var(--a-transparent), - inset -2px 0 0 0 var(--a-transparent), - inset 0 2px 0 0 var(--a-transparent), - inset 0 -2px 0 0 var(--__ac-accordion-header-shadow-color); +.navds-accordion__header::before, +.navds-accordion__header::after { + content: ""; + display: block; + position: absolute; + top: 0; + left: 0; + right: 0; + width: 100%; + height: 1px; + background-color: var(--ax-border-subtleA); } -.navds-accordion__item--open > :where(.navds-accordion__header) { - box-shadow: var(--__ac-accordion-header-shadow); +.navds-accordion__item:last-child > .navds-accordion__content { + border-bottom: 1px solid transparent; } -.navds-accordion__header:focus-visible { - outline: 2px solid transparent; - outline-offset: 3px; - box-shadow: var(--a-shadow-focus); - border-radius: var(--a-border-radius-large); +.navds-accordion__header::after { + top: initial; + bottom: 0; } -@supports not selector(:focus-visible) { - .navds-accordion__header:focus { - outline: none; - box-shadow: var(--a-shadow-focus); - border-radius: var(--a-border-radius-large); - } +.navds-accordion__item[data-expanded="true"] > .navds-accordion__header::after, +.navds-accordion__item:not(:last-child) > .navds-accordion__header::after { + display: none; } -.navds-accordion__header-content { - overflow: hidden; - text-overflow: ellipsis; +.navds-accordion__item[data-expanded="false"]:has(.navds-accordion__header:where(:hover, :focus-visible)) + + .navds-accordion__item + > .navds-accordion__header::before { + display: none; } -/************************* - * Icon * - *************************/ +/* ------------------------- Accordion chevron icon ------------------------- */ .navds-accordion__icon-wrapper { - display: grid; - place-content: center; - border-radius: var(--a-border-radius-medium); - height: var(--a-spacing-6); - width: var(--a-spacing-6); + border-radius: var(--ax-border-radius-large); + width: 22px; + height: 22px; align-self: center; -} - -.navds-accordion__header:hover > .navds-accordion__icon-wrapper { - background-color: var(--ac-accordion-header-icon-bg-hover, var(--a-surface-neutral-subtle-hover)); + background-color: var(--ax-bg-accent-moderateA); + color: var(--ax-text-accent-strong); } .navds-accordion__header-chevron { - border-radius: var(--a-border-radius-medium); - font-size: 1.5rem; - height: 1.75rem; + height: inherit; + width: inherit; flex-shrink: 0; - transition: transform 150ms ease-in-out; - align-self: center; + transition: transform 250ms cubic-bezier(0.2, 0, 0, 1); } -:where(.navds-accordion__header):hover > :where(.navds-accordion__icon-wrapper) > :where(.navds-accordion__header-chevron) { - transform: translateY(1px); +.navds-accordion__item[data-expanded="true"] > .navds-accordion__header .navds-accordion__header-chevron { + transform: rotateX(-180deg); } -.navds-accordion__item--open - > :where(.navds-accordion__header) - > :where(.navds-accordion__icon-wrapper) - > :where(.navds-accordion__header-chevron) { - transform: translateY(0) rotate(-180deg); -} - -.navds-accordion__item--open - > :where(.navds-accordion__header):hover - > :where(.navds-accordion__icon-wrapper) - > :where(.navds-accordion__header-chevron) { - transform: translateY(-1px) rotate(-180deg); -} - -/************************* - * Variant/Default * - *************************/ -.navds-accordion__item--open { - background-color: var(--ac-accordion-item-bg-open, var(--a-transparent)); -} - -/************************* - * Variant/Neutral * - *************************/ -.navds-accordion__item--open.navds-accordion__item--neutral { - background-color: var(--ac-accordion-neutral-item-bg-open, var(--a-surface-neutral-subtle)); -} - -/************************* - * Content * - *************************/ - +/* ---------------------------- Accordion content --------------------------- */ .navds-accordion__content { - padding: var(--a-spacing-1) var(--a-spacing-3) var(--a-spacing-5); - animation: fadeAccordionContent 250ms ease; -} - -.navds-accordion--indent > :where(.navds-accordion__item) > :where(.navds-accordion__content) { - padding: var(--a-spacing-1) var(--a-spacing-3) var(--a-spacing-5) var(--a-spacing-11); -} + --__acx-accordion-content-line-width: 2px; -.navds-accordion__content--closed { + padding-inline: var(--ax-spacing-6) var(--ax-spacing-3); display: none; + overflow: hidden; + padding-block: 0; + max-height: 0; + border-color: transparent; + transition: all 250ms cubic-bezier(0.2, 0, 0, 1) allow-discrete; + animation: navds-accordion-content-animation 250ms cubic-bezier(0.2, 0, 0, 1); } -.navds-accordion__item--no-animation :where(.navds-accordion__content) { +.navds-accordion__item--no-animation { animation: none; } -@keyframes fadeAccordionContent { +@keyframes navds-accordion-content-animation { 0% { - opacity: 0.25; - transform: translateY(-8px); + opacity: 0.01; } - 40% { - opacity: 0.7; + 20% { + opacity: 0.01; } 100% { opacity: 1; - transform: translateY(0); } } -@media (forced-colors: active) { - .navds-accordion__header { - border: 1px solid buttonborder; - background-color: canvas; - color: canvastext; +.navds-accordion--indent > .navds-accordion__item > .navds-accordion__content { + padding-inline: var(--ax-spacing-6) var(--ax-spacing-3); +} + +.navds-accordion--indent > .navds-accordion__item .navds-accordion__content-inner { + box-shadow: -2px 0 0 0 var(--ax-border-subtleA); + padding-block: var(--ax-spacing-2); + + /* Aligns content with heading-section */ + padding-inline: calc(var(--ax-spacing-5) + 2px) var(--ax-spacing-5); + + @media (forced-colors: active) { + border-left: 1px solid canvastext; } +} - .navds-accordion__header:hover { - background-color: canvas; - border: 1px solid highlight; - color: highlight; +.navds-accordion__item[data-expanded="true"] > .navds-accordion__content { + display: block; + opacity: 1; + overflow: visible; + max-height: fit-content; + padding-block: var(--ax-spacing-2); + padding-block-end: var(--ax-spacing-6); + border-color: var(--ax-border-subtleA); +} + +@starting-style { + .navds-accordion__item[data-expanded="true"]:not(.navds-accordion__item--no-animation) > .navds-accordion__content { + padding-block: 0; + max-height: 0; + border-color: transparent; } } diff --git a/@navikt/core/react/src/accordion/Accordion.tsx b/@navikt/core/react/src/accordion/Accordion.tsx index a6d4802b4b..024548df92 100644 --- a/@navikt/core/react/src/accordion/Accordion.tsx +++ b/@navikt/core/react/src/accordion/Accordion.tsx @@ -31,6 +31,7 @@ interface AccordionComponent export interface AccordionProps extends React.HTMLAttributes { /** + * @deprecated Prop will be removed in future versions. "default" will be the only variant. * @default "default" */ variant?: "default" | "neutral"; diff --git a/@navikt/core/react/src/accordion/AccordionContent.tsx b/@navikt/core/react/src/accordion/AccordionContent.tsx index 168958b7e3..30b125f0bb 100644 --- a/@navikt/core/react/src/accordion/AccordionContent.tsx +++ b/@navikt/core/react/src/accordion/AccordionContent.tsx @@ -1,5 +1,6 @@ import cl from "clsx"; import React, { forwardRef, useContext } from "react"; +import { UNSAFE_useAkselTheme } from "../provider"; import { BodyLong } from "../typography"; import { AccordionItemContext } from "./AccordionItem"; @@ -15,6 +16,8 @@ const AccordionContent = forwardRef( ({ children, className, ...rest }, ref) => { const context = useContext(AccordionItemContext); + const themeContext = UNSAFE_useAkselTheme(false); + if (context === null) { console.error( " has to be used within an ", @@ -38,7 +41,11 @@ const AccordionContent = forwardRef( !context.open || undefined } /* Added to fix bug with Radio component, where label text inside a span sometimes is ignored by screen readers after hiding/displaying the RadioGroup inside an Accordion */ > - {children} + {themeContext ? ( +
{children}
+ ) : ( + children + )} ); }, diff --git a/@navikt/core/react/src/accordion/AccordionHeader.tsx b/@navikt/core/react/src/accordion/AccordionHeader.tsx index f3e73e6d89..98e26ae47f 100644 --- a/@navikt/core/react/src/accordion/AccordionHeader.tsx +++ b/@navikt/core/react/src/accordion/AccordionHeader.tsx @@ -1,6 +1,7 @@ import cl from "clsx"; import React, { forwardRef, useContext } from "react"; import { ChevronDownIcon } from "@navikt/aksel-icons"; +import { UNSAFE_useAkselTheme } from "../provider"; import { Heading } from "../typography"; import { composeEventHandlers } from "../util/composeEventHandlers"; import { AccordionContext } from "./AccordionContext"; @@ -19,6 +20,8 @@ const AccordionHeader = forwardRef( const itemContext = useContext(AccordionItemContext); const accordionContext = useContext(AccordionContext); + const themeContext = UNSAFE_useAkselTheme(false); + if (itemContext === null) { console.error( " has to be used within an , which in turn must be within an ", @@ -26,6 +29,13 @@ const AccordionHeader = forwardRef( return null; } + let headingSize = accordionContext?.headingSize ?? "small"; + + if (themeContext) { + /* Fallback to "medium" Accordion-size if any other sizes are used */ + headingSize = accordionContext?.size === "small" ? "xsmall" : "small"; + } + return (