Skip to content

Commit

Permalink
Feature/oppdater stil på side meny (#3476)
Browse files Browse the repository at this point in the history
* redsign av side meny
  • Loading branch information
sirimykland authored Dec 13, 2024
1 parent d9fdb8a commit b0a0cf2
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 233 deletions.
1 change: 0 additions & 1 deletion packages/plattform-komponenter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ export { default as StatefulProcessMenu } from './src/process-menu/StatefulProce
export { default as Step } from './src/process-menu/Step';
export { default as ProcessMenuStepType } from './src/process-menu/StepType';
export { default as SideMenu } from './src/side-menu/SideMenu';
export { default as StatefulSideMenu } from './src/side-menu/StatefulSideMenu';
export { default as PersonCard, Gender } from './src/person-card/PersonCard';
export { default as EmptyPersonCard } from './src/person-card/EmptyPersonCard';
export { default as VisittKort } from './src/person-card/VisittKort';
Expand Down
58 changes: 10 additions & 48 deletions packages/plattform-komponenter/src/side-menu/MenuLink.tsx
Original file line number Diff line number Diff line change
@@ -1,68 +1,30 @@
import { bemUtils } from '@navikt/ft-utils';
import classnames from 'classnames';
import { BodyShort, Label } from '@navikt/ds-react';

import React from 'react';
import { BodyShort } from '@navikt/ds-react';

import styles from './menuLink.module.css';

interface MenuLinkProps {
label: string;
onClick: () => void;
active?: boolean;
icon?: React.ReactNode;
theme?: string;
}

const menuLinkCls = bemUtils('menuLink');

const MenuLink = ({ label, active, onClick, icon, theme }: MenuLinkProps): JSX.Element => {
const arrowTheme = theme === 'arrow';
const MenuLink = ({ label, active, onClick, icon }: MenuLinkProps) => {
const handleOnClick = (event: React.FormEvent<HTMLButtonElement>): void => {
event.preventDefault();
onClick();
};

const labelCls = classnames(
active
? `${styles[menuLinkCls.element('label')]} ${styles['menuLink__label--active']}`
: styles[menuLinkCls.element('label')],
{
[styles['menuLink__label--with-icon']]: !!icon,
},
);

const containerClassnames = classnames(styles[menuLinkCls.block], {
[styles[menuLinkCls.modifier('withArrows')]]: arrowTheme,
});

const buttonCls = active ? `${styles.menuLink__button} ${styles.menuLink__button__active}` : styles.menuLink__button;
return (
<li className={containerClassnames} aria-current={active ? true : undefined}>
<button
className={
active
? `${styles[menuLinkCls.element('button')]} ${styles['menuLink__button--active']}`
: styles[menuLinkCls.element('button')]
}
onClick={handleOnClick}
type="button"
data-testid={active ? 'activeMenuItemButton' : undefined}
>
{arrowTheme && active ? (
<Label size="small" as="span" className={labelCls}>
{label}
{icon}
</Label>
) : (
<BodyShort size="small" as="span" className={labelCls}>
{label}
{icon}
</BodyShort>
)}

{arrowTheme && active && <span className={styles[menuLinkCls.element('arrow-right')]} />}
<li aria-current={active ? true : undefined}>
<button className={buttonCls} onClick={handleOnClick}>
<BodyShort size="small" as="span">
{label}
</BodyShort>
{icon}
</button>
</li>
);
};

export default MenuLink;
22 changes: 13 additions & 9 deletions packages/plattform-komponenter/src/side-menu/SideMenu.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import { screen } from '@testing-library/react';
import { composeStories } from '@storybook/react';

import * as stories from './SideMenu.stories';

const { StatefulSideMenu } = composeStories(stories);
const { Default } = composeStories(stories);

describe('<SideMenu>', () => {
it('skal vise meny', async () => {
render(<StatefulSideMenu />);
describe('SideMenu', () => {
it('skal vise side meny med et aktivt element', async () => {
await Default.run();

expect(await screen.findByText('Dette er en test')).toBeInTheDocument();
expect(screen.getByText('en link')).toBeInTheDocument();
expect(screen.getByText('en link til')).toBeInTheDocument();
expect(await screen.findByText('Fakta om')).toBeInTheDocument();
expect(screen.getByText('Saken')).toBeInTheDocument();
expect(screen.getByText('Medlemskap')).toBeInTheDocument();
expect(screen.getByText('Arbeid og inntekt')).toBeInTheDocument();

expect(screen.getByText('Opptjening')).toBeInTheDocument();
expect(screen.getByText('Opptjening').closest('li')).toHaveAttribute('aria-current', 'true');
expect(screen.getByText('Opptjening').closest('button')).toHaveClass(/.menuLink__button__active/);
});
});
73 changes: 51 additions & 22 deletions packages/plattform-komponenter/src/side-menu/SideMenu.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,61 @@
import { StoryFn } from '@storybook/react';
import React, { ComponentProps } from 'react';
import WarningIcon from '../icons/WarningIcon';
import StatefulSideMenuComponent from './StatefulSideMenu';
import React, { useMemo, useState } from 'react';
import { Meta, StoryObj } from '@storybook/react';
import SideMenu from './SideMenu';
import { HStack } from '@navikt/ds-react';
import { ExclamationmarkTriangleFillIcon } from '@navikt/aksel-icons';

export default {
const meta = {
title: 'Side menu',
component: StatefulSideMenuComponent,
};
component: SideMenu,
render: ({ heading, links, onClick }) => {
const [currentIndex, setCurrentIndex] = useState(links.findIndex(({ active }) => active) ?? 0);
const handleOnClick = (index: number): void => {
setCurrentIndex(index);
onClick(index);
};

const linksWithActiveState = useMemo(
() =>
links.map((link, index) => ({
...link,
active: currentIndex === index,
})),
[links, currentIndex],
);
return (
<div style={{ width: '400px', border: '1px dotted black' }}>
<HStack>
<SideMenu heading={heading} links={linksWithActiveState} onClick={handleOnClick} />
<div style={{ width: '200px', height: '800px', padding: '24px' }}>annet innhold</div>
</HStack>
</div>
);
},
} satisfies Meta<typeof SideMenu>;

export default meta;

type Story = StoryObj<typeof meta>;

const Template: StoryFn<ComponentProps<typeof StatefulSideMenuComponent>> = () => (
<StatefulSideMenuComponent
heading="Dette er en test"
links={[
export const Default: Story = {
args: {
heading: 'Fakta om',
links: [
{
label: 'en link',
label: 'Saken',
},
{
label: 'en link til',
label: 'Medlemskap',
},
{
icon: <WarningIcon />,
label: 'en link med ikon',
icon: <ExclamationmarkTriangleFillIcon fontSize="1rem" color={'var(--a-icon-warning)'} />,
label: 'Opptjening',
active: true,
},
]}
onClick={() => null}
/>
);

export const StatefulSideMenu = Template.bind({});
StatefulSideMenu.args = {};
{
label: 'Arbeid og inntekt',
},
],
onClick: () => null,
},
};
39 changes: 9 additions & 30 deletions packages/plattform-komponenter/src/side-menu/SideMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,54 +1,33 @@
import { bemUtils } from '@navikt/ft-utils';
import { BodyShort } from '@navikt/ds-react';
import React from 'react';
import classnames from 'classnames';
import { Detail } from '@navikt/ds-react';
import MenuLink from './MenuLink';
import styles from './sideMenu.module.css';

const sideMenuCls = bemUtils('sideMenu');
import styles from './sideMenu.module.css';

export interface Link {
label: string;
active?: boolean;
icon?: React.ReactNode;
}

export type ThemeProp = 'arrow';

interface SideMenuProps {
heading?: string;
links: Link[];
onClick: (index: number) => void;
theme?: ThemeProp;
}

const SideMenu = ({ links, heading, onClick, theme }: SideMenuProps): JSX.Element => {
const sideMenuRootClassnames = classnames(
styles[sideMenuCls.block],
theme
? {
[styles[sideMenuCls.modifier(theme)]]: theme,
}
: {},
);
const SideMenu = ({ links, heading, onClick }: SideMenuProps) => {
return (
<div className={sideMenuRootClassnames}>
<nav className={styles[sideMenuCls.element('container')]}>
<div>
<nav className={styles.sideMenu__container}>
{heading && (
<BodyShort size="small" className={styles[sideMenuCls.element('heading')]}>
<Detail uppercase className={styles.sideMenu__heading}>
{heading}
</BodyShort>
</Detail>
)}
<ul className={styles[sideMenuCls.element('link-list')]}>
<ul className={styles.sideMenu__linkList}>
{links.map(({ label, active, icon }, index) => (
<MenuLink
key={label.split(' ').join('')}
label={label}
active={active}
onClick={() => onClick(index)}
icon={icon}
theme={theme}
/>
<MenuLink key={label} label={label} active={active} onClick={() => onClick(index)} icon={icon} />
))}
</ul>
</nav>
Expand Down
27 changes: 0 additions & 27 deletions packages/plattform-komponenter/src/side-menu/StatefulSideMenu.tsx

This file was deleted.

88 changes: 18 additions & 70 deletions packages/plattform-komponenter/src/side-menu/menuLink.module.css
Original file line number Diff line number Diff line change
@@ -1,84 +1,32 @@
.menuLink__button {
background: none;
border: 3px solid transparent;
color: #3e3832;
border: none;
cursor: pointer;
padding: 0;
display: flex;
gap: var(--a-spacing-2);
justify-content: space-between;
padding-block: var(--a-spacing-2);
padding-left: var(--a-spacing-6);
padding-right: var(--a-spacing-4);
position: relative;
text-align: left;
text-decoration: none;
width: 100%;
}

.menuLink__button:hover {
background: #e7e9e9;
}
.menuLink__button:focus {
border: 3px solid #254b6d;
outline: none;
background: var(--a-surface-hover);
}
.menuLink__button--active {
background: #e7e9e9;
border: 3px solid #e7e9e9;
border-left: transparent;
padding-left: 0.1875rem;

.menuLink__button__active {
background: var(--a-surface-hover);
text-shadow: 0 0 0.1px #333; /* bruker text-shadow i steden for font-weight for å unngå endring i bredde */
}
.menuLink__button--active:before {
background: #0067c5;

.menuLink__button__active:before {
background: var(--a-surface-action);
content: '';
height: calc(100% + 0.375rem);
left: 0;
position: absolute;
top: -0.1875rem;
width: 0.25rem;
z-index: 1;
}
.menuLink__button--active:focus {
padding-left: 0;
}
.menuLink__button--active:focus:before {
height: 100%;
left: 0;
top: 0;
}
.menuLink__label,
.menuLink__label {
align-items: center;
color: #3e3832;
display: flex;
justify-content: space-between;
min-height: 1.625rem;
padding: 0 1.75rem;
position: relative;
}
.menuLink__label--active,
.menuLink__label--active {
background: #e7e9e9;
font-weight: 600;
}
.menuLink__label--with-icon,
.menuLink__label--with-icon {
padding-right: 0.8125rem;
}
.menuLink__icon {
margin-left: 1rem;
}
.menuLink--withArrows .menu-link__button--active:before {
display: none;
}
.menuLink--withArrows .menu-link__button:focus .menu-link__arrow-right {
border-bottom: 13px solid transparent;
border-top: 13px solid transparent;
right: 0;
top: 0;
}
.menuLink__arrow-right {
background-color: white;
border-bottom: 16px solid transparent;
border-left: 17px solid #e7e9e9;
border-top: 16px solid transparent;
height: 0;
position: absolute;
right: -3px;
top: -3px;
width: 0;
top: 0;
width: var(--a-spacing-1);
}
Loading

0 comments on commit b0a0cf2

Please sign in to comment.