Skip to content

Commit

Permalink
feat(Button, Theme): style on dark background (#3339)
Browse files Browse the repository at this point in the history
Added a property to the theme context that can be used to tell
components that they are on a dark background. This will let us create
styling for components that can't be used on dark background today.

* Added Theme context prop `darkBackground`
* Added `Theme.Provider` wrapper to easily define theme context areas
without changing DOM
* Added styling for sbanken buttons on dark background
  • Loading branch information
snorrekim authored Feb 27, 2024
1 parent af0d901 commit 29e6549
Show file tree
Hide file tree
Showing 54 changed files with 141 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
import React from 'react'
import ComponentBox from '../../../../shared/tags/ComponentBox'
import { bell_medium as Bell, question } from '@dnb/eufemia/src/icons'
import { Button, IconPrimary } from '@dnb/eufemia/src'
import { VisibilityByTheme } from '@dnb/eufemia/src/shared'
import { Button, IconPrimary, Section } from '@dnb/eufemia/src'
import { VisibilityByTheme, Theme } from '@dnb/eufemia/src/shared'

export const ButtonPrimary = () => (
<ComponentBox>
Expand Down Expand Up @@ -524,3 +524,30 @@ export const TertiaryButtonAlignment = () => {
</ComponentBox>
)
}

export const ButtonHasDarkBackground = () => (
<ComponentBox hideCode scope={{ Theme }}>
<Section innerSpace="1rem" backgroundColor="var(--sb-color-purple)">
<Theme.Provider darkBackground>
<Button data-visual-test="button-primary-on-dark" right>
Primary button
</Button>
<Button
data-visual-test="button-secondary-on-dark"
right
variant="secondary"
>
Secondary button
</Button>
<Button
data-visual-test="button-tertiary-on-dark"
variant="tertiary"
icon_position="left"
icon="chevron_left"
>
Tertiary button
</Button>
</Theme.Provider>
</Section>
</ComponentBox>
)
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
ButtonSignal,
ButtonSignalLarge,
ButtonIcon,
ButtonHasDarkBackground,
} from 'Docs/uilib/components/button/Examples'

## Demos
Expand Down Expand Up @@ -90,3 +91,14 @@ This is, as all of the demos, only an example of how to achieve various needs, a
<ButtonErrorState />

</VisibleWhenVisualTest>

<VisibilityByTheme visible="sbanken">

### Button on dark background

When placing the button on a dark background wrap the content of the dark section with `<Theme.Provider darkBackground>`
to get the correct styles.

<ButtonHasDarkBackground />

