-
-
Notifications
You must be signed in to change notification settings - Fork 187
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(counter): add Counter component
- Loading branch information
Showing
7 changed files
with
374 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import React from 'react'; | ||
import propTypes from 'prop-types'; | ||
import styled from 'styled-components'; | ||
|
||
import { createWellBorderStyles } from '../common'; | ||
import Digit from './Digit'; | ||
|
||
const CounterWrapper = styled.div` | ||
${createWellBorderStyles(true)} | ||
display: inline-flex; | ||
background: #000000; | ||
`; | ||
|
||
const pixelSizes = { | ||
sm: 1, | ||
md: 2, | ||
lg: 3, | ||
xl: 4 | ||
}; | ||
|
||
const Counter = React.forwardRef(function Counter(props, ref) { | ||
const { value, minLength, size, ...otherProps } = props; | ||
let stringValue = value.toString(); | ||
if (minLength && minLength > stringValue.length) { | ||
stringValue = | ||
Array(minLength - stringValue.length) | ||
.fill('0') | ||
.join('') + stringValue; | ||
} | ||
return ( | ||
<CounterWrapper ref={ref} {...otherProps}> | ||
{stringValue.split('').map((digit, i) => ( | ||
<Digit digit={digit} pixelSize={pixelSizes[size]} key={i} /> | ||
))} | ||
</CounterWrapper> | ||
); | ||
}); | ||
|
||
Counter.defaultProps = { | ||
minLength: 3, | ||
size: 'md', | ||
value: 0 | ||
}; | ||
|
||
Counter.propTypes = { | ||
minLength: propTypes.number, | ||
size: propTypes.oneOf(['sm', 'md', 'lg']), | ||
value: propTypes.number | ||
}; | ||
|
||
export default Counter; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
--- | ||
name: Bar | ||
menu: Components | ||
--- | ||
|
||
import { Playground, Props } from 'docz'; | ||
|
||
import Counter from '../Counter/Counter' | ||
|
||
# Counter | ||
|
||
## Usage | ||
|
||
<Playground> | ||
<Counter value={4017} minLength={7} size='lg' /> | ||
</Playground> | ||
|
||
## API | ||
|
||
### Import | ||
|
||
### Props | ||
|
||
<Props of={Counter} /> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import React from 'react'; | ||
import { renderWithTheme } from '../../test/utils'; | ||
|
||
import Counter from './Counter'; | ||
|
||
describe('<Counter />', () => { | ||
it('should render', () => { | ||
const { container } = renderWithTheme(<Counter />); | ||
const counter = container.firstChild; | ||
|
||
expect(counter).toBeInTheDocument(); | ||
}); | ||
|
||
it('should handle custom style', () => { | ||
const { container } = renderWithTheme( | ||
<Counter style={{ backgroundColor: 'papayawhip' }} /> | ||
); | ||
const counter = container.firstChild; | ||
|
||
expect(counter).toHaveAttribute('style', 'background-color: papayawhip;'); | ||
}); | ||
|
||
it('should handle custom props', () => { | ||
const customProps = { title: 'potatoe' }; | ||
const { container } = renderWithTheme(<Counter {...customProps} />); | ||
const counter = container.firstChild; | ||
|
||
expect(counter).toHaveAttribute('title', 'potatoe'); | ||
}); | ||
|
||
describe('prop: minLength', () => { | ||
it('renders correct number of digits', () => { | ||
const { container } = renderWithTheme( | ||
<Counter value={32} minLength={7} /> | ||
); | ||
const counter = container.firstChild; | ||
|
||
expect(counter.childElementCount).toBe(7); | ||
}); | ||
|
||
it('value length takes priority if bigger than minLength', () => { | ||
const { container } = renderWithTheme( | ||
<Counter value={1234} minLength={2} /> | ||
); | ||
const counter = container.firstChild; | ||
|
||
expect(counter.childElementCount).toBe(4); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import React, { useState } from 'react'; | ||
import styled from 'styled-components'; | ||
|
||
import { Counter, Panel, Button } from 'react95'; | ||
|
||
const Wrapper = styled.div` | ||
padding: 5rem; | ||
background: teal; | ||
.counter-wrapper { | ||
display: flex; | ||
margin-top: 1rem; | ||
} | ||
.counter-wrapper button { | ||
margin-left: 0.5rem; | ||
height: 51px; | ||
} | ||
.wrapper { | ||
padding: 1rem; | ||
} | ||
`; | ||
|
||
export default { | ||
title: 'Counter', | ||
component: Counter, | ||
decorators: [story => <Wrapper>{story()}</Wrapper>] | ||
}; | ||
|
||
export const Default = () => { | ||
const [count, setCount] = useState(13); | ||
const handleClick = () => setCount(count + 1); | ||
return ( | ||
<Panel className='wrapper'> | ||
<Counter value={123456789} minLength={11} size='lg' /> | ||
|
||
<div className='counter-wrapper'> | ||
<Counter value={count} minLength={3} /> | ||
<Button onClick={handleClick}>Click!</Button> | ||
</div> | ||
</Panel> | ||
); | ||
}; | ||
|
||
Default.story = { | ||
name: 'default' | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
import React from 'react'; | ||
import propTypes from 'prop-types'; | ||
import styled, { css } from 'styled-components'; | ||
|
||
import { createHatchedBackground } from '../common'; | ||
|
||
const DigitWrapper = styled.div` | ||
position: relative; | ||
--react95-digit-primary-color: #ff0102; | ||
--react95-digit-secondary-color: #740201; | ||
--react95-digit-bg-color: #000000; | ||
${({ pixelSize }) => css` | ||
width: ${11 * pixelSize}px; | ||
height: ${21 * pixelSize}px; | ||
margin: ${pixelSize}px; | ||
span, | ||
span:before, | ||
span:after { | ||
box-sizing: border-box; | ||
display: inline-block; | ||
position: absolute; | ||
} | ||
span.active, | ||
span.active:before, | ||
span.active:after { | ||
background: var(--react95-digit-primary-color); | ||
} | ||
span:not(.active), | ||
span:not(.active):before, | ||
span:not(.active):after { | ||
${createHatchedBackground({ | ||
mainColor: 'var(--react95-digit-bg-color)', | ||
secondaryColor: 'var(--react95-digit-secondary-color)', | ||
pixelSize | ||
})} | ||
} | ||
span.horizontal, | ||
span.horizontal:before, | ||
span.horizontal:after { | ||
height: ${pixelSize}px; | ||
border-left: ${pixelSize}px solid var(--react95-digit-bg-color); | ||
border-right: ${pixelSize}px solid var(--react95-digit-bg-color); | ||
} | ||
span.horizontal.active, | ||
span.horizontal.active:before, | ||
span.horizontal.active:after { | ||
height: ${pixelSize}px; | ||
border-left: ${pixelSize}px solid var(--react95-digit-primary-color); | ||
border-right: ${pixelSize}px solid var(--react95-digit-primary-color); | ||
} | ||
span.horizontal { | ||
left: ${pixelSize}px; | ||
width: ${9 * pixelSize}px; | ||
} | ||
span.horizontal:before { | ||
content: ''; | ||
width: 100%; | ||
top: ${pixelSize}px; | ||
left: ${0}px; | ||
} | ||
span.horizontal:after { | ||
content: ''; | ||
width: calc(100% - ${pixelSize * 2}px); | ||
top: ${2 * pixelSize}px; | ||
left: ${pixelSize}px; | ||
} | ||
span.horizontal.top { | ||
top: 0; | ||
} | ||
span.horizontal.bottom { | ||
bottom: 0; | ||
transform: rotateX(180deg); | ||
} | ||
span.center, | ||
span.center:before, | ||
span.center:after { | ||
height: ${pixelSize}px; | ||
border-left: ${pixelSize}px solid var(--react95-digit-bg-color); | ||
border-right: ${pixelSize}px solid var(--react95-digit-bg-color); | ||
} | ||
span.center.active, | ||
span.center.active:before, | ||
span.center.active:after { | ||
border-left: ${pixelSize}px solid var(--react95-digit-primary-color); | ||
border-right: ${pixelSize}px solid var(--react95-digit-primary-color); | ||
} | ||
span.center { | ||
top: 50%; | ||
transform: translateY(-50%); | ||
left: ${pixelSize}px; | ||
width: ${9 * pixelSize}px; | ||
} | ||
span.center:before, | ||
span.center:after { | ||
content: ''; | ||
width: 100%; | ||
} | ||
span.center:before { | ||
top: ${pixelSize}px; | ||
} | ||
span.center:after { | ||
bottom: ${pixelSize}px; | ||
} | ||
span.vertical, | ||
span.vertical:before, | ||
span.vertical:after { | ||
width: ${pixelSize}px; | ||
border-top: ${pixelSize}px solid var(--react95-digit-bg-color); | ||
border-bottom: ${pixelSize}px solid var(--react95-digit-bg-color); | ||
} | ||
span.vertical { | ||
height: ${11 * pixelSize}px; | ||
} | ||
span.vertical.left { | ||
left: 0; | ||
} | ||
span.vertical.right { | ||
right: 0; | ||
transform: rotateY(180deg); | ||
} | ||
span.vertical.top { | ||
top: 0px; | ||
} | ||
span.vertical.bottom { | ||
bottom: 0px; | ||
} | ||
span.vertical:before { | ||
content: ''; | ||
height: 100%; | ||
top: ${0}px; | ||
left: ${pixelSize}px; | ||
} | ||
span.vertical:after { | ||
content: ''; | ||
height: calc(100% - ${pixelSize * 2}px); | ||
top: ${pixelSize}px; | ||
left: ${pixelSize * 2}px; | ||
} | ||
`} | ||
`; | ||
|
||
const segments = [ | ||
'horizontal top', | ||
'center', | ||
'horizontal bottom', | ||
'vertical top left', | ||
'vertical top right', | ||
'vertical bottom left', | ||
'vertical bottom right' | ||
]; | ||
|
||
const digitActiveSegments = [ | ||
[1, 0, 1, 1, 1, 1, 1], // 0 | ||
[0, 0, 0, 0, 1, 0, 1], // 1 | ||
[1, 1, 1, 0, 1, 1, 0], // 2 | ||
[1, 1, 1, 0, 1, 0, 1], // 3 | ||
[0, 1, 0, 1, 1, 0, 1], // 4 | ||
[1, 1, 1, 1, 0, 0, 1], // 5 | ||
[1, 1, 1, 1, 0, 1, 1], // 6 | ||
[1, 0, 0, 0, 1, 0, 1], // 7 | ||
[1, 1, 1, 1, 1, 1, 1], // 8 | ||
[1, 1, 1, 1, 1, 0, 1] // 9 | ||
]; | ||
|
||
const Digit = ({ digit, pixelSize, ...otherProps }) => { | ||
const segmentClasses = digitActiveSegments[digit].map((isActive, i) => | ||
isActive ? `${segments[i]} active` : segments[i] | ||
); | ||
return ( | ||
<DigitWrapper pixelSize={pixelSize} {...otherProps}> | ||
{segmentClasses.map((className, i) => ( | ||
<span className={className} key={i} /> | ||
))} | ||
</DigitWrapper> | ||
); | ||
}; | ||
|
||
Digit.defaultProps = { | ||
pixelSize: 2, | ||
digit: 0 | ||
}; | ||
|
||
Digit.propTypes = { | ||
pixelSize: propTypes.number, | ||
digit: propTypes.oneOfType(propTypes.number, propTypes.string) | ||
}; | ||
|
||
export default Digit; |
Oops, something went wrong.
8c77b7a
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs: