Skip to content

Commit

Permalink
feat: New Busy Indicator component (#963)
Browse files Browse the repository at this point in the history
* feat: New Busy Indicator component

* Added ability to hide Busy Indicator

- Added prop 'show' to show/hide Busy Indicator
- Updated .size-limit

* Added localized text support || Fixes

Changes suggested in PR
- Updated style class for "s" size
- Added aria-label/aria-hidden
- Updated to return null intead of fragments when component is hidden

* Removed unused prop
  • Loading branch information
JaySardhara authored Apr 14, 2020
1 parent b70fe1a commit 510e8c9
Show file tree
Hide file tree
Showing 14 changed files with 261 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .size-limit
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
name: "Fundamental-React Size",
webpack: true,
path: "lib/index.js",
limit: "190 KB"
limit: "195 KB"
}
]
26 changes: 26 additions & 0 deletions src/BusyIndicator/BusyIndicator.Component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { BusyIndicator } from '../';
import path from 'path';
import React from 'react';
import { ComponentPage, Example } from '../_playground';

export const BusyIndicatorComponent = () => {
return (
<ComponentPage
description={'A **Busy Indicator** informs the user of an ongoing operation.'}
sourceModulePath={path.join(__dirname, './BusyIndicator')}
title='Busy Indicator'>
<Example centered title='Busy Indicator'>
<BusyIndicator show />
</Example>

<Example
centered
description={'There are 3 sizes for Busy Indicator: s, m & l'}
title='Busy Indicator Sizes'>
<BusyIndicator show size='s' />
<BusyIndicator show />
<BusyIndicator show size='l' />
</Example>
</ComponentPage>
);
};
75 changes: 75 additions & 0 deletions src/BusyIndicator/BusyIndicator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { BUSY_INDICATOR_SIZES } from '../utils/constants';
import classnames from 'classnames';
import CustomPropTypes from '../utils/CustomPropTypes/CustomPropTypes';
import PropTypes from 'prop-types';
import React, { useEffect } from 'react';

const BusyIndicator = React.forwardRef(({
className,
show,
size,
disableStyles,
localizedText,
...props
}, ref) => {

useEffect(() => {
if (!disableStyles) {
require('fundamental-styles/dist/icon.css');
require('fundamental-styles/dist/busy-indicator.css');
}
}, []);

const busyIndicatorClasses = classnames(
{
[`fd-busy-indicator--${size}`]: size === 'm' || size === 'l',
'fd-busy-indicator': size === 's'
},
className
);

if (!show)
return null;

return (
<div
{...props}
aria-hidden='false'
aria-label={localizedText.loading}
className={busyIndicatorClasses}
ref={ref} >
<div className='fd-busy-indicator--circle-0' />
<div className='fd-busy-indicator--circle-1' />
<div className='fd-busy-indicator--circle-2' />
</div>
);
});

BusyIndicator.displayName = 'BusyIndicator';

BusyIndicator.propTypes = {
className: PropTypes.string,
disableStyles: PropTypes.bool,
localizedText: CustomPropTypes.i18n({
loading: PropTypes.string
}),
show: PropTypes.bool,
size: PropTypes.oneOf(BUSY_INDICATOR_SIZES)
};

BusyIndicator.defaultProps = {
localizedText: {
loading: 'Loading'
},
size: 'm',
show: false
};

BusyIndicator.propDescriptions = {
show: 'Set to **true** to make Busy Indicator visible',
localizedTextShape: {
loading: 'aria-label for Busy Indicator component'
}
};

export default BusyIndicator;
64 changes: 64 additions & 0 deletions src/BusyIndicator/BusyIndicator.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import BusyIndicator from './BusyIndicator';
import { mount } from 'enzyme';
import React from 'react';
import renderer from 'react-test-renderer';

