Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add button icon gap prop #1367

Merged
merged 1 commit into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,7 @@ exports[`OuiInMemoryTable behavior pagination 1`] = `
>
<OuiButtonContent
className="ouiButtonEmpty__content"
iconGap="m"
iconSide="right"
iconSize="s"
iconType="arrowDown"
Expand Down Expand Up @@ -576,6 +577,7 @@ exports[`OuiInMemoryTable behavior pagination 1`] = `
>
<OuiButtonContent
className="ouiButtonEmpty__content"
iconGap="m"
iconSide="left"
iconSize="m"
textProps={
Expand Down Expand Up @@ -659,6 +661,7 @@ exports[`OuiInMemoryTable behavior pagination 1`] = `
>
<OuiButtonContent
className="ouiButtonEmpty__content"
iconGap="m"
iconSide="left"
iconSize="m"
textProps={
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 = 'm',
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 = 'm',
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
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,7 @@ exports[`OuiControlBar props leftOffset is rendered 1`] = `
>
<OuiButtonContent
className="ouiButton__content"
iconGap="m"
iconSide="left"
textProps={
Object {
Expand Down Expand Up @@ -690,6 +691,7 @@ exports[`OuiControlBar props maxHeight is rendered 1`] = `
>
<OuiButtonContent
className="ouiButton__content"
iconGap="m"
iconSide="left"
textProps={
Object {
Expand Down Expand Up @@ -1029,6 +1031,7 @@ exports[`OuiControlBar props mobile is rendered 1`] = `
>
<OuiButtonContent
className="ouiButton__content"
iconGap="m"
iconSide="left"
textProps={
Object {
Expand Down Expand Up @@ -1272,6 +1275,7 @@ exports[`OuiControlBar props position is rendered 1`] = `
>
<OuiButtonContent
className="ouiButton__content"
iconGap="m"
iconSide="left"
textProps={
Object {
Expand Down Expand Up @@ -1596,6 +1600,7 @@ exports[`OuiControlBar props rightOffset is rendered 1`] = `
>
<OuiButtonContent
className="ouiButton__content"
iconGap="m"
iconSide="left"
textProps={
Object {
Expand Down Expand Up @@ -1940,6 +1945,7 @@ exports[`OuiControlBar props showContent is rendered 1`] = `
>
<OuiButtonContent
className="ouiButton__content"
iconGap="m"
iconSide="left"
textProps={
Object {
Expand Down Expand Up @@ -2284,6 +2290,7 @@ exports[`OuiControlBar props size is rendered 1`] = `
>
<OuiButtonContent
className="ouiButton__content"
iconGap="m"
iconSide="left"
textProps={
Object {
Expand Down
Loading
Loading