Skip to content
Merged
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
22 changes: 22 additions & 0 deletions .changeset/hero-button-group.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
'@primer/react-brand': patch
---

Added `Hero.ButtonGroup` for rendering `Button` and `ActionMenu` children. `Hero.ButtonGroup` is now the de facto way to display buttons in the `Hero`.

⚠️ `Hero.PrimaryAction` and `Hero.SecondaryAction` are now deprecated. Please migrate over to `Hero.ButtonGroup` as they will be removed in a future release.

Migrate using the following approach:

```diff
-<Hero.PrimaryAction href="#">Primary action</Hero.PrimaryAction>
-<Hero.SecondaryAction href="#">Secondary action</Hero.SecondaryAction>
+<Hero.ButtonGroup>
+ <Button as="a" href="#">
+ Primary action
+ </Button>
+ <Button as="a" href="#">
+ Secondary action
+ </Button>
+</Hero.ButtonGroup>
```
15 changes: 15 additions & 0 deletions .changeset/hero-media-position-padding.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
'@primer/react-brand': minor
'@primer/brand-css': minor
---

⚠️ Breaking change to `Hero.Image` and `Hero.Video` ⚠️

Previously combined `padding` and `position` semantics have been separated.

The `position` prop will now only control layout and positioning relative to the content. It accepts `block-end`, `inline-start`, or `inline-end`.

```diff
-<Hero.Image position="block-end-padded" src="image.jpg" alt="" />
+<Hero.Image position="block-end" padding="all" src="image.jpg" alt="" />
```
6 changes: 3 additions & 3 deletions .changeset/quiet-otters-dance.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@

⚠️ Breaking change: Removed the `imageBackgroundColor` prop from `River.Visual`, `RiverBreakout.Visual`, and `RiverBreakoutTabs.Visual`.

The `gridline` variant now applies the full-bleed visual background layout by default. Remove `imageBackgroundColor="subtle"` from `River.Visual` and `RiverBreakout.Visual` when using the `gridline` variant.
The `River` `gridline` variant now applies the full-bleed visual background layout by default. Remove `imageBackgroundColor="subtle"` from `River.Visual` when using the `gridline` variant.

Remove `imageBackgroundColor` from `RiverBreakoutTabs.Visual` without replacement. Its default visual treatment is unchanged.
Remove `imageBackgroundColor` from `RiverBreakout.Visual` and `RiverBreakoutTabs.Visual` without replacement. Their default visual treatments are unchanged.

The background treatment is not applied to the default `River` or `RiverBreakout` variants.
The background treatment is not applied to the default `River` variant or either `RiverBreakout` variant.

Updated the River `gridline` variant tablet layout with a `618px` max-width and lateral gridlines.
16 changes: 16 additions & 0 deletions .changeset/river-visual-layout.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
'@primer/react-brand': minor
'@primer/brand-css': minor
'@primer/brand-primitives': minor
---

Added opt-in `position` and `padding` controls to `River.Visual` media in the `gridline` variant.

🔗 Storybook examples:

