Skip to content

Commit

Permalink
Merge pull request #120 from 8845musign/imple-divider
Browse files Browse the repository at this point in the history
Imple Divider Component
  • Loading branch information
takanorip authored Jul 17, 2024
2 parents c18e213 + c491db4 commit 4be9764
Show file tree
Hide file tree
Showing 9 changed files with 265 additions and 80 deletions.
16 changes: 16 additions & 0 deletions src/components/Divider/Divider.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.divider {
width: var(--width);
min-width: var(--min-width);
max-width: var(--max-width);
height: 1px;
margin: var(--margin-top) var(--margin-right) var(--margin-bottom) var(--margin-left);
border: none;
}

.divider.gray {
background-color: var(--color-border);
}

.divider.primary {
background-color: var(--color-primary);
}
42 changes: 42 additions & 0 deletions src/components/Divider/Divider.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { render, screen } from '@testing-library/react';
import { Divider } from './Divider';

describe('<Divider>', () => {
it('receives date attribute', async () => {
render(<Divider data-testid="divider" />);
const divider = screen.getByTestId('divider');

expect(divider).toBeInTheDocument();
});

it('receives max-width', async () => {
render(<Divider data-testid="divider" maxWidth="400px" />);
const divider = screen.getByTestId('divider');

expect(divider).toHaveStyle('--max-width: 400px');
});

it('receives min-width', async () => {
render(<Divider data-testid="divider" minWidth="400px" />);
const divider = screen.getByTestId('divider');

expect(divider).toHaveStyle('--min-width: 400px');
});

it('receives width', async () => {
render(<Divider data-testid="divider" width="400px" />);
const divider = screen.getByTestId('divider');

expect(divider).toHaveStyle('--width: 400px');
});

it('receives margins', async () => {
render(<Divider data-testid="divider" mt="xxs" mr="xs" mb="sm" ml="md" />);
const divider = screen.getByTestId('divider');

expect(divider).toHaveStyle('--margin-top: var(--size-spacing-xxs)');
expect(divider).toHaveStyle('--margin-right: var(--size-spacing-xs)');
expect(divider).toHaveStyle('--margin-bottom: var(--size-spacing-sm)');
expect(divider).toHaveStyle('--margin-left: var(--size-spacing-md)');
});
});
51 changes: 51 additions & 0 deletions src/components/Divider/Divider.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Meta, StoryObj } from '@storybook/react';
import { ComponentPropsWithoutRef } from 'react';
import { Divider } from './Divider';
import { Stack } from '../Stack/Stack';

export default {
component: Divider,
} satisfies Meta<typeof Divider>;

type Props = ComponentPropsWithoutRef<typeof Divider>;

const defaultArgs: Props = {
border: 'gray',
};

type Story = StoryObj<typeof Divider>;

export const Default: Story = {
render: (args) => <Divider {...args} />,
args: defaultArgs,
};

export const BorderVariants: Story = {
render: () => {
return (
<Stack spacing="md">
<Divider border="gray" />
<Divider border="primary" />
</Stack>
);
},
};

export const Margins: Story = {
render: (args) => <Divider {...args} />,
args: {
...defaultArgs,
mt: 'md',
mr: 'lg',
mb: 'xl',
ml: 'xxl',
},
};

export const Width: Story = {
render: (args) => <Divider {...args} />,
args: {
...defaultArgs,
width: '50%',
},
};
48 changes: 48 additions & 0 deletions src/components/Divider/Divider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
'use client';

import { clsx } from 'clsx';
import { forwardRef, type HTMLAttributes } from 'react';
import styles from './Divider.module.css';
import { MarginProps, WidthProps } from '../../types/style';
import { marginVariables, widthVariables } from '../../utils/style';

type AllowedHRAttributes = Omit<HTMLAttributes<HTMLHRElement>, 'className'>;

type Props = {
/**
* ボーダーの種類
*/
border?: 'gray' | 'primary';
} & WidthProps &
MarginProps &
AllowedHRAttributes;

export const Divider = forwardRef<HTMLHRElement, Props>(
({ border = 'gray', m, mx, my, mt, mr, mb, ml, width, minWidth, maxWidth, ...rest }, ref) => {
return (
<hr
className={clsx(styles.divider, styles[border])}
style={{
...marginVariables({
m,
mx,
my,
mt,
mr,
mb,
ml,
}),
...widthVariables({
width,
minWidth,
maxWidth,
}),
}}
ref={ref}
{...rest}
/>
);
},
);

Divider.displayName = 'Divider';
16 changes: 3 additions & 13 deletions src/components/FlexItem/FlexItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@
import { clsx } from 'clsx';
import { CSSProperties, forwardRef, type PropsWithChildren, type HTMLAttributes } from 'react';
import styles from './FlexItem.module.css';
import { MarginProps, PaddingProps } from '../../types/style';
import { CSSWitdh, MarginProps, PaddingProps, WidthProps } from '../../types/style';
import { marginVariables, paddingVariables } from '../../utils/style';
import { CSSWitdh, CSSMaxWidth, CSSMinWidth } from '../../utils/types';