</VisibilityByTheme>
2 changes: 2 additions & 0 deletions packages/dnb-eufemia/src/components/button/Button.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ export default class Button extends React.PureComponent {
'dnb-button',
`dnb-button--${usedVariant || 'primary'}`,
usedSize && usedSize !== 'default' && `dnb-button--size-${usedSize}`,
this.context?.theme?.darkBackground &&
`dnb-button--on-dark-background`,
icon && `dnb-button--icon-position-${icon_position}`,
isTrue(stretch) && 'dnb-button--stretch',
icon && iconSize && `dnb-button--icon-size-${iconSize}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,42 @@ describe.each(['sbanken'])('Button for %s', (themeName) => {
})
expect(screenshot).toMatchImageSnapshot()
})

describe.each(['primary', 'secondary', 'tertiary'])(
'on dark background %s',
(variant) => {
it('default', async () => {
const screenshot = await makeScreenshot({
selector: `[data-visual-test="button-${variant}-on-dark"]`,
})
expect(screenshot).toMatchImageSnapshot()
})

it('hover', async () => {
const screenshot = await makeScreenshot({
selector: `[data-visual-test="button-${variant}-on-dark"]`,
simulate: 'hover',
})
expect(screenshot).toMatchImageSnapshot()
})

it('active', async () => {
const screenshot = await makeScreenshot({
selector: `[data-visual-test="button-${variant}-on-dark"]`,
simulate: 'active',
})
expect(screenshot).toMatchImageSnapshot()
})

it('focus', async () => {
const screenshot = await makeScreenshot({
selector: `[data-visual-test="button-${variant}-on-dark"]`,
simulate: 'focus',
})
expect(screenshot).toMatchImageSnapshot()
})
}
)
})

describe.each(['ui'])('Button for %s', (themeName) => {
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,8 @@ html[data-whatinput=keyboard] .dnb-button--tertiary:hover:focus .dnb-button__tex
--button-secondary-border--default
);
--button-secondary-border--disabled: var(--sb-color-gray-light);
--button-tertiary-color: var(--sb-color-violet);
--button-tertiary-border: var(--sb-color-violet);
border: none;
}
.dnb-button.dnb-button--has-text.dnb-button--size-large.dnb-button--primary, .dnb-button.dnb-button--has-text.dnb-button--size-large.dnb-button--secondary {
Expand Down Expand Up @@ -912,7 +914,7 @@ html:not([data-whatintent=touch]) .dnb-button--primary:focus-visible:not([disabl
--button-tertiary-underline-bottom: -0.5rem;
--button-tertiary-text-bottom--icon: 0.5rem;
--button-tertiary-text-top--icon: 0;
color: var(--sb-color-violet);
color: var(--button-tertiary-color);
background-color: transparent;
}
.dnb-button--tertiary .dnb-button__text::after {
Expand All @@ -939,7 +941,7 @@ html:not([data-whatintent=touch]) .dnb-button--tertiary:hover[disabled] {
cursor: not-allowed;
}
html:not([data-whatintent=touch]) .dnb-button--tertiary:hover:not([disabled]):not(:focus-visible) .dnb-button__text::after {
color: var(--sb-color-violet);
color: var(--button-tertiary-border);
transition: none;
}
html:not([data-whatintent=touch]) .dnb-button--tertiary:hover:not([disabled]):not(.dnb-button--has-text) {
Expand Down Expand Up @@ -969,12 +971,6 @@ html:not([data-whatintent=touch]) .dnb-button--tertiary:hover:not([disabled]):no
html:not([data-whatintent=touch]) .dnb-button--tertiary:hover:not([disabled]):not(.dnb-button--has-text) > * {
z-index: 2;
}
.dnb-button--tertiary:active[disabled], html:not([data-whatintent=touch]) .dnb-button--tertiary:active[disabled] {
cursor: not-allowed;
}
.dnb-button--tertiary:active:not([disabled]) .dnb-button__text::after, html:not([data-whatintent=touch]) .dnb-button--tertiary:active:not([disabled]) .dnb-button__text::after {
color: var(--sb-color-violet);
}
html:not([data-whatintent=touch]) .dnb-button--tertiary:focus-visible[disabled] {
cursor: not-allowed;
}
Expand Down Expand Up @@ -1003,11 +999,27 @@ html:not([data-whatintent=touch]) .dnb-button--tertiary:focus-visible:not([disab
html:not([data-whatintent=touch]) .dnb-button--tertiary:focus-visible:not([disabled]) > * {
z-index: 2;
}
html:not([data-whatintent=touch]) .dnb-button--tertiary:focus-visible:not([disabled]) .dnb-button__text::after {
visibility: hidden;
}
.dnb-button--tertiary[disabled] {
color: var(--sb-color-gray-dark);
}
.dnb-button--on-dark-background {
--button-primary-color: var(--sb-color-text);
--button-primary-color--hover: var(--sb-color-purple-alternative);
--button-primary-color--active: var(--sb-color-purple-alternative);
--button-primary-background: var(--sb-color-green);
--button-primary-background--hover: var(--sb-color-violet-light-2);
--button-primary-background--active: var(--sb-color-violet-light-3);
--button-secondary-color: var(--sb-color-white);
--button-secondary-color--hover: var(--sb-color-purple-alternative);
--button-secondary-color--active: var(--sb-color-purple-alternative);
--button-secondary-background: transparent;
--button-secondary-background--hover: var(--sb-color-violet-light-2);
--button-secondary-background--active: var(--sb-color-violet-light-3);
--button-secondary-border--default: var(--sb-color-green);
--button-secondary-border--hover: var(--sb-color-violet-light);
--button-secondary-border--active: var(--sb-color-violet-light);
--button-tertiary-color: var(--sb-color-white);
--button-tertiary-border: var(--sb-color-green);
}"
`;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@
);
--button-secondary-border--disabled: var(--sb-color-gray-light);

