Skip to content

Commit

Permalink
refactor(textarea): Insert padding-right in order to prevent overlapp…
Browse files Browse the repository at this point in the history
…ing text and icons
  • Loading branch information
ryanoglesby08 committed Dec 1, 2017
1 parent 3d6c063 commit d29634c
Show file tree
Hide file tree
Showing 12 changed files with 114 additions and 61 deletions.
3 changes: 0 additions & 3 deletions src/components/Box/Box.modules.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
@import '../../scss/settings/responsive-grid';
@import '../../scss/utility/responsive';

$spacing-base: 1rem; // 16px

$mobile: (
Expand Down
5 changes: 2 additions & 3 deletions src/components/FormField/FormField.modules.scss
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,8 @@

/* ICON */

.iconPosition {
top: 0.5rem;
right: 0.5rem;
.iconRight {
right: 1rem;
}

/* END ICON */
21 changes: 21 additions & 0 deletions src/components/FormField/__tests__/addRightPadding.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import addRightPadding from '../addRightPadding'

describe('icon positioning calculations to prevent text overlapping', () => {
it('does not add padding when there are no visible icons', () => {
const style = addRightPadding(0)

expect(style).toBeUndefined()
})

it('adds padding for 1 icon', () => {
const style = addRightPadding(1)

expect(style).toEqual({ paddingRight: 'calc(16px + 2rem)' })
})

it('adds padding for 2 icons', () => {
const style = addRightPadding(2)

expect(style).toEqual({ paddingRight: 'calc(32px + 3rem)' })
})
})
13 changes: 13 additions & 0 deletions src/components/FormField/addRightPadding.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const betweenSpacing = 1 // rem
const iconWidth = 16 // px

export default numberOfIcons => {
if (numberOfIcons === 0) {
return undefined
}

return {
paddingRight: `calc(${iconWidth * numberOfIcons}px + ${betweenSpacing *
(numberOfIcons + 1)}rem)`,
}
}
30 changes: 16 additions & 14 deletions src/components/Select/Select.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,25 @@ import DecorativeIcon from '../Icons/DecorativeIcon/DecorativeIcon'
import Tooltip from '../Tooltip/Tooltip'
import FormField from '../FormField/FormField'
import FeedbackIcon from '../FormField/FeedbackIcon'
import Box from '../Box/Box'

import addRightPadding from '../FormField/addRightPadding'

import styles from './Select.modules.scss'
import iconWrapperStyles from '../Icons/IconWrapper.modules.scss'

const Select = ({ options, placeholder, ...props }) => (
<FormField {...props}>
{({ className, ...selectProps }, showIcon, feedback) => (
{({ className, ...selectProps }, showFeedbackIcon, feedback) => (
<div className={styles.wrapper}>
<select
{...selectProps}
className={joinClassNames(
className,
styles.select,
!selectProps.disabled && styles.positionSelectOnTop,
!selectProps.disabled && styles.positionSelectOnTop
)}
style={addRightPadding(showFeedbackIcon ? 2 : 1)}
>
{placeholder && (
<option value="" hidden disabled data-no-global-styles>
Expand All @@ -37,19 +41,17 @@ const Select = ({ options, placeholder, ...props }) => (
</select>

{!selectProps.disabled && (
<div className={styles.feedbackIconPosition}>
<FeedbackIcon showIcon={showIcon} feedback={feedback} />
</div>
)}
<Box inline between={3} dangerouslyAddClassName={styles.iconsPosition}>
<FeedbackIcon showIcon={showFeedbackIcon} feedback={feedback} />

{!selectProps.disabled && (
<div className={joinClassNames(iconWrapperStyles.fixLineHeight, styles.caretPosition)}>
<DecorativeIcon
symbol="caretDown"
variant={feedback === 'error' ? 'error' : 'primary'}
size={16}
/>
</div>
<div className={iconWrapperStyles.fixLineHeight}>
<DecorativeIcon
symbol="caretDown"
variant={feedback === 'error' ? 'error' : 'primary'}
size={16}
/>
</div>
</Box>
)}
</div>
)}
Expand Down
15 changes: 2 additions & 13 deletions src/components/Select/Select.modules.scss
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,9 @@
background: transparent;
}

.feedbackIconPosition {
.iconsPosition {
composes: absolute centerVertically from '../Position.modules.scss';
composes: iconRight from '../FormField/FormField.modules.scss';

z-index: 1;

// FIXME: This value is made up.
right: 2rem;
}

.caretPosition {
composes: absolute centerVertically from '../Position.modules.scss';

z-index: 1;

// FIXME: This value is made up.
right: 1rem;
}
24 changes: 18 additions & 6 deletions src/components/Select/__tests__/Select.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,18 @@ describe('Select', () => {
)
})

it('positions the select on top of the icons so that it can be clicked', () => {
const { findSelectElement } = doMount()

expect(findSelectElement()).toHaveClassName('positionSelectOnTop')
})

it('positions the down caret so that the text does not overlap it', () => {
const { findSelectElement } = doMount()

expect(findSelectElement()).toHaveStyle('paddingRight', 'calc(16px + 2rem)')
})

describe('label', () => {
it('must have a label', () => {
const { label } = doMount({ label: 'The label' })
Expand Down Expand Up @@ -232,12 +244,12 @@ describe('Select', () => {
focus()
expect(findFeedbackIconFade()).toHaveProp('in', false)
})
})

it('positions the select on top of the icons so that it can be clicked', () => {
const { findSelectElement } = doMount()
it('ensures that the contents do not overlap the icons', () => {
const { findSelectElement } = doMount({ feedback: 'success' })

expect(findSelectElement()).toHaveClassName('positionSelectOnTop')
expect(findSelectElement()).toHaveStyle('paddingRight', 'calc(32px + 3rem)')
})
})

describe('disabling', () => {
Expand Down Expand Up @@ -390,7 +402,7 @@ describe('Select', () => {
style: { color: 'hotpink' },
})

expect(findSelectElement()).not.toHaveProp('className', 'my-custom-class')
expect(findSelectElement()).not.toHaveProp('style')
expect(findSelectElement()).not.toHaveClassName('my-custom-class')
expect(findSelectElement()).not.toHaveStyle('color', 'hotpink')
})
})
37 changes: 20 additions & 17 deletions src/components/Select/__tests__/__snapshots__/Select.spec.jsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ exports[`Select renders 1`] = `
class="default select positionSelectOnTop"
data-no-global-styles="true"
id="the-select"
style="padding-right:calc(16px + 2rem)"
>
<option
data-no-global-styles="true"
Expand All @@ -45,15 +46,16 @@ exports[`Select renders 1`] = `
</option>
</select>
<div
class="feedbackIconPosition"
/>
<div
class="fixLineHeight caretPosition"
class="betweenRightMarginDesktop-3 inline iconsPosition"
>
<i
aria-hidden="true"
class="iconCaretDown primary size16"
/>
<div
class="fixLineHeight"
>
<i
aria-hidden="true"
class="iconCaretDown primary size16"
/>
</div>
</div>
</div>
</div>
Expand Down Expand Up @@ -89,6 +91,7 @@ exports[`Select renders with a feedback state and icon 1`] = `
class="error select positionSelectOnTop"
data-no-global-styles="true"
id="the-select"
style="padding-right:calc(32px + 3rem)"
>
<option
data-no-global-styles="true"
Expand All @@ -104,7 +107,7 @@ exports[`Select renders with a feedback state and icon 1`] = `
</option>
</select>
<div
class="feedbackIconPosition"
class="betweenRightMarginDesktop-3 inline iconsPosition"
>
<div
style="transition:opacity 100ms ease-in-out;opacity:1"
Expand All @@ -118,14 +121,14 @@ exports[`Select renders with a feedback state and icon 1`] = `
/>
</div>
</div>
</div>
<div
class="fixLineHeight caretPosition"
>
<i
aria-hidden="true"
class="iconCaretDown error size16"
/>
<div
class="fixLineHeight"
>
<i
aria-hidden="true"
class="iconCaretDown error size16"
/>
</div>
</div>
</div>
</div>
Expand Down
7 changes: 5 additions & 2 deletions src/components/Textarea/Textarea.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,24 @@ import Tooltip from '../Tooltip/Tooltip'
import FormField from '../FormField/FormField'
import FeedbackIcon from '../FormField/FeedbackIcon'

import addRightPadding from '../FormField/addRightPadding'

import styles from './Textarea.modules.scss'
import positionStyles from '../Position.modules.scss'

const Textarea = props => (
<FormField {...props}>
{({ className, ...textareaProps }, showIcon, feedback) => (
{({ className, ...textareaProps }, showFeedbackIcon, feedback) => (
<div className={joinClassNames(positionStyles.relative, styles.preventWidthResizing)}>
<textarea
{...textareaProps}
className={joinClassNames(className, styles.preventWidthResizing)}
style={addRightPadding(showFeedbackIcon ? 1 : 0)}
/>

{!textareaProps.disabled && (
<div className={styles.feedbackIconPosition}>
<FeedbackIcon showIcon={showIcon} feedback={feedback} />
<FeedbackIcon showIcon={showFeedbackIcon} feedback={feedback} />
</div>
)}
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/Textarea/Textarea.modules.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

.feedbackIconPosition {
composes: absolute from '../Position.modules.scss';
composes: iconRight from '../FormField/FormField.modules.scss';

top: 0.5rem;
right: 0.5rem;
}
17 changes: 15 additions & 2 deletions src/components/Textarea/__tests__/Textarea.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ describe('Textarea', () => {

it('can have an error feedback state', () => {
const { findTextareaElement, findFeedbackIconFade } = doMount({ feedback: 'error' })

expect(findTextareaElement()).toHaveClassName('error')
expect(findFeedbackIconFade()).toContainReact(
<StandaloneIcon
Expand Down Expand Up @@ -212,6 +213,18 @@ describe('Textarea', () => {
focus()
expect(findFeedbackIconFade()).toHaveProp('in', false)
})

it('ensures that the contents do not overlap the icon', () => {
const { findTextareaElement } = doMount({ feedback: 'success' })

expect(findTextareaElement()).toHaveStyle('paddingRight', 'calc(16px + 2rem)')
})

it('does not add any extra padding when there are no icons displayed', () => {
const { findTextareaElement } = doMount()

expect(findTextareaElement()).toHaveProp('style', undefined)
})
})

describe('disabling', () => {
Expand Down Expand Up @@ -348,7 +361,7 @@ describe('Textarea', () => {
style: { color: 'hotpink' },
})

expect(findTextareaElement()).not.toHaveProp('className', 'my-custom-class')
expect(findTextareaElement()).not.toHaveProp('style')
expect(findTextareaElement()).not.toHaveClassName('my-custom-class')
expect(findTextareaElement()).not.toHaveStyle('color', 'hotpink')
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ exports[`Textarea renders with a feedback state and icon 1`] = `
class="error preventWidthResizing"
data-no-global-styles="true"
id="the-textarea"
style="padding-right:calc(16px + 2rem)"
/>
<div
class="feedbackIconPosition"
Expand Down

0 comments on commit d29634c

Please sign in to comment.