Skip to content

Commit

Permalink
feat(Card, Section): add outset property for moderate layout breakout
Browse files Browse the repository at this point in the history
  • Loading branch information
tujoworker committed Nov 21, 2024
1 parent 5a06b2e commit 8e63423
Show file tree
Hide file tree
Showing 28 changed files with 296 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,12 @@ import { Field, Form } from '@dnb/eufemia/src/extensions/forms'

export const Default = () => {
return (
<ComponentBox>
<Card data-visual-test="layout-card-border">
<ComponentBox data-visual-test="layout-card-border">
<Card>
<P>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi
cursus pharetra elit in bibendum.
</P>
<P>
Praesent nunc ipsum, convallis eget convallis gravida, vehicula
vitae metus.
</P>
</Card>
</ComponentBox>
)
Expand All @@ -35,11 +31,11 @@ export const Default = () => {
export const NestedCards = () => {
return (
<ComponentBox data-visual-test="layout-card-nested">
<Card>
<Card stack>
<P>First Card</P>
<Card top>
<Card stack>
<P>Second Card</P>
<Card top>
<Card stack>
<P>Third Card (for edge cases only)</P>
</Card>
</Card>
Expand Down Expand Up @@ -274,3 +270,20 @@ export const WithNestedSection = () => {
</ComponentBox>
)
}

export const WithOutset = () => {
return (
<ComponentBox data-visual-test="layout-card-outset">
<Flex.Vertical>
<Form.MainHeading>Main heading</Form.MainHeading>
<Card stack outset>
<P>Card content</P>
<Card>
<P>Nested card</P>
</Card>
</Card>
<Form.SubmitButton />
</Flex.Vertical>
</ComponentBox>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ Nested cards have `responsive={false}` by default and will not behave responsive

<Examples.NestedCards />

## With `outset`

On small screens (mobile) the outset is removed.

<Examples.WithOutset />

### Without padding

<Examples.WithoutPadding />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,12 @@
showTabs: true
---

import PropertiesTable from 'dnb-design-system-portal/src/shared/parts/PropertiesTable'
import { SectionProperties } from '@dnb/eufemia/src/components/section/SectionDocs'

## Properties

| Properties | Description |
| --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `variant` | _(optional)_ defines the semantic purpose and subsequently the style of the visual helper. Will take precedence over the style_type property |
| `element` | _(optional)_ define what HTML element should be used. Defaults to `<section>`. |
| `breakout` | _(optional)_ use `true` to enable a fullscreen breakout look. Supports also media query breakpoints like `{ small: boolean }`. Defaults to `true`. |
| `outline` | _(optional)_ define a custom border color. If `true` is given, `color-black-8` is used. Use a Eufemia [color](/uilib/usage/customisation/colors/). Supports also media query breakpoints like `{ small: 'black-8' }` |
| `roundedCorner` | _(optional)_ use `true` to enable rounded corners (border-radius). Supports also media query breakpoints like `{ small: boolean }`. Defaults to `false`. |
| `backgroundColor` | _(optional)_ define a custom background color, instead of a variant. Use a Eufemia [color](/uilib/usage/customisation/colors/). Supports also media query breakpoints like `{ small: 'white' }`. |
| `dropShadow` | _(optional)_ use `true` to show the default Eufemia DropShadow. Supports also media query breakpoints like `{ small: true }`. |
| `textColor` | _(optional)_ define a custom text color to compliment the backgroundColor. Use a Eufemia [color](/uilib/usage/customisation/colors/). Supports also media query breakpoints like `{ small: 'black-80' }`. |
| `innerSpace` | _(optional)_ will add a padding around the content. Supports also media query breakpoints like `{small: { top: 'medium' }}`. |
| `innerRef` | _(optional)_ by providing a React Ref we can get the internally used element (DOM). E.g. `inner_ref={myRef}` by using `React.createRef()` or `React.useRef()`. |
| [Space](/uilib/layout/space/properties) | _(optional)_ spacing properties like `top` or `bottom` are supported. |
<PropertiesTable props={SectionProperties} />

## Variants

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -624,9 +624,19 @@ button.dnb-button::-moz-focus-inner {
.dnb-section:not([style*="--breakout"]) {
--breakout: var(--breakout--on);
}
.dnb-section[style*="--outset"].dnb-space[style]:not(.dnb-card) {
padding-left: calc(var(--padding-left) * (1 - var(--outset)));
padding-right: calc(var(--padding-right) * (1 - var(--outset)));
}
.dnb-section[style*="--outset"]::before {
margin-left: calc(var(--padding-left, var(--spacing-medium)) * -1 * var(--outset));
margin-right: calc(var(--padding-right, var(--spacing-medium)) * -1 * var(--outset));
background-color: inherit;
}
@media screen and (max-width: 60em) {
.dnb-section {
--breakout: var(--breakout--small, var(--breakout--fallback));
--outset: var(--outset--small, var(--outset--fallback));
--background-color--value: var(--background-color--small);
--text-color--value: var(--text-color--small);
--outline-color: var(--outline-color--small);
Expand All @@ -640,6 +650,7 @@ button.dnb-button::-moz-focus-inner {
@media screen and (max-width: 60em) and (min-width: 40.00625em) {
.dnb-section {
--breakout: var(--breakout--medium, var(--breakout--fallback));
--outset: var(--outset--medium, var(--outset--fallback));
--background-color--value: var(--background-color--medium);
--text-color--value: var(--text-color--medium);
--outline-color: var(--outline-color--medium);
Expand All @@ -653,6 +664,7 @@ button.dnb-button::-moz-focus-inner {
@media screen and (min-width: 60.00625em) {
.dnb-section {
--breakout: var(--breakout--large, var(--breakout--fallback));
--outset: var(--outset--large, var(--outset--fallback));
--background-color--value: var(--background-color--large);
--text-color--value: var(--text-color--large);
--outline-color: var(--outline-color--large);
Expand Down
7 changes: 7 additions & 0 deletions packages/dnb-eufemia/src/components/card/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export type Props = {
*/
filled?: boolean
} & FlexContainerProps &
Pick<SectionProps, 'outset'> &
FlexItemProps & {
stack?: boolean
} & SpaceProps &
Expand All @@ -49,6 +50,7 @@ function Card(props: Props) {
rowGap,
responsive = !nestedContext?.isNested,
filled,
outset,
title,
children,
...rest
Expand Down Expand Up @@ -79,6 +81,11 @@ function Card(props: Props) {
filled && 'dnb-card--filled'
),
breakout: responsive ? trueWhenSmall : false,
outset: nestedContext?.isNested
? false
: outset === true
? falseWhenSmall
: outset,
roundedCorner: responsive ? falseWhenSmall : true,
outline: '--outline-card-color',
innerSpace:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ describe.each(['ui', 'sbanken'])('Card for %s', (themeName) => {
})
expect(screenshot).toMatchImageSnapshot()
})

it('have to match outset', async () => {
const screenshot = await makeScreenshot({
selector: '[data-visual-test="layout-card-outset"]',
})
expect(screenshot).toMatchImageSnapshot()
})
})

describe.each(['ui', 'sbanken'])(
Expand Down Expand Up @@ -118,5 +125,12 @@ describe.each(['ui', 'sbanken'])(
})
expect(screenshot).toMatchImageSnapshot()
})

it('have to match outset', async () => {
const screenshot = await makeScreenshot({
selector: '[data-visual-test="layout-card-outset"]',
})
expect(screenshot).toMatchImageSnapshot()
})
}
)
50 changes: 50 additions & 0 deletions packages/dnb-eufemia/src/components/card/__tests__/Card.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ describe('Card', () => {
expect(element).toHaveClass('dnb-flex-item--align-self-stretch')
expect(container).toHaveClass('dnb-flex-container--align-stretch')
expect(container).toHaveClass('dnb-flex-container--align-self-stretch')
expect(container).toHaveClass('dnb-flex-container--spacing-medium')
})

it('should set align="stretch" classes', () => {
Expand Down Expand Up @@ -331,6 +332,55 @@ describe('Card', () => {
expect(element.getAttribute('style')).not.toContain('--space-')
})

it('should support "outset"', () => {
const { rerender } = render(<Card outset />)

const element = document.querySelector('.dnb-card')

expect(element).toHaveStyle('--outset--small: 0')
expect(element).toHaveStyle('--outset--medium: 1')
expect(element).toHaveStyle('--outset--large: 1')

rerender(
<Card
outset={{
small: true,
medium: false,
large: false,
}}
/>
)

expect(element).toHaveStyle('--outset--small: 1')
expect(element).toHaveStyle('--outset--medium: 0')
expect(element).toHaveStyle('--outset--large: 0')

rerender(<Card outset={false} />)

expect(element).toHaveStyle('--outset--small: 0')
expect(element).toHaveStyle('--outset--medium: 0')
expect(element).toHaveStyle('--outset--large: 0')
})

it('should not allow "outset" on nested cards', () => {
render(
<Card outset>
<Card outset />
</Card>
)

const firstCard = document.querySelector('.dnb-card')
const secondCard = firstCard.querySelector('.dnb-card')

expect(firstCard).toHaveStyle('--outset--small: 0')
expect(firstCard).toHaveStyle('--outset--medium: 1')
expect(firstCard).toHaveStyle('--outset--large: 1')

expect(secondCard).toHaveStyle('--outset--small: 0')
expect(secondCard).toHaveStyle('--outset--medium: 0')
expect(secondCard).toHaveStyle('--outset--large: 0')
})

it('should support "responsive" of false', () => {
const { rerender } = render(
<Card>
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.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import React from 'react'

import { Field, Form } from '../../../extensions/forms'
import { Card, Flex, Grid } from '../../'
import { Card, Flex, Grid, Section, Space } from '../../'
import { Wrapper, Box } from 'storybook-utils/helpers'
import { H2, P } from '../../../elements'

Expand Down Expand Up @@ -190,3 +190,31 @@ export const WithGrid = () => {
</div>
)
}

export const WithOutset = () => {
return (
<Space space="large">
<Flex.Vertical>
<Form.MainHeading>Main heading</Form.MainHeading>
<Card stack outset>
<P>Card content</P>
<Card>
<P>Nested card</P>
</Card>
</Card>
<Form.SubmitButton />
</Flex.Vertical>

<Section
top
roundedCorner
outline
outset={{ small: false, medium: true, large: true }}
innerSpace="medium"
backgroundColor="transparent"
>
<P>Nested card</P>
</Section>
</Space>
)
}
31 changes: 24 additions & 7 deletions packages/dnb-eufemia/src/components/card/style/dnb-card.scss
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,19 @@
align-self: flex-start;
}

// Nested Cards
& .dnb-card {
--outline-width: 0.125rem;
&[style*='--outset'] {
&.dnb-space[style]:not(.dnb-card) {
padding-left: calc(var(--padding-left) * calc(1 - var(--outset)));
padding-right: calc(var(--padding-right) * calc(1 - var(--outset)));
}
&.dnb-card > .dnb-flex-container {
margin-left: calc(
var(--padding-left, var(--spacing-medium)) * -1 * var(--outset)
);
margin-right: calc(
var(--padding-right, var(--spacing-medium)) * -1 * var(--outset)
);
}
}
}

Expand All @@ -125,14 +135,21 @@
+ * + .dnb-card,/* e.g. one paragraph */
+ * + * + .dnb-card,/* e.g. two paragraphs */
+ .dnb-help-button__content + .dnb-section + .dnb-card
) {
&:not([class*='space__bottom']) {
margin-bottom: var(--spacing-small);
}
}

.dnb-card--auto-indent:has(
+ .dnb-card:not([style*='--outset']),
+ * + .dnb-card:not([style*='--outset']),/* e.g. one paragraph */
+ * + * + .dnb-card:not([style*='--outset']),/* e.g. two paragraphs */
+ .dnb-help-button__content + .dnb-section + .dnb-card:not([style*='--outset'])
) {
&:not([class*='space__left']) {
@include allAbove(small) {
margin-left: var(--spacing-medium);
}
}

&:not([class*='space__bottom']) {
margin-bottom: var(--spacing-small);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -624,9 +624,19 @@ button.dnb-button::-moz-focus-inner {
.dnb-section:not([style*="--breakout"]) {
--breakout: var(--breakout--on);
}
.dnb-section[style*="--outset"].dnb-space[style]:not(.dnb-card) {
padding-left: calc(var(--padding-left) * (1 - var(--outset)));
padding-right: calc(var(--padding-right) * (1 - var(--outset)));
}
.dnb-section[style*="--outset"]::before {
margin-left: calc(var(--padding-left, var(--spacing-medium)) * -1 * var(--outset));
margin-right: calc(var(--padding-right, var(--spacing-medium)) * -1 * var(--outset));
background-color: inherit;
}
@media screen and (max-width: 60em) {
.dnb-section {
--breakout: var(--breakout--small, var(--breakout--fallback));
--outset: var(--outset--small, var(--outset--fallback));
--background-color--value: var(--background-color--small);
--text-color--value: var(--text-color--small);
--outline-color: var(--outline-color--small);
Expand All @@ -640,6 +650,7 @@ button.dnb-button::-moz-focus-inner {
@media screen and (max-width: 60em) and (min-width: 40.00625em) {
.dnb-section {
--breakout: var(--breakout--medium, var(--breakout--fallback));
--outset: var(--outset--medium, var(--outset--fallback));
--background-color--value: var(--background-color--medium);
--text-color--value: var(--text-color--medium);
--outline-color: var(--outline-color--medium);
Expand All @@ -653,6 +664,7 @@ button.dnb-button::-moz-focus-inner {
@media screen and (min-width: 60.00625em) {
.dnb-section {
--breakout: var(--breakout--large, var(--breakout--fallback));
--outset: var(--outset--large, var(--outset--fallback));
--background-color--value: var(--background-color--large);
--text-color--value: var(--text-color--large);
--outline-color: var(--outline-color--large);
Expand Down
Loading

0 comments on commit 8e63423

Please sign in to comment.