diff --git a/components/button-group/__tests__/__snapshots__/index.test.tsx.snap b/components/button-group/__tests__/__snapshots__/index.test.tsx.snap new file mode 100644 index 0000000..ae8ca85 --- /dev/null +++ b/components/button-group/__tests__/__snapshots__/index.test.tsx.snap @@ -0,0 +1,493 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ButtonGroup buttons should be displayed vertically 1`] = ` +"
" +`; + +exports[`ButtonGroup props should be passed to each button 1`] = ` +"
" +`; + +exports[`ButtonGroup props should be passed to each button 2`] = ` +"
" +`; + +exports[`ButtonGroup should render correctly 1`] = ` +"
" +`; diff --git a/components/button-group/__tests__/index.test.tsx b/components/button-group/__tests__/index.test.tsx new file mode 100644 index 0000000..d85eda9 --- /dev/null +++ b/components/button-group/__tests__/index.test.tsx @@ -0,0 +1,53 @@ +import React from 'react' +import { mount } from 'enzyme' +import { ButtonGroup, Button } from 'components' +import { nativeEvent } from 'tests/utils' + +describe('ButtonGroup', () => { + it('should render correctly', () => { + const wrapper = mount( + + + , + ) + expect(wrapper.html()).toMatchSnapshot() + expect(() => wrapper.unmount()).not.toThrow() + }) + + it('props should be passed to each button', () => { + const wrapper = mount( + + + , + ) + expect(wrapper.html()).toMatchSnapshot() + wrapper.setProps({ ghost: true }) + expect(wrapper.html()).toMatchSnapshot() + expect(() => wrapper.unmount()).not.toThrow() + }) + + it('should ignore events when group disabled', () => { + const handler = jest.fn() + const wrapper = mount( + + + , + ) + wrapper.find('button').simulate('click', nativeEvent) + expect(handler).toHaveBeenCalledTimes(1) + wrapper.setProps({ disabled: true }) + wrapper.find('button').simulate('click', nativeEvent) + expect(handler).toHaveBeenCalledTimes(1) + }) + + it('buttons should be displayed vertically', () => { + const wrapper = mount( + + + + , + ) + expect(wrapper.html()).toMatchSnapshot() + expect(() => wrapper.unmount()).not.toThrow() + }) +}) diff --git a/components/button-group/button-group-context.ts b/components/button-group/button-group-context.ts new file mode 100644 index 0000000..a9c9329 --- /dev/null +++ b/components/button-group/button-group-context.ts @@ -0,0 +1,20 @@ +import React from 'react' +import { NormalSizes, ButtonTypes } from '../utils/prop-types' + +export interface ButtonGroupConfig { + size?: NormalSizes + type?: ButtonTypes + ghost?: boolean + disabled?: boolean + isButtonGroup: boolean +} + +const defaultContext = { + isButtonGroup: false, + disabled: false, +} + +export const ButtonGroupContext = React.createContext(defaultContext) + +export const useButtonGroupContext = (): ButtonGroupConfig => + React.useContext(ButtonGroupContext) diff --git a/components/button-group/button-group.tsx b/components/button-group/button-group.tsx new file mode 100644 index 0000000..867ebda --- /dev/null +++ b/components/button-group/button-group.tsx @@ -0,0 +1,116 @@ +import React, { useMemo } from 'react' +import useTheme from '../styles/use-theme' +import withDefaults from '../utils/with-defaults' +import { NormalSizes, ButtonTypes } from '../utils/prop-types' +import { ButtonGroupContext, ButtonGroupConfig } from './button-group-context' +import { getButtonColors } from '../button/styles' + +interface Props { + disabled?: boolean + vertical?: boolean + ghost?: boolean + size?: NormalSizes + type?: ButtonTypes + className?: string +} + +const defaultProps = { + disabled: false, + vertical: false, + ghost: false, + size: 'medium' as NormalSizes, + type: 'default' as ButtonTypes, + className: '', +} + +type NativeAttrs = Omit, keyof Props> +export type ButtonGroupProps = Props & typeof defaultProps & NativeAttrs + +const ButtonGroup: React.FC> = ({ + disabled, + size, + type, + ghost, + vertical, + children, + className, +}) => { + const theme = useTheme() + const initialValue = useMemo( + () => ({ + disabled, + size, + type, + ghost, + isButtonGroup: true, + }), + [disabled, size, type], + ) + + const { border } = useMemo(() => { + const results = getButtonColors(theme, type, disabled, ghost) + if (!ghost && type !== 'default') + return { + ...results, + border: theme.palette.background, + } + return results + }, [theme, type, disabled, ghost]) + + return ( + +
+ {children} + +
+
+ ) +} + +const MemoButtonGroup = React.memo(ButtonGroup) + +export default withDefaults(MemoButtonGroup, defaultProps) diff --git a/components/button-group/index.ts b/components/button-group/index.ts new file mode 100644 index 0000000..cc398ed --- /dev/null +++ b/components/button-group/index.ts @@ -0,0 +1,3 @@ +import ButtonGroup from './button-group' + +export default ButtonGroup diff --git a/components/button/__tests__/__snapshots__/icon.test.tsx.snap b/components/button/__tests__/__snapshots__/icon.test.tsx.snap index 07c3288..cdaf903 100644 --- a/components/button/__tests__/__snapshots__/icon.test.tsx.snap +++ b/components/button/__tests__/__snapshots__/icon.test.tsx.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`ButtonIcon should render correctly 1`] = ` -"