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

feat(StepIndicator): Add Step Indicator and Step #199

Merged
merged 8 commits into from
Jul 1, 2019
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 src/components/List/List.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Use the *ordered* `variant` to create an ordered list.
<li>List Item Four</li>
</List>
```

### Plain List

Use the *plain* `variant` to create a plain list with no decoration.
Expand Down
1 change: 1 addition & 0 deletions src/components/StepIndicator/Step.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
`Step` contains the individual steps in a step indicator. See the examples in [StepIndicator](/#/Page%20Content?id=StepIndicator)
50 changes: 50 additions & 0 deletions src/components/StepIndicator/Step.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
Copyright (C) 2019 The Trustees of Indiana University
SPDX-License-Identifier: BSD-3-Clause
*/
import { mount } from 'enzyme';
import * as React from 'react';

import Step from './Step'

describe('<Step />', () => {
describe('Rendering and styling', () =>{
it('should render without throwing an error', () => {
const cut = mount(<Step indicator={<span>1</span>} screenReaderIndicator="1" label={<span>Step</span>} />);
expect(cut.find('li')).toHaveLength(1);
});
it('should pass attributes through', () => {
const cut = mount(<Step id="the_id" indicator={<span>1</span>} screenReaderIndicator="1" label={<span>Step</span>} />);
expect(cut.find('li').prop('id')).toEqual('the_id');
});
it('should apply custom classes', () => {
const cut = mount(<Step className="foo" indicator={<span>1</span>} screenReaderIndicator="1" label={<span>Step</span>} />);
expect(cut.find('li').hasClass('foo')).toBe(true);
});

it('should set aria-current when current is set', () => {
const cut = mount(<Step current indicator={<span>1</span>} screenReaderIndicator="1" label={<span>Step</span>} />);
expect(cut.find('span[aria-current]')).toHaveLength(1);
});

it('should set aria-current when current is set in an href', () => {
const cut = mount(<Step current href="https://foo.com" indicator={<span>1</span>} screenReaderIndicator="1" label={<span>Step</span>} />);
expect(cut.find('[aria-current="step"]')).toHaveLength(1);
});

it('should not set aria-current when current is not set', () => {
const cut = mount(<Step indicator={<span>1</span>} screenReaderIndicator="1" label={<span>Step</span>} />);
expect(cut.find('span[aria-current]')).toHaveLength(0);
});

it('should provide a link when href is set', () => {
const cut = mount(<Step indicator={<span>1</span>} screenReaderIndicator="1" label={<span>Step</span>} href="https://foo.com" />);
expect(cut.find('a')).toHaveLength(1);
});

it('should set a variant if the variant property is set', () => {
const cut = mount(<Step indicator={<span>1</span>} screenReaderIndicator="1" label={<span>Step</span>} variant="warning"/>);
expect(cut.find('span .rvt-steps__indicator--warning')).toHaveLength(1)
});
});
});
76 changes: 76 additions & 0 deletions src/components/StepIndicator/Step.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
Copyright (C) 2019 The Trustees of Indiana University
SPDX-License-Identifier: BSD-3-Clause
*/
import * as classNames from 'classnames';
import * as React from 'react'


export interface StepProps {
/**
* Defines whether the indicated step is the current step
*/
current?: boolean;

/**
* An optional URL that can be used to create a link from this step to another location
*/
href?: string;

/**
* A visual indicator to identify this step
*/
indicator: JSX.Element;

/**
* A label for this step
*/
label: JSX.Element;

/**
* An textual indicator to be used by screenreaders since the visual indicator may not include text
*/
screenReaderIndicator: string

/**
* An optional variant to be applied to the indicator
*/
variant?: 'success' | 'warning' | 'danger';
}

const indicatorClass = 'rvt-steps__indicator';

const variantClass = (variant) => variant && `${indicatorClass}--${variant}`;

const Step : React.SFC <StepProps & React.HTMLAttributes<HTMLLIElement>> =
({ current, href, indicator, label, screenReaderIndicator, variant, ...attrs}) => {
const content = (
<>
<span className="rvt-steps__label">{label}</span>
<span className={classNames(indicatorClass, variantClass(variant))}>
<span className="rvt-sr-only">{screenReaderIndicator}</span> {indicator}
</span>
</>
);
let wrapper = (
<span className="rvt-steps__item-content" aria-current={current && 'step'}>
{content}
</span>
);
if (href) {
wrapper = (
<a href={href} className="rvt-steps__item-content" aria-current={current && 'step'}>
{content}
</a>
);
}

return (
<li className="rvt-steps__item" {...attrs}>
{wrapper}
</li>
)
};
Step.displayName = 'Step';

export default Step;
24 changes: 24 additions & 0 deletions src/components/StepIndicator/StepIndicator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Use the step indicator component to help users keep track of their progress in a multi-step process, such as an application form.

View the [Rivet documentation for Step Indicator](https://rivet.iu.edu/components/page-content/step-indicator/)

### Basic step indicator

```jsx
<StepIndicator>
<Step href="#" label="Personal Information" indicator="1" screenReaderIndicator="Step"/>
<Step label="Records & transcripts" indicator="2" screenReaderIndicator="Step" current />
<Step label="Confirmation" indicator="3" screenReaderIndicator="Step" variant="success" />
</StepIndicator>
```

### Vertical Step Indicator

```jsx
<StepIndicator vertical>
<Step href="#" label="Personal Information" indicator="1" screenReaderIndicator="Step"/>
<Step label="Records & transcripts" indicator="2" screenReaderIndicator="Step" current />
<Step label="Confirmation" indicator="3" screenReaderIndicator="Step" variant="success" />
</StepIndicator>

