Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
89 changes: 89 additions & 0 deletions src/components/experimental/Divider/Divider.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import * as React from 'react';
import { render, screen } from '@testing-library/react';
import { Divider } from './Divider';

describe('Experimental: Divider', () => {
it('renders a horizontal divider by default when not passing any props', () => {
render(<Divider />);
expect(screen.getByTestId('horizontal-divider-experimental')).toBeInTheDocument();
expect(screen.queryByTestId('vertical-divider-experimental')).not.toBeInTheDocument();
});

it('renders a vertical divider when passing vertical prop', () => {
render(<Divider vertical />);
expect(screen.getByTestId('vertical-divider-experimental')).toBeInTheDocument();
expect(screen.queryByTestId('horizontal-divider-experimental')).not.toBeInTheDocument();
});

it('renders horizontal divider with 1rem top and bottom offset', () => {
render(<Divider mt="1rem" mb="1rem" />);
const dividerInstance = screen.getByTestId('horizontal-divider-experimental');
const dividerStyle = window.getComputedStyle(dividerInstance);

expect(dividerStyle.marginTop).toBe('1rem');
expect(dividerStyle.marginBottom).toBe('1rem');
});

it('renders vertical divider with 1rem left and right offset', () => {
render(<Divider vertical ml="1rem" mr="1rem" />);
const dividerInstance = screen.getByTestId('vertical-divider-experimental');
const dividerStyle = window.getComputedStyle(dividerInstance);

expect(dividerStyle.marginLeft).toBe('1rem');
expect(dividerStyle.marginRight).toBe('1rem');
});

it('renders vertical divider with 1rem top and bottom offset when variant is middle-inset', () => {
render(<Divider vertical variant="middle-inset" />);
const dividerInstance = screen.getByTestId('vertical-divider-experimental');
const dividerStyle = window.getComputedStyle(dividerInstance);

expect(dividerStyle.marginTop).toBe('1rem');
expect(dividerStyle.marginBottom).toBe('1rem');
});

it('renders vertical divider with 1rem offset when variant is inset', () => {
render(<Divider vertical variant="inset" />);
const dividerInstance = screen.getByTestId('vertical-divider-experimental');
const dividerStyle = window.getComputedStyle(dividerInstance);

expect(dividerStyle.marginTop).toBe('1rem');
expect(dividerStyle.marginBottom).toBe('');
});

it('renders horizontal divider with 1rem left offset when variant is inset', () => {
render(<Divider variant="inset" />);
const dividerInstance = screen.getByTestId('horizontal-divider-experimental');
const dividerStyle = window.getComputedStyle(dividerInstance);

expect(dividerStyle.marginRight).toBe('');
expect(dividerStyle.marginLeft).toBe('1rem');
});

it('renders horizontal divider with overridden offset when variant is inset', () => {
render(<Divider variant="inset" ml="2rem" />);
const dividerInstance = screen.getByTestId('horizontal-divider-experimental');
const dividerStyle = window.getComputedStyle(dividerInstance);

expect(dividerStyle.marginRight).toBe('');
expect(dividerStyle.marginLeft).toBe('2rem');
});

it('renders horizontal divider with 1rem left and right offset when variant is middle-inset', () => {
render(<Divider variant="middle-inset" />);
const dividerInstance = screen.getByTestId('horizontal-divider-experimental');
const dividerStyle = window.getComputedStyle(dividerInstance);

expect(dividerStyle.marginRight).toBe('1rem');
expect(dividerStyle.marginLeft).toBe('1rem');
});

it('renders horizontal divider with overridden offset when variant is middle-inset', () => {
render(<Divider variant="middle-inset" mr="2rem" />);
const dividerInstance = screen.getByTestId('horizontal-divider-experimental');
const dividerStyle = window.getComputedStyle(dividerInstance);

expect(dividerStyle.marginRight).toBe('2rem');
expect(dividerStyle.marginLeft).toBe('1rem');
});
});
71 changes: 71 additions & 0 deletions src/components/experimental/Divider/Divider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import React from 'react';
import { compose, LayoutProps, space, SpaceProps, variant } from 'styled-system';
import styled from 'styled-components';
import { getSemanticValue } from '../../../essentials/experimental';

type DividerProps = SpaceProps &
LayoutProps & {
/**
* Set the direction of the divider to vertical
*/
vertical?: boolean;
/**
* Set the variant of the divider
*/
variant?: 'full-width' | 'inset' | 'middle-inset';
};

