diff --git a/CHANGELOG.md b/CHANGELOG.md
index 32138579a4..5c0bca2d7c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@
### 📈 Features/Enhancements
- Add new icons for workspaces ([#1365](https://github.com/opensearch-project/oui/pull/1365))
+- Add a property to control the gap between an icon and the content of OuiButton and OuiButtonEmpty ([#1367](https://github.com/opensearch-project/oui/pull/1367))
### 🐛 Bug Fixes
diff --git a/src/components/button/__snapshots__/button.test.tsx.snap b/src/components/button/__snapshots__/button.test.tsx.snap
index 23d70d6fdb..3f88b56ce5 100644
--- a/src/components/button/__snapshots__/button.test.tsx.snap
+++ b/src/components/button/__snapshots__/button.test.tsx.snap
@@ -205,6 +205,72 @@ exports[`OuiButton props href secures the rel attribute when the target is _blan
`;
+exports[`OuiButton props iconGap m is rendered 1`] = `
+
+
+
+
+ Content
+
+
+
+`;
+
+exports[`OuiButton props iconGap none is rendered 1`] = `
+
+
+
+
+ Content
+
+
+
+`;
+
+exports[`OuiButton props iconGap s is rendered 1`] = `
+
+
+
+
+ Content
+
+
+
+`;
+
exports[`OuiButton props iconSide left is rendered 1`] = `
{
test('is rendered', () => {
@@ -151,6 +151,20 @@ describe('OuiButton', () => {
});
});
+ describe('iconGap', () => {
+ ICON_GAPS.forEach((iconGap) => {
+ test(`${iconGap} is rendered`, () => {
+ const component = render(
+
+ Content
+
+ );
+
+ expect(component).toMatchSnapshot();
+ });
+ });
+ });
+
describe('href', () => {
it('secures the rel attribute when the target is _blank', () => {
const component = render( );
diff --git a/src/components/button/button.tsx b/src/components/button/button.tsx
index d091a866dd..a0cc3c2297 100644
--- a/src/components/button/button.tsx
+++ b/src/components/button/button.tsx
@@ -90,7 +90,7 @@ export const SIZES = keysOf(sizeToClassNameMap);
/**
* Extends OuiButtonContentProps which provides
- * `iconType`, `iconSide`, and `textProps`
+ * `iconType`, `iconSide`, `iconGap`, and `textProps`
*/
export interface OuiButtonProps extends OuiButtonContentProps, CommonProps {
children?: ReactNode;
@@ -161,6 +161,7 @@ const OuiButtonDisplay = forwardRef(
children,
className,
iconType,
+ iconGap,
iconSide = 'left',
color = 'primary',
size = 'm',
@@ -210,6 +211,7 @@ const OuiButtonDisplay = forwardRef(
isLoading={isLoading}
iconType={iconType}
iconSide={iconSide}
+ iconGap={iconGap}
textProps={{ ...textProps, className: textClassNames }}
{...contentProps}
// className has to come last to override contentProps.className
diff --git a/src/components/button/button_content.tsx b/src/components/button/button_content.tsx
index a4a5bb8a7f..f9eef9259a 100644
--- a/src/components/button/button_content.tsx
+++ b/src/components/button/button_content.tsx
@@ -35,6 +35,7 @@ import { OuiLoadingSpinner } from '../loading';
import { OuiIcon, IconType } from '../icon';
export type ButtonContentIconSide = 'left' | 'right';
+export type ButtonContentIconGap = 's' | 'm' | 'none';
const iconSideToClassNameMap: {
[side in ButtonContentIconSide]: string | null;
@@ -43,8 +44,18 @@ const iconSideToClassNameMap: {
right: 'ouiButtonContent--iconRight',
};
+const iconGapToClassNameMap: {
+ [gap in ButtonContentIconGap]: string | null;
+} = {
+ m: null,
+ s: 'ouiButtonContent--smallIconGap',
+ none: 'ouiButtonContent--noIconGap',
+};
+
export const ICON_SIDES = keysOf(iconSideToClassNameMap);
+export const ICON_GAPS = keysOf(iconGapToClassNameMap);
+
export type OuiButtonContentType = HTMLAttributes;
/**
@@ -70,6 +81,10 @@ export interface OuiButtonContentProps extends CommonProps {
'data-text'?: string;
};
iconSize?: 's' | 'm';
+ /**
+ * The gap between the icon and the content
+ */
+ iconGap?: ButtonContentIconGap;
}
export const OuiButtonContent: FunctionComponent<
@@ -80,6 +95,7 @@ export const OuiButtonContent: FunctionComponent<
isLoading = false,
iconType,
iconSize = 'm',
+ iconGap = 'm',
iconSide = 'left',
...contentProps
}) => {
@@ -105,6 +121,7 @@ export const OuiButtonContent: FunctionComponent<
const contentClassNames = classNames(
'ouiButtonContent',
iconSide ? iconSideToClassNameMap[iconSide] : null,
+ iconGap ? iconGapToClassNameMap[iconGap] : null,
contentProps && contentProps.className
);
diff --git a/src/components/button/button_empty/__snapshots__/button_empty.test.tsx.snap b/src/components/button/button_empty/__snapshots__/button_empty.test.tsx.snap
index 9bb95ce7bc..acefe9bc2c 100644
--- a/src/components/button/button_empty/__snapshots__/button_empty.test.tsx.snap
+++ b/src/components/button/button_empty/__snapshots__/button_empty.test.tsx.snap
@@ -190,6 +190,72 @@ exports[`OuiButtonEmpty props href secures the rel attribute when the target is
`;
+exports[`OuiButtonEmpty props iconGap m is rendered 1`] = `
+
+
+
+
+ Content
+
+
+
+`;
+
+exports[`OuiButtonEmpty props iconGap none is rendered 1`] = `
+
+
+
+
+ Content
+
+
+
+`;
+
+exports[`OuiButtonEmpty props iconGap s is rendered 1`] = `
+
+
+
+
+ Content
+
+
+
+`;
+
exports[`OuiButtonEmpty props iconSide left is rendered 1`] = `
{
test('is rendered', () => {
@@ -129,6 +129,20 @@ describe('OuiButtonEmpty', () => {
});
});
+ describe('iconGap', () => {
+ ICON_GAPS.forEach((iconGap) => {
+ test(`${iconGap} is rendered`, () => {
+ const component = render(
+
+ Content
+
+ );
+
+ expect(component).toMatchSnapshot();
+ });
+ });
+ });
+
describe('flush', () => {
FLUSH_TYPES.forEach((flushType) => {
test(`${flushType} is rendered`, () => {
diff --git a/src/components/button/button_empty/button_empty.tsx b/src/components/button/button_empty/button_empty.tsx
index 4c4495ebda..708bb6ca45 100644
--- a/src/components/button/button_empty/button_empty.tsx
+++ b/src/components/button/button_empty/button_empty.tsx
@@ -85,7 +85,7 @@ export const FLUSH_TYPES = keysOf(flushTypeToClassNameMap);
/**
* Extends OuiButtonContentProps which provides
- * `iconType`, `iconSide`, and `textProps`
+ * `iconType`, `iconSide`, `iconGap`, and `textProps`
*/
export interface CommonOuiButtonEmptyProps
extends OuiButtonContentProps,
@@ -136,6 +136,7 @@ export const OuiButtonEmpty: FunctionComponent = ({
children,
className,
iconType,
+ iconGap,
iconSide = 'left',
color = 'primary',
size,
@@ -189,6 +190,7 @@ export const OuiButtonEmpty: FunctionComponent = ({
iconType={iconType}
iconSide={iconSide}
iconSize={iconSize}
+ iconGap={iconGap}
textProps={{ ...textProps, className: textClassNames }}
{...contentProps}
// className has to come last to override contentProps.className
diff --git a/src/global_styling/mixins/_button.scss b/src/global_styling/mixins/_button.scss
index 9aa4c37ad2..2d5aec7052 100644
--- a/src/global_styling/mixins/_button.scss
+++ b/src/global_styling/mixins/_button.scss
@@ -76,6 +76,16 @@
margin-inline-start: 0; // 1, 2
margin-inline-end: $ouiSizeS; // 1, 2
}
+
+ &.ouiButtonContent--smallIconGap > * + * {
+ margin-inline-start: 0; // 1, 2
+ margin-inline-end: $ouiSizeXXS; // 1, 2
+ }
+
+ &.ouiButtonContent--noIconGap > * + * {
+ margin-inline-start: 0; // 1, 2
+ margin-inline-end: 0; // 1, 2
+ }
} @else {
display: flex;
justify-content: center;
@@ -84,6 +94,14 @@
> * + * {
margin-inline-start: $ouiSizeS; // 1
}
+
+ &.ouiButtonContent--smallIconGap > * + * {
+ margin-inline-start: $ouiSizeXXS; // 1
+ }
+
+ &.ouiButtonContent--noIconGap > * + * {
+ margin-inline-start: 0; // 1
+ }
}
}
diff --git a/src/global_styling/variables/_size.scss b/src/global_styling/variables/_size.scss
index 12cd4115fd..3e1670e055 100644
--- a/src/global_styling/variables/_size.scss
+++ b/src/global_styling/variables/_size.scss
@@ -11,6 +11,7 @@
$ouiSize: 16px !default;
+$ouiSizeXXS: $ouiSize * .125 !default;
$ouiSizeXS: $ouiSize * .25 !default;
$ouiSizeS: $ouiSize * .5 !default;
$ouiSizeM: $ouiSize * .75 !default;
diff --git a/src/themes/oui-next/global_styling/mixins/_button.scss b/src/themes/oui-next/global_styling/mixins/_button.scss
index 0e3f7dfc19..47de315008 100644
--- a/src/themes/oui-next/global_styling/mixins/_button.scss
+++ b/src/themes/oui-next/global_styling/mixins/_button.scss
@@ -77,6 +77,16 @@
margin-inline-start: 0; // 1, 2
margin-inline-end: $ouiSizeS; // 1, 2
}
+
+ &.ouiButtonContent--smallIconGap > * + * {
+ margin-inline-start: 0; // 1, 2
+ margin-inline-end: $ouiSizeXXS;
+ }
+
+ &.ouiButtonContent--noIconGap > * + * {
+ margin-inline-start: 0; // 1, 2
+ margin-inline-end: 0;
+ }
} @else {
display: flex;
justify-content: center;
@@ -85,6 +95,14 @@
> * + * {
margin-inline-start: $ouiSizeS; // 1
}
+
+ &.ouiButtonContent--smallIconGap > * + * {
+ margin-inline-start: $ouiSizeXXS; // 1
+ }
+
+ &.ouiButtonContent--noIconGap > * + * {
+ margin-inline-start: 0; // 1
+ }
}
}
diff --git a/src/themes/oui-next/global_styling/variables/_size.scss b/src/themes/oui-next/global_styling/variables/_size.scss
index 12cd4115fd..3e1670e055 100644
--- a/src/themes/oui-next/global_styling/variables/_size.scss
+++ b/src/themes/oui-next/global_styling/variables/_size.scss
@@ -11,6 +11,7 @@
$ouiSize: 16px !default;
+$ouiSizeXXS: $ouiSize * .125 !default;
$ouiSizeXS: $ouiSize * .25 !default;
$ouiSizeS: $ouiSize * .5 !default;
$ouiSizeM: $ouiSize * .75 !default;
diff --git a/src/themes/v9/global_styling/mixins/_button.scss b/src/themes/v9/global_styling/mixins/_button.scss
index 0e3f7dfc19..493ea25bc1 100644
--- a/src/themes/v9/global_styling/mixins/_button.scss
+++ b/src/themes/v9/global_styling/mixins/_button.scss
@@ -77,6 +77,16 @@
margin-inline-start: 0; // 1, 2
margin-inline-end: $ouiSizeS; // 1, 2
}
+
+ &.ouiButtonContent--smallIconGap > * + * {
+ margin-inline-start: 0; // 1, 2
+ margin-inline-end: $ouiSizeXXS; // 1, 2
+ }
+
+ &.ouiButtonContent--noIconGap > * + * {
+ margin-inline-start: 0; // 1, 2
+ margin-inline-end: 0; // 1, 2
+ }
} @else {
display: flex;
justify-content: center;
@@ -85,6 +95,14 @@
> * + * {
margin-inline-start: $ouiSizeS; // 1
}
+
+ &.ouiButtonContent--smallIconGap > * + * {
+ margin-inline-start: $ouiSizeXXS; // 1
+ }
+
+ &.ouiButtonContent--noIconGap > * + * {
+ margin-inline-start: 0; // 1
+ }
}
}
diff --git a/src/themes/v9/global_styling/variables/_size.scss b/src/themes/v9/global_styling/variables/_size.scss
index 12cd4115fd..3e1670e055 100644
--- a/src/themes/v9/global_styling/variables/_size.scss
+++ b/src/themes/v9/global_styling/variables/_size.scss
@@ -11,6 +11,7 @@
$ouiSize: 16px !default;
+$ouiSizeXXS: $ouiSize * .125 !default;
$ouiSizeXS: $ouiSize * .25 !default;
$ouiSizeS: $ouiSize * .5 !default;
$ouiSizeM: $ouiSize * .75 !default;