Skip to content

Commit

Permalink
feat(input): Adjust spacing of label, helper, and field to follow spa…
Browse files Browse the repository at this point in the history
…cing system.

Also add an initial Flexbox component and WithSpacing component to help describe layout and spacing.
  • Loading branch information
ryanoglesby08 committed Sep 13, 2017
1 parent b9bd3f8 commit fabe775
Show file tree
Hide file tree
Showing 17 changed files with 236 additions and 68 deletions.
19 changes: 19 additions & 0 deletions src/components/Flexbox/Flexbox.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react'
import PropTypes from 'prop-types'

import safeRest from '../../safeRest'

import styles from './Flexbox.modules.scss'

const Flexbox = ({ direction, children, ...rest }) => (
<div {...safeRest(rest)} className={styles[direction]}>
{children}
</div>
)

Flexbox.propTypes = {
direction: PropTypes.oneOf(['column', 'row']).isRequired,
children: PropTypes.node.isRequired
}

export default Flexbox
9 changes: 9 additions & 0 deletions src/components/Flexbox/Flexbox.modules.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.column {
display: flex;
flex-direction: column;
}

.row {
display: flex;
flex-direction: row;
}
46 changes: 46 additions & 0 deletions src/components/Flexbox/__tests__/Flexbox.spec.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React from 'react'
import { shallow } from 'enzyme'
import toJson from 'enzyme-to-json'

import Flexbox from '../Flexbox'

