Skip to content
Open
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
4 changes: 2 additions & 2 deletions packages/core/src/components/workflow-step/workflow-step.scss
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,8 @@
}

&:focus-visible {
outline: 1px solid var(--focus--border-color);
border-radius: 0;
outline: 1px solid var(--theme-color-focus-bdr);
outline-offset: var(--theme-btn--focus--outline-offset);
}

&.selected {
Expand Down
21 changes: 13 additions & 8 deletions packages/core/src/components/workflow-step/workflow-step.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ export class WorkflowStep {
@Event() selectedChanged!: EventEmitter<HTMLIxWorkflowStepElement>;

private customIconSlot: boolean = false;

@Watch('selected')
selectedHandler() {
this.setWorkflowStepStyles();
Expand Down Expand Up @@ -139,7 +138,12 @@ export class WorkflowStep {
this.selectedChanged.emit(this.hostElement);
}
}

onKeyDown(event: KeyboardEvent) {
if (event.key === ' ' || event.key === 'Enter') {
event.preventDefault();
this.onStepClick();
}
}
getIconAriaLabel() {
switch (this.iconName) {
case iconCircle:
Expand Down Expand Up @@ -181,14 +185,15 @@ export class WorkflowStep {
></ix-icon>
</Fragment>
) : null;

return (
<Host
class={{ 'host-vertical': this.vertical }}
onClick={() => this.onStepClick()}
>
<Host class={{ 'host-vertical': this.vertical }}>
<div
tabIndex={0}
tabIndex={this.disabled || !this.clickable ? -1 : 0}
role={this.clickable ? 'button' : undefined}
aria-disabled={this.disabled ? 'true' : undefined}
aria-current={this.selected ? 'step' : undefined}
onClick={() => this.onStepClick()}
onKeyDown={(e) => this.onKeyDown(e)}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
class={{
step: true,
selected: this.selected,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,51 @@ regressionTest('renders', async ({ mount, page }) => {
await expect(step).toBeVisible();
});

regressionTest('accessibility', async ({ mount, makeAxeBuilder }) => {
await mount(`
<ix-workflow-steps>
<ix-workflow-step status="done">Step 1</ix-workflow-step>
<ix-workflow-step status="success">Step 2</ix-workflow-step>
<ix-workflow-step status="open">Step 3</ix-workflow-step>
</ix-workflow-steps>
`);

const results = await makeAxeBuilder().analyze();
expect(results.violations).toEqual([]);
});
regressionTest(
'should have correct aria attributes for accessibility',
async ({ mount, page }) => {
await mount(`
<ix-workflow-steps clickable>
<ix-workflow-step status="error">Step 1</ix-workflow-step>
<ix-workflow-step status="error" disabled>Step 2</ix-workflow-step>
<ix-workflow-step status="error">Step 3</ix-workflow-step>
</ix-workflow-steps>
`);

const workflowSteps = page.locator('ix-workflow-steps');
const steps = page.locator('ix-workflow-step');

await expect(workflowSteps).toHaveClass(/hydrated/);

await workflowSteps.evaluate(
(el: HTMLIxWorkflowStepsElement) => (el.selectedIndex = 2)
);

const step1Div = steps.nth(0).locator('.step');
const step2Div = steps.nth(1).locator('.step');
const step3Div = steps.nth(2).locator('.step');

await expect(step1Div).toHaveAttribute('role', 'button');
await expect(step1Div).toHaveAttribute('tabindex', '0');

await expect(step2Div).toHaveAttribute('aria-disabled', 'true');
await expect(step2Div).toHaveAttribute('tabindex', '-1');

await expect(step3Div).toHaveAttribute('aria-current', 'step');
}
);
regressionTest('should be clickable', async ({ mount, page }) => {
await mount(`
<ix-workflow-steps clickable>
Expand Down Expand Up @@ -73,6 +118,28 @@ regressionTest('should prevent click navigation', async ({ mount, page }) => {
await expect(firstStepDiv).toHaveClass(/selected/);
await expect(lastStepDiv).not.toHaveClass(/selected/);
});
regressionTest(
'supports keyboard selection via Enter and Space',
async ({ mount, page }) => {
await mount(`
<ix-workflow-steps clickable>
<ix-workflow-step>Step 1</ix-workflow-step>
<ix-workflow-step>Step 2</ix-workflow-step>
</ix-workflow-steps>
`);

const first = page.locator('ix-workflow-step').nth(0).locator('.step');
const second = page.locator('ix-workflow-step').nth(1).locator('.step');

await first.focus();
await first.press('Enter');
await expect(first).toHaveClass(/selected/);

await second.focus();
await second.press('Space');
await expect(second).toHaveClass(/selected/);
}
);

regressionTest(
'should have the correct visuals after toggling state from open to error and back again to open',
Expand Down
Loading