Skip to content

Commit

Permalink
feat: enhance #space to support booleans and strings, along with obje…
Browse files Browse the repository at this point in the history
…ct (#756)

* feat: enhance #space to support booleans and strings, along with object

* chore: add tests for  prop
  • Loading branch information
tujoworker authored Feb 2, 2021
1 parent f5ecdfa commit b80e2f3
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -321,25 +321,31 @@ const VisualSpace = ({ label, children, ...rest }) => {

React.useEffect(() => {
if (!label) {
try {
const style = window.getComputedStyle(ref.current.children[0])
const top = parseFloat(style.getPropertyValue('margin-top'))
const bottom = parseFloat(style.getPropertyValue('margin-bottom'))
let spaceInPixels = top

if (bottom > 0) {
spaceInPixels = bottom
setDirection('bottom')
const elem = ref.current
const timeout = setTimeout(() => {
try {
const style = window.getComputedStyle(elem.children[0])
const top = parseFloat(style.getPropertyValue('margin-top'))
const bottom = parseFloat(
style.getPropertyValue('margin-bottom')
)
let spaceInPixels = top

if (bottom > 0) {
spaceInPixels = bottom
setDirection('bottom')
}

const spaceInRem = `${spaceInPixels / 16}`
setLabel(spaceInRem)

const title = elem.parentElement.getAttribute('class')
setTitle(title)
} catch (e) {
console.warn(e)
}

const spaceInRem = `${spaceInPixels / 16}`
setLabel(spaceInRem)

const title = ref.current.parentElement.getAttribute('class')
setTitle(title)
} catch (e) {
console.warn(e)
}
}, 1)
return () => clearTimeout(timeout)
}
}, [label, ref])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,45 @@ To get a spacing of e.g. **2.5rem** (40px)- You may combine types `large` and `x
<Space top="large x-small" right="2.5" bottom="2.5rem" left="40px" />
```

With React, you can also use an object with the different directions:

```jsx
/** All of these methods will result in the same spacing */
<Space
space={{
top: 'large x-small',
right: '2.5',
bottom: '2.5rem',
left: '40px'
}}
/>
```

### Components and Spacing

Every component supports the spacing patterns, so it's possible to send in the `top`, `right`, `bottom` and `left` properties directly, like:
Every component supports the spacing patterns, so it's possible to send in the `top`, `right`, `bottom`, `left` and `space` properties directly, like:

```jsx
<Button top="large x-small medium" />
<Button space={{ top: "large x-small medium" }} />
```

### Spacing shorthands

A shorthand for getting 1rem (most used) is to simply send in a boolean, set as true. No given value in JSX means true, so you only need the property key:

```jsx
/** Equivalent to top="small" */
<Button top />

/** Equivalent to top="small" right="small" bottom="small" left="small" */
<Button space />
```

In order to set all four directions at once, you can provide a string as the `space` value:

```jsx
<Button space="large x-small medium" />
```

### Does it not work as expected?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ Spacing follows a specific pattern:
Also, have a look at the [Space](/uilib/components/space) component and the fact that every component supports [spacing out of the box](/uilib/components/space#components-and-spacing).

```jsx
<Button top="small" text="Title" />
<Input right="large x-small medium" placeholder="Title" />
<Button top="small" />
<Button right="large x-small medium" />
<Button space={{ top='small', right: 'large x-small medium' }} />
```

### CSS Custom Property
Expand Down
3 changes: 2 additions & 1 deletion packages/dnb-ui-lib/src/components/space/Space.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ export default class Space extends React.PureComponent {
right,
bottom,
left,
space,
skeleton,
id: _id, // eslint-disable-line
className,
Expand All @@ -108,7 +109,7 @@ export default class Space extends React.PureComponent {
'dnb-space',
isTrue(inline) && 'dnb-space--inline',
createSkeletonClass(null, skeleton), // do not send along this.context
createSpacingClasses({ top, right, bottom, left }),
createSpacingClasses({ top, right, bottom, left, space }),
className,
_className
),
Expand Down
56 changes: 34 additions & 22 deletions packages/dnb-ui-lib/src/components/space/SpacingHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,33 @@ import PropTypes from 'prop-types'
import { warn } from '../../shared/component-helper'

export const spacingPropTypes = {
space: PropTypes.shape({
top: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.bool
]),
right: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.bool
]),
bottom: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.bool
]),
left: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.bool
])
}),
space: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.bool,
PropTypes.shape({
top: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.bool
]),
right: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.bool
]),
bottom: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.bool
]),
left: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.bool
])
})
]),
top: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
Expand Down Expand Up @@ -207,6 +212,13 @@ export const removeSpaceProps = ({ ...props }) => {
// Creates a valid space CSS class out from given space types
export const createSpacingClasses = (props, Element = null) => {
if (typeof props.space !== 'undefined') {
if (
typeof props.space === 'string' ||
typeof props.space === 'number' ||
(typeof props.space === 'boolean' && props.space)
) {
props.top = props.right = props.bottom = props.left = props.space
}
for (let i in props.space) {
if (!props[i] && isValidSpaceProp(i)) {
props[i] = props.space[i]
Expand Down
13 changes: 13 additions & 0 deletions packages/dnb-ui-lib/src/components/space/__tests__/Space.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,19 @@ describe('Space component', () => {
).toBe(true)
})

it('should accept space only prop', () => {
const Comp = mount(<Component element="span" space="large" />)
expect(
Object.values(Comp.find('span.dnb-space').instance().classList)
).toEqual([
'dnb-space',
'dnb-space__top--large',
'dnb-space__right--large',
'dnb-space__bottom--large',
'dnb-space__left--large'
])
})

it('should have collapse CSS classe', () => {
const Comp = mount(<Component top="large" no_collapse={true} />)
expect(Comp.find('.dnb-space--no-collapse').exists()).toBe(true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,28 @@ describe('createSpacingClasses', () => {
])
expect(createSpacingClasses({ right: null })).toEqual([])
})
it('should handle the space prop for in all directions', () => {
expect(createSpacingClasses({ space: false })).toEqual([]) // we may extend that with all four "--zero" in future
expect(createSpacingClasses({ space: 0 })).toEqual([
'dnb-space__left--zero',
'dnb-space__bottom--zero',
'dnb-space__right--zero',
'dnb-space__top--zero'
])
expect(createSpacingClasses({ space: true })).toEqual([
'dnb-space__left--small',
'dnb-space__bottom--small',
'dnb-space__right--small',
'dnb-space__top--small'
])
expect(createSpacingClasses({ space: '1rem' })).toEqual([
'dnb-space__left--small',
'dnb-space__bottom--small',
'dnb-space__right--small',
'dnb-space__top--small'
])
expect(createSpacingClasses({ space: null })).toEqual([])
})
})

describe('createStyleObject', () => {
Expand Down

0 comments on commit b80e2f3

Please sign in to comment.