describe('<BusyIndicator />', () => {
const showDefaultBusyIndicator = <BusyIndicator show />;
const smallBusyIndicator = <BusyIndicator show size='s' />;
const largeBusyIndicator = <BusyIndicator show size='l' />;
const defaultBusyIndicator = <BusyIndicator />;
const hideBusyIndicator = <BusyIndicator show={false} />;

test('create busy indicators', () => {
// show default busy indicator
let component = renderer.create(showDefaultBusyIndicator);
let tree = component.toJSON();
expect(tree).toMatchSnapshot();

// small busy indicator
component = renderer.create(smallBusyIndicator);
tree = component.toJSON();
expect(tree).toMatchSnapshot();

// large busy indicator
component = renderer.create(largeBusyIndicator);
tree = component.toJSON();
expect(tree).toMatchSnapshot();

// default busy indicator
component = renderer.create(defaultBusyIndicator);
tree = component.toJSON();
expect(tree).toMatchSnapshot();
});

test('hide busy indicator', () => {
// hide busy indicator
let component = renderer.create(hideBusyIndicator);
let tree = component.toJSON();
expect(tree).toMatchSnapshot();
});

describe('Prop spreading', () => {
test('should allow props to be spread to the Busy Indicator component', () => {
const element = mount(<BusyIndicator data-sample='Sample' show />);

expect(
element.getDOMNode().attributes['data-sample'].value
).toBe('Sample');
});
});
test('forwards the ref', () => {
let ref;
class Test extends React.Component {
constructor(props) {
super(props);
ref = React.createRef();
}
render = () => <BusyIndicator ref={ref} show />;
}
mount(<Test />);
expect(ref.current.tagName).toEqual('DIV');
expect(ref.current.className).toEqual('fd-busy-indicator--m');
});
});
59 changes: 59 additions & 0 deletions src/BusyIndicator/__snapshots__/BusyIndicator.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`<BusyIndicator /> create busy indicators 1`] = `
<div
aria-hidden="false"
aria-label="Loading"
className="fd-busy-indicator--m"
>
<div
className="fd-busy-indicator--circle-0"
/>
<div
className="fd-busy-indicator--circle-1"
/>
<div
className="fd-busy-indicator--circle-2"
/>
</div>
`;

exports[`<BusyIndicator /> create busy indicators 2`] = `
<div
aria-hidden="false"
aria-label="Loading"
className="fd-busy-indicator"
>
<div
className="fd-busy-indicator--circle-0"
/>
<div
className="fd-busy-indicator--circle-1"
/>
<div
className="fd-busy-indicator--circle-2"
/>
</div>
`;

exports[`<BusyIndicator /> create busy indicators 3`] = `
<div
aria-hidden="false"
aria-label="Loading"
className="fd-busy-indicator--l"
>
<div
className="fd-busy-indicator--circle-0"
/>
<div
className="fd-busy-indicator--circle-1"
/>
<div
className="fd-busy-indicator--circle-2"
/>
</div>
`;

exports[`<BusyIndicator /> create busy indicators 4`] = `null`;

exports[`<BusyIndicator /> hide busy indicator 1`] = `null`;
22 changes: 22 additions & 0 deletions src/BusyIndicator/__stories__/BusyIndicator.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import BusyIndicator from '../BusyIndicator';
import React from 'react';
import { storiesOf } from '@storybook/react';
import { withKnobs } from '@storybook/addon-knobs';

storiesOf('Components|BusyIndicator', module)
.addDecorator(withKnobs)
.add('Default', () => (
<BusyIndicator show />
))
.add('small', () => (
<BusyIndicator show size='s' />
))
.add('large', () => (
<BusyIndicator show size='l' />
))
.add('hidden', () => (
<BusyIndicator />
))
.add('disable styles', () => (
<BusyIndicator disableStyles show>Default</BusyIndicator>
));
7 changes: 7 additions & 0 deletions src/_playground/Routes.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ActionBarComponent } from '../ActionBar/ActionBar.Component';
import { BreadcrumbComponent } from '../Breadcrumb/Breadcrumb.Component';
import { BusyIndicatorComponent } from '../BusyIndicator/BusyIndicator.Component';
import Button from '../Button/Button';
import { ButtonComponent } from '../Button/Button.Component';
import { CalendarComponent } from '../Calendar/Calendar.Component';
Expand Down Expand Up @@ -90,6 +91,12 @@ const routes = [
component: BreadcrumbComponent,
section: 'Components'
},
{
url: '/busyIndicator',
name: 'Busy Indicator',
component: BusyIndicatorComponent,
section: 'Components'
},
{
url: '/button',
name: 'Button',
Expand Down
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export { default as ActionBar } from './ActionBar/ActionBar';
export { default as Checkbox } from './Forms/Checkbox';
export { default as Counter } from './Counter/Counter';
export { default as Breadcrumb } from './Breadcrumb/Breadcrumb';
export { default as BusyIndicator } from './BusyIndicator/BusyIndicator';
export { default as Button } from './Button/Button';
export { default as ButtonGroup } from './Button/ButtonGroup';
export { default as Calendar } from './Calendar/Calendar';
Expand Down
6 changes: 6 additions & 0 deletions src/utils/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ export const MESSAGESTRIP_TYPES = [
'information'
];

export const BUSY_INDICATOR_SIZES = [
's',
'm',
'l'
];

export const BUTTON_OPTIONS = [
'emphasized',
'transparent'
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 510e8c9

Please sign in to comment.