-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feat(web-react): Introduce ActionGroup component #DS-1607
- Loading branch information
1 parent
06895ab
commit c01dc94
Showing
25 changed files
with
633 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
37 changes: 37 additions & 0 deletions
37
packages/web-react/src/components/ActionGroup/ActionGroup.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
'use client'; | ||
|
||
import classNames from 'classnames'; | ||
import React, { ReactElement } from 'react'; | ||
import { useStyleProps } from '../../hooks'; | ||
import { SpiritActionGroupProps } from '../../types'; | ||
import { useActionGroupStyleProps } from './useActionGroupStyleProps'; | ||
|
||
const defaultProps: Partial<SpiritActionGroupProps> = { | ||
direction: 'row', | ||
}; | ||
|
||
const ActionGroup = (props: SpiritActionGroupProps): ReactElement => { | ||
const { children, ...restProps } = props; | ||
const propsWithDefaults = { ...defaultProps, ...restProps }; | ||
const { | ||
classProps, | ||
props: modifiedProps, | ||
styleProps: actionGroupStyle, | ||
} = useActionGroupStyleProps(propsWithDefaults); | ||
const { styleProps, props: otherProps } = useStyleProps(modifiedProps); | ||
|
||
const actionGroupStyleProps = { | ||
style: { | ||
...styleProps.style, | ||
...actionGroupStyle, | ||
}, | ||
}; | ||
|
||
return ( | ||
<div {...otherProps} {...actionGroupStyleProps} className={classNames(classProps, styleProps.className)}> | ||
{children} | ||
</div> | ||
); | ||
}; | ||
|
||
export default ActionGroup; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# Action Group |
102 changes: 102 additions & 0 deletions
102
packages/web-react/src/components/ActionGroup/__tests__/ActionGroup.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
import '@testing-library/jest-dom'; | ||
import { render, screen } from '@testing-library/react'; | ||
import React from 'react'; | ||
import { classNamePrefixProviderTest, restPropsTest, stylePropsTest } from '@local/tests'; | ||
import ActionGroup from '../ActionGroup'; | ||
|
||
describe('ActionGroup', () => { | ||
const text = 'Hello world'; | ||
const testId = 'action-group-test-id'; | ||
|
||
classNamePrefixProviderTest(ActionGroup, 'ActionGroup'); | ||
|
||
stylePropsTest(ActionGroup); | ||
|
||
restPropsTest(ActionGroup, 'div'); | ||
|
||
it('should render text children', () => { | ||
render(<ActionGroup data-testid={testId}>{text}</ActionGroup>); | ||
|
||
expect(screen.getByText(text)).toBeInTheDocument(); | ||
expect(screen.getByTestId(testId)).toHaveClass('ActionGroup ActionGroup--row'); | ||
}); | ||
|
||
it('should have direction class name', () => { | ||
render(<ActionGroup direction="column" data-testid={testId} />); | ||
|
||
expect(screen.getByTestId(testId)).toHaveClass('ActionGroup--column'); | ||
}); | ||
|
||
it('should have responsive direction class name', () => { | ||
render(<ActionGroup direction={{ mobile: 'row', tablet: 'column', desktop: 'column' }} data-testid={testId} />); | ||
|
||
expect(screen.getByTestId(testId)).toHaveClass( | ||
'ActionGroup--row ActionGroup--tablet--column ActionGroup--desktop--column', | ||
); | ||
}); | ||
|
||
it('should have alignmentX class name', () => { | ||
render(<ActionGroup alignmentX="left" data-testid={testId} />); | ||
|
||
expect(screen.getByTestId(testId)).toHaveClass('ActionGroup--alignmentXLeft'); | ||
}); | ||
|
||
it('should have responsive alignmentX class name', () => { | ||
render(<ActionGroup alignmentX={{ mobile: 'left', tablet: 'center', desktop: 'right' }} data-testid={testId} />); | ||
|
||
expect(screen.getByTestId(testId)).toHaveClass( | ||
'ActionGroup--alignmentXLeft ActionGroup--tablet--alignmentXCenter ActionGroup--desktop--alignmentXRight', | ||
); | ||
}); | ||
|
||
it('should render with custom spacing', () => { | ||
render(<ActionGroup spacing="space-600" data-testid={testId} />); | ||
|
||
expect(screen.getByTestId(testId)).toHaveStyle({ '--flex-spacing-x': 'var(--spirit-space-600)' }); | ||
expect(screen.getByTestId(testId)).toHaveStyle({ '--flex-spacing-y': 'var(--spirit-space-600)' }); | ||
}); | ||
|
||
it('should render with custom spacingX and spacingY', () => { | ||
render(<ActionGroup spacingX="space-500" spacingY="space-1600" data-testid={testId} />); | ||
|
||
expect(screen.getByTestId(testId)).toHaveStyle({ '--flex-spacing-x': 'var(--spirit-space-500)' }); | ||
expect(screen.getByTestId(testId)).toHaveStyle({ '--flex-spacing-y': 'var(--spirit-space-1600)' }); | ||
}); | ||
|
||
it('should render with custom spacing for each breakpoint', () => { | ||
render( | ||
<ActionGroup | ||
spacing={{ mobile: 'space-100', tablet: 'space-1000', desktop: 'space-1200' }} | ||
data-testid={testId} | ||
/>, | ||
); | ||
|
||
const element = screen.getByTestId(testId) as HTMLElement; | ||
|
||
expect(element).toHaveStyle({ '--flex-spacing-x': 'var(--spirit-space-100)' }); | ||
expect(element).toHaveStyle({ '--flex-spacing-y': 'var(--spirit-space-100)' }); | ||
expect(element).toHaveStyle({ '--flex-spacing-x-tablet': 'var(--spirit-space-1000)' }); | ||
expect(element).toHaveStyle({ '--flex-spacing-y-tablet': 'var(--spirit-space-1000)' }); | ||
expect(element).toHaveStyle({ '--flex-spacing-x-desktop': 'var(--spirit-space-1200)' }); | ||
expect(element).toHaveStyle({ '--flex-spacing-y-desktop': 'var(--spirit-space-1200)' }); | ||
}); | ||
|
||
it('should render with custom spacingX and spacingY for each breakpoint', () => { | ||
render( | ||
<ActionGroup | ||
spacingX={{ mobile: 'space-100', tablet: 'space-1000', desktop: 'space-1200' }} | ||
spacingY={{ mobile: 'space-200', tablet: 'space-1100', desktop: 'space-1600' }} | ||
data-testid={testId} | ||
/>, | ||
); | ||
|
||
const element = screen.getByTestId(testId) as HTMLElement; | ||
|
||
expect(element).toHaveStyle({ '--flex-spacing-x': 'var(--spirit-space-100)' }); | ||
expect(element).toHaveStyle({ '--flex-spacing-y': 'var(--spirit-space-200)' }); | ||
expect(element).toHaveStyle({ '--flex-spacing-x-tablet': 'var(--spirit-space-1000)' }); | ||
expect(element).toHaveStyle({ '--flex-spacing-y-tablet': 'var(--spirit-space-1100)' }); | ||
expect(element).toHaveStyle({ '--flex-spacing-x-desktop': 'var(--spirit-space-1200)' }); | ||
expect(element).toHaveStyle({ '--flex-spacing-y-desktop': 'var(--spirit-space-1600)' }); | ||
}); | ||
}); |
92 changes: 92 additions & 0 deletions
92
packages/web-react/src/components/ActionGroup/__tests__/useActionGroupStyleProps.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
import { renderHook } from '@testing-library/react'; | ||
import { SpiritFlexProps } from '../../../types'; | ||
import { useActionGroupStyleProps } from '../useActionGroupStyleProps'; | ||
|
||
describe('useActionGroupStyleProps', () => { | ||
it.each([ | ||
// props, expectedClasses | ||
[{}, 'ActionGroup'], | ||
[{ direction: 'row' }, 'ActionGroup ActionGroup--row'], | ||
[{ direction: 'column' }, 'ActionGroup ActionGroup--column'], | ||
[ | ||
{ | ||
direction: { mobile: 'row', tablet: 'column', desktop: 'row' }, | ||
}, | ||
'ActionGroup ActionGroup--row ActionGroup--tablet--column ActionGroup--desktop--row', | ||
], | ||
[{ alignmentX: 'left' }, 'ActionGroup ActionGroup--alignmentXLeft'], | ||
[ | ||
{ | ||
alignmentX: { mobile: 'left', tablet: 'center', desktop: 'right' }, | ||
}, | ||
'ActionGroup ActionGroup--alignmentXLeft ActionGroup--tablet--alignmentXCenter ActionGroup--desktop--alignmentXRight', | ||
], | ||
])('should return the correct classes for props %o', (props, expectedClasses) => { | ||
const { result } = renderHook(() => useActionGroupStyleProps(props as SpiritFlexProps)); | ||
|
||
expect(result.current.classProps).toBe(expectedClasses); | ||
}); | ||
|
||
it.each([ | ||
// props, expectedStyleProps | ||
[{}, {}], | ||
[ | ||
{ spacing: 'space-100' }, | ||
{ '--flex-spacing-x': 'var(--spirit-space-100)', '--flex-spacing-y': 'var(--spirit-space-100)' }, | ||
], | ||
[ | ||
{ spacingX: 'space-100', spacingY: 'space-200' }, | ||
{ '--flex-spacing-x': 'var(--spirit-space-100)', '--flex-spacing-y': 'var(--spirit-space-200)' }, | ||
], | ||
[ | ||
{ | ||
spacing: { mobile: 'space-100', tablet: 'space-200' }, | ||
}, | ||
{ | ||
'--flex-spacing-x': 'var(--spirit-space-100)', | ||
'--flex-spacing-x-tablet': 'var(--spirit-space-200)', | ||
'--flex-spacing-y': 'var(--spirit-space-100)', | ||
'--flex-spacing-y-tablet': 'var(--spirit-space-200)', | ||
}, | ||
], | ||
[ | ||
{ | ||
spacingX: { mobile: 'space-100', tablet: 'space-200' }, | ||
spacingY: { mobile: 'space-300', tablet: 'space-400' }, | ||
}, | ||
{ | ||
'--flex-spacing-x': 'var(--spirit-space-100)', | ||
'--flex-spacing-x-tablet': 'var(--spirit-space-200)', | ||
'--flex-spacing-y': 'var(--spirit-space-300)', | ||
'--flex-spacing-y-tablet': 'var(--spirit-space-400)', | ||
}, | ||
], | ||
[ | ||
{ | ||
spacing: { mobile: 'space-100', tablet: 'space-200', desktop: 'space-400' }, | ||
}, | ||
{ | ||
'--flex-spacing-x': 'var(--spirit-space-100)', | ||
'--flex-spacing-x-tablet': 'var(--spirit-space-200)', | ||
'--flex-spacing-x-desktop': 'var(--spirit-space-400)', | ||
'--flex-spacing-y': 'var(--spirit-space-100)', | ||
'--flex-spacing-y-tablet': 'var(--spirit-space-200)', | ||
'--flex-spacing-y-desktop': 'var(--spirit-space-400)', | ||
}, | ||
], | ||
[ | ||
{ | ||
spacingX: { mobile: 'space-100', tablet: 'space-200', desktop: 'space-400' }, | ||
}, | ||
{ | ||
'--flex-spacing-x': 'var(--spirit-space-100)', | ||
'--flex-spacing-x-tablet': 'var(--spirit-space-200)', | ||
'--flex-spacing-x-desktop': 'var(--spirit-space-400)', | ||
}, | ||
], | ||
])('should return the correct style properties for props %o', (props, expectedStyleProps) => { | ||
const { result } = renderHook(() => useActionGroupStyleProps(props as SpiritFlexProps)); | ||
|
||
expect(result.current.styleProps).toEqual(expectedStyleProps); | ||
}); | ||
}); |
15 changes: 15 additions & 0 deletions
15
packages/web-react/src/components/ActionGroup/demo/ColumnLayout.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import React from 'react'; | ||
import { Button } from '../../Button'; | ||
import ActionGroup from '../ActionGroup'; | ||
|
||
const ColumnLayout = () => { | ||
return ( | ||
<ActionGroup direction="column"> | ||
<Button color="primary">Primary Action</Button> | ||
<Button color="secondary">Secondary Action</Button> | ||
<Button color="tertiary">Tertiary Action</Button> | ||
</ActionGroup> | ||
); | ||
}; | ||
|
||
export default ColumnLayout; |
15 changes: 15 additions & 0 deletions
15
packages/web-react/src/components/ActionGroup/demo/ColumnReverseLayout.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import React from 'react'; | ||
import { Button } from '../../Button'; | ||
import ActionGroup from '../ActionGroup'; | ||
|
||
const ColumnReverseLayout = () => { | ||
return ( | ||
<ActionGroup direction="column-reverse"> | ||
<Button color="primary">Primary Action</Button> | ||
<Button color="secondary">Secondary Action</Button> | ||
<Button color="tertiary">Tertiary Action</Button> | ||
</ActionGroup> | ||
); | ||
}; | ||
|
||
export default ColumnReverseLayout; |
15 changes: 15 additions & 0 deletions
15
packages/web-react/src/components/ActionGroup/demo/CustomHorizontalSpacing.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import React from 'react'; | ||
import { Button } from '../../Button'; | ||
import ActionGroup from '../ActionGroup'; | ||
|
||
const CustomHorizontalSpacing = () => { | ||
return ( | ||
<ActionGroup spacingX="space-1200"> | ||
<Button color="primary">Primary Action</Button> | ||
<Button color="secondary">Secondary Action</Button> | ||
<Button color="tertiary">Tertiary Action</Button> | ||
</ActionGroup> | ||
); | ||
}; | ||
|
||
export default CustomHorizontalSpacing; |
15 changes: 15 additions & 0 deletions
15
packages/web-react/src/components/ActionGroup/demo/CustomVerticalLayout.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import React from 'react'; | ||
import { Button } from '../../Button'; | ||
import ActionGroup from '../ActionGroup'; | ||
|
||
const CustomVerticalSpacing = () => { | ||
return ( | ||
<ActionGroup direction="column" spacingY="space-1200"> | ||
<Button color="primary">Primary Action</Button> | ||
<Button color="secondary">Secondary Action</Button> | ||
<Button color="tertiary">Tertiary Action</Button> | ||
</ActionGroup> | ||
); | ||
}; | ||
|
||
export default CustomVerticalSpacing; |
27 changes: 27 additions & 0 deletions
27
packages/web-react/src/components/ActionGroup/demo/HorizontalAlignment.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import React from 'react'; | ||
import { Button } from '../../Button'; | ||
import ActionGroup from '../ActionGroup'; | ||
|
||
const HorizontalAlignment = () => { | ||
return ( | ||
<> | ||
<ActionGroup alignmentX="left"> | ||
<Button color="primary">Primary Action</Button> | ||
<Button color="secondary">Secondary Action</Button> | ||
<Button color="tertiary">Tertiary Action</Button> | ||
</ActionGroup> | ||
<ActionGroup alignmentX="center"> | ||
<Button color="primary">Primary Action</Button> | ||
<Button color="secondary">Secondary Action</Button> | ||
<Button color="tertiary">Tertiary Action</Button> | ||
</ActionGroup> | ||
<ActionGroup alignmentX="right"> | ||
<Button color="primary">Primary Action</Button> | ||
<Button color="secondary">Secondary Action</Button> | ||
<Button color="tertiary">Tertiary Action</Button> | ||
</ActionGroup> | ||
</> | ||
); | ||
}; | ||
|
||
export default HorizontalAlignment; |
15 changes: 15 additions & 0 deletions
15
packages/web-react/src/components/ActionGroup/demo/ResponsiveCustomHorizontalSpacing.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import React from 'react'; | ||
import { Button } from '../../Button'; | ||
import ActionGroup from '../ActionGroup'; | ||
|
||
const CustomHorizontalSpacing = () => { | ||
return ( | ||
<ActionGroup spacingX={{ mobile: 'space-700', tablet: 'space-1200' }}> | ||
<Button color="primary">Primary Action</Button> | ||
<Button color="secondary">Secondary Action</Button> | ||
<Button color="tertiary">Tertiary Action</Button> | ||
</ActionGroup> | ||
); | ||
}; | ||
|
||
export default CustomHorizontalSpacing; |
15 changes: 15 additions & 0 deletions
15
packages/web-react/src/components/ActionGroup/demo/ResponsiveCustomVerticalSpacing.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import React from 'react'; | ||
import { Button } from '../../Button'; | ||
import ActionGroup from '../ActionGroup'; | ||
|
||
const ResponsiveCustomVerticalSpacing = () => { | ||
return ( | ||
<ActionGroup direction="column" spacingY={{ mobile: 'space-700', tablet: 'space-1200' }}> | ||
<Button color="primary">Primary Action</Button> | ||
<Button color="secondary">Secondary Action</Button> | ||
<Button color="tertiary">Tertiary Action</Button> | ||
</ActionGroup> | ||
); | ||
}; | ||
|
||
export default ResponsiveCustomVerticalSpacing; |
15 changes: 15 additions & 0 deletions
15
packages/web-react/src/components/ActionGroup/demo/ResponsiveHorizontalAlignment.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import React from 'react'; | ||
import { Button } from '../../Button'; | ||
import ActionGroup from '../ActionGroup'; | ||
|
||
const ResponsiveHorizontalAlignment = () => { | ||
return ( | ||
<ActionGroup alignmentX={{ mobile: 'right', tablet: 'center', desktop: 'left' }}> | ||
<Button color="primary">Primary Action</Button> | ||
<Button color="secondary">Secondary Action</Button> | ||
<Button color="tertiary">Tertiary Action</Button> | ||
</ActionGroup> | ||
); | ||
}; | ||
|
||
export default ResponsiveHorizontalAlignment; |
Oops, something went wrong.