Skip to content

Commit e2beed3

Browse files
feat: [BpkPanel] Add bgColor prop with surface color support (#4220)
* feat: [BpkPanel] Add bgColor prop with surface color support Add a bgColor prop to BpkPanel that supports all design system surface colours, following the same pattern as BpkText's color prop. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: [BpkPanel] Improve storybook examples with keyline comparison and context backgrounds Show each bgColor variant with and without keyline side by side. Use dark background for surfaceLowContrast and gradient background for surfaceTint to demonstrate semi-transparency. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: Extract surface colors into shared bpk-react-utils and bpk-mixins Move surface color definitions from BpkPanel into shared locations so they can be reused by other components. BpkPanel re-exports as PANEL_BG_COLORS for backwards compatibility. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: Add Record type to rowStyleForBg to fix TS7053 indexing error Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: Restore simple Default story and add cross-reference comments - Restore DefaultExample as the Default storybook story for simplest usage - Add BackgroundColors as a separate story for the surface color showcase - Extract common row styles using CSS Modules composes - Add sync comments between SCSS and JS surface color definitions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: Use Partial<Record<PanelBgColor, string>> for rowStyleForBg type Tightens the type of the partial bg-to-style mapping in examples so keys are constrained to valid PanelBgColor values. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent d2eae13 commit e2beed3

12 files changed

Lines changed: 199 additions & 7 deletions

File tree

examples/bpk-component-panel/examples.module.scss

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,29 @@
2020

2121
.bpk-panel-examples--wrapper {
2222
padding: tokens.bpk-spacing-base();
23-
background-color: tokens.$bpk-surface-highlight-day;
23+
background-color: tokens.$bpk-canvas-contrast-day;
24+
}
25+
26+
.bpk-panel-examples--row {
27+
display: grid;
28+
margin-bottom: tokens.bpk-spacing-base();
29+
grid-template-columns: 1fr 1fr;
30+
gap: tokens.bpk-spacing-base();
31+
}
32+
33+
.bpk-panel-examples--row-dark {
34+
padding: tokens.bpk-spacing-base();
35+
background-color: tokens.$bpk-surface-contrast-day;
36+
composes: bpk-panel-examples--row;
37+
}
38+
39+
.bpk-panel-examples--row-gradient {
40+
padding: tokens.bpk-spacing-base();
41+
background: linear-gradient(
42+
135deg,
43+
tokens.$bpk-core-accent-day,
44+
tokens.$bpk-status-danger-spot-day,
45+
tokens.$bpk-status-warning-spot-day
46+
);
47+
composes: bpk-panel-examples--row;
2448
}

examples/bpk-component-panel/examples.tsx

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,29 @@
1616
* limitations under the License.
1717
*/
1818

19-
import BpkPanel from '../../packages/bpk-component-panel';
19+
import BpkPanel, { PANEL_BG_COLORS } from '../../packages/bpk-component-panel';
20+
import BpkText, { TEXT_COLORS } from '../../packages/bpk-component-text';
21+
22+
import type { PanelBgColor } from '../../packages/bpk-component-panel';
2023

2124
import STYLES from './examples.module.scss';
2225

26+
const textColorForBg = {
27+
[PANEL_BG_COLORS.surfaceDefault]: TEXT_COLORS.textPrimary,
28+
[PANEL_BG_COLORS.surfaceElevated]: TEXT_COLORS.textPrimary,
29+
[PANEL_BG_COLORS.surfaceHero]: TEXT_COLORS.textOnDark,
30+
[PANEL_BG_COLORS.surfaceContrast]: TEXT_COLORS.textOnDark,
31+
[PANEL_BG_COLORS.surfaceHighlight]: TEXT_COLORS.textPrimary,
32+
[PANEL_BG_COLORS.surfaceSubtle]: TEXT_COLORS.textPrimary,
33+
[PANEL_BG_COLORS.surfaceLowContrast]: TEXT_COLORS.textPrimary,
34+
[PANEL_BG_COLORS.surfaceTint]: TEXT_COLORS.textPrimary,
35+
};
36+
37+
const rowStyleForBg: Partial<Record<PanelBgColor, string>> = {
38+
[PANEL_BG_COLORS.surfaceLowContrast]: 'bpk-panel-examples--row-dark',
39+
[PANEL_BG_COLORS.surfaceTint]: 'bpk-panel-examples--row-gradient',
40+
};
41+
2342
export const DefaultExample = () => (
2443
<div className={STYLES['bpk-panel-examples--wrapper']}>
2544
<BpkPanel>
@@ -28,7 +47,7 @@ export const DefaultExample = () => (
2847
consectetur, dolor nec vulputate vehicula, ex metus mattis ante, non dictum
2948
mi ante eu arcu.
3049
</BpkPanel>
31-
</div >
50+
</div>
3251
);
3352

3453
export const WithoutPaddingExample = () => (
@@ -64,9 +83,37 @@ export const NoKeylineExample = () => (
6483
</div>
6584
);
6685

86+
export const BackgroundColorExample = () => (
87+
<div className={STYLES['bpk-panel-examples--wrapper']}>
88+
{Object.entries(PANEL_BG_COLORS).map(([key, value]) => (
89+
<div key={key} className={STYLES[rowStyleForBg[value] || 'bpk-panel-examples--row']}>
90+
<BpkPanel bgColor={value}>
91+
<BpkText tagName="p" textStyle="heading-4" color={textColorForBg[value]}>
92+
{key}
93+
</BpkText>
94+
<BpkText tagName="p" color={textColorForBg[value]}>
95+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque
96+
imperdiet lobortis tellus, non rhoncus erat tincidunt id.
97+
</BpkText>
98+
</BpkPanel>
99+
<BpkPanel bgColor={value} keyline={false}>
100+
<BpkText tagName="p" textStyle="heading-4" color={textColorForBg[value]}>
101+
{key} (no keyline)
102+
</BpkText>
103+
<BpkText tagName="p" color={textColorForBg[value]}>
104+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque
105+
imperdiet lobortis tellus, non rhoncus erat tincidunt id.
106+
</BpkText>
107+
</BpkPanel>
108+
</div>
109+
))}
110+
</div>
111+
);
112+
67113
export const MixedExample = () => (
68114
<div>
69115
<DefaultExample />
116+
<BackgroundColorExample />
70117
<WithoutPaddingExample />
71118
<FullWidthExample />
72119
<NoKeylineExample />

examples/bpk-component-panel/stories.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import BpkPanel from '../../packages/bpk-component-panel/src/BpkPanel';
2020

2121
import {
2222
DefaultExample,
23+
BackgroundColorExample,
2324
WithoutPaddingExample,
2425
FullWidthExample,
2526
MixedExample,
@@ -32,6 +33,7 @@ export default {
3233
};
3334

3435
export const Default = DefaultExample;
36+
export const BackgroundColors = BackgroundColorExample;
3537
export const WithoutPadding = WithoutPaddingExample;
3638

3739
export const FullWidth = FullWidthExample;

packages/bpk-component-panel/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ Check the main [Readme](https://github.com/skyscanner/backpack#usage) for a comp
99
## Usage
1010

1111
```js
12-
import BpkPanel from '@skyscanner/backpack-web/bpk-component-panel';
12+
import BpkPanel, { PANEL_BG_COLORS } from '@skyscanner/backpack-web/bpk-component-panel';
1313

1414
export default () => (
15-
<BpkPanel>
15+
<BpkPanel bgColor={PANEL_BG_COLORS.surfaceSubtle}>
1616
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
1717
commodo ligula eget dolor. Aenean massa. Cum sociis natoque
1818
penatibus et magnis dis parturient montes, nascetur ridiculus mus.

packages/bpk-component-panel/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,6 @@
1818

1919
import BpkPanel from './src/BpkPanel';
2020

21+
export type { PanelBgColor } from './src/BpkPanel';
22+
export { PANEL_BG_COLORS } from './src/BpkPanel';
2123
export default BpkPanel;

packages/bpk-component-panel/src/BpkPanel-test.tsx

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
import { render } from '@testing-library/react';
2020

21-
import BpkPanel from './BpkPanel';
21+
import BpkPanel, { PANEL_BG_COLORS } from './BpkPanel';
2222

2323
describe('BpkPanel', () => {
2424
it('should render correctly', () => {
@@ -84,4 +84,22 @@ describe('BpkPanel', () => {
8484
expect(container.querySelector('.bpk-panel')).not.toHaveClass('bpk-panel--full-width-keyline');
8585
expect(container.querySelector('.bpk-panel')).toHaveClass('bpk-panel--full-width');
8686
});
87+
88+
it('should render with bgColor', () => {
89+
const { container } = render(
90+
<BpkPanel bgColor={PANEL_BG_COLORS.surfaceSubtle}>
91+
Content
92+
</BpkPanel>,
93+
);
94+
expect(container.querySelector('.bpk-panel')).toHaveClass('bpk-panel--surface-subtle');
95+
});
96+
97+
it('should default to surfaceDefault bgColor', () => {
98+
const { container } = render(
99+
<BpkPanel>
100+
Content
101+
</BpkPanel>,
102+
);
103+
expect(container.querySelector('.bpk-panel')).toHaveClass('bpk-panel--surface-default');
104+
});
87105
});

packages/bpk-component-panel/src/BpkPanel.module.scss

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@
1717
*/
1818

1919
@use '../../bpk-mixins/panels';
20+
@use '../../bpk-mixins/surfaces';
2021

2122
.bpk-panel {
2223
@include panels.bpk-panel;
24+
@include surfaces.bpk-surface-bg-colors;
2325

2426
&--padded {
2527
@include panels.bpk-panel--padded;

packages/bpk-component-panel/src/BpkPanel.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,22 @@
1717
*/
1818
import type { ReactNode } from 'react';
1919

20-
import { cssModules, getDataComponentAttribute } from '../../bpk-react-utils';
20+
import { cssModules, getDataComponentAttribute, SURFACE_COLORS } from '../../bpk-react-utils';
21+
22+
import type { SurfaceBgColor } from '../../bpk-react-utils';
2123

2224
import STYLES from './BpkPanel.module.scss';
2325

2426

2527
const getClassName = cssModules(STYLES);
2628

29+
export const PANEL_BG_COLORS = SURFACE_COLORS;
30+
31+
export type PanelBgColor = SurfaceBgColor;
32+
2733
export type Props = {
2834
children: ReactNode;
35+
bgColor?: PanelBgColor,
2936
padded?: boolean,
3037
fullWidth?: boolean,
3138
className?: string | null,
@@ -35,6 +42,7 @@ export type Props = {
3542

3643

3744
const BpkPanel = ({
45+
bgColor = PANEL_BG_COLORS.surfaceDefault,
3846
children,
3947
className = null,
4048
fullWidth = false,
@@ -57,6 +65,7 @@ const BpkPanel = ({
5765
classNames.push(getClassName('bpk-panel--keyline'));
5866
}
5967
}
68+
classNames.push(getClassName(`bpk-panel--${bgColor}`));
6069
if (className) {
6170
classNames.push(className);
6271
}

packages/bpk-mixins/_index.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
@forward 'scroll-indicators';
3333
@forward 'shadows';
3434
@forward 'spinners';
35+
@forward 'surfaces';
3536
@forward 'typography';
3637
@forward 'utils';
3738

packages/bpk-mixins/_surfaces.scss

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Backpack - Skyscanner's Design System
3+
*
4+
* Copyright 2016 Skyscanner Ltd
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
/* stylelint-disable at-rule-disallowed-list */
20+
21+
@use 'tokens';
22+
23+
////
24+
/// @group surfaces
25+
////
26+
27+
// Keys must stay in sync with bpk-react-utils/src/surfaceColors.ts
28+
$bpk-surface-bg-colors: (
29+
'surface-default': tokens.$bpk-surface-default-day,
30+
'surface-elevated': tokens.$bpk-surface-elevated-day,
31+
'surface-hero': tokens.$bpk-surface-hero-day,
32+
'surface-contrast': tokens.$bpk-surface-contrast-day,
33+
'surface-highlight': tokens.$bpk-surface-highlight-day,
34+
'surface-subtle': tokens.$bpk-surface-subtle-day,
35+
'surface-low-contrast': tokens.$bpk-surface-low-contrast-day,
36+
'surface-tint': tokens.$bpk-surface-tint-day,
37+
);
38+
39+
/// Generates background-color modifier classes for all surface colors.
40+
///
41+
/// @example scss
42+
/// .bpk-panel {
43+
/// @include bpk-surface-bg-colors;
44+
/// }
45+
46+
@mixin bpk-surface-bg-colors {
47+
@each $color-name, $color-value in $bpk-surface-bg-colors {
48+
&--#{$color-name} {
49+
background-color: $color-value;
50+
}
51+
}
52+
}

0 commit comments

Comments
 (0)