Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 677
Tooltip: Tooltip V2 as an experimental/draft with the new popover API#3394
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
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
2ae8d45a8aad6ec01b61f3b65cd2f846b3813d3aa243db25046630d44b0dd7d49b2ca8cd1bd7f99469e1a8b8fb6966bdf8851a6c21632030beeace0709128569dbf4e067a09e364d2eac64323f8b6da3e2b3bf1451f738f8e7d40612e5bdee65ff6fabddbf57c24bb065ed0f96507faf0fd97357e3744870d09dcab7edcded27858b2d30fb78a2f3514b7ecdf2c4157f48a15f782dbdf1849f6122a48bbec448133e0cb790c8c5e6def9954a9e80199527ea48cd5ebd229c5273f29dadba5d060edc0615b56fb96a05474ebb78acca662853133246dFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| --- | ||
| '@primer/react': minor | ||
| --- | ||
| Tooltip: Release Tooltip v2 as a draft/experimental | ||
| <!-- Changed components: _none_ --> |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| --- | ||
| componentId: tooltip | ||
| title: Tooltip | ||
| status: Alpha | ||
| --- | ||
| import data from '../../../src/drafts/Tooltip/Tooltip.docs.json' | ||
| The Tooltip component is used to add context to interactive elements on the page. | ||
| **_β οΈ Usage warning! β οΈ_** | ||
| Tooltips as a UI pattern should be our last resort for conveying information because it is hidden by default and often with zero or little visual indicator of its existence. | ||
| Before adding a tooltip, please consider: Is this information essential and necessary? Can the UI be made clearer? Can the information be shown on the page by default? See [Tooltip alternatives](https://primer.style/design/accessibility/tooltip-alternatives) for more accessible alternatives. | ||
| Tooltip should only be used on an element that is interactive such as a button or a link. | ||
| ## Examples | ||
| ### Default (For additional context) | ||
| Default tooltip is suitable for interactive controls that require additional context. | ||
| ```jsx live | ||
| <Tooltip text="This change cannot be undone."> | ||
| <Button>Delete</Button> | ||
| </Tooltip> | ||
| ``` | ||
| ### As a label | ||
| Tooltip can be used to label interactive controls that has no visible text label such as interactive icon links. | ||
| ```jsx live | ||
| <Tooltip text="Contribution Documentation for 'Primer React'" type="label"> | ||
| <Link href="https://github.com/primer/react/contributor-docs/CONTRIBUTING.md" sx={{ml: 1, color: 'fg.muted'}}> | ||
| <StyledOcticon icon={BookIcon} sx={{color: 'fg.muted'}} /> | ||
| </Link> | ||
| </Tooltip> | ||
| ``` | ||
| ### With direction | ||
| ```jsx live | ||
| <Box sx={{padding: 5, display: 'flex', gap: '8px'}}> | ||
| <Tooltip direction="n" text="Supplementary text"> | ||
| <Button>North</Button> | ||
| </Tooltip> | ||
| <Tooltip direction="s" text="Supplementary text"> | ||
| <Button>South</Button> | ||
| </Tooltip> | ||
| <Tooltip direction="e" text="Supplementary text"> | ||
| <Button>East</Button> | ||
| </Tooltip> | ||
| <Tooltip direction="w" text="Supplementary text"> | ||
| <Button>West</Button> | ||
| </Tooltip> | ||
| <Tooltip direction="ne" text="Supplementary text"> | ||
| <Button>North East</Button> | ||
| </Tooltip> | ||
| <Tooltip direction="nw" text="Supplementary text"> | ||
| <Button>North West</Button> | ||
| </Tooltip> | ||
| <Tooltip direction="se" text="Supplementary text"> | ||
| <Button>Southeast</Button> | ||
| </Tooltip> | ||
| <Tooltip direction="sw" text="Supplementary text"> | ||
| <Button>Southwest</Button> | ||
| </Tooltip> | ||
| </Box> | ||
| ``` | ||
| ## Props | ||
| <ComponentProps data={data} /> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,175 @@ | ||
| import {test, expect} from '@playwright/test' | ||
| import {visit} from '../test-helpers/storybook' | ||
| import {themes} from '../test-helpers/themes' | ||
| test.describe('Tooltip--experimental', () => { | ||
| test.describe('Default', () => { | ||
| for (const theme of themes) { | ||
| test.describe(theme, () => { | ||
| test('default @vrt', async ({page}) => { | ||
| await visit(page, { | ||
| id: 'drafts-components-tooltip--default', | ||
| globals: { | ||
| colorScheme: theme, | ||
| }, | ||
| }) | ||
| // Default state | ||
| await page.keyboard.press('Tab') | ||
| expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot( | ||
| `Tooltip--experimental.Default.${theme}.png`, | ||
| { | ||
| threshold: 0.1, | ||
| }, | ||
| ) | ||
| }) | ||
| test('axe @aat', async ({page}) => { | ||
| await visit(page, { | ||
| id: 'drafts-components-tooltip--default', | ||
| globals: { | ||
| colorScheme: theme, | ||
| }, | ||
| }) | ||
| await expect(page).toHaveNoViolations() | ||
| }) | ||
| }) | ||
| } | ||
| }) | ||
| test.describe('Anchor Has Margin', () => { | ||
| for (const theme of themes) { | ||
| test.describe(theme, () => { | ||
| test('default @vrt', async ({page}) => { | ||
| await visit(page, { | ||
| id: 'drafts-components-tooltip-features--anchor-has-margin', | ||
| globals: { | ||
| colorScheme: theme, | ||
| }, | ||
| }) | ||
| // Default state | ||
| await page.keyboard.press('Tab') | ||
| expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot( | ||
| `Tooltip--experimental.Anchor Has Margin.${theme}.png`, | ||
| { | ||
| threshold: 0.1, | ||
| }, | ||
| ) | ||
| }) | ||
| test('axe @aat', async ({page}) => { | ||
| await visit(page, { | ||
| id: 'drafts-components-tooltip-features--anchor-has-margin', | ||
| globals: { | ||
| colorScheme: theme, | ||
| }, | ||
| }) | ||
| await expect(page).toHaveNoViolations() | ||
| }) | ||
| }) | ||
| } | ||
| }) | ||
| test.describe('Calculated Direction', () => { | ||
| for (const theme of themes) { | ||
| test.describe(theme, () => { | ||
| test('default @vrt', async ({page}) => { | ||
| await visit(page, { | ||
| id: 'drafts-components-tooltip-features--calculated-direction', | ||
| globals: { | ||
| colorScheme: theme, | ||
| }, | ||
| }) | ||
| // Default state | ||
| await page.keyboard.press('Tab') | ||
| expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot( | ||
| `Tooltip--experimental.Calculated Direction.${theme}.png`, | ||
| { | ||
| threshold: 0.1, | ||
| }, | ||
| ) | ||
| }) | ||
| test('axe @aat', async ({page}) => { | ||
| await visit(page, { | ||
| id: 'drafts-components-tooltip-features--calculated-direction', | ||
| globals: { | ||
| colorScheme: theme, | ||
| }, | ||
| }) | ||
| await expect(page).toHaveNoViolations() | ||
| }) | ||
| }) | ||
| } | ||
| }) | ||
| test.describe('Icon Button With Description', () => { | ||
| for (const theme of themes) { | ||
| test.describe(theme, () => { | ||
| test('default @vrt', async ({page}) => { | ||
| await visit(page, { | ||
| id: 'drafts-components-tooltip-features--icon-button-with-description', | ||
| globals: { | ||
| colorScheme: theme, | ||
| }, | ||
| }) | ||
| // Default state | ||
| await page.keyboard.press('Tab') | ||
| expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot( | ||
| `Tooltip--experimental.Icon Button With Description.${theme}.png`, | ||
| { | ||
| threshold: 0.1, | ||
| }, | ||
| ) | ||
| }) | ||
| test('axe @aat', async ({page}) => { | ||
| await visit(page, { | ||
| id: 'drafts-components-tooltip-features--icon-button-with-description', | ||
| globals: { | ||
| colorScheme: theme, | ||
| }, | ||
| }) | ||
| await expect(page).toHaveNoViolations() | ||
| }) | ||
| }) | ||
| } | ||
| }) | ||
| test.describe('Label Type', () => { | ||
| for (const theme of themes) { | ||
| test.describe(theme, () => { | ||
| test('default @vrt', async ({page}) => { | ||
| await visit(page, { | ||
| id: 'drafts-components-tooltip-features--label-type', | ||
| globals: { | ||
| colorScheme: theme, | ||
| }, | ||
| }) | ||
| // Default state | ||
| await page.keyboard.press('Tab') | ||
| expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot( | ||
| `Tooltip--experimental.Label Type.${theme}.png`, | ||
| { | ||
| threshold: 0.1, | ||
| }, | ||
| ) | ||
| }) | ||
| test('axe @aat', async ({page}) => { | ||
| await visit(page, { | ||
| id: 'drafts-components-tooltip-features--label-type', | ||
| globals: { | ||
| colorScheme: theme, | ||
| }, | ||
| }) | ||
| await expect(page).toHaveNoViolations() | ||
| }) | ||
| }) | ||
| } | ||
| }) | ||
| }) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -2,6 +2,7 @@ | ||
| 'use strict' | ||
| const path = require('node:path') | ||
| const {REACT_VERSION_17} = process.env | ||
| /** | ||
| @@ -17,12 +18,21 @@ module.exports = { | ||
| collectCoverageFrom: ['src/**/*.{js,jsx,ts,tsx}', '!src/stories/**', '!**/*.stories.{js,jsx,ts,tsx}'], | ||
| moduleNameMapper: { | ||
| '\\.css$': 'jest-css-modules', | ||
| // We need to specify this package subpath because it does not provide a `require` conditional export path | ||
broccolinisoup marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| '@oddbird/popover-polyfill/fn': path.join( | ||
| __dirname, | ||
| 'node_modules', | ||
| '@oddbird', | ||
| 'popover-polyfill', | ||
| 'dist', | ||
| 'popover-fn.js', | ||
| ), | ||
| }, | ||
| setupFiles: ['<rootDir>/src/utils/test-helpers.tsx'], | ||
| setupFilesAfterEnv: ['<rootDir>/src/utils/test-matchers.tsx', '<rootDir>/src/utils/test-deprecations.tsx'], | ||
| testMatch: ['<rootDir>/(src|codemods)/**/*.test.[jt]s?(x)', '!**/*.types.test.[jt]s?(x)'], | ||
| transformIgnorePatterns: [ | ||
| 'node_modules/(?!@github/combobox-nav|@koddsson/textarea-caret|@github/[a-z-]+-element|@lit-labs/react)', | ||
| 'node_modules/(?!@github/combobox-nav|@koddsson/textarea-caret|@github/[a-z-]+-element|@lit-labs/react|@oddbird/popover-polyfill)', | ||
| ], | ||
| watchPlugins: ['jest-watch-typeahead/filename', 'jest-watch-typeahead/testname'], | ||
| } | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.