-
Notifications
You must be signed in to change notification settings - Fork 674
feat: add TopicTag component #7177
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
Merged
Merged
Changes from 10 commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
37beefd
feat: add TopicTag component
joshblack 6c422b9
test: update snapshots
joshblack f98b59d
test: update snapshots size
joshblack 115040a
test: update snapshots size
joshblack 3534681
test: add focus snapshots
joshblack 81ecae0
chore: use rounded line-height
joshblack d74d504
chore: update styles, screenshots
joshblack 77f9e30
feat: add TopicTagGroup
joshblack eb58ced
chore: clean up types for TopicTagGroup
joshblack 13862cb
chore: fix stylelint errors
joshblack 0b8d16a
Merge branch 'main' of github.com:primer/react into feat/add-topic-ta…
joshblack c41826c
refactor: set <a> as the default element type
joshblack bc395e3
chore: add changeset
joshblack 95162f3
docs: update as group story example
joshblack 1a048f1
refactor: update :where style to be scoped
joshblack 74b40ee
Merge branch 'main' into feat/add-topic-tag-component
hectahertz 8da6b00
Merge branch 'main' of github.com:primer/react into feat/add-topic-ta…
joshblack 11ba1d6
refactor: update examples, add button reset styles
joshblack d727f1d
refactor: create buttonReset helper mixin
joshblack 80688be
test(vrt): update snapshots
joshblack 7a751ad
chore: update snapshots
joshblack 2cb5652
test: fix failures from link changes
joshblack File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Binary file added
BIN
+9.76 KB
.../snapshots/components/TopicTag.test.ts-snapshots/TopicTag-As-Group-md-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+9.81 KB
.../snapshots/components/TopicTag.test.ts-snapshots/TopicTag-As-Group-sm-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+10.3 KB
.../snapshots/components/TopicTag.test.ts-snapshots/TopicTag-As-Group-xs-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+2.7 KB
...nts/TopicTag.test.ts-snapshots/TopicTag-Default-dark-colorblind-focus-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+2.04 KB
...nts/TopicTag.test.ts-snapshots/TopicTag-Default-dark-colorblind-hover-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+2.01 KB
...omponents/TopicTag.test.ts-snapshots/TopicTag-Default-dark-colorblind-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+2.73 KB
...ponents/TopicTag.test.ts-snapshots/TopicTag-Default-dark-dimmed-focus-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+2.04 KB
...ponents/TopicTag.test.ts-snapshots/TopicTag-Default-dark-dimmed-hover-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1.97 KB
...ts/components/TopicTag.test.ts-snapshots/TopicTag-Default-dark-dimmed-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+2.7 KB
...ots/components/TopicTag.test.ts-snapshots/TopicTag-Default-dark-focus-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+2.71 KB
.../TopicTag.test.ts-snapshots/TopicTag-Default-dark-high-contrast-focus-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+2.25 KB
.../TopicTag.test.ts-snapshots/TopicTag-Default-dark-high-contrast-hover-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+2.27 KB
...onents/TopicTag.test.ts-snapshots/TopicTag-Default-dark-high-contrast-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+2.04 KB
...ots/components/TopicTag.test.ts-snapshots/TopicTag-Default-dark-hover-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+2.01 KB
...snapshots/components/TopicTag.test.ts-snapshots/TopicTag-Default-dark-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+2.7 KB
...nts/TopicTag.test.ts-snapshots/TopicTag-Default-dark-tritanopia-focus-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+2.04 KB
...nts/TopicTag.test.ts-snapshots/TopicTag-Default-dark-tritanopia-hover-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+2.01 KB
...omponents/TopicTag.test.ts-snapshots/TopicTag-Default-dark-tritanopia-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+2.39 KB
...ts/TopicTag.test.ts-snapshots/TopicTag-Default-light-colorblind-focus-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+2.02 KB
...ts/TopicTag.test.ts-snapshots/TopicTag-Default-light-colorblind-hover-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1.9 KB
...mponents/TopicTag.test.ts-snapshots/TopicTag-Default-light-colorblind-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+2.39 KB
...ts/components/TopicTag.test.ts-snapshots/TopicTag-Default-light-focus-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+2.4 KB
...TopicTag.test.ts-snapshots/TopicTag-Default-light-high-contrast-focus-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+2.13 KB
...TopicTag.test.ts-snapshots/TopicTag-Default-light-high-contrast-hover-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+2.24 KB
...nents/TopicTag.test.ts-snapshots/TopicTag-Default-light-high-contrast-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+2.02 KB
...ts/components/TopicTag.test.ts-snapshots/TopicTag-Default-light-hover-linux.png
Oops, something went wrong.
Binary file added
BIN
+1.9 KB
...napshots/components/TopicTag.test.ts-snapshots/TopicTag-Default-light-linux.png
Oops, something went wrong.
Binary file added
BIN
+2.39 KB
...ts/TopicTag.test.ts-snapshots/TopicTag-Default-light-tritanopia-focus-linux.png
Oops, something went wrong.
Binary file added
BIN
+2.02 KB
...ts/TopicTag.test.ts-snapshots/TopicTag-Default-light-tritanopia-hover-linux.png
Oops, something went wrong.
Binary file added
BIN
+1.9 KB
...mponents/TopicTag.test.ts-snapshots/TopicTag-Default-light-tritanopia-linux.png
Oops, something went wrong.
This file contains hidden or 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,69 @@ | ||
| import {test, expect} from '@playwright/test' | ||
| import {visit} from '../test-helpers/storybook' | ||
| import {themes} from '../test-helpers/themes' | ||
| import {viewports} from '../test-helpers/viewports' | ||
|
|
||
| const stories = [ | ||
| { | ||
| title: 'Default', | ||
| id: 'experimental-components-topictag--default', | ||
| }, | ||
| ] as const | ||
|
|
||
| test.describe('TopicTag', () => { | ||
| for (const story of stories) { | ||
| test.describe(story.title, () => { | ||
| for (const theme of themes) { | ||
| test.describe(theme, () => { | ||
| test('default @vrt', async ({page}) => { | ||
| await visit(page, { | ||
| id: story.id, | ||
| globals: { | ||
| colorScheme: theme, | ||
| }, | ||
| }) | ||
| await page.setViewportSize({width: 400, height: 200}) | ||
|
|
||
| // Default state | ||
| await expect(page).toHaveScreenshot(`TopicTag.${story.title}.${theme}.png`) | ||
|
|
||
| // Hover state | ||
| await page.getByText('React').hover() | ||
| await expect(page).toHaveScreenshot(`TopicTag.${story.title}.${theme}.hover.png`) | ||
|
|
||
| // Focus state | ||
| // eslint-disable-next-line github/no-blur | ||
| await page.getByText('React').blur() | ||
| await page.getByText('React').focus() | ||
| await expect(page).toHaveScreenshot(`TopicTag.${story.title}.${theme}.focus.png`) | ||
| }) | ||
| }) | ||
| } | ||
| }) | ||
| } | ||
|
|
||
| test.describe('As Group', () => { | ||
| const story = { | ||
| title: 'As Group', | ||
| id: 'experimental-components-topictag-features--as-group', | ||
| } | ||
|
|
||
| test('default @vrt', async ({page}) => { | ||
| await visit(page, { | ||
| id: story.id, | ||
| }) | ||
|
|
||
| // Viewport: xs | ||
| await page.setViewportSize({width: viewports['primer.breakpoint.xs'], height: 500}) | ||
| await expect(page).toHaveScreenshot(`TopicTag.${story.title}.xs.png`) | ||
|
|
||
| // Viewport: sm | ||
| await page.setViewportSize({width: viewports['primer.breakpoint.sm'], height: 500}) | ||
| await expect(page).toHaveScreenshot(`TopicTag.${story.title}.sm.png`) | ||
|
|
||
| // Viewport: md | ||
| await page.setViewportSize({width: viewports['primer.breakpoint.md'], height: 500}) | ||
| await expect(page).toHaveScreenshot(`TopicTag.${story.title}.md.png`) | ||
| }) | ||
| }) | ||
| }) |
This file contains hidden or 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,21 @@ | ||
| { | ||
| "id": "topic_tag", | ||
| "name": "TopicTag", | ||
| "status": "alpha", | ||
| "a11yReviewed": false, | ||
| "stories": [], | ||
| "importPath": "@primer/react/experimental", | ||
| "props": [ | ||
| { | ||
| "name": "as", | ||
| "type": "React.ElementType", | ||
| "description": "The HTML element or React component to render as the root element" | ||
| }, | ||
| { | ||
| "name": "className", | ||
| "type": "string", | ||
| "description": "Class name for custom styling" | ||
| } | ||
| ], | ||
| "subcomponents": [] | ||
| } |
This file contains hidden or 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,39 @@ | ||
| import type {Meta} from '@storybook/react-vite' | ||
| import {TopicTag} from './TopicTag' | ||
| import {TopicTagGroup} from './TopicTagGroup' | ||
|
|
||
| export default { | ||
| title: 'Experimental/Components/TopicTag/Features', | ||
| component: TopicTag, | ||
| } satisfies Meta<typeof TopicTag> | ||
|
|
||
| export const AsLink = () => ( | ||
| <TopicTag as="a" href="/topics/react"> | ||
| React | ||
| </TopicTag> | ||
| ) | ||
|
|
||
| export const AsGroup = () => { | ||
| const tags = [ | ||
| 'react', | ||
| 'nodejs', | ||
| 'javascript', | ||
| 'd3', | ||
| 'teachers', | ||
| 'community', | ||
| 'education', | ||
| 'programming', | ||
| 'curriculum', | ||
| 'math', | ||
| ] | ||
|
|
||
| return ( | ||
| <TopicTagGroup> | ||
| {tags.map(tag => ( | ||
| <TopicTag as="a" href={`/topics/${tag.toLowerCase()}`} key={tag}> | ||
| {tag} | ||
| </TopicTag> | ||
| ))} | ||
| </TopicTagGroup> | ||
| ) | ||
| } |
This file contains hidden or 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,25 @@ | ||
| .TopicTag { | ||
| background-color: var(--bgColor-accent-muted); | ||
| color: var(--fgColor-accent); | ||
| font-size: var(--text-body-size-small); | ||
| font-weight: var(--base-text-weight-semibold); | ||
| /* --text-body-lineHeight-small */ | ||
| /* stylelint-disable-next-line primer/typography */ | ||
| line-height: 1.66667; | ||
| border-radius: var(--borderRadius-full); | ||
| padding: var(--base-size-2) var(--base-size-12); | ||
| border: var(--borderWidth-thin) solid var(--topicTag-borderColor, transparent); | ||
| display: inline-flex; | ||
| white-space: nowrap; | ||
|
|
||
| &:hover { | ||
| background-color: var(--bgColor-accent-emphasis); | ||
| color: var(--fgColor-onEmphasis); | ||
| } | ||
| } | ||
|
|
||
| /* Add a reset to when TopicTag is an <a> element since our link styles apply an underline text-decoration by default */ | ||
| /* stylelint-disable-next-line selector-no-qualifying-type */ | ||
| :where(a.TopicTag) { | ||
| text-decoration: none; | ||
| } |
This file contains hidden or 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,13 @@ | ||
| import type {Meta, StoryObj} from '@storybook/react-vite' | ||
| import {TopicTag} from './TopicTag' | ||
|
|
||
| export default { | ||
| title: 'Experimental/Components/TopicTag', | ||
| component: TopicTag, | ||
| } satisfies Meta<typeof TopicTag> | ||
|
|
||
| export const Default = () => <TopicTag>React</TopicTag> | ||
|
|
||
| export const Playground: StoryObj<typeof TopicTag> = { | ||
| render: args => <TopicTag {...args}>React</TopicTag>, | ||
| } |
This file contains hidden or 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,41 @@ | ||
| import {render, screen} from '@testing-library/react' | ||
| import {describe, test, expect, vi} from 'vitest' | ||
| import {userEvent} from 'vitest/browser' | ||
| import {TopicTag} from '../TopicTag' | ||
|
|
||
| describe('TopicTag', () => { | ||
| test('defaults to <button> semantics', async () => { | ||
| const onClick = vi.fn() | ||
| render(<TopicTag onClick={onClick}>test</TopicTag>) | ||
|
|
||
| await userEvent.click(screen.getByRole('button', {name: 'test'})) | ||
| expect(onClick).toHaveBeenCalled() | ||
| }) | ||
|
|
||
| test('support <a> semantics through `href` prop', async () => { | ||
| const onClick = vi.fn() | ||
| render( | ||
| <TopicTag as="a" href="#test" onClick={onClick}> | ||
| test | ||
| </TopicTag>, | ||
| ) | ||
|
|
||
| await userEvent.click(screen.getByRole('link', {name: 'test'})) | ||
| expect(onClick).toHaveBeenCalled() | ||
| }) | ||
|
|
||
| test('supports `className` merging', () => { | ||
| const {container} = render(<TopicTag className="custom-class">test</TopicTag>) | ||
| expect(container.firstChild).toHaveClass('custom-class') | ||
| }) | ||
|
|
||
| test('additional props are supplied to outermost element', () => { | ||
| const {container} = render( | ||
| <TopicTag data-testid="test" id="test-id"> | ||
| test | ||
| </TopicTag>, | ||
| ) | ||
| expect(container.firstChild).toHaveAttribute('data-testid', 'test') | ||
| expect(container.firstChild).toHaveAttribute('id', 'test-id') | ||
| }) | ||
| }) | ||
This file contains hidden or 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,26 @@ | ||
| import {clsx} from 'clsx' | ||
| import type {ElementType} from 'react' | ||
| import buttonResetClasses from '../internal/components/ButtonReset.module.css' | ||
| import classes from './TopicTag.module.css' | ||
|
|
||
| type TopicTagProps<As extends ElementType> = { | ||
| as?: As | ||
| className?: string | ||
| } & Omit<React.ComponentPropsWithoutRef<As>, 'as' | 'className'> | ||
|
|
||
| function TopicTag<As extends ElementType = 'button'>({as, children, className, ...rest}: TopicTagProps<As>) { | ||
| const BaseComponent = as ?? 'button' | ||
| return ( | ||
| <BaseComponent | ||
| {...rest} | ||
| className={clsx(className, classes.TopicTag, { | ||
| [buttonResetClasses.ButtonReset]: BaseComponent === 'button', | ||
| })} | ||
| > | ||
| {children} | ||
| </BaseComponent> | ||
| ) | ||
| } | ||
|
|
||
| export {TopicTag} | ||
| export type {TopicTagProps} |
This file contains hidden or 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,6 @@ | ||
| .TopicTagGroup { | ||
| display: flex; | ||
| flex-wrap: wrap; | ||
| column-gap: var(--base-size-2); | ||
| row-gap: var(--base-size-8); | ||
| } |
This file contains hidden or 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,16 @@ | ||
| import {clsx} from 'clsx' | ||
| import type React from 'react' | ||
| import classes from './TopicTagGroup.module.css' | ||
|
|
||
| type TopicTagGroupProps = React.HTMLAttributes<HTMLElement> | ||
|
|
||
| function TopicTagGroup({children, ...rest}: TopicTagGroupProps) { | ||
| return ( | ||
| <div {...rest} className={clsx(classes.TopicTagGroup)}> | ||
| {children} | ||
| </div> | ||
| ) | ||
| } | ||
|
|
||
| export {TopicTagGroup} | ||
| export type {TopicTagGroupProps} |
This file contains hidden or 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,2 @@ | ||
| export {TopicTag} from './TopicTag' | ||
| export type {TopicTagProps} from './TopicTag' |
This file contains hidden or 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 hidden or 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
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test on line 27 is incorrect. When
as="button"is used, the component should render a<button>element with role "button", not "link". The test should usescreen.getByRole('button', {name: 'test'})instead.