Skip to content
Open
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
6 changes: 6 additions & 0 deletions .storybook/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,14 @@ module.exports = {
styles: path.resolve(__dirname, '../src/styles'),
hooks: path.resolve(__dirname, '../src/hooks'),
utils: path.resolve(__dirname, '../src/utils'),
helpers: path.resolve(__dirname, '../src/helpers'),
}

return config
},

babel: async (options) => ({
...options,
plugins: [['@babel/plugin-proposal-class-properties', { loose: true }]],
}),
}
1 change: 1 addition & 0 deletions .storybook/preview.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import '../src/styles/index.css'
import '../src/styles/theme.css'
import './styles/theme.css'

export const parameters = {
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
"test:ci": "jest --ci --coverage",
"storybook": "start-storybook -p 6006 -s ./.storybook",
"build-storybook": "build-storybook -s ./.storybook",
"prepare": "yarn build",
"commit": "cz",
"semantic-release": "semantic-release"
},
Expand All @@ -38,6 +37,7 @@
"@rollup/plugin-commonjs": "^15.0.0",
"@testing-library/user-event": "^12.1.3",
"@types/react-transition-group": "^4.4.0",
"@types/tailwindcss": "^2.2.1",
"clsx": "^1.1.1",
"compute-scroll-into-view": "^1.0.16",
"dayjs": "^1.9.3",
Expand All @@ -64,6 +64,7 @@
"@testing-library/react": "^10.4.9",
"@types/jest": "^26.0.10",
"@types/react": "^17.0.0",
"@types/react-color": "^3.0.5",
"@types/react-dom": "^17.0.0",
"@typescript-eslint/eslint-plugin": "^4.14.1",
"@typescript-eslint/parser": "^4.14.1",
Expand Down Expand Up @@ -92,6 +93,7 @@
"postcss-loader": "^3.0.0",
"prettier": "^2.1.1",
"react": "^17.0.1",
"react-color": "^2.19.3",
"react-dom": "^17.0.1",
"react-icons": "^4.2.0",
"react-is": "^16.13.1",
Expand Down
75 changes: 75 additions & 0 deletions src/components/button/button.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import React from 'react'
import { Meta } from '@storybook/react/types-6-0'
import colors from 'tailwindcss/colors'
import defaultTheme from 'tailwindcss/defaultTheme'
import {
HiShieldCheck,
HiOutlinePlus,
Expand All @@ -8,11 +10,47 @@ import {
HiOutlinePencilAlt,
HiOutlineChevronRight,
} from 'react-icons/hi'
import ThemeDecorator from 'helpers/theme-decorator'
import { Button } from './button'

export default {
title: 'General/Button',
component: Button,
decorators: [
(Story) => (
<ThemeDecorator
darkTheme={{
'--primary-color': colors.cyan['600'],
'--error-color': colors.red['500'],
'--disabled-color': colors.gray['600'],
}}
themeConfig={{
'--primary-color': {
type: 'color',
initialValue: colors.green['600'],
},
'--error-color': {
type: 'color',
initialValue: colors.rose['500'],
},
'--disabled-color': {
type: 'color',
initialValue: colors.blueGray['400'],
},
'--border-radius-default': {
type: 'number',
initialValue: 0.25,
},
'--font-family': {
type: 'string',
initialValue: defaultTheme.fontFamily?.sans.join(',') ?? '',
},
}}
>
<Story />
</ThemeDecorator>
),
],
} as Meta

export function DefaultButton() {
Expand All @@ -23,6 +61,10 @@ export function DefaultButtonWithIcon() {
return <Button label="Update Password" icon={<HiShieldCheck />} />
}

export function DefaultDisabledButtonWithIcon() {
return <Button label="Update Password" icon={<HiShieldCheck />} disabled />
}

export function DefaultIconButton() {
return <Button icon={<HiOutlinePlus />} />
}
Expand Down Expand Up @@ -61,6 +103,17 @@ export function PrimaryButtonWithIcon() {
)
}

export function PrimaryDisabledButtonWithIcon() {
return (
<Button
buttonType={Button.ButtonType.primary}
label="Create Account"
icon={<HiCheckCircle />}
disabled
/>
)
}

export function PrimaryLoadingButton() {
return (
<Button
Expand Down Expand Up @@ -107,8 +160,30 @@ export function LinkButtonWithIcon() {
)
}

export function LinkDisabledButtonWithIcon() {
return (
<Button
buttonType={Button.ButtonType.link}
label="Edit Post"
icon={<HiOutlinePencilAlt />}
disabled
/>
)
}

export function LinkLoadingButton() {
return (
<Button buttonType={Button.ButtonType.link} label="Updating Post" loading />
)
}

export function LinkDisabledLoadingButton() {
return (
<Button
buttonType={Button.ButtonType.link}
label="Updating Post"
loading
disabled
/>
)
}
10 changes: 6 additions & 4 deletions src/components/button/button.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,17 @@ test('render icon after label when iconPlacement is afterLabel', () => {
test('render default disabled button correctly', () => {
render(<Button label="Click Me" disabled />)
expect(screen.getByRole('button')).toHaveClass(
'border-gray-400 text-gray-400',
'border-disabled text-disabled',
)
})

test('render primary disabled button correctly', () => {
render(
<Button label="Click Me" disabled buttonType={Button.ButtonType.primary} />,
)
expect(screen.getByRole('button')).toHaveClass('bg-gray-400 text-white')
expect(screen.getByRole('button')).toHaveClass(
'bg-disabled text-text-inverse',
)
})

test('render danger disabled button correctly', () => {
Expand All @@ -123,13 +125,13 @@ test('render danger disabled button correctly', () => {
/>,
)
expect(screen.getByRole('button')).toHaveClass(
'border-gray-400 text-gray-400',
'border-disabled text-disabled',
)
})

test('render link disabled button correctly', () => {
render(
<Button label="Click Me" disabled buttonType={Button.ButtonType.link} />,
)
expect(screen.getByRole('button')).toHaveClass('text-gray-400')
expect(screen.getByRole('button')).toHaveClass('text-disabled')
})
18 changes: 9 additions & 9 deletions src/components/button/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,32 +64,32 @@ const ButtonComponent = forwardRef(
const buttonClassNames = useMemo(() => {
if (buttonType === ButtonType.default) {
if (disabled) {
return 'border-gray-400 text-gray-400 default'
return 'border-disabled text-disabled default'
}
return 'border-blue-600 text-blue-600 hover:bg-blue-600 hover:text-white default'
return 'border-primary text-primary hover:bg-primary hover:text-text-inverse default'
}

if (buttonType === ButtonType.primary) {
if (disabled) {
return 'bg-gray-400 text-white border-transparent primary'
return 'bg-disabled text-text-inverse border-transparent primary'
}

return 'bg-blue-600 text-white border-transparent primary'
return 'bg-primary text-text-inverse border-transparent primary'
}

if (buttonType === ButtonType.danger) {
if (disabled) {
return 'border-gray-400 text-gray-400 danger'
return 'border-disabled text-disabled danger'
}

return 'border-red-500 text-red-500 hover:bg-red-500 hover:text-white danger'
return 'border-error text-error hover:bg-error hover:text-text-inverse danger'
}

// if none of the above branches are satisfied, then the button is of type link
if (disabled) {
return 'border-transparent text-gray-400 link'
return 'border-transparent text-disabled link'
}
return 'border-transparent text-blue-600 link'
return 'border-transparent text-primary link'
}, [buttonType, disabled])

const iconComponent = loading ? (
Expand All @@ -102,7 +102,7 @@ const ButtonComponent = forwardRef(
<button
aria-label={label || restProps['aria-label']}
className={clsx(
'py-2 rounded-md focus:outline-none focus:ring-2 border text-sm font-medium flex items-center justify-center space-x-2 transition-colors duration-300',
'font-default py-2 rounded-default focus:outline-none focus:ring-2 border text-sm font-medium flex items-center justify-center space-x-2 transition-colors duration-300',
iconOnlyButton ? 'px-2' : 'px-3',
buttonClassNames,
disabled || loading ? 'cursor-not-allowed' : 'cursor-pointer',
Expand Down
6 changes: 4 additions & 2 deletions src/components/form/form.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,12 @@ test('children as function works correctly with form', async () => {
)}
</Form>,
)
expect(screen.getByText('Submit').parentElement).toHaveClass('bg-gray-400')
expect(screen.getByText('Submit').parentElement).toHaveAttribute('disabled')
userEvent.type(screen.getByRole('textbox'), 'test@example.com')
await waitFor(() => {
expect(screen.getByText('Submit').parentElement).toHaveClass('bg-blue-600')
expect(screen.getByText('Submit').parentElement).not.toHaveAttribute(
'disabled',
)
})
})

Expand Down
24 changes: 12 additions & 12 deletions src/components/pagination/pagination.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,23 @@ test('pagination component working correctly', () => {

test('Next button of pagination component working correctly', () => {
render(<Pagination total={50} />)
expect(screen.getByText('1').parentElement).toHaveClass('bg-blue-600')
expect(screen.getByText('1').parentElement).toHaveClass('primary')
fireEvent.click(screen.getByText('Next'))
expect(screen.getByText('2').parentElement).toHaveClass('bg-blue-600')
expect(screen.getByText('2').parentElement).toHaveClass('primary')
})

test('Previous button of pagination component working correctly', () => {
render(<Pagination total={50} defaultCurrent={3} />)
expect(screen.getByText('3').parentElement).toHaveClass('bg-blue-600')
expect(screen.getByText('3').parentElement).toHaveClass('primary')
fireEvent.click(screen.getByText('Previous'))
expect(screen.getByText('2').parentElement).toHaveClass('bg-blue-600')
expect(screen.getByText('2').parentElement).toHaveClass('primary')
})

test('Page buttons of pagination component working correctly', () => {
render(<Pagination total={50} />)
expect(screen.getByText('1').parentElement).toHaveClass('bg-blue-600')
expect(screen.getByText('1').parentElement).toHaveClass('primary')
fireEvent.click(screen.getByText('3'))
expect(screen.getByText('3').parentElement).toHaveClass('bg-blue-600')
expect(screen.getByText('3').parentElement).toHaveClass('primary')
})

/** Tests for page size changer in pagination component */
Expand All @@ -43,42 +43,42 @@ test('Change selected page when value of total number of pages changes', () => {
render(<Pagination total={100} showSizeChanger defaultCurrent={10} />)
fireEvent.click(screen.getByText('10 / page'))
fireEvent.click(screen.getByText('20 / page'))
expect(screen.getByText('5').parentElement).toHaveClass('bg-blue-600')
expect(screen.getByText('5').parentElement).toHaveClass('primary')
})

/** Tests for page jumper */
test('Page jumper of pagination component working correctly', () => {
render(<Pagination total={50} showQuickJumper />)
userEvent.type(screen.getByRole('textbox'), '3')
fireEvent.blur(screen.getByDisplayValue('3'))
expect(screen.getByText('3').parentElement).toHaveClass('bg-blue-600')
expect(screen.getByText('3').parentElement).toHaveClass('primary')
})

test('Out of range value in page jumper working correctly', () => {
render(<Pagination total={50} defaultCurrent={3} showQuickJumper />)
userEvent.type(screen.getByRole('textbox'), '-1')
fireEvent.blur(screen.getByDisplayValue('-1'))
expect(screen.getByText('1').parentElement).toHaveClass('bg-blue-600')
expect(screen.getByText('1').parentElement).toHaveClass('primary')

userEvent.type(screen.getByRole('textbox'), '10')
fireEvent.blur(screen.getByDisplayValue('10'))
expect(screen.getByText('5').parentElement).toHaveClass('bg-blue-600')
expect(screen.getByText('5').parentElement).toHaveClass('primary')
})

test('Enter key shortcut for page jumper working correctly', () => {
render(<Pagination total={100} showQuickJumper />)
const input = screen.getByRole('textbox')
userEvent.type(input, '5')
fireEvent.keyDown(input, { key: 'Enter', code: 13 })
expect(screen.getByText('5').parentElement).toHaveClass('bg-blue-600')
expect(screen.getByText('5').parentElement).toHaveClass('primary')
})

test('invalid entries in page jumper working correctly', () => {
render(<Pagination total={100} defaultCurrent={5} showQuickJumper />)
const input = screen.getByRole('textbox')
userEvent.type(input, 'abc')
fireEvent.keyDown(input, { key: 'Enter', code: 13 })
expect(screen.getByText('5').parentElement).toHaveClass('bg-blue-600')
expect(screen.getByText('5').parentElement).toHaveClass('primary')
})

/** Test cases for page wrap in pagination component */
Expand Down
Loading