```
35 changes: 35 additions & 0 deletions src/components/StepIndicator/StepIndicator.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
Copyright (C) 2019 The Trustees of Indiana University
SPDX-License-Identifier: BSD-3-Clause
*/
import { mount } from 'enzyme';
import * as React from 'react';

import StepIndicator from './StepIndicator'

describe('<StepIndicator />', () => {
describe('Rendering and styling', () =>{
it('should render without throwing an error', () => {
const cut = mount(<StepIndicator />);
expect(cut.find('ol')).toHaveLength(1);
});
it('should pass attributes through', () => {
const cut = mount(<StepIndicator id="the_id" />);
expect(cut.find('ol').prop('id')).toEqual('the_id');
});
it('should apply custom classes', () => {
const cut = mount(<StepIndicator className="foo" />);
expect(cut.find('ol').hasClass('foo')).toBe(true);
});

it('should apply vertical styling if the vertical property is set', () => {
const cut = mount(<StepIndicator vertical />);
expect(cut.find('ol').hasClass('rvt-steps--vertical')).toBe(true);
});

it('should not apply vertical styling if the vertical property is set', () => {
const cut = mount(<StepIndicator />);
expect(cut.find('ol').hasClass('rvt-steps--vertical')).toBe(false);
});
});
});
26 changes: 26 additions & 0 deletions src/components/StepIndicator/StepIndicator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
Copyright (C) 2019 The Trustees of Indiana University
SPDX-License-Identifier: BSD-3-Clause
*/
import * as classNames from 'classnames';
import * as React from 'react';
import * as Rivet from '../util/Rivet';

export interface StepIndicatorProps {
/**
* Defines whether the step indicator should use the alternate vertical styling
*/
vertical?: boolean
}

const componentClass = 'rvt-steps';

export const StepIndicator: React.SFC<StepIndicatorProps & React.HTMLAttributes<HTMLOListElement>> =
({ className, children, vertical, id = Rivet.shortuid(), ...attrs }) => (
<ol id={id} className={classNames(componentClass, { 'rvt-steps--vertical': vertical}, className)} {...attrs}>
{children}
</ol>
);
StepIndicator.displayName = 'StepIndicator';

export default Rivet.rivetize(StepIndicator);
6 changes: 6 additions & 0 deletions src/components/StepIndicator/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
Copyright (C) 2019 The Trustees of Indiana University
SPDX-License-Identifier: BSD-3-Clause
*/
export { default as Step } from './Step';
export { default as StepIndicator } from './StepIndicator';
1 change: 1 addition & 0 deletions src/components/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ export * from './Pagination';
export * from './Panel';
export * from './RadioButton';
export * from './Section';
export * from './StepIndicator';
export * from './Table';
export * from './Tabs';
1 change: 1 addition & 0 deletions styleguide.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ module.exports = {
components: () => [
'src/components/Badge/*.tsx',
'src/components/List/*.tsx',
'src/components/StepIndicator/*.tsx',
'src/components/Table/*.tsx',
'src/components/Tabs/*.tsx',
],
Expand Down
38 changes: 13 additions & 25 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -171,19 +171,12 @@
"@types/node" "*"
"@types/react" "*"

"@types/react@*":
"@types/react@*", "@types/react@16.4.1":
version "16.4.1"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.4.1.tgz#c53bbfb4a78933db587da085ac60dbf5fcf73f8f"
dependencies:
csstype "^2.2.0"

"@types/react@16.4.7":
version "16.4.7"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.4.7.tgz#f33f6d759a7e1833befa15224d68942d178a5a3f"
integrity sha512-tHpSs7HMyjnpyfzka1G0pYh7rBNdpwGgcIDT4vfV6jUaR69yOHo/vNH2H+d9iYHo9xnX4qDe7UalPe9HiGRkLw==
dependencies:
csstype "^2.2.0"

"@vxna/mini-html-webpack-template@^0.1.7":
version "0.1.7"
resolved "https://registry.yarnpkg.com/@vxna/mini-html-webpack-template/-/mini-html-webpack-template-0.1.7.tgz#2a8270e513ee14f395cc17c2ce22ced383c45d22"
Expand Down Expand Up @@ -8604,25 +8597,20 @@ ripemd160@^2.0.0, ripemd160@^2.0.1:
hash-base "^3.0.0"
inherits "^2.0.1"

rivet-collapsible@0.1.1-alpha:
version "0.1.1-alpha"
resolved "https://registry.yarnpkg.com/rivet-collapsible/-/rivet-collapsible-0.1.1-alpha.tgz#27c211891a8510e2c592f1caf305d14fb5337ffb"
dependencies:
rivet-uits "^1.0.0"

rivet-switch@0.1.1-alpha:
version "0.1.1-alpha"
resolved "https://registry.yarnpkg.com/rivet-switch/-/rivet-switch-0.1.1-alpha.tgz#a49ee1e291d223010caeff54351a69703ad61b10"
dependencies:
rivet-uits "^1.0.0"
rivet-collapsible@0.2.10:
version "0.2.10"
resolved "https://registry.npmjs.org/rivet-collapsible/-/rivet-collapsible-0.2.10.tgz#6ef38eadc032021b57495c8e17337cd92fbb1a4f"
integrity sha512-JWtF3nmysDb8yhT3wbpaiOIBC7SxJAQvnhnI2dmZxXlDub06RLxXQwFiPSpV+LObmgrI8huVNPVtkAgXzR/3ow==

rivet-uits@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/rivet-uits/-/rivet-uits-1.1.0.tgz#bd50edae3fd222cd1f8d67416e6513eecf9a4c23"
rivet-switch@0.3.1:
version "0.3.1"
resolved "https://registry.npmjs.org/rivet-switch/-/rivet-switch-0.3.1.tgz#1a58086aad8f00760adbd4bcbdc26a0d0ae314b1"
integrity sha512-JWA/3/jN6qqb4+RadxHeukLNPf2EgRMMgzO9fypvY2kRw5W1HOaW2bJIwTC85j/SVvn+VciZjucYcmnQjYhlHQ==

rivet-uits@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/rivet-uits/-/rivet-uits-1.0.0.tgz#73f8d011be56cdb3637245d0b9f8af9038a2478a"
rivet-uits@1.6.0:
version "1.6.0"
resolved "https://registry.npmjs.org/rivet-uits/-/rivet-uits-1.6.0.tgz#d58d57183afb55d501bfa841d597634d1e6dcaaf"
integrity sha512-SEpELSU4c5swRSIpWqVD+z/e71gdpaJNTZ19V5gqGwEZO16xlKxENPA+FSSuKkCVaoZ0OHUwmJdLZhUp4bZdUw==

rst-selector-parser@^2.2.3:
version "2.2.3"
Expand Down