diff --git a/src-docs/src/views/button/button_example.js b/src-docs/src/views/button/button_example.js index b864a9b9e5..f74918b59f 100644 --- a/src-docs/src/views/button/button_example.js +++ b/src-docs/src/views/button/button_example.js @@ -139,6 +139,11 @@ const buttonGroupIconsHtml = renderToHtml(ButtonGroupIcons); import ButtonGroupCompressed from './button_group_compressed'; const buttonGroupCompressedSource = require('!!raw-loader!./button_group_compressed'); const buttonGroupCompressedHtml = renderToHtml(ButtonGroupCompressed); + +import ButtonGroupVertical from './button_group_vertical'; +const ButtonGroupVerticalSource = require('!!raw-loader!./button_group_vertical'); +const ButtonGroupVerticalHtml = renderToHtml(ButtonGroupVertical); + const buttonGroupSnippet = [ ``, ]; +const ButtonGroupVerticalSnippet = [ + ` {}} +/>`, +]; + export const ButtonExample = { title: 'Button', sections: [ @@ -469,6 +491,26 @@ export const ButtonExample = { demo: , snippet: buttonGroupIconsSnippet, }, + { + source: [ + { + type: GuideSectionTypes.JS, + code: ButtonGroupVerticalSource, + }, + { + type: GuideSectionTypes.HTML, + code: ButtonGroupVerticalHtml, + }, + ], + wrapText: false, + text: ( + +

Vertical orientated

+
+ ), + demo: , + snippet: ButtonGroupVerticalSnippet, + }, { source: [ { diff --git a/src-docs/src/views/button/button_group_vertical.js b/src-docs/src/views/button/button_group_vertical.js new file mode 100644 index 0000000000..8590fb970a --- /dev/null +++ b/src-docs/src/views/button/button_group_vertical.js @@ -0,0 +1,179 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +import React, { useState, Fragment } from 'react'; + +import { + OuiButtonGroup, + OuiSpacer, + OuiTitle, +} from '../../../../src/components'; + +import { htmlIdGenerator } from '../../../../src/services'; + +const idPrefix = htmlIdGenerator()(); +const idPrefix3 = htmlIdGenerator()(); + +export default () => { + const [toggleIdSelected, setToggleIdSelected] = useState(`${idPrefix}1`); + + const onChange = (optionId) => { + setToggleIdSelected(optionId); + }; + + const toggleButtons = [ + { + id: `${idPrefix}0`, + label: 'Option one', + }, + { + id: `${idPrefix}1`, + label: 'Option two', + }, + { + id: `${idPrefix}2`, + label: 'Option three', + }, + ]; + + const toggleButtonsIcons = [ + { + id: `${idPrefix3}0`, + label: 'Align left', + iconType: 'editorAlignLeft', + }, + { + id: `${idPrefix3}1`, + label: 'Align center', + iconType: 'editorAlignCenter', + }, + { + id: `${idPrefix3}2`, + label: 'Align right', + iconType: 'editorAlignRight', + isDisabled: true, + }, + ]; + + const toggleButtonsIconsMulti = [ + { + id: `${idPrefix3}3`, + label: 'Bold', + name: 'bold', + iconType: 'editorBold', + }, + { + id: `${idPrefix3}4`, + label: 'Italic', + name: 'italic', + iconType: 'editorItalic', + isDisabled: true, + }, + { + id: `${idPrefix3}5`, + label: 'Underline', + name: 'underline', + iconType: 'editorUnderline', + }, + { + id: `${idPrefix3}6`, + label: 'Strikethrough', + name: 'strikethrough', + iconType: 'editorStrike', + }, + ]; + + const [toggleIconIdSelected, setToggleIconIdSelected] = useState( + `${idPrefix3}1` + ); + const [toggleIconIdToSelectedMap, setToggleIconIdToSelectedMap] = useState( + {} + ); + + const onChangeIcons = (optionId) => { + setToggleIconIdSelected(optionId); + }; + + const onChangeIconsMulti = (optionId) => { + const newToggleIconIdToSelectedMap = { + ...toggleIconIdToSelectedMap, + ...{ + [optionId]: !toggleIconIdToSelectedMap[optionId], + }, + }; + + setToggleIconIdToSelectedMap(newToggleIconIdToSelectedMap); + }; + + return ( + + onChange(id)} + /> +    + onChangeIcons(id)} + isIconOnly + /> +    + onChangeIconsMulti(id)} + type="multi" + isIconOnly + /> + + +

Compressed

+
+ onChange(id)} + /> +    + onChangeIcons(id)} + isIconOnly + /> +    + onChangeIconsMulti(id)} + type="multi" + isIconOnly + /> +
+ ); +}; diff --git a/src/components/button/button_group/__snapshots__/button_group.test.tsx.snap b/src/components/button/button_group/__snapshots__/button_group.test.tsx.snap index 54c1542442..45f3628bff 100644 --- a/src/components/button/button_group/__snapshots__/button_group.test.tsx.snap +++ b/src/components/button/button_group/__snapshots__/button_group.test.tsx.snap @@ -2475,6 +2475,546 @@ exports[`OuiButtonGroup button props isIconOnly is rendered for single 1`] = ` `; +exports[`OuiButtonGroup button props orientation horizontal is rendered for multi 1`] = ` +
+ + test + +
+ + + +
+
+`; + +exports[`OuiButtonGroup button props orientation horizontal is rendered for single 1`] = ` +
+ + test + +
+ + + +
+
+`; + +exports[`OuiButtonGroup button props orientation horizontal is rendered with compressed 1`] = ` +
+ + test + +
+ + + +
+
+`; + +exports[`OuiButtonGroup button props orientation vertical is rendered for multi 1`] = ` +
+ + test + +
+ + + +
+
+`; + +exports[`OuiButtonGroup button props orientation vertical is rendered for single 1`] = ` +
+ + test + +
+ + + +
+
+`; + +exports[`OuiButtonGroup button props orientation vertical is rendered with compressed 1`] = ` +
+ + test + +
+ + + +
+
+`; + exports[`OuiButtonGroup button props selection idSelected is rendered for single 1`] = `
= [ 'compressed', ]; +const ORIENTATIONS: Array = [ + 'horizontal', + 'vertical', +]; + const options: OuiButtonGroupOptionProps[] = [ { id: 'button00', @@ -102,6 +107,39 @@ describe('OuiButtonGroup', () => { }); describe('button props', () => { + describe('orientation', () => { + ORIENTATIONS.forEach((orientation) => { + test(`${orientation} is rendered for single`, () => { + const component = render( + + ); + + expect(component).toMatchSnapshot(); + }); + test(`${orientation} is rendered for multi`, () => { + const component = render( + + ); + + expect(component).toMatchSnapshot(); + }); + test(`${orientation} is rendered with compressed`, () => { + const component = render( + + ); + + expect(component).toMatchSnapshot(); + }); + }); + }); + describe('buttonSize', () => { SIZES.forEach((size) => { test(`${size} is rendered for single`, () => { diff --git a/src/components/button/button_group/button_group.tsx b/src/components/button/button_group/button_group.tsx index c0e5a00f3c..10ae34c6f6 100644 --- a/src/components/button/button_group/button_group.tsx +++ b/src/components/button/button_group/button_group.tsx @@ -90,6 +90,10 @@ export type OuiButtonGroupProps = CommonProps & { * With `'multi'` multiple options selected (similar to checkbox group). */ type?: 'single' | 'multi'; + /** + * Determines if the buttons should be horizontal oriented or vertical oriented + */ + orientation?: 'horizontal' | 'vertical'; /** * An array of #OuiButtonGroupOptionProps */ @@ -155,6 +159,7 @@ export const OuiButtonGroup: FunctionComponent = ({ onChange, options = [], type = 'single', + orientation = 'horizontal', ...rest }) => { // Compressed style can't support `ghost` color because it's more like a form field than a button @@ -173,6 +178,7 @@ export const OuiButtonGroup: FunctionComponent = ({ { 'ouiButtonGroup--fullWidth': isFullWidth, 'ouiButtonGroup--isDisabled': isDisabled, + 'ouiButtonGroup--vertical': orientation === 'vertical', }, className );