-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(VisualPageIndicator): introduce 1.0 component (#2118)
- add in new token eds-theme-color-background-visual-page-indicator-current - add in new token eds-theme-color-background-visual-page-indicator - add in component VisualPageIndicator with tests/snapshots - add in dynamic usage assertions - add in reduce motion support
- Loading branch information
1 parent
032cb5d
commit 3df98a3
Showing
12 changed files
with
277 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
src/components/VisualPageIndicator/VisualPageIndicator.module.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/*------------------------------------*\ | ||
# VISUAL PAGE INDICATOR | ||
\*------------------------------------*/ | ||
|
||
/** | ||
* VisualPageIndicator | ||
*/ | ||
.visual-page-indicator { | ||
display: flex; | ||
justify-content: center; | ||
gap: calc(var(--eds-size-1-and-half) / 16 * 1rem); | ||
} | ||
|
||
.visual-page-indicator__item { | ||
--visual-page-indicator-bg: var(--eds-theme-color-background-visual-page-indicator); | ||
|
||
height: calc(var(--eds-size-1-and-half) / 16 * 1rem); | ||
width: calc(var(--eds-size-1-and-half) / 16 * 1rem); | ||
border-radius: calc(var(--eds-border-radius-full) * 1px); | ||
|
||
transition: background-color ease calc(var(--eds-anim-move-medium) * 1s); | ||
|
||
background-color: var(--visual-page-indicator-bg); | ||
} | ||
|
||
.visual-page-indicator--active { | ||
--visual-page-indicator-bg: var(--eds-theme-color-background-visual-page-indicator-current); | ||
} | ||
|
||
@media screen and (prefers-reduced-motion: reduce) { | ||
.visual-page-indicator__item { | ||
transition: none; | ||
} | ||
} |
37 changes: 37 additions & 0 deletions
37
src/components/VisualPageIndicator/VisualPageIndicator.stories.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import type { StoryObj, Meta } from '@storybook/react'; | ||
import type React from 'react'; | ||
|
||
import { VisualPageIndicator } from './VisualPageIndicator'; | ||
|
||
export default { | ||
title: 'Components/VisualPageIndicator', | ||
component: VisualPageIndicator, | ||
parameters: { | ||
badges: ['api-1.0', 'theme-2.0'], | ||
}, | ||
} as Meta<Args>; | ||
|
||
type Args = React.ComponentProps<typeof VisualPageIndicator>; | ||
|
||
export const Default: StoryObj<Args> = { | ||
args: { | ||
activePage: 0, | ||
totalPageCount: 6, | ||
}, | ||
}; | ||
|
||
export const MinimumPages: StoryObj<Args> = { | ||
args: { | ||
activePage: 1, | ||
totalPageCount: 2, | ||
}, | ||
}; | ||
|
||
export const FivePages: StoryObj<Args> = { | ||
args: { | ||
activePage: 2, | ||
totalPageCount: 5, | ||
}, | ||
}; | ||
|
||
// TODO: add implementation example showing usage of state with a label for a11y handling |
55 changes: 55 additions & 0 deletions
55
src/components/VisualPageIndicator/VisualPageIndicator.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import { generateSnapshots } from '@chanzuckerberg/story-utils'; | ||
import { render } from '@testing-library/react'; | ||
|
||
import React from 'react'; | ||
import { VisualPageIndicator } from './VisualPageIndicator'; | ||
|
||
import * as stories from './VisualPageIndicator.stories'; | ||
import type { StoryFile } from '../../util/utility-types'; | ||
|
||
describe('<VisualPageIndicator />', () => { | ||
beforeEach(() => { | ||
// Add in mocks for the calls that can occur in implementation to suppress logging in tests | ||
const consoleMock = jest.spyOn(console, 'error'); | ||
const consoleWarnMock = jest.spyOn(console, 'warn'); | ||
consoleMock.mockImplementation(); | ||
consoleWarnMock.mockImplementation(); | ||
}); | ||
|
||
afterEach(() => { | ||
jest.resetAllMocks(); | ||
}); | ||
|
||
generateSnapshots(stories as StoryFile); | ||
|
||
describe('emits messages when misused', () => { | ||
let consoleErrorMock: jest.SpyInstance, consoleWarnMock: jest.SpyInstance; | ||
beforeEach(() => { | ||
consoleWarnMock = jest.spyOn(console, 'warn'); | ||
consoleErrorMock = jest.spyOn(console, 'error'); | ||
consoleWarnMock.mockImplementation(); | ||
consoleErrorMock.mockImplementation(); | ||
}); | ||
|
||
it('errors when active page is above range', () => { | ||
render(<VisualPageIndicator activePage={3} totalPageCount={2} />); | ||
|
||
expect(consoleWarnMock).toHaveBeenCalledTimes(0); | ||
expect(consoleErrorMock).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
it('errors when active page is below range', () => { | ||
render(<VisualPageIndicator activePage={-1} totalPageCount={2} />); | ||
|
||
expect(consoleWarnMock).toHaveBeenCalledTimes(0); | ||
expect(consoleErrorMock).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
it('warns when total page count is too small', () => { | ||
render(<VisualPageIndicator activePage={0} totalPageCount={1} />); | ||
|
||
expect(consoleWarnMock).toHaveBeenCalledTimes(1); | ||
expect(consoleErrorMock).toHaveBeenCalledTimes(0); | ||
}); | ||
}); | ||
}); |
68 changes: 68 additions & 0 deletions
68
src/components/VisualPageIndicator/VisualPageIndicator.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import clsx from 'clsx'; | ||
import React from 'react'; | ||
import { assertEdsUsage } from '../../util/logging'; | ||
|
||
import styles from './VisualPageIndicator.module.css'; | ||
|
||
export type VisualPageIndicatorProps = { | ||
// Component API | ||
/** | ||
* CSS class names that can be appended to the component. | ||
*/ | ||
className?: string; | ||
// Design API | ||
/** | ||
* Index of the active page in the indicator (0-based). | ||
*/ | ||
activePage: number; | ||
/** | ||
* Total number of pages available in this experience | ||
*/ | ||
totalPageCount: number; | ||
}; | ||
|
||
/** | ||
* `import {VisualPageIndicator} from "@chanzuckerberg/eds";` | ||
* | ||
* Static visual cue to help users understand their current position within a series of content or pages. | ||
*/ | ||
export const VisualPageIndicator = ({ | ||
className, | ||
activePage, | ||
totalPageCount, | ||
...other | ||
}: VisualPageIndicatorProps) => { | ||
const componentClassName = clsx(styles['visual-page-indicator'], className); | ||
|
||
assertEdsUsage( | ||
[totalPageCount < 2], | ||
'The minimum allowed count of indicators is 2', | ||
); | ||
|
||
assertEdsUsage( | ||
[activePage < 0, activePage > totalPageCount - 1], | ||
`The position in the indicator is out of range: [0, ${totalPageCount - 1}]`, | ||
'error', | ||
); | ||
|
||
return ( | ||
<ul className={componentClassName} {...other}> | ||
{Array(totalPageCount) | ||
.fill(0) | ||
.map((_, index) => { | ||
return `Page ${index}`; | ||
}) | ||
.map((name, index) => { | ||
return ( | ||
<li | ||
className={clsx( | ||
styles['visual-page-indicator__item'], | ||
index === activePage && styles['visual-page-indicator--active'], | ||
)} | ||
key={name} | ||
></li> | ||
); | ||
})} | ||
</ul> | ||
); | ||
}; |
61 changes: 61 additions & 0 deletions
61
src/components/VisualPageIndicator/__snapshots__/VisualPageIndicator.test.tsx.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`<VisualPageIndicator /> Default story renders snapshot 1`] = ` | ||
<ul | ||
class="visual-page-indicator" | ||
> | ||
<li | ||
class="visual-page-indicator__item visual-page-indicator--active" | ||
/> | ||
<li | ||
class="visual-page-indicator__item" | ||
/> | ||
<li | ||
class="visual-page-indicator__item" | ||
/> | ||
<li | ||
class="visual-page-indicator__item" | ||
/> | ||
<li | ||
class="visual-page-indicator__item" | ||
/> | ||
<li | ||
class="visual-page-indicator__item" | ||
/> | ||
</ul> | ||
`; | ||
|
||
exports[`<VisualPageIndicator /> FivePages story renders snapshot 1`] = ` | ||
<ul | ||
class="visual-page-indicator" | ||
> | ||
<li | ||
class="visual-page-indicator__item" | ||
/> | ||
<li | ||
class="visual-page-indicator__item" | ||
/> | ||
<li | ||
class="visual-page-indicator__item visual-page-indicator--active" | ||
/> | ||
<li | ||
class="visual-page-indicator__item" | ||
/> | ||
<li | ||
class="visual-page-indicator__item" | ||
/> | ||
</ul> | ||
`; | ||
|
||
exports[`<VisualPageIndicator /> MinimumPages story renders snapshot 1`] = ` | ||
<ul | ||
class="visual-page-indicator" | ||
> | ||
<li | ||
class="visual-page-indicator__item" | ||
/> | ||
<li | ||
class="visual-page-indicator__item visual-page-indicator--active" | ||
/> | ||
</ul> | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { VisualPageIndicator as default } from './VisualPageIndicator'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters