diff --git a/.changeset/flat-avocados-cheer.md b/.changeset/flat-avocados-cheer.md
new file mode 100644
index 00000000000..1c248bdaec4
--- /dev/null
+++ b/.changeset/flat-avocados-cheer.md
@@ -0,0 +1,5 @@
+---
+'@primer/react': patch
+---
+
+Utilizes `[disabled]` selector instead of `:disabled` in `TooltipV2` to address a false positive
diff --git a/.changeset/fuzzy-jobs-deny.md b/.changeset/fuzzy-jobs-deny.md
new file mode 100644
index 00000000000..4a63867dc87
--- /dev/null
+++ b/.changeset/fuzzy-jobs-deny.md
@@ -0,0 +1,5 @@
+---
+"@primer/react": patch
+---
+
+Add missing `wide` CSS + className to Stack
diff --git a/packages/react/src/ActionMenu/ActionMenu.figma.tsx b/packages/react/src/ActionMenu/ActionMenu.figma.tsx
new file mode 100644
index 00000000000..3e2f971401e
--- /dev/null
+++ b/packages/react/src/ActionMenu/ActionMenu.figma.tsx
@@ -0,0 +1,28 @@
+import React from 'react'
+import {ActionMenu} from '../../src'
+import figma from '@figma/code-connect'
+
+figma.connect(
+ ActionMenu,
+ 'https://www.figma.com/design/GCvY3Qv8czRgZgvl1dG6lp/Primer-Web?node-id=26998-2424&t=GFf1GorpZXk4F8Mq-4',
+ {
+ props: {
+ trigger: figma.children('trigger'),
+ open: figma.boolean('open'),
+ align: figma.enum('align', {
+ right: 'end',
+ left: 'start',
+ center: 'center',
+ }),
+ actionList: figma.nestedProps('ActionMenu/Content', {
+ items: figma.children('*'),
+ }),
+ },
+ example: ({trigger, open, align, actionList}) => (
+
+ {trigger}
+ {actionList.items}
+
+ ),
+ },
+)
diff --git a/packages/react/src/Blankslate/Blankslate.figma.tsx b/packages/react/src/Blankslate/Blankslate.figma.tsx
new file mode 100644
index 00000000000..3e09985e29e
--- /dev/null
+++ b/packages/react/src/Blankslate/Blankslate.figma.tsx
@@ -0,0 +1,96 @@
+import React from 'react'
+import {Blankslate} from '../../src/drafts'
+import figma from '@figma/code-connect'
+
+figma.connect(Blankslate, 'https://www.figma.com/design/GCvY3Qv8czRgZgvl1dG6lp/Primer-Web?node-id=4398-2383&m=dev', {
+ props: {
+ leadingVisual: figma.nestedProps('_BlankslateVisual', {
+ item: figma.children('leadingVisual'),
+ }),
+ narrow: figma.boolean('narrow?'),
+ spacious: figma.boolean('spacious?'),
+ border: figma.boolean('border?'),
+ heading: figma.textContent('Text: Heading'),
+ description: figma.textContent('Text: Description'),
+ },
+ variant: {primaryAction: 'false', secondaryAction: 'false'},
+ example: ({leadingVisual, border, spacious, narrow, description, heading}) => (
+
+ {leadingVisual.item}
+ {heading}
+ {description}
+
+ ),
+})
+figma.connect(Blankslate, 'https://www.figma.com/design/GCvY3Qv8czRgZgvl1dG6lp/Primer-Web?node-id=4398-2383&m=dev', {
+ props: {
+ leadingVisual: figma.nestedProps('_BlankslateVisual', {
+ item: figma.children('leadingVisual'),
+ }),
+ narrow: figma.boolean('narrow?'),
+ spacious: figma.boolean('spacious?'),
+ border: figma.boolean('border?'),
+ heading: figma.textContent('Text: Heading'),
+ description: figma.textContent('Text: Description'),
+ primaryAction: figma.nestedProps('Primary action', {
+ text: figma.textContent('Button'),
+ }),
+ },
+ variant: {primaryAction: 'true', secondaryAction: 'false'},
+ example: ({leadingVisual, border, spacious, narrow, description, heading, primaryAction}) => (
+
+ {leadingVisual.item}
+ {heading}
+ {description}
+ {primaryAction.text}
+
+ ),
+})
+figma.connect(Blankslate, 'https://www.figma.com/design/GCvY3Qv8czRgZgvl1dG6lp/Primer-Web?node-id=4398-2383&m=dev', {
+ props: {
+ leadingVisual: figma.nestedProps('_BlankslateVisual', {
+ item: figma.children('leadingVisual'),
+ }),
+ narrow: figma.boolean('narrow?'),
+ spacious: figma.boolean('spacious?'),
+ border: figma.boolean('border?'),
+ heading: figma.textContent('Text: Heading'),
+ description: figma.textContent('Text: Description'),
+ primaryAction: figma.nestedProps('Primary action', {
+ text: figma.textContent('Button'),
+ }),
+ secondaryAction: figma.textContent('Secondary action link'),
+ },
+ variant: {primaryAction: 'true', secondaryAction: 'true'},
+ example: ({leadingVisual, border, spacious, narrow, description, heading, primaryAction, secondaryAction}) => (
+
+ {leadingVisual.item}
+ {heading}
+ {description}
+ {primaryAction.text}
+ {secondaryAction}
+
+ ),
+})
+figma.connect(Blankslate, 'https://www.figma.com/design/GCvY3Qv8czRgZgvl1dG6lp/Primer-Web?node-id=4398-2383&m=dev', {
+ props: {
+ leadingVisual: figma.nestedProps('_BlankslateVisual', {
+ item: figma.children('leadingVisual'),
+ }),
+ narrow: figma.boolean('narrow?'),
+ spacious: figma.boolean('spacious?'),
+ border: figma.boolean('border?'),
+ heading: figma.textContent('Text: Heading'),
+ description: figma.textContent('Text: Description'),
+ secondaryAction: figma.textContent('Secondary action link'),
+ },
+ variant: {primaryAction: 'false', secondaryAction: 'true'},
+ example: ({leadingVisual, border, spacious, narrow, description, heading, secondaryAction}) => (
+
+ {leadingVisual.item}
+ {heading}
+ {description}
+ {secondaryAction}
+
+ ),
+})
diff --git a/packages/react/src/ButtonGroup/ButtonGroup.figma.tsx b/packages/react/src/ButtonGroup/ButtonGroup.figma.tsx
new file mode 100644
index 00000000000..72f6026b9b4
--- /dev/null
+++ b/packages/react/src/ButtonGroup/ButtonGroup.figma.tsx
@@ -0,0 +1,10 @@
+import React from 'react'
+import {ButtonGroup} from '../../src'
+import figma from '@figma/code-connect'
+
+figma.connect(ButtonGroup, 'https://www.figma.com/design/GCvY3Qv8czRgZgvl1dG6lp/Primer-Web?node-id=36325-3634&m=dev', {
+ props: {
+ children: figma.children('*'),
+ },
+ example: ({children}) => {children},
+})
diff --git a/packages/react/src/Label/Label.figma.tsx b/packages/react/src/Label/Label.figma.tsx
new file mode 100644
index 00000000000..bb2d6c85281
--- /dev/null
+++ b/packages/react/src/Label/Label.figma.tsx
@@ -0,0 +1,30 @@
+import React from 'react'
+import {Label} from '../../src'
+import figma from '@figma/code-connect'
+
+figma.connect(Label, 'https://www.figma.com/design/GCvY3Qv8czRgZgvl1dG6lp/Primer-Web?node-id=18959-65008&m=dev', {
+ props: {
+ text: figma.textContent('Label'),
+ size: figma.enum('size', {
+ small: 'small',
+ large: 'large',
+ }),
+ variant: figma.enum('variant', {
+ default: 'default',
+ primary: 'primary',
+ secondary: 'secondary',
+ accent: 'accent',
+ success: 'success',
+ attention: 'attention',
+ severe: 'severe',
+ danger: 'danger',
+ done: 'done',
+ sponsors: 'sponsors',
+ }),
+ },
+ example: ({size, variant, text}) => (
+
+ ),
+})
diff --git a/packages/react/src/Popover/Popover.figma.tsx b/packages/react/src/Popover/Popover.figma.tsx
new file mode 100644
index 00000000000..9ce95da1600
--- /dev/null
+++ b/packages/react/src/Popover/Popover.figma.tsx
@@ -0,0 +1,48 @@
+import React from 'react'
+import {Heading, Popover, Text} from '../../src'
+import figma from '@figma/code-connect'
+
+/**
+ * -- This file was auto-generated by `figma connect create` --
+ * `props` includes a mapping from Figma properties and variants to
+ * suggested values. You should update this to match the props of your
+ * code component, and update the `example` function to return the
+ * code example you'd like to see in Figma
+ */
+
+figma.connect(Popover, 'https://www.figma.com/design/GCvY3Qv8czRgZgvl1dG6lp/Primer-Web?node-id=19015-63778&m=dev', {
+ props: {
+ body: figma.string('body'),
+ heading: figma.string('heading'),
+ action: figma.children('Action'),
+ caret: figma.enum('caret', {
+ top: 'top',
+ 'top-left': 'top-left',
+ 'top-right': 'top-right',
+ bottom: 'bottom',
+ 'bottom-left': 'bottom-left',
+ 'bottom-right': 'bottom-right',
+ left: 'left',
+ 'left-top': 'left-top',
+ 'left-bottom': 'left-bottom',
+ right: 'right',
+ 'right-top': 'right-top',
+ 'right-bottom': 'right-bottom',
+ }),
+ },
+ example: ({caret, heading, body, action}) => (
+
+
+
+ {heading}
+
+ {body}
+ {action}
+
+
+ ),
+})
diff --git a/packages/react/src/Spinner/Spinner.figma.tsx b/packages/react/src/Spinner/Spinner.figma.tsx
new file mode 100644
index 00000000000..194c59e275b
--- /dev/null
+++ b/packages/react/src/Spinner/Spinner.figma.tsx
@@ -0,0 +1,14 @@
+import React from 'react'
+import {Spinner} from '../../src'
+import figma from '@figma/code-connect'
+
+figma.connect(Spinner, 'https://www.figma.com/design/GCvY3Qv8czRgZgvl1dG6lp/Primer-Web?node-id=11025-38126&m=dev', {
+ props: {
+ size: figma.enum('size', {
+ small: 'small',
+ medium: 'medium',
+ large: 'large',
+ }),
+ },
+ example: ({size}) => ,
+})
diff --git a/packages/react/src/Stack/Stack.docs.json b/packages/react/src/Stack/Stack.docs.json
index 386648b99ea..968e1143328 100644
--- a/packages/react/src/Stack/Stack.docs.json
+++ b/packages/react/src/Stack/Stack.docs.json
@@ -35,6 +35,10 @@
"name": "padding",
"type": "'none' | 'condensed' | 'normal' | 'spacious' | ResponsiveValue<'none' | 'condensed' | 'normal' | 'spacious'>",
"description": "Specify the padding of the stack container."
+ },
+ {
+ "name": "className",
+ "type": "string"
}
],
"subcomponents": [
@@ -45,6 +49,10 @@
"name": "grow",
"type": "boolean | ResponsiveValue",
"description": "Allow item to keep size or expand to fill the available space."
+ },
+ {
+ "name": "className",
+ "type": "string"
}
]
}
diff --git a/packages/react/src/Stack/Stack.tsx b/packages/react/src/Stack/Stack.tsx
index 9aafa0e11b3..6b14b52a3e8 100644
--- a/packages/react/src/Stack/Stack.tsx
+++ b/packages/react/src/Stack/Stack.tsx
@@ -281,6 +281,14 @@ const StyledStack = styled.div`
&[data-justify-wide='space-evenly'] {
justify-content: space-evenly;
}
+
+ &[data-wrap-wide='wrap'] {
+ flex-wrap: wrap;
+ }
+
+ &[data-wrap-wide='nowrap'] {
+ flex-wrap: nowrap;
+ }
}
`
@@ -342,6 +350,7 @@ type StackProps = React.PropsWithChildren<{
* @default none
*/
padding?: Padding
+ className?: string
}>
function Stack({
@@ -353,6 +362,7 @@ function Stack({
justify = 'start',
padding = 'none',
wrap = 'nowrap',
+ className,
...rest
}: StackProps & React.ComponentPropsWithoutRef) {
const BaseComponent = as ?? 'div'
@@ -361,6 +371,7 @@ function Stack({
= React.PropsWithChildren<{
* @default false
*/
grow?: boolean | ResponsiveValue
+ className?: string
}>
function StackItem({
as,
children,
grow,
+ className,
...rest
}: StackItemProps & React.ComponentPropsWithoutRef) {
const BaseComponent = as ?? 'div'
return (
-
+
{children}
)
diff --git a/packages/react/src/StateLabel/StateLabel.figma.tsx b/packages/react/src/StateLabel/StateLabel.figma.tsx
new file mode 100644
index 00000000000..ebdae7cf3f4
--- /dev/null
+++ b/packages/react/src/StateLabel/StateLabel.figma.tsx
@@ -0,0 +1,57 @@
+import React from 'react'
+import {StateLabel} from '../../src'
+import figma from '@figma/code-connect'
+
+figma.connect(
+ StateLabel,
+ 'https://www.figma.com/design/GCvY3Qv8czRgZgvl1dG6lp/Primer-Web?node-id=18959-64962&t=gQF1OJTEGB3vTxPz-4',
+ {
+ props: {
+ size: figma.enum('size', {
+ small: 'small',
+ normal: 'normal',
+ }),
+ status: figma.enum('status', {
+ draft: 'issueDraft',
+ open: 'issueOpened',
+ closed: 'issueClosed',
+ unavailable: 'unavailable',
+ }),
+ text: figma.textContent('Label'),
+ },
+ variant: {variant: 'issue'},
+ example: ({text, size, status}) => (
+
+ {text}
+
+ ),
+ },
+)
+
+figma.connect(
+ StateLabel,
+ 'https://www.figma.com/design/GCvY3Qv8czRgZgvl1dG6lp/Primer-Web?node-id=18959-64962&t=gQF1OJTEGB3vTxPz-4',
+ {
+ props: {
+ size: figma.enum('size', {
+ small: 'small',
+ normal: 'normal',
+ }),
+ status: figma.enum('status', {
+ draft: 'draft',
+ open: 'pullOpened',
+ closed: 'pullClosed',
+ merged: 'pullMerged',
+ queued: 'pullQueued',
+ unavailable: 'unavailable',
+ }),
+ text: figma.textContent('Label'),
+ },
+ variant: {variant: 'pull request'},
+ example: ({text, size, status}) => (
+
+ {text}
+
+ ),
+ },
+)
diff --git a/packages/react/src/TooltipV2/Tooltip.tsx b/packages/react/src/TooltipV2/Tooltip.tsx
index b4756ff12d0..ab5c5fe6648 100644
--- a/packages/react/src/TooltipV2/Tooltip.tsx
+++ b/packages/react/src/TooltipV2/Tooltip.tsx
@@ -171,7 +171,7 @@ const positionToDirection: Record = {
// The list is from GitHub's custom-axe-rules https://github.com/github/github/blob/master/app/assets/modules/github/axe-custom-rules.ts#L3
const interactiveElements = [
'a[href]',
- 'button:not(:disabled)',
+ 'button:not([disabled])',
'summary',
'select',
'input:not([type=hidden])',
diff --git a/packages/react/src/TooltipV2/__tests__/Tooltip.test.tsx b/packages/react/src/TooltipV2/__tests__/Tooltip.test.tsx
index df52b73dcbd..3a237603182 100644
--- a/packages/react/src/TooltipV2/__tests__/Tooltip.test.tsx
+++ b/packages/react/src/TooltipV2/__tests__/Tooltip.test.tsx
@@ -109,4 +109,31 @@ describe('Tooltip', () => {
const triggerEL = getByRole('button')
expect(triggerEL.getAttribute('aria-describedby')).toContain('custom-tooltip-id')
})
+ it('should throw an error if the trigger element is disabled', () => {
+ const spy = jest.spyOn(console, 'error').mockImplementation()
+ expect(() => {
+ HTMLRender(
+
+
+ ,
+ )
+ }).toThrow(
+ 'The `Tooltip` component expects a single React element that contains interactive content. Consider using a `