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 Exercise 3 for the ProgressIndicator #16

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from
Draft
29 changes: 29 additions & 0 deletions INSTRUCTIONS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Progress Indicator Component

This is where the block comes together.

You'll see the block render in the editor.

And you'll almost be finished once you finish this exercise.

## Exercise

When this works, `npm run lint:js` and `npm run test:js` should pass.

In `ProgressIndicator`, you'll conditionally render an `<svg>` or a number.

When conditionally rendering in React, we'll usually use ternary conditionals:
```jsx
<div>
{ isOpen
? __( 'This is open', 'progress-indicator' )
: __( 'This is closed', 'progress-indicator' )
}
</div>
```

### Files
- [js/src/progress-indicator.exercise.js](js/src/progress-indicator.exercise.js)
- [js/src/edit.js](js/src/edit.js)

[Solution video](https://bit.ly/364b0Is)
4 changes: 2 additions & 2 deletions js/src/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
*/
import ProgressIndicator from './progress-indicator';
// 🚧 Import the ProgressIndicator

/**
* The component for the editor.
Expand All @@ -33,7 +33,7 @@ export default function Edit( { attributes, setAttributes } ) {
);

return <div { ...blockProps }>
<ProgressIndicator attributes={ attributes } />
{ /* 🚧 Render the ProgressIndicator here, with the prop it expects. */ }
<InspectorControls>
<PanelBody title={ __( 'Color', 'progress-indicator' ) }>
<ColorPalette
Expand Down
62 changes: 62 additions & 0 deletions js/src/progress-indicator.exercise.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/**
* External dependencies
*/
import * as React from 'react';
import tinycolor2 from 'tinycolor2';

/**
* The progress indicator component.
*
* @param {{attributes: import('./index').Attributes}} props
* @return {React.ReactElement} The component.
*/
export default function ProgressIndicator( { attributes } ) {
const color = tinycolor2( attributes.color );
const isColorDark = color.getBrightness() < 130;

return <div className="pib-progress-indicator">
{ /* Step Lines */ }
<div className="pib-progress-indicator__lines">
{ [ ...Array( attributes.numberOfSteps - 1 ) ].map( ( value, index ) => {
const isLineComplete = attributes.currentStep > index + 1;
const style = {
backgroundColor: isLineComplete ? attributes.color : '#d1d5db',
};

// 🚧 Return a <div /> with these props:
// key: some unique value
// style: the style object above
// className: "pib-progress-indicator__line"
} ) }
</div>
{ /* Step Circles */ }
{ [ ...Array( attributes.numberOfSteps ) ].map( ( value, index ) => {
const stepNumber = index + 1;
let style = {};

if ( attributes.currentStep === stepNumber ) {
style = {
border: `2px solid ${ attributes.color }`,
boxShadow: `#ffffff 0 0 0 0, ${ color.lighten( 43 ).toString() } 0 0 0 4px, #000000 0 0 0 0`,
color: isColorDark ? attributes.color : '#6b7280',
};
} else if ( attributes.currentStep > stepNumber ) {
style = {
backgroundColor: attributes.color,
border: `2px solid ${ attributes.color }`,
color: isColorDark ? '#ecfdf5' : '#6b7280',
};
}

return <div key={ index } style={ style } className="pib-progress-indicator__step">
{ /*
🚧 If the current step is more than stepNumber, render:
<svg role="img" version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" />
</svg>
Otherwise, simply render stepNumber
*/ }
</div>;
} ) }
</div>;
}
61 changes: 61 additions & 0 deletions js/src/progress-indicator.final.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* External dependencies
*/
import * as React from 'react';
import tinycolor2 from 'tinycolor2';

