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

feat(Box): New internal component #1001

Merged
merged 13 commits into from
Nov 2, 2023
15 changes: 15 additions & 0 deletions packages/react/src/components/Box/Box.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Meta, Canvas, Story, Controls, Primary } from '@storybook/blocks';
import * as BoxStories from './Box.stories';

<Meta of={BoxStories} />

# Box

`Box` er en primitiv komponent som brukes for å bygge andre komponenter.

<Primary />
<Controls />

## As Header

<Canvas of={BoxStories.AsHeader} />
51 changes: 51 additions & 0 deletions packages/react/src/components/Box/Box.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
.box {
display: block;
}

.xsmallShadow {
box-shadow: var(--fds-shadow-xsmall);
}

.smallShadow {
box-shadow: var(--fds-shadow-small);
}

.mediumShadow {
box-shadow: var(--fds-shadow-medium);
}

.largeShadow {
box-shadow: var(--fds-shadow-large);
}

.xlargeShadow {
box-shadow: var(--fds-shadow-xlarge);
}

.defaultBorderColor {
border-color: var(--fds-semantic-border-neutral-default);
}

.subtleBorderColor {
border-color: var(--fds-semantic-border-neutral-subtle);
}

.smallBorderRadius {
border-radius: var(--fds-border_radius-small);
}

.mediumBorderRadius {
border-radius: var(--fds-border_radius-medium);
}

.largeBorderRadius {
border-radius: var(--fds-border_radius-large);
}

.defaultBackground {
background-color: var(--fds-semantic-background-default);
}

.subtleBackground {
background-color: var(--fds-semantic-background-subtle);
}
34 changes: 34 additions & 0 deletions packages/react/src/components/Box/Box.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from 'react';
import type { Meta, StoryFn } from '@storybook/react';

import { Box } from './Box';

type Story = StoryFn<typeof Box>;

const meta: Meta<typeof Box> = {
title: 'Felles/Box',
component: Box,
parameters: {
layout: 'padded',
},
};

export default meta;

export const Preview: Story = (args) => <Box {...args}>Box!</Box>;

Preview.args = {
children: 'Box!',
shadow: 'medium',
borderRadius: 'medium',
background: 'default',
};

export const AsHeader: Story = (args) => (
<Box
{...args}
as='header'
>
Box!
</Box>
);
53 changes: 53 additions & 0 deletions packages/react/src/components/Box/Box.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React from 'react';
import { render as renderRtl, screen } from '@testing-library/react';

import type { BoxProps } from './Box';
import { Box } from './Box';

const render = (props?: BoxProps) =>
renderRtl(
<Box
{...props}
title='box'
/>,
);

describe('Box', () => {
it('should render a div with default classname', () => {
render();
const box = screen.getByTitle('box');

expect(box.classList).toContain('box');
expect(box.classList).toContain('mediumShadow');
expect(box.classList).toContain('mediumBorderRadius');
expect(box.classList).toContain('defaultBackground');
});

it('should render a div with correct classname when shadow is xsmall', () => {
render({ shadow: 'xsmall' });
const box = screen.getByTitle('box');

expect(box.classList).toContain('xsmallShadow');
});

it('should render a div with correct classname when borderColor is subtle', () => {
render({ borderColor: 'subtle' });
const box = screen.getByTitle('box');

expect(box.classList).toContain('subtleBorderColor');
});

it('should render a div with correct classname when borderRadius is small', () => {
render({ borderRadius: 'small' });
const box = screen.getByTitle('box');

expect(box.classList).toContain('smallBorderRadius');
});

it('should render the box as a header', () => {
render({ as: 'header' });
const box = screen.getByTitle('box');

expect(box.tagName).toBe('HEADER');
});
});
58 changes: 58 additions & 0 deletions packages/react/src/components/Box/Box.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import type { ElementType, HTMLAttributes } from 'react';
import React from 'react';
import cn from 'classnames';

import classes from './Box.module.css';

export type BoxProps = {
/**
* The element to render as
*/
as?: ElementType;
/**
* Shadow size of the box
* @default medium
*/
shadow?: 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge';
/**
* Border color of the box
* @default undefined
*/
borderColor?: 'default' | 'subtle';
/**
* Border radius of the box
* @default medium
*/
borderRadius?: 'small' | 'medium' | 'large';
/**
* Background color of the box
* @default 'defualt'
*/
background?: 'default' | 'subtle';
} & HTMLAttributes<HTMLDivElement>;

export const Box = ({
as: Component = 'div',
shadow = 'medium',
borderColor,
borderRadius = 'medium',
background = 'default',
children,
...rest
}: BoxProps) => {
return (
<Component
className={cn(
classes.box,
classes[shadow + 'Shadow'],
classes[borderRadius + 'BorderRadius'],
borderColor && classes[borderColor + 'BorderColor'],
classes[background + 'Background'],
rest.className,
)}
{...rest}
>
{children}
</Component>
);
};
2 changes: 2 additions & 0 deletions packages/react/src/components/Box/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { Box } from './Box';
export type { BoxProps } from './Box';
Loading