const horizontalVariants = variant({
prop: 'variant',
variants: {
'full-width': {
minWidth: '100%'
},
inset: {
marginLeft: '1rem'
},
'middle-inset': {
marginLeft: '1rem',
marginRight: '1rem'
}
}
});

const verticalVariants = variant({
prop: 'variant',
variants: {
'full-width': {
minHeight: '100%'
},
inset: {
marginTop: '1rem'
},
'middle-inset': {
marginTop: '1rem',
marginBottom: '1rem'
}
}
});

const HorizontalLine = styled.div<DividerProps>`
border-top: 1px solid ${getSemanticValue('divider')};
${compose(space, horizontalVariants)}
`;

const VerticalLine = styled.div<DividerProps>`
display: inline-block;
height: 100%;
border-left: 1px solid ${getSemanticValue('divider')};
${compose(space, verticalVariants)}
`;

export const Divider: React.FC<DividerProps> = ({
vertical = false,
variant: variantVal = 'full-width',
...props
}: DividerProps) =>
vertical ? (
<VerticalLine data-testid="vertical-divider-experimental" variant={variantVal} {...props} />
) : (
<HorizontalLine data-testid="horizontal-divider-experimental" variant={variantVal} {...props} />
);
131 changes: 131 additions & 0 deletions src/components/experimental/Divider/docs/Divider.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import React from 'react';
import { StoryObj, Meta } from '@storybook/react';
import { Divider } from '../Divider';
import { Text } from '../../Text/Text';

const meta: Meta = {
title: 'Experimental/Components/Divider',
component: Divider,
parameters: {
layout: 'centered'
}
};

export default meta;

type Story = StoryObj<typeof Divider>;

export const Default: Story = {
decorators: [
Story => (
<div style={{ width: '6rem', height: '6rem' }}>
<Text>One</Text>
<Story />
<Text>Two</Text>
</div>
)
],
args: {
vertical: false
}
};

export const Inset: Story = {
decorators: [
Story => (
<div style={{ width: '6rem', height: '6rem' }}>
<Text>One</Text>
<Story />
<Text>Two</Text>
</div>
)
],
args: {
vertical: false,
variant: 'inset'
}
};

export const MiddleInset: Story = {
decorators: [
Story => (
<div style={{ width: '6rem', height: '6rem' }}>
<Text>One</Text>
<Story />
<Text>Two</Text>
</div>
)
],
args: {
vertical: false,
variant: 'middle-inset'
}
};

export const VerticalDivider: Story = {
args: {
vertical: true
},
decorators: [
Story => (
<div
style={{
display: 'flex',
height: '6rem',
width: '6rem',
alignItems: 'center'
}}
>
<Text>One</Text>
<Story />
<Text>Two</Text>
</div>
)
]
};

export const VerticalInset: Story = {
decorators: [
Story => (
<div
style={{
display: 'flex',
height: '6rem',
width: '6rem',
alignItems: 'center'
}}
>
<Text>One</Text>
<Story />
<Text>Two</Text>
</div>
)
],
args: {
vertical: true,
variant: 'inset'
}
};

export const VerticalMiddleInset: Story = {
decorators: [
Story => (
<div
style={{
display: 'flex',
height: '6rem',
width: '6rem',
alignItems: 'center'
}}
>
<Text>One</Text>
<Story />
<Text>Two</Text>
</div>
)
],
args: {
vertical: true,
variant: 'middle-inset'
}
};
2 changes: 2 additions & 0 deletions src/essentials/experimental/Colors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ export const ColorPalette = {
export const SemanticColorsLight = {
// Accent
accent: 'transparent',
divider: ColorPalette.neutral['90'],
'on-accent': 'transparent',
// Interactive
interactive: ColorPalette.marooned['50'],
Expand Down Expand Up @@ -130,6 +131,7 @@ export const SemanticColorsLight = {
export const SemanticColorsDark = {
// Accent
accent: 'transparent',
divider: ColorPalette.neutral['40'],
'on-accent': 'transparent',
// Interactive
interactive: ColorPalette.marooned['70'],
Expand Down
1 change: 1 addition & 0 deletions src/essentials/experimental/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export type SemanticColorsSchema = {
'on-interactive-container': Color;
// Neutrals
surface: Color;
divider: Color;
'on-surface': Color;
'surface-variant': Color;
'on-surface-variant': Color;
Expand Down