Skip to content

Commit

Permalink
Merge pull request #739 from inhibitor1217/features/stack
Browse files Browse the repository at this point in the history
Stack 컴포넌트군 추가
  • Loading branch information
inhibitor1217 authored Apr 28, 2022
2 parents e3ce9ee + 978d452 commit 505f710
Show file tree
Hide file tree
Showing 26 changed files with 846 additions and 0 deletions.
19 changes: 19 additions & 0 deletions src/components/Stack/HStack/HStack.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/* External dependencies */
import React, { forwardRef } from 'react'
import type { Ref } from 'react'

/* Internal dependencies */
import { Stack } from 'Components/Stack/Stack'
import type HStackProps from './HStack.types'

/**
* A container for horizontal flex layout.
*/
function HStack(
props: HStackProps,
forwardedRef: Ref<HTMLElement>,
) {
return (<Stack ref={forwardedRef} direction="horizontal" {...props} />)
}

export default forwardRef(HStack)
4 changes: 4 additions & 0 deletions src/components/Stack/HStack/HStack.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/* Internal dependencies */
import type { StackProps } from 'Components/Stack/Stack'

export default interface HStackProps extends Omit<StackProps, 'direction'> {}
2 changes: 2 additions & 0 deletions src/components/Stack/HStack/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as HStack } from './HStack'
export type { default as HStackProps } from './HStack.types'
25 changes: 25 additions & 0 deletions src/components/Stack/Spacer/Spacer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/* External dependencies */
import React, { forwardRef } from 'react'
import type { Ref } from 'react'

/* Internal dependencies */
import { StackItem } from 'Components/Stack/StackItem'
import type SpacerProps from './Spacer.types'

function Spacer(
props: SpacerProps,
forwardedRef: Ref<HTMLElement>,
) {
return (
<StackItem
ref={forwardedRef}
size={0}
weight={1}
grow
shrink
{...props}
/>
)
}

export default forwardRef(Spacer)
5 changes: 5 additions & 0 deletions src/components/Stack/Spacer/Spacer.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/* Internal dependencies */
import type { BezierComponentProps } from 'Types/ComponentProps'

export default interface SpacerProps extends
BezierComponentProps {}
2 changes: 2 additions & 0 deletions src/components/Stack/Spacer/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as Spacer } from './Spacer'
export type { default as SpacerProps } from './Spacer.types'
182 changes: 182 additions & 0 deletions src/components/Stack/Stack.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
/* External dependencies */
import React, { useState } from 'react'
import type {
Meta,
Story,
} from '@storybook/react'
import base from 'paths.macro'
import {
keys,
random,
range,
values,
} from 'lodash-es'

/* Internal dependencies */
import type { SemanticNames } from 'Foundation'
import { LightTheme } from 'Foundation/Colors/Theme'
import { getTitle } from 'Utils/storyUtils'
import { Stack } from './Stack'
import { StackItem } from './StackItem'
import type { AxisAlignment } from './types'

export default {
title: getTitle(base),
argTypes: {
containerSize: {
control: {
type: 'range',
min: 400,
max: 1200,
step: 10,
},
},
direction: {
control: {
type: 'radio',
options: ['horizontal', 'vertical'],
},
},
justify: {
control: {
type: 'radio',
options: ['start', 'center', 'end', 'stretch'],
},
},
align: {
control: {
type: 'radio',
options: ['start', 'center', 'end', 'stretch'],
},
},
spacing: {
control: {
type: 'range',
min: 0,
max: 32,
step: 4,
},
},
},
} as Meta

const randomColor = (): SemanticNames => values(LightTheme)[random(keys(LightTheme).length)] as SemanticNames
const randomSize = (): number => Math.floor((random(true) * 240) + 120)

const Item = ({
fixedSize,
direction,
}: {
fixedSize: boolean
direction: 'horizontal' | 'vertical'
}) => {
const [color] = useState(() => randomColor())
const [alignSize] = useState(() => randomSize())

return (
<div
style={{
width: (fixedSize && direction === 'vertical') ? alignSize : '100%',
height: (fixedSize && direction === 'horizontal') ? alignSize : '100%',
backgroundColor: color,
borderRadius: '4px',
boxShadow: 'inset 0 0 1px #c0c0c0',
}}
/>
)
}

interface StackPreviewProps {
containerSize: number

/* Stack Props */
direction: 'horizontal' | 'vertical'
justify: AxisAlignment
align: AxisAlignment
spacing: number

/* Item Props */
itemJustifies: (AxisAlignment | undefined)[]
itemAligns: (AxisAlignment | undefined)[]
itemSizes: (number | undefined)[]
itemWeights: (number | undefined)[]
itemGrows: (boolean | undefined)[]
itemShrinks: (boolean | undefined)[]
itemMarginBefores: (number | undefined)[]
itemMarginAfters: (number | undefined)[]
}

