Skip to content
This repository has been archived by the owner on Aug 21, 2023. It is now read-only.

Commit

Permalink
Merge 7284df1 into eb42e5b
Browse files Browse the repository at this point in the history
  • Loading branch information
tinkertrain committed Aug 4, 2020
2 parents eb42e5b + 7284df1 commit f44a458
Show file tree
Hide file tree
Showing 49 changed files with 886 additions and 129 deletions.
13 changes: 9 additions & 4 deletions .remake/component/remake-name/remake-name.jsx
Expand Up @@ -3,15 +3,20 @@ import PropTypes from 'prop-types'
import getValidProps from '@helpscout/react-utils/dist/getValidProps'
import { classNames } from '../../utilities/classNames'
import { noop } from '../../utilities/other'
import { <%= name %>UI } from './styles/<%= name %>.css'
import { <%= name %>UI } from './<%= name %>.css'

export class <%= name %> extends React.Component {
static className = 'c-<%= name %>'
constructor(props) {
super(props)

this.<%= name %>Ref = React.createRef()
}

getClassName() {
const { className } = this.props

return classNames(
<%= name %>.className,
'c-<%= name %>',
className
)
}
Expand All @@ -23,7 +28,7 @@ export class <%= name %> extends React.Component {
<<%= name %>UI
{...getValidProps(rest)}
className={this.getClassName()}
ref={innerRef}
ref={this.<%= name %>Ref}
>
{children}
</<%= name %>UI>
Expand Down
4 changes: 2 additions & 2 deletions .remake/component/remake-name/remake-name.stories.mdx
@@ -1,11 +1,11 @@
import React from 'react'
import <%= name %> from '../src/components/<%= name %>'
import { Meta, Story, Props, Preview } from '@storybook/addon-docs/blocks'
import {
boolean,
number,
text,
select,
} from '@storybook/addon-knobs'
import <%= name %> from './<%= name %>'


<Meta
Expand Down
2 changes: 1 addition & 1 deletion .remake/component/remake-name/remake-name.test.js
Expand Up @@ -6,7 +6,7 @@ describe('className', () => {
test('Has default className', () => {
const wrapper = mount(<<%= name %> />)

expect(wrapper.hasClass('c-<%= name %>')).toBeTruthy()
expect(wrapper.find('.c-<%= name %>').length).toBeTruthy()
})

test('Can render custom className', () => {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -56,7 +56,7 @@
"new:pr": "open https://github.com/helpscout/hsds-react/compare",
"pretty": "npm run prettier",
"remake:component": "remake component --output=src/components",
"remake": "npm run remake:component",
"remake": "remake component --output=src/components",
"release": "np --no-yarn --contents=dist",
"release:patch": "npm run release -- patch",
"release:beta": "npm run release -- --yolo --any-branch",
Expand Down
2 changes: 1 addition & 1 deletion src/components/Animate/Animate.stories.mdx
Expand Up @@ -4,7 +4,7 @@ import { Animate as AnimateComponent } from './Animate'
import { Card, Heading, Text } from '../index'
import { AnimateOutExample } from './Animate.storiesHelpers'

<Meta component={Animate} title="🛠 Utilities/Animate" />
<Meta component={Animate} title="🛠 Utilities/Animation/Animate" />

# Animate

Expand Down
2 changes: 1 addition & 1 deletion src/components/AnimateGroup/AnimateGroup.stories.mdx
Expand Up @@ -2,7 +2,7 @@ import { Meta, Story, Props, Preview } from '@storybook/addon-docs/blocks'
import AnimateGroup from './'
import { Animate, Card } from '../index'

<Meta title="🛠 Utilities/AnimateGroup" component={AnimateGroup} />
<Meta title="🛠 Utilities/Animation/AnimateGroup" component={AnimateGroup} />

# AnimateGroup

Expand Down
5 changes: 4 additions & 1 deletion src/components/ChatScroller/ChatScroller.stories.mdx
Expand Up @@ -2,7 +2,10 @@ import { Meta, Story, Props, Preview } from '@storybook/addon-docs/blocks'
import { Default } from './ChatScroller.storiesHelpers'
import ChatScroller from './'

<Meta title="🛠 Utilities/ChatScroller" component={ChatScroller} />
<Meta
title="🛠 Utilities/UI Interactive/ChatScroller"
component={ChatScroller}
/>

# ChatScroller

Expand Down
72 changes: 72 additions & 0 deletions src/components/CheckMarkCard/CheckMarkCard.css.js
@@ -0,0 +1,72 @@
import styled from 'styled-components'
import { getColor } from '../../styles/utilities/color'
import { rgba } from '../../utilities/color'

export const CheckMarkCardUI = styled('label')`
box-sizing: border-box;
position: relative;
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
width: 100%;
max-width: ${({ maxWidth }) => (maxWidth ? maxWidth : '100px')};
height: ${({ height }) => (height ? height : 'auto')};
min-height: 100px;
border: 1px solid ${rgba(getColor('grey.700'), 0.7)};
border-radius: 4px;
background: white;
box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.1);
transition: all 0.15s;
will-change: box-shadow, border;
cursor: pointer;
&:hover {
box-shadow: 0px 4px 20px rgba(0, 0, 0, 0.1);
transform: translateY(-2px);
}
&.is-checked,
&.is-focused,
&.is-focused.is-checked,
&:focus-within,
&.is-checked:focus-within {
border-color: transparent;
box-shadow: 0px 0px 0 2px ${getColor('blue.500')};
}
&.is-disabled {
cursor: not-allowed;
opacity: 0.4;
box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.1);
&:hover {
box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.1);
transform: translateY(0);
}
}
`

export const CheckMarkUI = styled('div')`
position: absolute;
top: -2px;
left: -2px;
height: 28px;
width: 28px;
border-radius: 4px 0px 5px;
background: ${getColor('blue.500')};
opacity: 0;
transition: opacity 0.15s;
will-change: opacity;
.is-checked & {
opacity: 1;
}
.checkmark-icon {
color: white;
position: absolute;
top: calc(50% - 13px);
left: calc(50% - 13px);
}
`
162 changes: 162 additions & 0 deletions src/components/CheckMarkCard/CheckMarkCard.jsx
@@ -0,0 +1,162 @@
import React from 'react'
import PropTypes from 'prop-types'
import { classNames } from '../../utilities/classNames'
import { createUniqueIDFactory } from '../../utilities/id'
import { noop } from '../../utilities/other'
import Icon from '../Icon'
import Checkbox from '../Checkbox'
import VisuallyHidden from '../VisuallyHidden'
import { CheckMarkCardUI, CheckMarkUI } from './CheckMarkCard.css'

const uniqueID = createUniqueIDFactory('CheckMarkCard')

export class CheckMarkCard extends React.Component {
constructor(props) {
super(props)

this.state = {
id: props.id || uniqueID(),
}

this.checkMarkCardRef = React.createRef()
}

componentDidMount() {
if (this.props.isFocused && this.inputNode) {
this.checkMarkCardRef.current.classList.add('is-focused')
this.inputNode.focus()
}
}

getClassName() {
const { className, checked, disabled } = this.props

return classNames(
'c-CheckMarkCard',
className,
checked && 'is-checked',
disabled && 'is-disabled'
)
}

setInputNodeRef = node => {
this.inputNode = node
this.props.inputRef(node)
}

handleOnChange = (value, checked) => {
if (checked) {
this.checkMarkCardRef.current.classList.add('is-checked')
} else {
this.checkMarkCardRef.current.classList.remove('is-checked')
}

this.props.onChange(value, checked)
}

handleOnBlur = event => {
this.checkMarkCardRef.current.classList.remove('is-focused')
this.props.onBlur(event)
}

handleOnFocus = event => {
this.checkMarkCardRef.current.classList.add('is-focused')
this.props.onFocus(event)
}

render() {
const {
checked,
children,
disabled,
label,
maxWidth,
height,
value,
...rest
} = this.props
const { id } = this.state

return (
<CheckMarkCardUI
{...rest}
className={this.getClassName()}
htmlFor={id}
maxWidth={maxWidth}
height={height}
ref={this.checkMarkCardRef}
>
<CheckMarkUI>
<Icon className="checkmark-icon" name="checkmark" size="24" />
</CheckMarkUI>
<VisuallyHidden>
<Checkbox
checked={checked}
disabled={disabled}
id={id}
inputRef={this.setInputNodeRef}
label={label || value}
onBlur={this.handleOnBlur}
onFocus={this.handleOnFocus}
onChange={this.handleOnChange}
value={value}
/>
</VisuallyHidden>
{children}
</CheckMarkCardUI>
)
}
}

CheckMarkCard.defaultProps = {
checked: false,
'data-cy': 'CheckMarkCard',
inputRef: noop,
isFocused: false,
onBlur: noop,
onChange: noop,
onFocus: noop,
}

CheckMarkCard.propTypes = {
/** Custom class names to be added to the component. */
className: PropTypes.string,
/** Determines if the card is checked. */
checked: PropTypes.bool,
/** Data attr for Cypress tests. */
'data-cy': PropTypes.string,
/** Determines if the card is disabled. */
disabled: PropTypes.bool,
/** ID for the input. */
id: PropTypes.string,
/** Callback to obtain the <input> node. */
inputRef: PropTypes.func,
/** Whether the card should be focused */
isFocused: PropTypes.bool,
/** Set the height of the Card. */
height: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.func,
]),
/** Set the max width of the Card. */
maxWidth: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.func,
]),
/** Callback when the input is blurred. */
onBlur: PropTypes.func,
/** Callback when the input value is changed. */
onChange: PropTypes.func,
/** Callback when the input is focused. */
onFocus: PropTypes.func,
/** The value of the input. */
value: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.bool,
]),
}

export default CheckMarkCard

0 comments on commit f44a458

Please sign in to comment.