Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Darkside] Accordion CSS-rewrite #3296

Merged
merged 28 commits into from
Nov 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
cc1000c
[Darkside] Migrated typo to new CSS
KenAJoh Oct 29, 2024
a7c5d07
memo: Added comments
KenAJoh Oct 29, 2024
22004d6
change: Implemented accordion header and content
KenAJoh Oct 29, 2024
afadea7
change: Added lines
KenAJoh Oct 29, 2024
5e10278
feat: added todo
KenAJoh Oct 29, 2024
4523a0b
change: Fixed layering issues with lines
KenAJoh Oct 30, 2024
28fb9ab
change: Avoid animation on initial render
KenAJoh Oct 30, 2024
b3758d7
change: Removed comments
KenAJoh Oct 30, 2024
b4a9f79
change: moved icon state into nesting
KenAJoh Oct 30, 2024
f15d94a
change: Added alpha-background for icon, updated fontweight
KenAJoh Oct 30, 2024
24b2155
Merge branch 'main' into darkside-accordion-updated
KenAJoh Oct 30, 2024
4b7310e
change: Added forced-colors support
KenAJoh Oct 30, 2024
a70edfd
Removed use op --open class
KenAJoh Nov 1, 2024
5f90ca8
Removed old grid centering
KenAJoh Nov 1, 2024
6271cb1
Top, bottom line is now alpha
KenAJoh Nov 1, 2024
474d76b
Fixed animation
KenAJoh Nov 1, 2024
1eb1821
bug: Revert to transparent bg
KenAJoh Nov 1, 2024
fc64936
deprecation: Added tags to accordion props that are to be removed
KenAJoh Nov 1, 2024
d2488b9
removed deprecation for accordion headingSize prop
KenAJoh Nov 1, 2024
82e7a02
Merge branch 'main' into darkside-accordion-updated
KenAJoh Nov 5, 2024
1969780
Merge branch 'main' into darkside-accordion-updated
KenAJoh Nov 5, 2024
74a9bff
Updated implementation of line in accordion
KenAJoh Nov 5, 2024
6f8406f
Remove position relative in accordion content
KenAJoh Nov 5, 2024
ae9bc02
Implemented size-update for accordion
KenAJoh Nov 5, 2024
e6972aa
bug: removed old comment
KenAJoh Nov 6, 2024
43725d3
Clarify comments
KenAJoh Nov 6, 2024
264702a
Removed redundant header class
KenAJoh Nov 6, 2024
842a042
Re-added className in accordionHeader
KenAJoh Nov 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .storybook/preview.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down
260 changes: 122 additions & 138 deletions @navikt/core/css/darkside/accordion.darkside.css
HalvorHaugan marked this conversation as resolved.
Show resolved Hide resolved
HalvorHaugan marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you might want to add some sticky (and non alpha bg colors) to mirror the nav.no behaviour when you can't see the top of the accordion header anymore?

image

  position: sticky;
  top: 0;
  background-color: white;
  z-index: 1;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's a good feature 🙌, so I vote for adding it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think this feature might need to be implemented by the teams themselves, because of the possible edgecases for where "top" is. If you dig down into how they handle it, they have a custom css-variable for "top" that changes based on decorator height

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the top being 0 should work out as long as parent has position relative no? it seemed to work out great in my testing 🤔 The header is always inside an accordion item wrapper, so that can be the top: 0 position?

Copy link
Contributor

@JulianNymark JulianNymark Nov 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nvm, it works badly after all 😅

They need to be sticky towards the same containing element with offsets 😢

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;
}
}
1 change: 1 addition & 0 deletions @navikt/core/react/src/accordion/Accordion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ interface AccordionComponent

export interface AccordionProps extends React.HTMLAttributes<HTMLDivElement> {
/**
* @deprecated Prop will be removed in future versions. "default" will be the only variant.
* @default "default"
*/
variant?: "default" | "neutral";
Expand Down
9 changes: 8 additions & 1 deletion @navikt/core/react/src/accordion/AccordionContent.tsx
Original file line number Diff line number Diff line change
@@ -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";

Expand All @@ -15,6 +16,8 @@ const AccordionContent = forwardRef<HTMLDivElement, AccordionContentProps>(
({ children, className, ...rest }, ref) => {
const context = useContext(AccordionItemContext);

const themeContext = UNSAFE_useAkselTheme(false);

if (context === null) {
console.error(
"<Accordion.Content> has to be used within an <Accordion.Item>",
Expand All @@ -38,7 +41,11 @@ const AccordionContent = forwardRef<HTMLDivElement, AccordionContentProps>(
!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 ? (
<div className="navds-accordion__content-inner">{children}</div>
) : (
children
)}
</BodyLong>
);
},
Expand Down
Loading
Loading