type FlexProperty = {
grow?: number;
Expand All @@ -21,17 +20,8 @@ type Props = {
* @defaultValue none
*/
flex?: 'none' | FlexProperty;
/**
* 最小幅
* @defaultValue auto
*/
minWidth?: CSSMinWidth;
/**
* 最大幅
* @defaultValue none
*/
maxWidth?: CSSMaxWidth;
} & MarginProps &
} & Omit<WidthProps, 'width'> &
MarginProps &
PaddingProps &
AllowedDivAttributes;

Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export { Box } from './components/Box/Box';
export { Button } from './components/Button/Button';
export { ButtonCard } from './components/ButtonCard/ButtonCard';
export { Center } from './components/Center/Center';
export { Divider } from './components/Divider/Divider';
export { Heading } from './components/Heading/Heading';
export { LinkButton } from './components/Button/LinkButton';
export { ErrorMessage } from './components/ErrorMessage/ErrorMessage';
Expand Down
85 changes: 85 additions & 0 deletions src/types/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,88 @@ export type RadiusProp = {
};

export type BackgroundColor = 'primary' | 'primaryDarken' | 'accent' | 'accentDarken' | 'alert' | 'gray' | 'white';

export type CSSVariable = `var(--${string})`;

// ref: https://developer.mozilla.org/en-US/docs/Web/CSS/flex-basis
export type CSSLength =
| `${string}cap`
| `${string}ch`
| `${string}em`
| `${string}ex`
| `${string}ic`
| `${string}lh`
| `${string}rcap`
| `${string}rem`
| `${string}rex`
| `${string}ric`
| `${string}rlh`
| `${string}vh`
| `${string}vmax`
| `${string}vmin`
| `${string}vw`
| `${string}vb`
| `${string}vi`
| `${string}cqw`
| `${string}cqh`
| `${string}cqi`
| `${string}cqb`
| `${string}cqmin`
| `${string}cqmax`
| `${string}px`
| `${string}cm`
| `${string}mm`
| `${string}q`
| `${string}in`
| `${string}pc`
| `${string}pt`;

export type CSSPercentage = `${string}%`;

export type CSSLengthPercentage = CSSLength | CSSPercentage;

export type CSSWitdh =
| CSSLength
| CSSPercentage
| 'auto'
| 'fit-content'
| `fit-content(${CSSLengthPercentage})`
| 'min-content'
| 'max-content'
| CSSVariable;

export type CSSMaxWidth =
| 'none'
| CSSLengthPercentage
| 'min-content'
| 'max-content'
| 'fit-content'
| `fit-content(${CSSLengthPercentage})`
| CSSVariable;

export type CSSMinWidth =
| 'auto'
| CSSLengthPercentage
| 'min-content'
| 'max-content'
| 'fit-content'
| `fit-content(${CSSLengthPercentage})`
| CSSVariable;

export type WidthProps = {
/**
* 幅を指定
* @default 'auto'
*/
width?: CSSWitdh;
/**
* 最小幅
* @default 'auto'
*/
minWidth?: CSSMinWidth;
/**
* 最大幅
* @default 'none'
*/
maxWidth?: CSSMaxWidth;
};
19 changes: 19 additions & 0 deletions src/utils/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ import type {
HeadingLeading,
TagLeading,
TextColor,
CSSMinWidth,
CSSMaxWidth,
CSSWitdh,
} from '../types/style';
import type { CSSProperties } from 'react';

Expand Down Expand Up @@ -239,3 +242,19 @@ export const gapVariables = (spacing?: Spacing) => {
'--gap': spacing ? `var(--size-spacing-${spacing})` : '0',
} as CSSProperties;
};

export const widthVariables = ({
width = 'auto',
minWidth = 'auto',
maxWidth = 'none',
}: {
width?: CSSWitdh;
minWidth?: CSSMinWidth;
maxWidth?: CSSMaxWidth;
}) => {
return {
'--width': width,
'--min-width': minWidth,
'--max-width': maxWidth,
} as CSSProperties;
};
67 changes: 0 additions & 67 deletions src/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,70 +4,3 @@ export type AllOrNone<T> = T | Partial<Record<keyof T, undefined>>;
export type DistributiveOmit<T, TOmitted extends PropertyKey> = T extends any ? Omit<T, TOmitted> : never;

export type HTMLTagname = keyof HTMLElementTagNameMap;

export type CSSVariable = `var(--${string})`;

// ref: https://developer.mozilla.org/en-US/docs/Web/CSS/flex-basis
export type CSSLength =
| `${string}cap`
| `${string}ch`
| `${string}em`
| `${string}ex`
| `${string}ic`
| `${string}lh`
| `${string}rcap`
| `${string}rem`
| `${string}rex`
| `${string}ric`
| `${string}rlh`
| `${string}vh`
| `${string}vmax`
| `${string}vmin`
| `${string}vw`
| `${string}vb`
| `${string}vi`
| `${string}cqw`
| `${string}cqh`
| `${string}cqi`
| `${string}cqb`
| `${string}cqmin`
| `${string}cqmax`
| `${string}px`
| `${string}cm`
| `${string}mm`
| `${string}q`
| `${string}in`
| `${string}pc`
| `${string}pt`;

export type CSSPercentage = `${string}%`;

export type CSSLengthPercentage = CSSLength | CSSPercentage;

export type CSSWitdh =
| CSSLength
| CSSPercentage
| 'auto'
| 'fit-content'
| `fit-content(${CSSLengthPercentage})`
| 'min-content'
| 'max-content'
| CSSVariable;

export type CSSMaxWidth =
| 'none'
| CSSLengthPercentage
| 'min-content'
| 'max-content'
| 'fit-content'
| `fit-content(${CSSLengthPercentage})`
| CSSVariable;

export type CSSMinWidth =
| 'auto'
| CSSLengthPercentage
| 'min-content'
| 'max-content'
| 'fit-content'
| `fit-content(${CSSLengthPercentage})`
| CSSVariable;

0 comments on commit 4be9764

Please sign in to comment.