- [Center position](https://stunning-chainsaw-j82glqz.pages.github.io/brand/storybook/?path=/story/components-river-features-gridline-variants--grid-line-visual-position-center)
- [Block-end position](https://stunning-chainsaw-j82glqz.pages.github.io/brand/storybook/?path=/story/components-river-features-gridline-variants--grid-line-visual-position-block-end)
- [Block-end inline-start position](https://stunning-chainsaw-j82glqz.pages.github.io/brand/storybook/?path=/story/components-river-features-gridline-variants--grid-line-visual-position-block-end-inline-start)
- [Block-end inline-end position](https://stunning-chainsaw-j82glqz.pages.github.io/brand/storybook/?path=/story/components-river-features-gridline-variants--grid-line-visual-position-block-end-inline-end)
- [No padding](https://stunning-chainsaw-j82glqz.pages.github.io/brand/storybook/?path=/story/components-river-features-gridline-variants--grid-line-visual-padding-none)
- [Padding on all sides](https://stunning-chainsaw-j82glqz.pages.github.io/brand/storybook/?path=/story/components-river-features-gridline-variants--grid-line-visual-padding-all)
1 change: 1 addition & 0 deletions .changeset/soft-banners-sparkle.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@

- Restored rounded corners to `CTABanner` while preserving square edges when grid lines are enabled.
- Improved `ButtonGroup` to forward custom class names alongside its default styles.
- Added native `ActionMenu` child support to `ButtonGroup`, including automatic sizes and positional variants, and the `CTABanner.ButtonGroup` wrapper.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
run: npm run check

- name: Run unit tests
run: npm run test
run: npm run test --workspaces --if-present

- name: Run MCP server smoke tests
run: npm run smoke --workspace=packages/mcp
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ npm-debug.log*
yarn-debug.log*
yarn-error.log*
debug-storybook.log
.playwright-mcp/

# local env files
.env
Expand Down
29 changes: 25 additions & 4 deletions apps/next-docs/content/components/ButtonGroup/react.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Button group
description: Use the button group component to group related buttons together.
description: Use the button group component to group related buttons and action menus together.
keywords: ['buttons', 'control', 'action', 'group', 'paired']
show-tabs: true
tab-label: React
Expand All @@ -12,14 +12,14 @@ storybook: '/brand/storybook/?path=/story/components-buttongroup--playground'
import {ButtonGroupSizesProp, ButtonGroupAsProp} from './react'

```js
import {ButtonGroup, Button} from '@primer/react-brand'
import {ActionMenu, Button, ButtonGroup} from '@primer/react-brand'
```

## Examples

### Default

This is the default variant for the ButtonGroup component. The first button in the group is the primary button and the second button is the secondary button.
This is the default variant for the ButtonGroup component. The first item in the group uses the primary button variant and the second uses the secondary button variant.

```jsx live
<ButtonGroup>
Expand All @@ -28,9 +28,30 @@ This is the default variant for the ButtonGroup component. The first button in t
</ButtonGroup>
```

### Action menus

`ButtonGroup` supports up to two `Button` or `ActionMenu` children and applies a default `variant` to each one.

Explicit `variant` overrides to `Button` or `ActionMenu.Button` will override the default values.

`buttonSize` applies to both child types. Because `ActionMenu` supports only `small` and `medium`, it remains `medium` when `buttonSize="large"`. Set `size` on `ActionMenu` to override the inherited size.

```jsx live
<ButtonGroup>
<Button>Primary action</Button>
<ActionMenu>
<ActionMenu.Button>More actions</ActionMenu.Button>
<ActionMenu.Overlay aria-label="More actions">
<ActionMenu.Item value="contact-sales">Contact sales</ActionMenu.Item>
<ActionMenu.Item value="view-pricing">View pricing</ActionMenu.Item>
</ActionMenu.Overlay>
</ActionMenu>
</ButtonGroup>
```

### Sizes

The ButtonGroup component can be rendered in different sizes in `medium` and `large` sizes. The default size is `medium`.
The ButtonGroup component supports `small`, `medium`, and `large` buttons. The default size is `medium`. ActionMenu children support `small` and `medium`.

```jsx live
<ButtonGroup buttonSize="large">
Expand Down
2 changes: 1 addition & 1 deletion apps/next-docs/content/components/ButtonGroup/react.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use client'
import {PropTableValues} from '@primer/doctocat-nextjs/components'

export const ButtonGroupSizesProp = () => <PropTableValues values={['medium', 'large']} commaSeparated />
export const ButtonGroupSizesProp = () => <PropTableValues values={['small', 'medium', 'large']} commaSeparated />
export const ButtonGroupAsProp = () => <PropTableValues values={['button', 'a']} commaSeparated />
104 changes: 82 additions & 22 deletions apps/next-docs/content/components/Hero/react.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
} from './react'

```js
import {Hero} from '@primer/react-brand'
import {ActionMenu, Button, Hero} from '@primer/react-brand'
```

## Examples
Expand All @@ -33,8 +33,36 @@ import {Hero} from '@primer/react-brand'
Lorem ipsum dolor sit amet, consectetur adipiscing elit. In sapien sit ullamcorper id. Aliquam luctus sed turpis
felis nam pulvinar risus elementum.
</Hero.Description>
<Hero.PrimaryAction href="#">Primary action</Hero.PrimaryAction>
<Hero.SecondaryAction href="#">Secondary action</Hero.SecondaryAction>
<Hero.ButtonGroup>
<Button as="a" href="#">
Primary action
</Button>
<Button as="a" href="#">
Secondary action
</Button>
</Hero.ButtonGroup>
</Hero>
```

### Action menus

`Hero.ButtonGroup` accepts up to two `Button` or `ActionMenu` children and applies the primary variant to the first item and the secondary variant to the second. Set `variant` on `Button` or `ActionMenu.Button` to override it.

```jsx live
<Hero>
<Hero.Heading>This is my super sweet hero heading</Hero.Heading>
<Hero.ButtonGroup>
<Button as="a" href="#">
Primary action
</Button>
<ActionMenu>
<ActionMenu.Button>More actions</ActionMenu.Button>
<ActionMenu.Overlay aria-label="More actions">
<ActionMenu.Item value="contact-sales">Contact sales</ActionMenu.Item>
<ActionMenu.Item value="view-pricing">View pricing</ActionMenu.Item>
</ActionMenu.Overlay>
</ActionMenu>
</Hero.ButtonGroup>
</Hero>
```

Expand All @@ -47,14 +75,22 @@ import {Hero} from '@primer/react-brand'
<Hero>
<Hero.Label>Actions</Hero.Label>
<Hero.Heading>Automate your workflow from idea to production</Hero.Heading>
<Hero.PrimaryAction href="#">Get started with Actions</Hero.PrimaryAction>
<Hero.ButtonGroup>
<Button as="a" href="#">
Get started with Actions
</Button>
</Hero.ButtonGroup>
<Hero.Image src="/images/placeholder.png" alt="placeholder, blank area with a gray background color" />
</Hero>
<br />
<Hero align="center">
<Hero.Label>Actions</Hero.Label>
<Hero.Heading size="2">Automate your workflow from idea to production</Hero.Heading>
<Hero.PrimaryAction href="#">Get started with Actions</Hero.PrimaryAction>
<Hero.ButtonGroup>
<Button as="a" href="#">
Get started with Actions
</Button>
</Hero.ButtonGroup>
<Hero.Image
position="inline-end"
src="/images/placeholder.png"
Expand All @@ -78,7 +114,11 @@ The `GridLine` variants all feature a trailing border by default. Use `Box` if y
Lorem ipsum dolor sit amet, consectetur adipiscing elit. In sapien sit ullamcorper id. Aliquam luctus sed turpis
felis nam pulvinar risus elementum.
</Hero.Description>
<Hero.PrimaryAction href="#">Primary action</Hero.PrimaryAction>
<Hero.ButtonGroup>
<Button as="a" href="#">
Primary action
</Button>
</Hero.ButtonGroup>
<Hero.Image src="/images/placeholder.png" alt="placeholder, blank area with a gray background color" />
</Hero>
```
Expand All @@ -96,7 +136,11 @@ The `GridLine` variants all feature a trailing border by default. Use `Box` if y
Lorem ipsum dolor sit amet, consectetur adipiscing elit. In sapien sit ullamcorper id. Aliquam luctus sed turpis
felis nam pulvinar risus elementum.
</Hero.Description>
<Hero.PrimaryAction href="#">Primary action</Hero.PrimaryAction>
<Hero.ButtonGroup>
<Button as="a" href="#">
Primary action
</Button>
</Hero.ButtonGroup>
<Hero.Image src="/images/placeholder.png" alt="placeholder, blank area with a gray background color" />
</Hero>
```
Expand All @@ -115,7 +159,11 @@ Use [VideoPlayer](/components/VideoPlayer), a native `<video>` element or a YouT
Lorem ipsum dolor sit amet, consectetur adipiscing elit. In sapien sit ullamcorper id. Aliquam luctus sed turpis
felis nam pulvinar risus elementum.
</Hero.Description>
<Hero.PrimaryAction href="#">Primary action</Hero.PrimaryAction>
<Hero.ButtonGroup>
<Button as="a" href="#">
Primary action
</Button>
</Hero.ButtonGroup>
<Hero.Video>
<iframe
src="https://www.youtube.com/embed/fHwtrOcLAnI"
Expand All @@ -142,7 +190,11 @@ Use [VideoPlayer](/components/VideoPlayer), a native `<video>` element or a YouT
<br />
developer environments
</Hero.Heading>
<Hero.PrimaryAction href="#">Primary action</Hero.PrimaryAction>
<Hero.ButtonGroup>
<Button as="a" href="#">
Primary action
</Button>
</Hero.ButtonGroup>
</Hero>
```

Expand Down Expand Up @@ -186,8 +238,14 @@ Forwards all props from the [Heading component](/typography/Heading), including

Forwards `size` and `weight` props from the [Text component](/typography/Text).

### Hero.ButtonGroup

Groups up to two [Button](/components/Button) or [ActionMenu](/components/ActionMenu) children. Forwards all props from the [ButtonGroup component](/components/ButtonGroup).

### Hero.PrimaryAction

Deprecated. Use `Hero.ButtonGroup` with a `Button` child instead.

| name | type | default | description |
| ----------- | ------------- | ------- | ----------------------------------- |
| `className` | `string` | | Primary link custom class |
Expand All @@ -198,6 +256,8 @@ Forwards all props from the [Button component](/components/Button).

### Hero.SecondaryAction

Deprecated. Use `Hero.ButtonGroup` with a `Button` child instead.

| name | type | default | description |
| ----------- | ------------- | ------- | ----------------------------------- |
| `className` | `string` | | Secondary link custom class |
Expand All @@ -208,21 +268,21 @@ Forwards all props from the [Button component](/components/Button).

### Hero.Image

| name | type | default | description |
| ---------- | ------------------------- | ------------- | -------------------------------------------- |
| `position` | <HeroImagePositionProp /> | `'block-end'` | Controls positioning of the foreground image |
| name | type | default | description |
| ---------- | ------------------------------ | ------------- | ------------------------------------------------- |
| `position` | <HeroImagePositionProp /> | `'block-end'` | Controls positioning of the foreground image |
| `padding` | `'default'`, `'none'`, `'all'` | `'default'` | Controls padding around media in gridline layouts |

Forwards all props from the [Image component](/components/Image), including `src`, `alt`, and `aspectRatio`.

### Hero.Video

| name | type | default | description |
| --------------- | ------------------------- | ------------- | --------------------------------------------------------------------------------------------------------------- |
| `position` | <HeroImagePositionProp /> | `'block-end'` | Controls positioning of the child video element |
| `poster` | `string` | | URL of the poster image to display before video plays. When set, `posterAltText` and `posterTitle` are required |
| `posterAltText` | `string` | | Alt text for the poster image. Required when `poster` is set |
| `posterTitle` | `string` | | Title text displayed on the poster overlay. Required when `poster` is set |
`position` and `padding` props currently only apply to `gridline` variants. The `default` Hero variant ignores non-default media padding and logs a warning during development.

```
### Hero.Video

```
| name | type | default | description |
| --------------- | ------------------------------ | ------------- | --------------------------------------------------------------------------------------------------------------- |
| `position` | <HeroImagePositionProp /> | `'block-end'` | Controls positioning of the child video element |
| `padding` | `'default'`, `'none'`, `'all'` | `'default'` | Controls padding around media in gridline layouts |
| `poster` | `string` | | URL of the poster image to display before video plays. When set, `posterAltText` and `posterTitle` are required |
| `posterAltText` | `string` | | Alt text for the poster image. Required when `poster` is set |
| `posterTitle` | `string` | | Title text displayed on the poster overlay. Required when `poster` is set |
5 changes: 1 addition & 4 deletions apps/next-docs/content/components/Hero/react.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ import {TextVariants, defaultTextVariant} from '@primer/react-brand'
export const HeroDescriptionVariantProp = () => <PropTableValues values={[...TextVariants]} addLineBreaks />
export const HeroDescriptionVariantPropDefault = () => <PropTableValues values={[defaultTextVariant]} />
export const HeroImagePositionProp = () => (
<PropTableValues
values={['block-end', 'block-end-padded', 'inline-end', 'inline-end-padded', 'inline-start', 'inline-start-padded']}
addLineBreaks
/>
<PropTableValues values={['block-end', 'inline-end', 'inline-start']} addLineBreaks />
)
export const HeroVariantProp = () => <PropTableValues values={['default', 'gridline']} addLineBreaks />
Loading
Loading