Skip to content

Commit 6120a91

Browse files
committed
Add ButtonGroup component (#205)
1 parent cf4b190 commit 6120a91

File tree

22 files changed

+444
-40
lines changed

22 files changed

+444
-40
lines changed

demo/generated/demo.js

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/lib.js

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@react-ui-org/react-ui",
3-
"version": "0.20.0",
3+
"version": "0.21.0",
44
"license": "MIT",
55
"main": "dist/lib.js",
66
"repository": {

src/demo/pages/DemoContainer.jsx

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
Alert,
1010
Badge,
1111
Button,
12+
ButtonGroup,
1213
Card,
1314
CheckboxField,
1415
Documentation,
@@ -628,6 +629,45 @@ class DemoContainer extends React.Component {
628629
</>
629630
)}
630631
/>
632+
<h3 id="ui-components-button-group" className="typography-size-4 mb-6">Button Group</h3>
633+
<Documentation
634+
name="Button group"
635+
component={(
636+
<>
637+
<div className="mb-3">
638+
<ButtonGroup aria-label="Accessible group label">
639+
<Button clickHandler={loggerClick} label="One" variant="dark" />
640+
<Button clickHandler={loggerClick} label="Two" />
641+
<Button clickHandler={loggerClick} label="Three" />
642+
</ButtonGroup>
643+
</div>
644+
<div className="mb-3">
645+
<ButtonGroup aria-label="Accessible group label" priority="outline">
646+
<Button clickHandler={loggerClick} label="One" variant="dark" />
647+
<Button clickHandler={loggerClick} label="Two" />
648+
<Button clickHandler={loggerClick} label="Three" />
649+
</ButtonGroup>
650+
</div>
651+
<div>
652+
<ButtonGroup aria-label="Accessible group label" priority="flat">
653+
<Button clickHandler={loggerClick} label="One" variant="dark" />
654+
<Button clickHandler={loggerClick} label="Two" />
655+
<Button clickHandler={loggerClick} label="Three" />
656+
</ButtonGroup>
657+
</div>
658+
</>
659+
)}
660+
/>
661+
<Documentation
662+
name="Block button group"
663+
component={(
664+
<ButtonGroup aria-label="Accessible group label" block priority="outline">
665+
<Button clickHandler={loggerClick} label="One" variant="dark" />
666+
<Button clickHandler={loggerClick} label="Two" />
667+
<Button clickHandler={loggerClick} label="Three" />
668+
</ButtonGroup>
669+
)}
670+
/>
631671
<h3 id="ui-components-card" className="typography-size-4 mb-6">Card</h3>
632672
<Documentation
633673
name="Card types"

src/demo/pages/navigation.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ export default [
6161
link: '#ui-components-button',
6262
title: 'Button',
6363
},
64+
{
65+
link: '#ui-components-button-group',
66+
title: 'Button Group',
67+
},
6468
{
6569
link: '#ui-components-card',
6670
title: 'Card',

src/lib/components/screens/Login/__tests__/__snapshots__/ForgotPassword.test.jsx.snap

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ exports[`rendering renders correctly 1`] = `
9090
clickHandler={null}
9191
disabled={false}
9292
endCorner={null}
93+
grouped={false}
9394
label="Reset password"
9495
labelVisibility="all"
9596
loadingIcon={null}
@@ -219,6 +220,7 @@ exports[`rendering renders correctly 2`] = `
219220
clickHandler={null}
220221
disabled={false}
221222
endCorner={null}
223+
grouped={false}
222224
label="Reset password"
223225
labelVisibility="all"
224226
loadingIcon={null}
@@ -376,6 +378,7 @@ exports[`rendering renders correctly with all props except translations 1`] = `
376378
clickHandler={null}
377379
disabled={false}
378380
endCorner={null}
381+
grouped={false}
379382
id="custom-id__resetPasswordButton"
380383
label="Reset password"
381384
labelVisibility="all"

src/lib/components/screens/Login/__tests__/__snapshots__/Login.test.jsx.snap

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ exports[`rendering renders correctly 1`] = `
143143
clickHandler={null}
144144
disabled={false}
145145
endCorner={null}
146+
grouped={false}
146147
label="Sign in"
147148
labelVisibility="all"
148149
loadingIcon={null}
@@ -352,6 +353,7 @@ exports[`rendering renders correctly with all props except translations 1`] = `
352353
clickHandler={null}
353354
disabled={false}
354355
endCorner={null}
356+
grouped={false}
355357
id="custom-id__signInButton"
356358
label="Sign in"
357359
labelVisibility="all"
@@ -549,6 +551,7 @@ exports[`rendering renders correctly with translations 1`] = `
549551
clickHandler={null}
550552
disabled={false}
551553
endCorner={null}
554+
grouped={false}
552555
label="Přihlásit se"
553556
labelVisibility="all"
554557
loadingIcon={null}
@@ -727,6 +730,7 @@ exports[`rendering renders correctly with username 1`] = `
727730
clickHandler={null}
728731
disabled={false}
729732
endCorner={null}
733+
grouped={false}
730734
label="Sign in"
731735
labelVisibility="all"
732736
loadingIcon={null}

src/lib/components/screens/Login/__tests__/__snapshots__/NewPassword.test.jsx.snap

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ exports[`rendering renders correctly 1`] = `
141141
clickHandler={null}
142142
disabled={false}
143143
endCorner={null}
144+
grouped={false}
144145
label="Change password"
145146
labelVisibility="all"
146147
loadingIcon={null}
@@ -348,6 +349,7 @@ exports[`rendering renders correctly with all props except translations 1`] = `
348349
clickHandler={null}
349350
disabled={false}
350351
endCorner={null}
352+
grouped={false}
351353
id="custom-id__changePasswordButton"
352354
label="Change password"
353355
labelVisibility="all"
@@ -542,6 +544,7 @@ exports[`rendering renders correctly with translations 1`] = `
542544
clickHandler={null}
543545
disabled={false}
544546
endCorner={null}
547+
grouped={false}
545548
label="Změnit heslo"
546549
labelVisibility="all"
547550
loadingIcon={null}

src/lib/components/ui/Button/Button.jsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ const Button = (props) => {
3535
blockClass = styles.isRootBlock;
3636
}
3737

38+
let groupedClass = '';
39+
if (props.grouped) {
40+
groupedClass = styles.isRootGrouped;
41+
}
42+
3843
let labelVisibilityClass = '';
3944
if (props.labelVisibility === 'desktop') {
4045
labelVisibilityClass = styles.withLabelHiddenMobile;
@@ -50,6 +55,7 @@ const Button = (props) => {
5055
${sizeClass}
5156
${variantClass}
5257
${blockClass}
58+
${groupedClass}
5359
${labelVisibilityClass}
5460
`).trim()}
5561
id={props.id}
@@ -100,6 +106,7 @@ Button.defaultProps = {
100106
clickHandler: null,
101107
disabled: false,
102108
endCorner: null,
109+
grouped: false,
103110
id: undefined,
104111
labelVisibility: 'all',
105112
loadingIcon: null,
@@ -117,6 +124,7 @@ Button.propTypes = {
117124
clickHandler: PropTypes.func,
118125
disabled: PropTypes.bool,
119126
endCorner: PropTypes.element,
127+
grouped: PropTypes.bool,
120128
id: PropTypes.string,
121129
label: PropTypes.string.isRequired,
122130
labelVisibility: PropTypes.oneOf(['all', 'desktop', 'none']),

src/lib/components/ui/Button/Button.scss

Lines changed: 58 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,35 @@
3434
justify-content: center;
3535
}
3636

37+
.loadingIcon {
38+
animation: rotateIcon 2s linear infinite;
39+
}
40+
41+
.beforeLabel {
42+
margin-right: $button-icon-offset;
43+
}
44+
45+
.afterLabel,
46+
.loadingIcon {
47+
margin-left: $button-icon-offset;
48+
}
49+
50+
.startCorner,
51+
.endCorner {
52+
position: absolute;
53+
top: -0.35rem;
54+
}
55+
56+
.startCorner {
57+
left: 0;
58+
margin-left: -0.35rem;
59+
}
60+
61+
.endCorner {
62+
right: 0;
63+
margin-right: -0.35rem;
64+
}
65+
3766
.sizeSmall {
3867
@include button-size(small);
3968
}
@@ -58,6 +87,20 @@
5887
}
5988
}
6089

90+
.isRootGrouped {
91+
&:not(:first-child) {
92+
margin-left: calc(-1 * #{$button-border-width});
93+
border-top-left-radius: 0;
94+
border-bottom-left-radius: 0;
95+
}
96+
97+
&:not(:last-child) {
98+
margin-right: 0;
99+
border-top-right-radius: 0;
100+
border-bottom-right-radius: 0;
101+
}
102+
}
103+
61104
.withLabelHidden .label,
62105
.withLabelHiddenMobile .label {
63106
@include accessibility-hide-text();
@@ -71,35 +114,6 @@
71114
}
72115
}
73116

74-
.loadingIcon {
75-
animation: rotateIcon 2s linear infinite;
76-
}
77-
78-
.beforeLabel {
79-
margin-right: $button-icon-offset;
80-
}
81-
82-
.afterLabel,
83-
.loadingIcon {
84-
margin-left: $button-icon-offset;
85-
}
86-
87-
.startCorner,
88-
.endCorner {
89-
position: absolute;
90-
top: -0.35rem;
91-
}
92-
93-
.startCorner {
94-
left: 0;
95-
margin-left: -0.35rem;
96-
}
97-
98-
.endCorner {
99-
right: 0;
100-
margin-right: -0.35rem;
101-
}
102-
103117
.withLabelHidden .beforeLabel,
104118
.withLabelHidden .afterLabel,
105119
.withLabelHiddenMobile .beforeLabel,
@@ -194,3 +208,18 @@
194208
.priorityFlat.variantDark {
195209
@include button-variant(flat, dark);
196210
}
211+
212+
// Grouped buttons
213+
.priorityDefault.isRootGrouped:not(:first-child)::before,
214+
.priorityFlat.isRootGrouped:not(:first-child)::before {
215+
content: '';
216+
position: absolute;
217+
top: calc(-1 * #{$button-border-width});
218+
bottom: calc(-1 * #{$button-border-width});
219+
left: calc(-1 * #{$button-border-width});
220+
border-left: $button-border-width solid $color-white;
221+
}
222+
223+
.priorityFlat.isRootGrouped:not(:first-child)::before {
224+
border-left-color: currentColor;
225+
}

src/lib/components/ui/Button/_mixins.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// 1. Get ready for position of corner elements.
1+
// 1. Get ready for position of corner elements and group separator.
22
// 2. Icon buttons should be squares.
33

44
@import '../../../styles/tools/explode';

src/lib/components/ui/Button/tests/Button.test.jsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ describe('rendering', () => {
8989
id="custom-id"
9090
disabled
9191
block
92+
grouped
9293
/>);
9394

9495
expect(shallowToJson(tree)).toMatchSnapshot();

src/lib/components/ui/Button/tests/__snapshots__/Button.test.jsx.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ exports[`rendering renders correctly label visibility 1`] = `
2626
sizeMedium
2727
variantPrimary
2828
29+
2930
withLabelHidden"
3031
disabled={false}
3132
onClick={null}
@@ -123,6 +124,7 @@ exports[`rendering renders correctly with all props 1`] = `
123124
sizeLarge
124125
variantSuccess
125126
isRootBlock
127+
isRootGrouped
126128
withLabelHiddenMobile"
127129
disabled={true}
128130
id="custom-id"

0 commit comments

Comments
 (0)