Skip to content

Commit

Permalink
showCancelLink -> cancelIcon (#518)
Browse files Browse the repository at this point in the history
* showCancelLink -> cancelIcon

This change allows us to pass multiple options for cancelIcon, so we can do things like set the label.

Closes #499

* Fix tests
  • Loading branch information
RobbieTheWagner authored Aug 17, 2019
1 parent 1d2aac8 commit a84ace7
Show file tree
Hide file tree
Showing 11 changed files with 88 additions and 38 deletions.
6 changes: 4 additions & 2 deletions demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,11 @@ <h3>Example</h3>
<code class="language-javascript">
const tour = new Shepherd.Tour({
defaultStepOptions: {
cancelIcon: {
enabled: true
},
classes: 'class-1 class-2',
scrollTo: { behavior: 'smooth', block: 'center' },
showCancelLink: true
scrollTo: { behavior: 'smooth', block: 'center' }
}
});

Expand Down
4 changes: 3 additions & 1 deletion demo/js/welcome.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@
var prefix = 'demo-';
var shepherd = new Shepherd.Tour({
defaultStepOptions: {
cancelIcon: {
enabled: true
},
classes: 'class-1 class-2',
scrollTo: {
behavior: 'smooth',
block: 'center'
},
showCancelLink: true,
tippyOptions: {
maxWidth: '400px',
popperOptions: {
Expand Down
4 changes: 3 additions & 1 deletion docs-src/tutorials/02-usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ the step will execute. For example:
},
```
- `canClickTarget` A boolean, that when set to false, will set `pointer-events: none` on the target
- `cancelIcon` Options for the cancel icon
- `enabled` Should a cancel “✕” be shown in the header of the step?
- `label` The label to add for `aria-label`
- `classes`: A string of extra classes to add to the step's content element.
- `buttons`: An array of buttons to add to the step. These will be rendered in a footer below the main body text. Each button in the array is an object of the format:
- `text`: The HTML text of the button
Expand Down Expand Up @@ -206,7 +209,6 @@ For example: `{selector: '.some-element', event: 'click'}`. It doesn't have to
You can also always manually advance the Tour by calling `myTour.next()`.
- `highlightClass`: An extra class to apply to the `attachTo` element when it is highlighted (that is, when its step is active). You can then target that selector in your CSS.
- `id`: The string to use as the `id` for the step. If an id is not passed one will be generated.
- `showCancelLink`: Should a cancel "✕" be shown in the header of the step?
- `showOn`: A function that, when it returns true, will show the step. If it returns false, the step will be skipped.
- `scrollTo`: Should the element be scrolled to when this step is shown?
- `scrollToHandler`: A function that lets you override the default `scrollTo` behavior and define a custom action to do the scrolling,
Expand Down
19 changes: 13 additions & 6 deletions src/js/components/shepherd-content/shepherd-header/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ export default class ShepherdHeader extends Component {

render(props) {
const { labelId, step, styles } = props;
const { showCancelLink, title } = step.options;
const { cancelIcon, title } = step.options;
return <header className={styles.header.trim()}>
{this.constructor._addTitle(labelId, styles, title)}
{this._addCancelLink(showCancelLink, styles)}
{this._addCancelLink(cancelIcon, styles)}
</header>;
}

Expand All @@ -41,11 +41,18 @@ export default class ShepherdHeader extends Component {
return null;
}

_addCancelLink(showCancelLink, styles) {
if (showCancelLink) {
/**
* If enabled, add the cancel "x" icon
* @param {object} cancelIcon The options for the cancel icon
* @param styles
* @return {null|*}
* @private
*/
_addCancelLink(cancelIcon, styles) {
if (cancelIcon && cancelIcon.enabled) {
return <button
aria-label='Close Tour'
className={styles['cancel-link'].trim()}
aria-label={cancelIcon.label ? cancelIcon.label : 'Close Tour'}
className={styles['cancel-icon'].trim()}
onClick={this.cancelStep}
type='button'
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { getLighterOrDarker } from '../../../styles/utils';

export default function headerStyles(classPrefix, variables) {
return {
'cancel-link': {
'cancel-icon': {
background: 'transparent',
border: 'none',
color: getLighterOrDarker(variables.shepherdThemeTextColor),
Expand Down
8 changes: 5 additions & 3 deletions src/js/step.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ export class Step extends Evented {
* @param {boolean} options.buttons.button.secondary If true, a shepherd-button-secondary class is applied to the button
* @param {string} options.buttons.button.text The HTML text of the button
* @param {boolean} options.canClickTarget A boolean, that when set to false, will set `pointer-events: none` on the target
* @param {object} options.cancelIcon Options for the cancel icon
* @param {boolean} options.cancelIcon.enabled Should a cancel “✕” be shown in the header of the step?
* @param {string} options.cancelIcon.label The label to add for `aria-label`
* @param {string} options.classes A string of extra classes to add to the step's content element.
* @param {string} options.highlightClass An extra class to apply to the `attachTo` element when it is
* highlighted (that is, when its step is active). You can then target that selector in your CSS.
Expand All @@ -90,7 +93,6 @@ export class Step extends Evented {
* if an object, passes that object as the params to `scrollIntoView` i.e. `{behavior: 'smooth', block: 'center'}`
* @param {function} options.scrollToHandler A function that lets you override the default scrollTo behavior and
* define a custom action to do the scrolling, and possibly other logic.
* @param {boolean} options.showCancelLink Should a cancel “✕” be shown in the header of the step?
* @param {function} options.showOn A function that, when it returns `true`, will show the step.
* If it returns false, the step will be skipped.
* @param {string} options.text The text in the body of the step. It can be one of three types:
Expand Down Expand Up @@ -230,8 +232,8 @@ export class Step extends Evented {
const descriptionId = `${this.id}-description`;
const labelId = `${this.id}-label`;

if (this.options.showCancelLink) {
classes += ` ${this.classPrefix}shepherd-has-cancel-link`;
if (this.options.cancelIcon && this.options.cancelIcon.enabled) {
classes += ` ${this.classPrefix}shepherd-has-cancel-icon`;
}

return render(
Expand Down
2 changes: 1 addition & 1 deletion src/js/styles/generateStyles.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export function generateStyles(options) {
pointerEvents: 'none'
},

[`.${classPrefix}shepherd-button, .${classPrefix}shepherd-cancel-link, .${classPrefix}shepherd-element, .${classPrefix}shepherd-target`]: {
[`.${classPrefix}shepherd-button, .${classPrefix}shepherd-cancel-icon, .${classPrefix}shepherd-element, .${classPrefix}shepherd-target`]: {
pointerEvents: 'auto',

'*': {
Expand Down
15 changes: 10 additions & 5 deletions src/types/step.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ declare namespace Step {
*/
buttons?: ReadonlyArray<StepOptionsButton>;

/**
* Should a cancel “✕” be shown in the header of the step?
*/
cancelIcon?: StepOptionsCancelIcon;

/**
* A string of extra classes to add to the step's content element.
*/
Expand Down Expand Up @@ -123,11 +128,6 @@ declare namespace Step {
*/
scrollToHandler?: ((element: HTMLElement) => void);

/**
* Should a cancel “✕” be shown in the header of the step?
*/
showCancelLink?: boolean;

/**
* A function that, when it returns `true`, will show the step.
* If it returns `false`, the step will be skipped.
Expand Down Expand Up @@ -217,6 +217,11 @@ declare namespace Step {
[key: string]: (() => void);
}

interface StepOptionsCancelIcon {
enabled?: boolean;
label?: string;
}

interface StepOptionsWhen {
[key: string]: (() => void);
}
Expand Down
24 changes: 16 additions & 8 deletions test/cypress/integration/test.acceptance.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ describe('Shepherd Acceptance Tests', () => {
};

const tour = setupTour(Shepherd, {
showCancelLink: false
cancelIcon: {
enabled: false
}
}, steps);

tour.start();
Expand Down Expand Up @@ -68,7 +70,9 @@ describe('Shepherd Acceptance Tests', () => {
];
};
const tour = setupTour(Shepherd, {
showCancelLink: false
cancelIcon: {
enabled: false
}
}, steps);
tour.start();
// Step text should be visible
Expand All @@ -89,7 +93,9 @@ describe('Shepherd Acceptance Tests', () => {
];
};
const tour = setupTour(Shepherd, {
showCancelLink: false
cancelIcon: {
enabled: false
}
}, steps);
tour.start();
// Step text should be visible
Expand Down Expand Up @@ -137,7 +143,7 @@ describe('Shepherd Acceptance Tests', () => {
const tour = setupTour(Shepherd);
tour.start();
cy.get('body').should('have.class', 'shepherd-active');
cy.get('.shepherd-cancel-link').click();
cy.get('.shepherd-cancel-icon').click();
cy.get('body').should('not.have.class', 'shepherd-active');
});

Expand All @@ -150,23 +156,25 @@ describe('Shepherd Acceptance Tests', () => {
// Step two text should be visible
cy.get('.shepherd-text')
.contains('Including Shepherd is easy!').should('be.visible');
cy.get('.shepherd-cancel-link:nth-child(2)').click();
cy.get('.shepherd-cancel-icon:nth-child(2)').click();
cy.get('body').should('not.have.class', 'shepherd-active');
});

it('Hides cancel link', () => {
const tour = setupTour(Shepherd, {
showCancelLink: false
cancelIcon: {
enabled: false
}
});
tour.start();
cy.get('.shepherd-cancel-link')
cy.get('.shepherd-cancel-icon')
.should('not.be.visible');
});

it('Shows cancel link', () => {
const tour = setupTour(Shepherd);
tour.start();
cy.get('.shepherd-cancel-link')
cy.get('.shepherd-cancel-icon')
.should('be.visible');
});
});
Expand Down
4 changes: 3 additions & 1 deletion test/cypress/utils/setup-tour.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import defaultSteps from './default-steps';
*/
export default function(Shepherd, globalDefaults, customSteps, otherOptions) {
const defaultStepOptions = Object.assign({}, {
showCancelLink: true
cancelIcon:{
enabled: true
}
}, globalDefaults);

const shepherdOptions = Object.assign({}, {
Expand Down
38 changes: 29 additions & 9 deletions test/unit/components/shepherd-header.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,56 @@ import { Step } from '../../../src/js/step';

describe('components/ShepherdHeader', () => {
const styles = {
'cancel-link': ' shepherd-cancel-link',
'cancel-icon': ' shepherd-cancel-icon',
header: ' shepherd-header'
};

it('cancel link is added when showCancelLink === true', () => {
it('cancel icon is added when cancelIcon.enabled === true', () => {
const step = {
options: {
showCancelLink: true
cancelIcon: {
enabled: true
}
}
};

const header = <ShepherdHeader step={step} styles={styles}/>;
expect(header).to.include(<button aria-label="Close Tour" class="shepherd-cancel-link" type="button"><span aria-hidden="true">×</span></button>);
expect(header).to.include(<button aria-label="Close Tour" class="shepherd-cancel-icon" type="button"><span aria-hidden="true">×</span></button>);
});

it('cancel link is not added when showCancelLink === false', () => {
it('cancel icon is not added when cancelIcon.enabled === false', () => {
const step = {
options: {
showCancelLink: false
cancelIcon: {
enabled: false
}
}
};

const header = <ShepherdHeader step={step} styles={styles}/>;
expect(header).to.not.include(<button aria-label="Close Tour" className="shepherd-cancel-link" type="button"><span aria-hidden="true">×</span></button>);
expect(header).to.not.include(<button aria-label="Close Tour" className="shepherd-cancel-icon" type="button"><span aria-hidden="true">×</span></button>);
});

it('cancel link cancels the tour', async () => {
it('cancel icon aria-label overridden when cancelIcon.label is set', () => {
const step = {
options: {
cancelIcon: {
enabled: true,
label: 'Test'
}
}
};

const header = <ShepherdHeader step={step} styles={styles}/>;
expect(header).to.include(<button aria-label="Test" class="shepherd-cancel-icon" type="button"><span aria-hidden="true">×</span></button>);
});

it('cancel icon cancels the tour', async () => {
const tour = new Tour();
const step = new Step(tour, {
showCancelLink: true
cancelIcon: {
enabled: true
}
});
const stepCancelSpy = spy(step, 'cancel');

Expand Down

0 comments on commit a84ace7

Please sign in to comment.