From 16b2980e6074cfe2db996931aa3b16e227a1f835 Mon Sep 17 00:00:00 2001 From: Francesca Guiducci Date: Wed, 12 Nov 2025 17:54:42 +0100 Subject: [PATCH 1/4] feat: Add children prop to Banner component --- src/banner/banner.module.css | 36 +++++++-- src/banner/banner.stories.mdx | 134 ++++++++++++++++++++++++++++++++++ src/banner/banner.tsx | 123 ++++++++++++++++++++----------- 3 files changed, 242 insertions(+), 51 deletions(-) diff --git a/src/banner/banner.module.css b/src/banner/banner.module.css index 64d4322e..c282be75 100644 --- a/src/banner/banner.module.css +++ b/src/banner/banner.module.css @@ -32,6 +32,22 @@ .content { padding: var(--reactist-spacing-large); + display: flex; + gap: var(--reactist-spacing-small); + align-items: flex-start; +} + +.body { + display: flex; + flex-direction: column; + gap: var(--reactist-spacing-small); + flex-grow: 1; +} + +.topContent { + display: flex; + gap: var(--reactist-spacing-small); + align-items: flex-start; } .title, @@ -74,24 +90,31 @@ .copy { padding: calc(var(--reactist-spacing-xsmall) / 2) 0; + flex: 1 1 auto; } .copy .inlineLink:first-of-type { margin-left: var(--reactist-spacing-xsmall); } +.childrenSection { + gap: var(--reactist-spacing-small); +} + @container banner (width < 235px) { - .content, - .staticContent { + .content { flex-direction: column; - align-items: flex-start; + align-items: stretch; } - .icon { display: flex; width: 100%; align-items: center; justify-content: space-between; } + .topContent { + flex-direction: column; + align-items: stretch; + } .icon:has(.closeButton:only-child) { display: flex; } @@ -101,8 +124,7 @@ .icon .closeButton:only-child { margin-left: auto; } - - .actions .closeButton { - display: none; + .childrenSection { + margin-top: var(--reactist-spacing-medium); } } diff --git a/src/banner/banner.stories.mdx b/src/banner/banner.stories.mdx index 15bd8548..e729df04 100644 --- a/src/banner/banner.stories.mdx +++ b/src/banner/banner.stories.mdx @@ -35,6 +35,10 @@ export function getButton(buttonText) { ) } +export function getLongDescription() { + return 'Lorem ipsum dolor sit, amet consectetur adipisicing elit. Provident cumque recusandae quibusdam, veniam cum illo? Inventore, doloremque necessitatibus! Sequi porro alias mollitia, temporibus quidem, aut modi tempora placeat laborum eos sapiente necessitatibus autem ipsum officia rerum distinctio consectetur tenetur qui! Perspiciatis ab corporis, itaque alias ex optio voluptatum nulla consequatur aut explicabo dolorem rerum ratione magnam. Mollitia dignissimos et ad commodi quasi molestias fugiat repellendus, magni distinctio voluptate neque quos esse asperiores iure excepturi eligendi eaque veniam voluptas blanditiis temporibus, omnis laborum quidem autem totam. Iure, numquam. Totam facilis dolorum, consequatur, eligendi est dolores modi dolore maiores ipsum magnam a.' +} + export function PlaygroundTemplate({ type, title, description, action }) { return ( @@ -168,6 +172,29 @@ export function BannerActionExamples({ theme }) { }} onClose={() => ({})} /> + } + title="This is a sample title" + description={getLongDescription()} + action={{ + type: 'button', + label: 'Action', + variant: 'primary', + }} + /> + } + title="This is a sample title" + description={getLongDescription()} + action={{ + type: 'button', + label: 'Action', + variant: 'primary', + }} + onClose={() => ({})} + /> ) @@ -230,6 +257,97 @@ export function BannerImageExamples({ theme }) { ) } +export function BannerContentExamples({ theme }) { + return ( + + + + Some extra content here + + + Some extra content here + + ({})} + > + Some extra content here + + } + > + Some extra content here + + } + action={getButton('Click me!')} + > + Some extra content here + + } + action={getButton('Click me!')} + > + + Some extra content here + + + + } + action={getButton('Click me!')} + > + + Some extra content here + + + + } + action={getButton('Click me!')} + onClose={() => ({})} + > + + Some extra content here + + + + + + ) +} + # Banner A simple banner component meant to be used to _inform_ the user of promotional content, disclaimers, warnings, as well as success and error states. @@ -340,6 +458,22 @@ Image banners do not feature icons but can include body text or a combination of +### Content + +Banners can include extra content. + + + + + + + ## Props diff --git a/src/banner/banner.tsx b/src/banner/banner.tsx index 103342c2..506847ad 100644 --- a/src/banner/banner.tsx +++ b/src/banner/banner.tsx @@ -66,6 +66,7 @@ type BaseBanner = { id?: string title?: React.ReactNode description: Exclude + children?: React.ReactNode action?: Action | React.ReactNode inlineLinks?: InlineLink[] } & CloseButton @@ -112,6 +113,7 @@ const Banner = React.forwardRef(function Banner( type, title, description, + children, action, icon, image, @@ -153,57 +155,90 @@ const Banner = React.forwardRef(function Banner( > {image ? {image} : null} - - - - {type === 'neutral' ? icon : } - {closeButton} - + + + {type === 'neutral' ? icon : } + {closeButton} + - - {title ? ( - - {title} - - ) : null} + + - {description} - {inlineLinks?.map(({ label, ...props }, index) => { - return ( - - - {label} - - {index < inlineLinks.length - 1 ? · : ''} - - ) - })} + {title ? ( + + {title} + + ) : null} + + {description} + {inlineLinks?.map(({ label, ...props }, index) => { + return ( + + + {label} + + {index < inlineLinks.length - 1 ? · : ''} + + ) + })} + - - - {action || closeButton ? ( - - {action ? ( - isActionObject(action) ? ( - action.type === 'button' ? ( - - ) : ( - - ) - ) : ( - action - ) + {action || closeButton ? ( + + {action ? ( + isActionObject(action) ? ( + action.type === 'button' ? ( + + ) : ( + + ) + ) : ( + action + ) + ) : null} + {closeButton} + ) : null} - {closeButton} - ) : null} + + {children ? ( + + {children} + + ) : null} + ) From c55d22be1729271afa9f6610a0ca78e39b6f6233 Mon Sep 17 00:00:00 2001 From: Francesca Guiducci Date: Wed, 12 Nov 2025 18:52:31 +0100 Subject: [PATCH 2/4] chore: Cleaup --- src/banner/banner.module.css | 28 +++++++--------------------- src/banner/banner.tsx | 25 +++---------------------- 2 files changed, 10 insertions(+), 43 deletions(-) diff --git a/src/banner/banner.module.css b/src/banner/banner.module.css index c282be75..9279b3ae 100644 --- a/src/banner/banner.module.css +++ b/src/banner/banner.module.css @@ -32,21 +32,6 @@ .content { padding: var(--reactist-spacing-large); - display: flex; - gap: var(--reactist-spacing-small); - align-items: flex-start; -} - -.body { - display: flex; - flex-direction: column; - gap: var(--reactist-spacing-small); - flex-grow: 1; -} - -.topContent { - display: flex; - gap: var(--reactist-spacing-small); align-items: flex-start; } @@ -95,15 +80,13 @@ .copy .inlineLink:first-of-type { margin-left: var(--reactist-spacing-xsmall); } - -.childrenSection { - gap: var(--reactist-spacing-small); +.actions { + align-self: center; } @container banner (width < 235px) { .content { flex-direction: column; - align-items: stretch; } .icon { display: flex; @@ -124,7 +107,10 @@ .icon .closeButton:only-child { margin-left: auto; } - .childrenSection { - margin-top: var(--reactist-spacing-medium); + .actions .closeButton { + display: none; + } + .actions { + align-self: flex-start; } } diff --git a/src/banner/banner.tsx b/src/banner/banner.tsx index 506847ad..70464310 100644 --- a/src/banner/banner.tsx +++ b/src/banner/banner.tsx @@ -161,13 +161,7 @@ const Banner = React.forwardRef(function Banner( {closeButton} - + (function Banner( {action || closeButton ? ( - + {action ? ( isActionObject(action) ? ( action.type === 'button' ? ( @@ -229,15 +218,7 @@ const Banner = React.forwardRef(function Banner( ) : null} - {children ? ( - - {children} - - ) : null} + {children} From edabbaf5ab5940688ddd6b3764d5dfe2d928e5ae Mon Sep 17 00:00:00 2001 From: Francesca Guiducci Date: Wed, 12 Nov 2025 19:00:43 +0100 Subject: [PATCH 3/4] chore: Cleaup --- src/banner/banner.module.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/banner/banner.module.css b/src/banner/banner.module.css index 9279b3ae..ae7d7dc9 100644 --- a/src/banner/banner.module.css +++ b/src/banner/banner.module.css @@ -107,10 +107,10 @@ .icon .closeButton:only-child { margin-left: auto; } - .actions .closeButton { - display: none; - } .actions { align-self: flex-start; } + .actions .closeButton { + display: none; + } } From 9db649c6cd26fa63b5ee2dd58d92df02dc5feb62 Mon Sep 17 00:00:00 2001 From: Francesca Guiducci Date: Thu, 13 Nov 2025 07:42:33 +0100 Subject: [PATCH 4/4] chore: Better stories --- src/banner/banner.stories.mdx | 23 +++++++++++++++-------- src/banner/banner.test.tsx | 9 +++++++++ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/banner/banner.stories.mdx b/src/banner/banner.stories.mdx index e729df04..64716961 100644 --- a/src/banner/banner.stories.mdx +++ b/src/banner/banner.stories.mdx @@ -5,6 +5,8 @@ import { Stack } from '../stack' import { Banner } from './banner' import { Button } from '../button' import { PromoImage } from './story-promo-image' +import { Notice } from '../notice' +import { CheckboxField } from '../checkbox-field' } action={getButton('Click me!')} > - + Some extra content here - } action={getButton('Click me!')} > - - Some extra content here - + + {getLongDescription()} + + Please check the box to continue. + + ({})} > - - Some extra content here - + + {getLongDescription()} + + Please check the box to continue. + + diff --git a/src/banner/banner.test.tsx b/src/banner/banner.test.tsx index ae39ccfb..dd33c318 100644 --- a/src/banner/banner.test.tsx +++ b/src/banner/banner.test.tsx @@ -245,4 +245,13 @@ describe('Banner', () => { const results = await axe(container) expect(results).toHaveNoViolations() }) + + it('renders a banner with children', () => { + render( + +

Child content

+
, + ) + expect(screen.getByText('Child content')).toBeInTheDocument() + }) })