Skip to content

Commit

Permalink
[Stepper] Refactor Stepper to resolve mui#3725 (mui#3903)
Browse files Browse the repository at this point in the history
Refactor Stepper to fix issues in the existing implementation
that are detailed in mui#3725. Documentation is also reworked for
the component and a new transition group added to the internal folder.
  • Loading branch information
nathanmarks authored and Cuong Le committed Apr 20, 2016
1 parent 7052d8f commit 9429899
Show file tree
Hide file tree
Showing 30 changed files with 2,098 additions and 1,165 deletions.
10 changes: 9 additions & 1 deletion docs/src/app/components/CodeExample/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import {parse} from 'react-docgen';
import CodeBlock from './CodeBlock';
import ClearFix from 'material-ui/internal/ClearFix';
import Paper from 'material-ui/Paper';
Expand Down Expand Up @@ -40,9 +41,16 @@ class CodeExample extends React.Component {
},
};

const docs = parse(code);

return (
<Paper style={styles.root}>
<CodeBlock title={this.props.title} description={this.props.description}>{code}</CodeBlock>
<CodeBlock
title={this.props.title}
description={this.props.description || docs.description}
>
{code}
</CodeBlock>
<ClearFix style={styles.exampleBlock}>{children}</ClearFix>
</Paper>
);
Expand Down
8 changes: 8 additions & 0 deletions docs/src/app/components/pages/components/Stepper/Advanced.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
## Advanced Usage

The `<Stepper>` can also be controlled by interfacing directly with the `<Step>` components placed inside `<Stepper>`. These individual props are also compatible with the `activeStep` prop, and will take precedence if found on the component.

You can also place completely custom components inside `<Step>` if required and they will be passed the same props as the other `<Step>` children.

These features allows for all sorts of usage scenarios -- the world is your oyster.

74 changes: 74 additions & 0 deletions docs/src/app/components/pages/components/Stepper/CustomIcon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React from 'react';
import {
Step,
Stepper,
StepLabel,
} from 'material-ui/Stepper';
import WarningIcon from 'material-ui/svg-icons/alert/warning';
import {red500} from 'material-ui/styles/colors';

/**
* Custom icons can be used to create different visual states.
*/
class CustomIcon extends React.Component {

state = {
stepIndex: 0,
};

handleNext = () => {
const {stepIndex} = this.state;
if (stepIndex < 2) {
this.setState({stepIndex: stepIndex + 1});
}
};

handlePrev = () => {
const {stepIndex} = this.state;
if (stepIndex > 0) {
this.setState({stepIndex: stepIndex - 1});
}
};

getStepContent(stepIndex) {
switch (stepIndex) {
case 0:
return 'Select campaign settings...';
case 1:
return 'What is an ad group anyways?';
case 2:
return 'This is the bit I really care about!';
default:
return 'You\'re a long way from home sonny jim!';
}
}

render() {
return (
<div style={{width: '100%', maxWidth: 700, margin: 'auto'}}>
<Stepper linear={false}>
<Step completed={false}>
<StepLabel>
Select campaign settings
</StepLabel>
</Step>
<Step completed={false}>
<StepLabel
icon={<WarningIcon color={red500} />}
style={{color: red500}}
>
Create an ad group
</StepLabel>
</Step>
<Step completed={false}>
<StepLabel>
Create an ad
</StepLabel>
</Step>
</Stepper>
</div>
);
}
}

export default CustomIcon;
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import React from 'react';
import {
Step,
Stepper,
StepButton,
} from 'material-ui/Stepper';
import RaisedButton from 'material-ui/RaisedButton';
import FlatButton from 'material-ui/FlatButton';

const getStyles = () => {
return {
root: {
width: '100%',
maxWidth: 700,
margin: 'auto',
},
content: {
margin: '0 16px',
},
actions: {
marginTop: 12,
},
backButton: {
marginRight: 12,
},
};
};

/**
* This is similiar to the horizontal non-linear example, except the
* `<Step>` components are being controlled manually via individual props.
*
* An enhancement made possible by this functionality (shown below),
* is to permanently mark steps as complete once the user has satisfied the
* application's required conditions (in this case, once it has visited the step).
*
*/
class GranularControlStepper extends React.Component {

state = {
stepIndex: null,
visited: [],
};

componentWillMount() {
const {stepIndex, visited} = this.state;
this.setState({visited: visited.concat(stepIndex)});
}

componentWillUpdate(nextProps, nextState) {
const {stepIndex, visited} = nextState;
if (visited.indexOf(stepIndex) === -1) {
this.setState({visited: visited.concat(stepIndex)});
}
}

handleNext = () => {
const {stepIndex} = this.state;
if (stepIndex < 2) {
this.setState({stepIndex: stepIndex + 1});
}
};

handlePrev = () => {
const {stepIndex} = this.state;
if (stepIndex > 0) {
this.setState({stepIndex: stepIndex - 1});
}
};

getStepContent(stepIndex) {
switch (stepIndex) {
case 0:
return 'Select campaign settings...';
case 1:
return 'What is an ad group anyways?';
case 2:
return 'This is the bit I really care about!';
default:
return 'Click a step to get started.';
}
}

render() {
const {stepIndex, visited} = this.state;
const styles = getStyles();

return (
<div style={styles.root}>
<p>
<a
href="#"
onClick={(event) => {
event.preventDefault();
this.setState({stepIndex: null, visited: []});
}}
>
Click here
</a> to reset the example.
</p>
<Stepper linear={false}>
<Step completed={visited.indexOf(0) !== -1} active={stepIndex === 0}>
<StepButton onClick={() => this.setState({stepIndex: 0})}>
Select campaign settings
</StepButton>
</Step>
<Step completed={visited.indexOf(1) !== -1} active={stepIndex === 1}>
<StepButton onClick={() => this.setState({stepIndex: 1})}>
Create an ad group
</StepButton>
</Step>
<Step completed={visited.indexOf(2) !== -1} active={stepIndex === 2}>
<StepButton onClick={() => this.setState({stepIndex: 2})}>
Create an ad
</StepButton>
</Step>
</Stepper>
<div style={styles.content}>
<p>{this.getStepContent(stepIndex)}</p>
{stepIndex !== null && (
<div style={styles.actions}>
<FlatButton
label="Back"
disabled={stepIndex === 0}
onTouchTap={this.handlePrev}
style={styles.backButton}
/>
<RaisedButton
label="Next"
primary={true}
onTouchTap={this.handleNext}
/>
</div>
)}
</div>
</div>
);
}
}

export default GranularControlStepper;
Loading

0 comments on commit 9429899

Please sign in to comment.