/**
* The progress indicator component.
*
* @param {{attributes: import('./index').Attributes}} props
* @return {React.ReactElement} The component.
*/
export default function ProgressIndicator( { attributes } ) {
const color = tinycolor2( attributes.color );
const isColorDark = color.getBrightness() < 130;

return <div className="pib-progress-indicator">
{ /* Step Lines */ }
<div className="pib-progress-indicator__lines">
{ [ ...Array( attributes.numberOfSteps - 1 ) ].map( ( value, index ) => {
const isLineComplete = attributes.currentStep > index + 1;

return <div
key={ index }
style={ {
backgroundColor: isLineComplete ? attributes.color : '#d1d5db',
} }
className="pib-progress-indicator__line"
/>;
} ) }
</div>
{ /* Step Circles */ }
{ [ ...Array( attributes.numberOfSteps ) ].map( ( value, index ) => {
const stepNumber = index + 1;
let style = {};

if ( attributes.currentStep === stepNumber ) {
style = {
border: `2px solid ${ attributes.color }`,
boxShadow: `#ffffff 0 0 0 0, ${ color.lighten( 43 ).toString() } 0 0 0 4px, #000000 0 0 0 0`,
color: isColorDark ? attributes.color : '#6b7280',
};
} else if ( attributes.currentStep > stepNumber ) {
style = {
backgroundColor: attributes.color,
border: `2px solid ${ attributes.color }`,
color: isColorDark ? '#ecfdf5' : '#6b7280',
};
}

return <div key={ index } style={ style } className="pib-progress-indicator__step">
{ attributes.currentStep > stepNumber
? <svg role="img" version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" />
</svg>
: stepNumber
}
</div>;
} ) }
</div>;
}
58 changes: 4 additions & 54 deletions js/src/progress-indicator.js
Original file line number Diff line number Diff line change
@@ -1,57 +1,7 @@
/**
* External dependencies
* Internal dependencies
*/
import * as React from 'react';
import tinycolor2 from 'tinycolor2';
import ProgressIndicator from './progress-indicator.exercise';
// import ProgressIndicator from './progress-indicator.final';

/**
* The progress indicator component.
*
* @param {{attributes: import('./index').Attributes}} props
* @return {React.ReactElement} The component.
*/
export default function ProgressIndicator( { attributes } ) {
const color = tinycolor2( attributes.color );
const isColorDark = color.getBrightness() < 130;

return <div className="pib-progress-indicator">
{ /* Step Lines */ }
<div className="pib-progress-indicator__lines">
{ [ ...Array( attributes.numberOfSteps - 1 ) ].map( ( value, index ) => {
const isLineComplete = attributes.currentStep > index + 1;

return <div
key={ index }
style={ {
backgroundColor: isLineComplete ? attributes.color : '#d1d5db',
} }
className="pib-progress-indicator__line"
/>;
} ) }
</div>
{ /* Step Circles */ }
{ [ ...Array( attributes.numberOfSteps ) ].map( ( value, index ) => {
const stepNumber = index + 1;
const style = {};

if ( attributes.currentStep === stepNumber ) {
style.border = `2px solid ${ attributes.color }`;
style.boxShadow = `#ffffff 0 0 0 0, ${ color.lighten( 43 ).toString() } 0 0 0 4px, #000000 0 0 0 0`;
style.color = isColorDark ? attributes.color : '#6b7280';
} else if ( attributes.currentStep > stepNumber ) {
style.backgroundColor = attributes.color;
style.border = `2px solid ${ attributes.color }`;
style.color = isColorDark ? '#ecfdf5' : '#6b7280';
}

return <div key={ index } style={ style } className="pib-progress-indicator__step">
{ attributes.currentStep > stepNumber
? <svg role="img" version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" />
</svg>
: stepNumber
}
</div>;
} ) }
</div>;
}
export default ProgressIndicator;
18 changes: 5 additions & 13 deletions js/src/save.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,15 @@ import * as React from 'react';
* WordPress dependencies
*/
// @ts-ignore The declaration file is outdated.
import { useBlockProps } from '@wordpress/block-editor';

/**
* Internal dependencies
*/
import ProgressIndicator from './progress-indicator';
import { __ } from '@wordpress/i18n';

/**
* The component to save the markup.
*
* @param {{attributes: import('./index').Attributes}} props
* @return {React.ReactElement} The component.
*/
export default function Save( { attributes } ) {
const blockProps = useBlockProps.save();

return <div { ...blockProps }>
<ProgressIndicator attributes={ attributes } />
</div>;
export default function Save() {
return <span>
{ __( 'This is a placeholder for the Progress Indicator block', 'progress-indicator' ) }
</span>;
}