// tertiary
--button-tertiary-color: var(--sb-color-violet);
--button-tertiary-border: var(--sb-color-violet);

border: none;

&#{&}--has-text#{&}--size-large {
Expand Down Expand Up @@ -167,7 +171,7 @@
--button-tertiary-text-bottom--icon: 0.5rem;
--button-tertiary-text-top--icon: 0;

color: var(--sb-color-violet);
color: var(--button-tertiary-color);
background-color: transparent;

.dnb-button__text::after {
Expand Down Expand Up @@ -219,7 +223,7 @@
@include hover() {
// underline
&:not(:focus-visible) .dnb-button__text::after {
color: var(--sb-color-violet);
color: var(--button-tertiary-border);
transition: none;
}

Expand All @@ -229,24 +233,36 @@
@include focus-tertiary();
}
}

@include active() {
// underline
.dnb-button__text::after {
color: var(--sb-color-violet);
}
}

@include focus-visible() {
@include focus-tertiary();
// underline
.dnb-button__text::after {
visibility: hidden;
}
}

&[disabled] {
color: var(--sb-color-gray-dark);
}
}
&--on-dark-background {
// primary
--button-primary-color: var(--sb-color-text);
--button-primary-color--hover: var(--sb-color-purple-alternative);
--button-primary-color--active: var(--sb-color-purple-alternative);
--button-primary-background: var(--sb-color-green);
--button-primary-background--hover: var(--sb-color-violet-light-2);
--button-primary-background--active: var(--sb-color-violet-light-3);

// secondary
--button-secondary-color: var(--sb-color-white);
--button-secondary-color--hover: var(--sb-color-purple-alternative);
--button-secondary-color--active: var(--sb-color-purple-alternative);
--button-secondary-background: transparent;
--button-secondary-background--hover: var(--sb-color-violet-light-2);
--button-secondary-background--active: var(--sb-color-violet-light-3);
--button-secondary-border--default: var(--sb-color-green);
--button-secondary-border--hover: var(--sb-color-violet-light);
--button-secondary-border--active: var(--sb-color-violet-light);

// tertiary
--button-tertiary-color: var(--sb-color-white);
--button-tertiary-border: var(--sb-color-green);
}
}
9 changes: 9 additions & 0 deletions packages/dnb-eufemia/src/shared/Theme.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export type ThemeSizes = 'basis'
export type PropMapping = string
export type ContrastMode = boolean
export type DarkMode = boolean
export type DarkBackground = boolean

export type ThemeProps = {
name?: ThemeNames
Expand All @@ -24,6 +25,7 @@ export type ThemeProps = {
propMapping?: PropMapping
contrastMode?: ContrastMode
darkMode?: DarkMode
darkBackground?: DarkBackground
element?: DynamicElement | false
}

Expand All @@ -41,6 +43,7 @@ export default function Theme(themeProps: ThemeAllProps) {
propMapping,
contrastMode,
darkMode,
darkBackground,
...restProps
} = themeProps

Expand All @@ -52,6 +55,7 @@ export default function Theme(themeProps: ThemeAllProps) {
propMapping,
contrastMode,
darkMode,
darkBackground,
},
null,
context?.theme
Expand All @@ -66,6 +70,11 @@ export default function Theme(themeProps: ThemeAllProps) {
)
}

Theme.Provider = ({ element, ...themeProps }: ThemeAllProps) => {
return <Theme {...themeProps} element={false} />
}
Theme.Provider['_supportsSpacingProps'] = 'children'

export function ThemeWrapper({
children,
theme,
Expand Down

0 comments on commit 29e6549

Please sign in to comment.