describe('Flexbox', () => {
const defaultProps = {
direction: 'row'
}
const doShallow = (props = {}) => (
shallow(<Flexbox {...defaultProps} {...props}>Some content</Flexbox>)
)

it('renders', () => {
const flexbox = doShallow()

expect(toJson(flexbox)).toMatchSnapshot()
})

it('can be a flex column', () => {
const flexbox = doShallow({ direction: 'column' })

expect(flexbox).toHaveClassName('column')
})

it('can be a flex row', () => {
const flexbox = doShallow({ direction: 'row' })

expect(flexbox).toHaveClassName('row')
})

it('passes additional attributes to the HTML element', () => {
const flexbox = doShallow({ id: 'the-id', 'data-some-property': 'a value' })

expect(flexbox).toHaveProp('id', 'the-id')
expect(flexbox).toHaveProp('data-some-property', 'a value')
})

it('does not allow custom CSS', () => {
const flexbox = doShallow({ className: 'my-custom-class', style: { color: 'hotpink' } })

expect(flexbox).not.toHaveProp('className', 'my-custom-class')
expect(flexbox).not.toHaveProp('style')
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Flexbox renders 1`] = `
<div
className="row"
>
Some content
</div>
`;
31 changes: 21 additions & 10 deletions src/components/Input/Input.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import PropTypes from 'prop-types'
import Icon from '../../old-components/Icon/Icon'
import Text from '../Typography/Text/Text'
import Paragraph from '../Typography/Paragraph/Paragraph'
import WithSpacing from './WithSpacing/WithSpacing'
import WithSpacing from '../Spacing/WithSpacing/WithSpacing'
import Flexbox from '../Flexbox/Flexbox'
import Helper from './Helper/Helper'
import Fade from './Fade'

Expand Down Expand Up @@ -124,14 +125,24 @@ class Input extends React.Component {
const showIcon = showFeedbackIcon(feedback, this.state.focused)

return (
<WithSpacing amount={1}>
<label htmlFor={inputId.identity()}>
<Text size="medium" bold>{label}</Text>
</label>

{ helper && this.renderHelper(helper, helperId, feedback, this.state.value) }

{ error && this.renderError(error, errorId) }
<Flexbox direction="column">
<WithSpacing amount={2}>
<label htmlFor={inputId.identity()} className={styles.resetLabel}>
<Text size="medium" bold>{label}</Text>
</label>
</WithSpacing>

{ helper &&
<WithSpacing amount={3}>
{this.renderHelper(helper, helperId, feedback, this.state.value)}
</WithSpacing>
}

{ error &&
<WithSpacing amount={3}>
{this.renderError(error, errorId)}
</WithSpacing>
}

<div className={wrapperClassName} data-testID="inputWrapper">
<input
Expand All @@ -151,7 +162,7 @@ class Input extends React.Component {
)}
</Fade>
</div>
</WithSpacing>
</Flexbox>
)
}
}
Expand Down
9 changes: 9 additions & 0 deletions src/components/Input/Input.modules.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@
@import '../../scss/settings/typography';
@import '../../scss/settings/spacing';

// FIXME: Override the global styles in forms.scss. This can be removed when the global styles are purged.
.resetLabel {
display: initial;
color: initial;
font-weight: initial;
letter-spacing: initial;
margin-bottom: 0;
}

.inputWrapper {
composes: thin rounded from '../Borders.modules.scss';

Expand Down
13 changes: 0 additions & 13 deletions src/components/Input/WithSpacing/WithSpacing.modules.scss

This file was deleted.

36 changes: 22 additions & 14 deletions src/components/Input/__tests__/Input.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ describe('Input', () => {
expect(input.find('label')).toContainReact(<Text size="medium" bold>The label</Text>)
})

// FIXME: Test for override of the global styles in forms.scss. This can be removed
// when the global styles are purged.
it('resets the styles of the label to override the global label styles', () => {
const input = doShallow()

expect(input.find('label')).toHaveClassName('resetLabel')
})

describe('connecting the label to the input', () => {
it('connects the label to the input', () => {
const input = doShallow()
Expand Down Expand Up @@ -233,20 +241,6 @@ describe('Input', () => {
})
})

it('passes additional attributes to the input element', () => {
const input = doShallow({ name: 'a name', placeholder: 'a placeholder' })

expect(findInputElement(input)).toHaveProp('name', 'a name')
expect(findInputElement(input)).toHaveProp('placeholder', 'a placeholder')
})

it('does not allow custom CSS', () => {
const input = doShallow({ className: 'my-custom-class', style: { color: 'hotpink' } })

expect(findInputElement(input)).not.toHaveProp('className', 'my-custom-class')
expect(findInputElement(input)).not.toHaveProp('style')
})

describe('accessibility', () => {
it('marks the input as invalid when in the error feedback state', () => {
let input = doShallow()
Expand Down Expand Up @@ -289,4 +283,18 @@ describe('Input', () => {
)
})
})

it('passes additional attributes to the input element', () => {
const input = doShallow({ name: 'a name', placeholder: 'a placeholder' })

expect(findInputElement(input)).toHaveProp('name', 'a name')
expect(findInputElement(input)).toHaveProp('placeholder', 'a placeholder')
})

it('does not allow custom CSS', () => {
const input = doShallow({ className: 'my-custom-class', style: { color: 'hotpink' } })

expect(findInputElement(input)).not.toHaveProp('className', 'my-custom-class')
expect(findInputElement(input)).not.toHaveProp('style')
})
})
58 changes: 34 additions & 24 deletions src/components/Input/__tests__/__snapshots__/Input.spec.jsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,26 @@

exports[`Input renders 1`] = `
<div
class="evenMarginBottom-1"
class="column"
>
<label
for="the-input"
<div
class="marginBottom-2"
>
<span
class="
medium
boldFont
color
"
<label
class="resetLabel"
for="the-input"
>
The input
</span>
</label>
<span
class="
medium
boldFont
color
"
>
The input
</span>
</label>
</div>
<div
class="default"
data-testid="inputWrapper"
Expand All @@ -34,21 +39,26 @@ exports[`Input renders 1`] = `

exports[`Input renders with a feedback state and icon 1`] = `
<div
class="evenMarginBottom-1"
class="column"
>
<label
for="the-input"
<div
class="marginBottom-2"
>
<span
class="
medium
boldFont
color
"
<label
class="resetLabel"
for="the-input"
>
The input
</span>
</label>
<span
class="
medium
boldFont
color
"
>
The input
</span>
</label>
</div>
<div
class="error"
data-testid="inputWrapper"
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import React from 'react'
import PropTypes from 'prop-types'

import safeRest from '../../../safeRest'

import styles from './WithSpacing.modules.scss'

const WithSpacing = ({ amount, children }) => (
<div className={styles[`evenMarginBottom-${amount}`]}>
const WithSpacing = ({ amount, children, ...rest }) => (
<div {...safeRest(rest)} className={styles[`marginBottom-${amount}`]}>
{children}
</div>
)
WithSpacing.propTypes = {
amount: PropTypes.oneOf([1]).isRequired,
amount: PropTypes.oneOf([2, 3]).isRequired,
children: PropTypes.node.isRequired
}

Expand Down
9 changes: 9 additions & 0 deletions src/components/Spacing/WithSpacing/WithSpacing.modules.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@import '../../../scss/settings/spacing';

.marginBottom-2 {
margin-bottom: $spacing-tight;
}

.marginBottom-3 {
margin-bottom: $spacing-base;
}
40 changes: 40 additions & 0 deletions src/components/Spacing/WithSpacing/__tests__/WithSpacing.spec.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from 'react'
import { shallow } from 'enzyme'
import toJson from 'enzyme-to-json'

import WithSpacing from '../WithSpacing'

describe('WithSpacing', () => {
const defaultProps = {
amount: 2
}
const doShallow = (props = {}) => (
shallow(<WithSpacing {...defaultProps} {...props}>Some content</WithSpacing>)
)

it('renders', () => {
const flexbox = doShallow()

expect(toJson(flexbox)).toMatchSnapshot()
})

it('applies margin bottom', () => {
const flexbox = doShallow({ amount: 3 })

expect(flexbox).toHaveClassName('marginBottom-3')
})

it('passes additional attributes to the HTML element', () => {
const flexbox = doShallow({ id: 'the-id', 'data-some-property': 'a value' })

expect(flexbox).toHaveProp('id', 'the-id')
expect(flexbox).toHaveProp('data-some-property', 'a value')
})

it('does not allow custom CSS', () => {
const flexbox = doShallow({ className: 'my-custom-class', style: { color: 'hotpink' } })

expect(flexbox).not.toHaveProp('className', 'my-custom-class')
expect(flexbox).not.toHaveProp('style')
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`WithSpacing renders 1`] = `
<div
className="marginBottom-2"
>
Some content
</div>
`;
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
}

.displayHeading {
composes: noSpacing from '../../Spacing.modules.scss';
composes: noSpacing from '../../Spacing/Spacing.modules.scss';

@include helvetica-neue-thin-35;

Expand Down
Loading

0 comments on commit fabe775

Please sign in to comment.