const Template: Story<StackPreviewProps> = ({
containerSize,

direction,
justify,
align,
spacing,

itemJustifies,
itemAligns,
itemSizes,
itemWeights,
itemGrows,
itemShrinks,
itemMarginBefores,
itemMarginAfters,
}: StackPreviewProps) => (
<>
<div
style={{
border: '1px solid #e0e0e0',
borderRadius: 4,
...(
direction === 'horizontal'
? { width: containerSize, height: 480 }
: { width: 480, height: containerSize }
),
}}
>
<Stack
direction={direction}
justify={justify}
align={align}
spacing={spacing}
>
{ range(4)
.map(i => (
<StackItem
key={`item-${i}`}
justify={itemJustifies[i]}
align={itemAligns[i]}
size={itemSizes[i]}
weight={itemWeights[i]}
grow={itemGrows[i]}
shrink={itemShrinks[i]}
marginBefore={itemMarginBefores[i]}
marginAfter={itemMarginAfters[i]}
>
<Item direction={direction} fixedSize={(align ?? itemAligns[i]) !== 'stretch'} />
</StackItem>
)) }
</Stack>
</div>
</>
)

export const Primary: Story<StackPreviewProps> = Template.bind({})
Primary.args = {
containerSize: 800,

direction: 'horizontal',
justify: 'start',
align: 'start',
spacing: 0,

itemJustifies: [],
itemAligns: [],
itemSizes: [120, 240, 180, 120],
itemWeights: [],
itemGrows: [],
itemShrinks: [],
itemMarginBefores: [],
itemMarginAfters: [],
}
30 changes: 30 additions & 0 deletions src/components/Stack/Stack/Stack.styled.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/* Internal dependencies */
import {
css,
styled,
} from 'Foundation'
import { flex } from 'Components/Stack/util'
import type StackProps from './Stack.types'

interface ContainerProps extends
Required<Pick<StackProps, 'interpolation' | 'direction' | 'justify' | 'align'>> {}

export const Container = styled.div<ContainerProps>`
display: flex;
width: 100%;
height: 100%;
${({ direction }) => css`
flex-direction: ${direction === 'horizontal' ? 'row' : 'column'};
`}
${({ justify }) => css`
justify-content: ${flex(justify)};
`}
${({ align }) => css`
align-items: ${flex(align)};
`}
${({ interpolation }) => interpolation}
`
55 changes: 55 additions & 0 deletions src/components/Stack/Stack/Stack.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/* External dependencies */
import React from 'react'

/* Internal dependencies */
import { css } from 'Foundation'
import { render } from 'Utils/testUtils'
import Stack from './Stack'

describe('Stack', () => {
describe('Flex layout', () => {
it('creates a flexbox', () => {
const { getByTestId } = render(<Stack direction="horizontal" testId="stack" />)

expect(getByTestId('stack')).toHaveStyle('display: flex')
})

it('creates a horizontal flexbox when given direction="horizontal"', () => {
const { getByTestId } = render(<Stack direction="horizontal" testId="stack" />)

expect(getByTestId('stack')).toHaveStyle('flex-direction: row')
})

it('creates a vertical flexbox when given direction="vertical"', () => {
const { getByTestId } = render(<Stack direction="vertical" testId="stack" />)

expect(getByTestId('stack')).toHaveStyle('flex-direction: column')
})
})

describe('Supports BezierComponentProps interface', () => {
it('supports as prop', () => {
const { getByTestId } = render(<Stack direction="horizontal" testId="stack" as="main" />)

expect(getByTestId('stack').tagName).toBe('MAIN')
})

it('supports style prop', () => {
const { getByTestId } = render(<Stack direction="horizontal" testId="stack" style={{ backgroundColor: 'red' }} />)

expect(getByTestId('stack')).toHaveStyle({ 'background-color': 'red' })
})

it('supports className prop', () => {
const { getByTestId } = render(<Stack direction="horizontal" testId="stack" className="foo" />)

expect(getByTestId('stack')).toHaveClass('foo')
})

it('supports interpolation prop', () => {
const { getByTestId } = render(<Stack direction="horizontal" testId="stack" interpolation={css`background-color: red;`} />)

expect(getByTestId('stack')).toHaveStyle({ 'background-color': 'red' })
})
})
})
Loading

0 comments on commit 505f710

Please sign in to comment.