Skip to content

Commit

Permalink
Allow controlling the gap between the icon and the content of OuiButt…
Browse files Browse the repository at this point in the history
…on and OuiButtonEmpty

Signed-off-by: Miki <[email protected]>
  • Loading branch information
AMoo-Miki committed Aug 21, 2024
1 parent cf9cf4a commit 335b41e
Show file tree
Hide file tree
Showing 14 changed files with 243 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
66 changes: 66 additions & 0 deletions src/components/button/__snapshots__/button.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,72 @@ exports[`OuiButton props href secures the rel attribute when the target is _blan
</a>
`;

exports[`OuiButton props iconGap m is rendered 1`] = `
<button
class="ouiButton ouiButton--primary"
type="button"
>
<span
class="ouiButtonContent ouiButton__content"
>
<span
class="ouiButtonContent__icon"
color="inherit"
data-ouiicon-type="user"
/>
<span
class="ouiButton__text"
>
Content
</span>
</span>
</button>
`;

exports[`OuiButton props iconGap none is rendered 1`] = `
<button
class="ouiButton ouiButton--primary"
type="button"
>
<span
class="ouiButtonContent ouiButtonContent--noIconGap ouiButton__content"
>
<span
class="ouiButtonContent__icon"
color="inherit"
data-ouiicon-type="user"
/>
<span
class="ouiButton__text"
>
Content
</span>
</span>
</button>
`;

exports[`OuiButton props iconGap s is rendered 1`] = `
<button
class="ouiButton ouiButton--primary"
type="button"
>
<span
class="ouiButtonContent ouiButtonContent--smallIconGap ouiButton__content"
>
<span
class="ouiButtonContent__icon"
color="inherit"
data-ouiicon-type="user"
/>
<span
class="ouiButton__text"
>
Content
</span>
</span>
</button>
`;

exports[`OuiButton props iconSide left is rendered 1`] = `
<button
class="ouiButton ouiButton--primary"
Expand Down
16 changes: 15 additions & 1 deletion src/components/button/button.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import { render, mount } from 'enzyme';
import { requiredProps } from '../../test/required_props';

import { OuiButton, COLORS, SIZES } from './button';
import { ICON_SIDES } from './button_content';
import { ICON_GAPS, ICON_SIDES } from './button_content';

describe('OuiButton', () => {
test('is rendered', () => {
Expand Down Expand Up @@ -151,6 +151,20 @@ describe('OuiButton', () => {
});
});

describe('iconGap', () => {
ICON_GAPS.forEach((iconGap) => {
test(`${iconGap} is rendered`, () => {
const component = render(
<OuiButton iconType="user" iconGap={iconGap}>
Content
</OuiButton>
);

expect(component).toMatchSnapshot();
});
});
});

describe('href', () => {
it('secures the rel attribute when the target is _blank', () => {
const component = render(<OuiButton href="#" target="_blank" />);
Expand Down
4 changes: 3 additions & 1 deletion src/components/button/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -161,6 +161,7 @@ const OuiButtonDisplay = forwardRef<HTMLElement, OuiButtonDisplayProps>(
children,
className,
iconType,
iconGap,
iconSide = 'left',
color = 'primary',
size = 'm',
Expand Down Expand Up @@ -210,6 +211,7 @@ const OuiButtonDisplay = forwardRef<HTMLElement, OuiButtonDisplayProps>(
isLoading={isLoading}
iconType={iconType}
iconSide={iconSide}
iconGap={iconGap}
textProps={{ ...textProps, className: textClassNames }}
{...contentProps}
// className has to come last to override contentProps.className
Expand Down
17 changes: 17 additions & 0 deletions src/components/button/button_content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<HTMLSpanElement>;

/**
Expand All @@ -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<
Expand All @@ -80,6 +95,7 @@ export const OuiButtonContent: FunctionComponent<
isLoading = false,
iconType,
iconSize = 'm',
iconGap = 'm',
iconSide = 'left',
...contentProps
}) => {
Expand All @@ -105,6 +121,7 @@ export const OuiButtonContent: FunctionComponent<
const contentClassNames = classNames(
'ouiButtonContent',
iconSide ? iconSideToClassNameMap[iconSide] : null,
iconGap ? iconGapToClassNameMap[iconGap] : null,
contentProps && contentProps.className
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,72 @@ exports[`OuiButtonEmpty props href secures the rel attribute when the target is
</a>
`;

exports[`OuiButtonEmpty props iconGap m is rendered 1`] = `
<button
class="ouiButtonEmpty ouiButtonEmpty--primary"
type="button"
>
<span
class="ouiButtonContent ouiButtonEmpty__content"
>
<span
class="ouiButtonContent__icon"
color="inherit"
data-ouiicon-type="user"
/>
<span
class="ouiButtonEmpty__text"
>
Content
</span>
</span>
</button>
`;

exports[`OuiButtonEmpty props iconGap none is rendered 1`] = `
<button
class="ouiButtonEmpty ouiButtonEmpty--primary"
type="button"
>
<span
class="ouiButtonContent ouiButtonContent--noIconGap ouiButtonEmpty__content"
>
<span
class="ouiButtonContent__icon"
color="inherit"
data-ouiicon-type="user"
/>
<span
class="ouiButtonEmpty__text"
>
Content
</span>
</span>
</button>
`;

exports[`OuiButtonEmpty props iconGap s is rendered 1`] = `
<button
class="ouiButtonEmpty ouiButtonEmpty--primary"
type="button"
>
<span
class="ouiButtonContent ouiButtonContent--smallIconGap ouiButtonEmpty__content"
>
<span
class="ouiButtonContent__icon"
color="inherit"
data-ouiicon-type="user"
/>
<span
class="ouiButtonEmpty__text"
>
Content
</span>
</span>
</button>
`;

exports[`OuiButtonEmpty props iconSide left is rendered 1`] = `
<button
class="ouiButtonEmpty ouiButtonEmpty--primary"
Expand Down
16 changes: 15 additions & 1 deletion src/components/button/button_empty/button_empty.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import { render, mount } from 'enzyme';
import { requiredProps } from '../../../test/required_props';

import { OuiButtonEmpty, COLORS, SIZES, FLUSH_TYPES } from './button_empty';
import { ICON_SIDES } from '../button_content';
import { ICON_GAPS, ICON_SIDES } from '../button_content';

describe('OuiButtonEmpty', () => {
test('is rendered', () => {
Expand Down Expand Up @@ -129,6 +129,20 @@ describe('OuiButtonEmpty', () => {
});
});

describe('iconGap', () => {
ICON_GAPS.forEach((iconGap) => {
test(`${iconGap} is rendered`, () => {
const component = render(
<OuiButtonEmpty iconType="user" iconGap={iconGap}>
Content
</OuiButtonEmpty>
);

expect(component).toMatchSnapshot();
});
});
});

describe('flush', () => {
FLUSH_TYPES.forEach((flushType) => {
test(`${flushType} is rendered`, () => {
Expand Down
4 changes: 3 additions & 1 deletion src/components/button/button_empty/button_empty.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -136,6 +136,7 @@ export const OuiButtonEmpty: FunctionComponent<OuiButtonEmptyProps> = ({
children,
className,
iconType,
iconGap,
iconSide = 'left',
color = 'primary',
size,
Expand Down Expand Up @@ -189,6 +190,7 @@ export const OuiButtonEmpty: FunctionComponent<OuiButtonEmptyProps> = ({
iconType={iconType}
iconSide={iconSide}
iconSize={iconSize}
iconGap={iconGap}
textProps={{ ...textProps, className: textClassNames }}
{...contentProps}
// className has to come last to override contentProps.className
Expand Down
18 changes: 18 additions & 0 deletions src/global_styling/mixins/_button.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -84,6 +94,14 @@
> * + * {
margin-inline-start: $ouiSizeS; // 1
}

&.ouiButtonContent--smallIconGap > * + * {
margin-inline-start: $ouiSizeXXS; // 1
}

&.ouiButtonContent--noIconGap > * + * {
margin-inline-start: 0; // 1
}
}
}

Expand Down
1 change: 1 addition & 0 deletions src/global_styling/variables/_size.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

$ouiSize: 16px !default;

$ouiSizeXXS: $ouiSize * .125 !default;
$ouiSizeXS: $ouiSize * .25 !default;
$ouiSizeS: $ouiSize * .5 !default;
$ouiSizeM: $ouiSize * .75 !default;
Expand Down
18 changes: 18 additions & 0 deletions src/themes/oui-next/global_styling/mixins/_button.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -85,6 +95,14 @@
> * + * {
margin-inline-start: $ouiSizeS; // 1
}

&.ouiButtonContent--smallIconGap > * + * {
margin-inline-start: $ouiSizeXXS; // 1
}

&.ouiButtonContent--noIconGap > * + * {
margin-inline-start: 0; // 1
}
}
}

Expand Down
1 change: 1 addition & 0 deletions src/themes/oui-next/global_styling/variables/_size.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

$ouiSize: 16px !default;

$ouiSizeXXS: $ouiSize * .125 !default;
$ouiSizeXS: $ouiSize * .25 !default;
$ouiSizeS: $ouiSize * .5 !default;
$ouiSizeM: $ouiSize * .75 !default;
Expand Down
Loading

0 comments on commit 335b41e

Please sign in to comment.