Skip to content

Commit

Permalink
Improved background customization options for CTABanner (#810)
Browse files Browse the repository at this point in the history
  • Loading branch information
rezrah authored Nov 5, 2024
1 parent bbb14ce commit 774b91b
Show file tree
Hide file tree
Showing 15 changed files with 492 additions and 45 deletions.
16 changes: 16 additions & 0 deletions .changeset/soft-frogs-build.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
'@primer/react-brand': patch
---

Added new background customization options to `CTABanner`

New props:

- `backgroundColor`
- `backgroundImageSrc`
- `backgroundImageSize`
- `backgroundImagePosition`

Also added `variant` prop to `CTABanner.Description`, to achieve higher contrast when using background images.

:link: [See the documentation for more details and usage examples](https://primer.style/brand/components/CTABanner/react/).
77 changes: 67 additions & 10 deletions apps/docs/content/components/CTABanner/react.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ description: Use the CTA banner component to highlight and create urgency around
---

import {Label} from '@primer/react'
import {PropTableValues} from '../../../src/components'
import {Link} from 'gatsby'
import ComponentLayout from '../../../src/layouts/component-layout'
export default ComponentLayout
import {TextVariants} from '@primer/react-brand'

```js
import {CTABanner, Button} from '@primer/react-brand'
Expand Down Expand Up @@ -57,6 +59,56 @@ The content alignment can be changed using the `align` prop on the root `CTABann
</CTABanner>
```

### Optional background image

```jsx live
<ThemeProvider colorMode="dark">
<CTABanner
backgroundImageSrc={{
narrow:
'https://github.com/user-attachments/assets/a28110fd-d019-41a4-8f80-b49ae8895708',
regular:
'https://github.com/user-attachments/assets/a28110fd-d019-41a4-8f80-b49ae8895708',
wide: 'https://github.com/user-attachments/assets/a28110fd-d019-41a4-8f80-b49ae8895708',
}}
align="center"
hasShadow={false}
>
<CTABanner.Heading>
Where the most ambitious teams build great things
</CTABanner.Heading>
<CTABanner.Description variant="default">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. In sapien sit
ullamcorper id. Aliquam luctus sed turpis felis nam pulvinar risus
elementum.
</CTABanner.Description>
<CTABanner.ButtonGroup>
<Button>Primary Action</Button>
</CTABanner.ButtonGroup>
</CTABanner>
</ThemeProvider>
```

### Optional background colors

`CTABanner` supports `default`, `subtle` and arbitrary `background-color` values

```jsx live
<CTABanner backgroundColor="subtle" hasShadow={false}>
<CTABanner.Heading>
Where the most ambitious teams build great things
</CTABanner.Heading>
<CTABanner.Description>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. In sapien sit
ullamcorper id. Aliquam luctus sed turpis felis nam pulvinar risus
elementum.
</CTABanner.Description>
<CTABanner.ButtonGroup>
<Button>Primary Action</Button>
</CTABanner.ButtonGroup>
</CTABanner>
```

### Optional border

A border can be provided using the `hasBorder` prop on the root `CTABanner`. This will render a border around the `CTABanner` component giving further separation between the foreground and background. Especially when there is no shadow present on the background.
Expand Down Expand Up @@ -166,13 +218,17 @@ render(<App />)

### CTABanner <Label>Required</Label>

| name | type | default | required | description |
| --------------- | -------------------------- | ----------- | -------- | ----------------------------------------------------------------- |
| `children` | `ReactNode`, `ReactNode[]` | `undefined` | `true` | Content to include within the banner component |
| `align` | `'start'`, `'center'` | `'start'` | `true` | The horizontal positioning of content within the banner component |
| `hasBorder` | `boolean` | `false` | `false` | A flag used to provide a border to the banner component |
| `hasShadow` | `boolean` | `true` | `false` | A flag used to provide a shadow to the banner component |
| `hasBackground` | `boolean` | `true` | `false` | A flag used to add a background to the banner component |
| name | type | default | required | description |
| ------------------------- | ---------------------------------------------------------------------------------------------------------- | ----------- | -------- | ----------------------------------------------------------------- |
| `children` | `ReactNode`, `ReactNode[]` | `undefined` | `true` | Content to include within the banner component |
| `align` | `'start'`, `'center'` | `'start'` | `true` | The horizontal positioning of content within the banner component |
| `backgroundColor` | <PropTableValues values={['default', 'subtle', 'string', `ResponsiveMap`]} addLineBreaks commaSeparated /> | `'default'` | `false` | Optional, custom background color |
| `backgroundImageSrc` | <PropTableValues values={['string' , `ResponsiveMap`]} addLineBreaks commaSeparated /> | `undefined` | `false` | Optional, custom background image |
| `backgroundImagePosition` | <PropTableValues values={['string' , `ResponsiveMap`]} addLineBreaks commaSeparated/> | `'center'` | `false` | Optional, custom background position |
| `backgroundImageSize` | <PropTableValues values={['string' , `ResponsiveMap`]} addLineBreaks commaSeparated /> | `'cover'` | `false` | Optional, custom background position size |
| `hasBorder` | `boolean` | `false` | `false` | A flag used to provide a border to the banner component |
| `hasShadow` | `boolean` | `true` | `false` | A flag used to provide a shadow to the banner component |
| `hasBackground` | `boolean` | `true` | `false` | A flag used to add a background to the banner component |

### CTABanner.Heading

Expand All @@ -184,9 +240,10 @@ render(<App />)

### CTABanner.Description

| name | type | default | required | description |
| ---------- | -------------------------- | ----------- | -------- | --------------------------------------------------- |
| `children` | `ReactNode`, `ReactNode[]` | `undefined` | `true` | Content to be displayed inside the banner component |
| name | type | default | required | description |
| ---------- | ------------------------------------------------------- | ----------- | ----------------------------------- | --------------------------------------------------- |
| `children` | `ReactNode`, `ReactNode[]` | `undefined` | `true` | Content to be displayed inside the banner component |
| `variant` | <PropTableValues values={TextVariants} addLineBreaks /> | `'muted'` | Specify alternative text appearance |

### CTABanner.ButtonGroup <Label>Required</Label>

Expand Down
2 changes: 1 addition & 1 deletion apps/docs/scripts/components-with-animation.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ export const supportedComponents = [
'Pillar',
'SectionIntro',
'Stack',
'Statistic',
'Testimonial',
'Text',
'Statistic',
'Timeline',
'Animate',
'River',
Expand Down
123 changes: 123 additions & 0 deletions packages/react/src/CTABanner/CTABanner.features.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ import {ActionMenu} from '../ActionMenu'
import {Button} from '../Button'

import {CTABanner} from './CTABanner'
import {Grid, Section, Stack, ThemeProvider} from '../'

import lightNarrowBg from '../fixtures/images/light-vertical-banner.png'
import lightWideBg from '../fixtures/images/light-horizontal-banner.png'
import darkNarrowBg from '../fixtures/images/dark-vertical-banner-alt.png'
import darkWideBg from '../fixtures/images/dark-horizontal-banner-alt.png'
import darkNarrowBg2 from '../fixtures/images/dark-vertical-banner-alt-2.png'
import darkWideBg2 from '../fixtures/images/dark-horizontal-banner-alt-2.png'

export default {
title: 'Components/CTABanner/Features',
Expand Down Expand Up @@ -98,3 +106,118 @@ export const CustomShadow = () => (
</CTABanner>
</div>
)

export const CustomBackgroundColors = () => (
<Stack direction="vertical">
<CTABanner hasShadow={false}>
<CTABanner.Heading>Default</CTABanner.Heading>
<CTABanner.Description>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. In sapien sit ullamcorper id. Aliquam luctus sed turpis
felis nam pulvinar risus elementum.
</CTABanner.Description>
<CTABanner.ButtonGroup>
<Button>Primary Action</Button>
<Button>Secondary Action</Button>
</CTABanner.ButtonGroup>
</CTABanner>
<CTABanner hasShadow={false} backgroundColor="subtle">
<CTABanner.Heading>Subtle</CTABanner.Heading>
<CTABanner.Description>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. In sapien sit ullamcorper id. Aliquam luctus sed turpis
felis nam pulvinar risus elementum.
</CTABanner.Description>
<CTABanner.ButtonGroup>
<Button>Primary Action</Button>
<Button>Secondary Action</Button>
</CTABanner.ButtonGroup>
</CTABanner>
<CTABanner hasShadow={false} backgroundColor="var(--base-color-scale-blue-0)">
<CTABanner.Heading>Base scale blue 0</CTABanner.Heading>
<CTABanner.Description>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. In sapien sit ullamcorper id. Aliquam luctus sed turpis
felis nam pulvinar risus elementum.
</CTABanner.Description>
<CTABanner.ButtonGroup>
<Button>Primary Action</Button>
<Button>Secondary Action</Button>
</CTABanner.ButtonGroup>
</CTABanner>
<CTABanner hasShadow={false} backgroundColor="cyan">
<CTABanner.Heading>Cyan</CTABanner.Heading>
<CTABanner.Description>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. In sapien sit ullamcorper id. Aliquam luctus sed turpis
felis nam pulvinar risus elementum.
</CTABanner.Description>
<CTABanner.ButtonGroup>
<Button>Primary Action</Button>
<Button>Secondary Action</Button>
</CTABanner.ButtonGroup>
</CTABanner>
<CTABanner hasShadow={false} backgroundColor={{narrow: 'yellow', regular: 'orange', wide: 'beige'}}>
<CTABanner.Heading>Responsive</CTABanner.Heading>
<CTABanner.Description>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. In sapien sit ullamcorper id. Aliquam luctus sed turpis
felis nam pulvinar risus elementum.
</CTABanner.Description>
<CTABanner.ButtonGroup>
<Button>Primary Action</Button>
<Button>Secondary Action</Button>
</CTABanner.ButtonGroup>
</CTABanner>
</Stack>
)

export const ResponsiveBackgroundImage = args => (
<CTABanner
align="center"
hasShadow={false}
backgroundImageSrc={
args.backgroundImageSrc || {
narrow: lightNarrowBg,
regular: lightWideBg,
wide: lightWideBg,
}
}
>
<CTABanner.Heading>Where the most ambitious teams build great things</CTABanner.Heading>
<CTABanner.Description variant="default">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. In sapien sit ullamcorper id. Aliquam luctus sed turpis
felis nam pulvinar risus elementum.
</CTABanner.Description>
<CTABanner.ButtonGroup>
<Button>Primary Action</Button>
</CTABanner.ButtonGroup>
</CTABanner>
)

export const ResponsiveBackgroundImageDark = () => (
<Stack padding="none" gap="spacious">
<ResponsiveBackgroundImage
backgroundImageSrc={{
narrow: darkNarrowBg,
regular: darkWideBg,
wide: darkWideBg,
}}
/>{' '}
<ResponsiveBackgroundImage
backgroundImageSrc={{
narrow: darkNarrowBg2,
regular: darkWideBg2,
wide: darkWideBg2,
}}
/>
</Stack>
)
ResponsiveBackgroundImageDark.decorators = [
Story => (
<ThemeProvider colorMode="dark">
<Section backgroundColor="default">
<Grid>
<Grid.Column>
<Story />
</Grid.Column>
</Grid>
</Section>
</ThemeProvider>
),
]
39 changes: 37 additions & 2 deletions packages/react/src/CTABanner/CTABanner.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,16 @@
}

.CTABanner-container--background {
background: var(--brand-CTABanner-bgColor);
border-radius: var(--brand-borderRadius-xlarge);
background-repeat: no-repeat;
background-color: var(--brand-CTABanner-narrow-background-color, var(--brand-CTABanner-background-color));
background-image: var(--brand-CTABanner-narrow-background-image-src, var(--brand-CTABanner-background-image-src));
background-size: var(--brand-CTABanner-narrow-background-image-size, var(--brand-CTABanner-background-image-size));

background-position: var(
--brand-CTABanner-narrow-background-image-position,
var(--brand-CTABanner-background-image-position, center)
);
}

.CTABanner-container--border {
Expand All @@ -50,7 +59,6 @@
}

.CTABanner-description {
color: var(--brand-color-text-muted);
margin-bottom: var(--base-size-16);
}

Expand All @@ -67,3 +75,30 @@
padding: var(--base-size-128) var(--base-size-64);
}
}

/* Regular */
@media screen and (min-width: 48rem) {
.CTABanner-container--background {
background-color: var(--brand-CTABanner-regular-background-color, var(--brand-CTABanner-background-color));
background-image: var(--brand-CTABanner-regular-background-image-src, var(--brand-CTABanner-background-image-src));
background-size: var(--brand-CTABanner-regular-background-image-size, var(--brand-CTABanner-background-image-size));
background-position: var(
--brand-CTABanner-regular-background-image-position,
var(--brand-CTABanner-background-image-position)
);
}
}

/* Wide */
@media screen and (min-width: 80rem) {
.CTABanner-container--background {
background-color: var(--brand-CTABanner-wide-background-color, var(--brand-CTABanner-background-color));
background-image: var(--brand-CTABanner-wide-background-image-src, var(--brand-CTABanner-background-image-src));
background-size: var(--brand-CTABanner-wide-background-image-size, var(--brand-CTABanner-background-image-size));

background-position: var(
--brand-CTABanner-wide-background-image-position,
var(--brand-CTABanner-background-image-position)
);
}
}
Loading

0 comments on commit 774b91b

Please sign in to comment.