Fixed problems with Input and Fieldset

Signed-off-by: Florian BOUILLON <florian.bouillon@delta-wings.net>
This commit is contained in:
Florian Bouillon 2021-03-05 10:07:02 +01:00
parent 8d99f1f3e6
commit d898dc2f5b
11 changed files with 804 additions and 975 deletions

View File

@ -5,7 +5,6 @@ module.exports = {
"../src/dzeio/**/*.stories.@(js|jsx|ts|tsx)", "../src/dzeio/**/*.stories.@(js|jsx|ts|tsx)",
], ],
"addons": [ "addons": [
"@storybook/addon-links",
"@storybook/addon-essentials" "@storybook/addon-essentials"
], ],
typescript: { typescript: {

View File

@ -24,6 +24,7 @@ module.exports = {
use: ['style-loader', { use: ['style-loader', {
loader: 'css-loader', loader: 'css-loader',
options: { options: {
url: false,
importLoaders: 1, importLoaders: 1,
modules: true modules: true
}, },

View File

@ -1,4 +1,5 @@
import '../src/dzeio/general.styl'
export const parameters = { export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" }, layout: 'centered'
} }

View File

@ -2,7 +2,7 @@
.fieldset .fieldset
border-radius 4px border-radius 4px
border 2px solid grey border 2px solid $grayDark
transition all $transition transition all $transition
margin 0 margin 0

View File

@ -0,0 +1,16 @@
import { Meta } from '@storybook/react/types-6-0'
import React from 'react'
import Component from '.'
import Input from '../Input'
export default {
title: 'DZEIO/Fieldset',
component: Component,
argTypes: {
title: { control: 'text'}
}
} as Meta
export const Basic = (args: any) => (
<Component {...args}><Input label="Test" /></Component>
)

View File

@ -34,7 +34,7 @@
left 16px // input padding-left left 16px // input padding-left
~ label ~ label
left 16px + 24px + 16px left 16px + 24px + 10px
&.right &.right
right 16px right 16px
@ -68,6 +68,7 @@
display flex display flex
opacity 0 opacity 0
transition all $transition transition all $transition
overflow-x hidden
pointer-events none pointer-events none
// display flex // display flex
flex-direction column flex-direction column
@ -109,10 +110,12 @@
@media (prefers-color-scheme dark) @media (prefers-color-scheme dark)
background lighten(lighten($foregroundDark, 5%), 20%) background lighten(lighten($foregroundDark, 5%), 20%)
div + .autocomplete
top calc(100% - 4px - .9em)
input:focus + .autocomplete input:focus ~ .autocomplete
select:focus + .autocomplete select:focus ~ .autocomplete
textarea:focus + .autocomplete textarea:focus ~ .autocomplete
.autocomplete:hover .autocomplete:hover
opacity 1 opacity 1
pointer-events inherit pointer-events inherit
@ -122,7 +125,7 @@
textarea textarea
padding 14px 16px padding 14px 16px
height 56px height 56px
border 2px solid rgba(black, .3) border 2px solid $grayDark
border-radius 4px border-radius 4px
max-width 100% max-width 100%
box-sizing border-box box-sizing border-box
@ -132,18 +135,7 @@
transition all $transition transition all $transition
color black color black
@media (prefers-color-scheme dark) @media (prefers-color-scheme dark)
border-color rgba(white, .3) border-color $grayLight
color white
&:not(:disabled):hover
border-color black
@media (prefers-color-scheme dark)
border-color white
+ svg
color black
@media (prefers-color-scheme dark)
color white color white
&:not(:placeholder-shown) &:not(:placeholder-shown)
@ -168,27 +160,47 @@
~ label ~ label
color #999 color #999
&:invalid &:not(:disabled)
border-color $danger &:hover
border-color black
@media (prefers-color-scheme dark)
border-color white
~ label + svg
color @border-color color black
~ svg @media (prefers-color-scheme dark)
color @border-color color white
&:focus &:focus
border-color $default border-color $main
~ label ~ label
color @border-color color @border-color
~ svg ~ svg
color @border-color color @border-color
&:invalid
border-color $errorLight
~ label
color @border-color
~ svg
color @border-color
@media (prefers-color-scheme dark)
border-color $errorDark
~ label
color @border-color
~ svg
color @border-color
&.iconLeft &.iconLeft
padding-left 16px + 24px + 16px padding-left 16px + 24px + 10px
&.iconRight &.iconRight
padding-right 16 + 24 + 16px padding-right 16 + 24 + 10px
&.filled &.filled
border none border none
background rgba(gray, .1) background rgba(gray, .1)
@ -235,12 +247,12 @@
padding 0 padding 0
font-size .75rem font-size .75rem
~ svg.left ~ label ~ svg.left ~ label
left 16px + 24px + 16px // .input/padding-left label/padding-left left 16px + 24px + 10px // .input/padding-left label/padding-left
~ svg.rotate ~ svg.rotate
transform rotateX(0) transform rotateX(0)
transition $transition transition $transition
&:hover:focus ~ svg.rotate, ~.autocomplete:hover ~ svg.rotate &:focus ~ svg.rotate, ~.autocomplete:hover ~ svg.rotate
transform rotateX(180deg) transform rotateX(180deg)
div div
display flex display flex

View File

@ -1,10 +1,29 @@
import { Meta } from '@storybook/react/types-6-0' import { Meta } from '@storybook/react/types-6-0'
import { Story } from "@storybook/react"
import React from 'react' import React from 'react'
import Component from '.' import Component from '.'
import { X } from 'react-feather'
export default { export default {
title: 'DZEIO/Input', title: 'DZEIO/Input',
component: Component component: Component
} as Meta } as Meta
export const Basic = (args: any) => <Component {...args} /> export const Basic: Story<any> = (args: any) => <Component {...args} />
let tmp = Basic.bind({})
tmp.args = {label: 'Label', helper: 'Helper', maxLength: 6, characterCount: true, icon: X}
export const Normal = tmp
tmp = Basic.bind({})
tmp.args = {label: 'Label', filled:true, helper: 'Helper', autocomplete: ['a', 'b', 'cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc'], characterCount: true, icon: X}
export const AutoComplete = tmp
export const Select: Story<any> = (args: any) => <Component type="select" {...args}>
<option>a</option>
<option>b</option>
<option>c</option>
<option>d</option>
</Component>

View File

@ -5,6 +5,7 @@ import Text from '../Text'
import { IconProps } from '../interfaces' import { IconProps } from '../interfaces'
import { buildClassName } from '../Util' import { buildClassName } from '../Util'
import css from './Input.module.styl' import css from './Input.module.styl'
import Row from '../Row'
interface Props extends React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement> { interface Props extends React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement> {
id?: string id?: string
@ -37,6 +38,8 @@ interface States {
export default class Input extends React.Component<Props, States> { export default class Input extends React.Component<Props, States> {
public state: States = {}
// any because f*ck types // any because f*ck types
private inputRef: React.RefObject<any> = React.createRef() private inputRef: React.RefObject<any> = React.createRef()
private parentRef: React.RefObject<HTMLDivElement> = React.createRef() private parentRef: React.RefObject<HTMLDivElement> = React.createRef()
@ -50,12 +53,15 @@ export default class Input extends React.Component<Props, States> {
} }
if (this.props.autocomplete) { if (this.props.autocomplete) {
window.addEventListener('scroll', this.parentScroll) window.addEventListener('scroll', this.parentScroll)
this.parentScroll()
} }
} }
public componentWillUnmount() { public componentWillUnmount() {
if (this.props.autocomplete) {
window.removeEventListener('scroll', this.parentScroll) window.removeEventListener('scroll', this.parentScroll)
} }
}
public render() { public render() {
const props: Props = Object.assign({}, this.props) const props: Props = Object.assign({}, this.props)
@ -65,7 +71,9 @@ export default class Input extends React.Component<Props, States> {
delete props.opaque delete props.opaque
delete props.helper delete props.helper
delete props.infinityText delete props.infinityText
delete props.autocomplete
delete props.filled delete props.filled
delete props.iconRight
delete props.inputRef delete props.inputRef
delete props.selectRef delete props.selectRef
delete props.block delete props.block
@ -77,7 +85,7 @@ export default class Input extends React.Component<Props, States> {
ref: this.props.inputRef || this.inputRef, ref: this.props.inputRef || this.inputRef,
className: buildClassName( className: buildClassName(
[css.iconLeft, this.props.icon], [css.iconLeft, this.props.icon],
[css.iconRight, this.props.iconRight], [css.iconRight, this.props.iconRight || this.props.autocomplete],
[css.filled, this.props.filled], [css.filled, this.props.filled],
[css.opaque, this.props.opaque] [css.opaque, this.props.opaque]
), ),
@ -94,7 +102,7 @@ export default class Input extends React.Component<Props, States> {
input = ( input = (
<select <select
ref={this.props.selectRef || this.inputRef} ref={this.props.selectRef || this.inputRef}
{...this.props as React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLSelectElement>, HTMLSelectElement>} {...props as React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLSelectElement>, HTMLSelectElement>}
className={buildClassName( className={buildClassName(
[css.iconLeft, this.props.icon], [css.iconLeft, this.props.icon],
[css.iconRight, !this.props.disabled || this.props.iconRight], [css.iconRight, !this.props.disabled || this.props.iconRight],
@ -138,12 +146,6 @@ export default class Input extends React.Component<Props, States> {
> >
{input} {input}
{this.props.autocomplete && this.props.autocomplete.indexOf(this.state?.value || '') === -1 && (
<ul className={buildClassName(css.autocomplete, [css.reverse, !this.state?.isInFirstPartOfScreen])}>
{this.props.autocomplete.filter((item) => item.includes(this.state?.value || '')).map((item) => (<li key={item} onClick={this.onAutoCompleteClick(item)}><Text>{item}</Text></li>))}
</ul>
)}
{/* Process Icon */} {/* Process Icon */}
{this.props.icon && ( {this.props.icon && (
<this.props.icon className={css.left} /> <this.props.icon className={css.left} />
@ -167,6 +169,12 @@ export default class Input extends React.Component<Props, States> {
)} )}
</div> </div>
)} )}
{this.props.autocomplete && this.props.autocomplete.indexOf(this.state?.value || '') === -1 && (
<ul className={buildClassName(css.autocomplete, [css.reverse, !this.state.isInFirstPartOfScreen])}>
{this.props.autocomplete.filter((item) => item.includes(this.state?.value || '')).map((item) => (<li key={item} onClick={this.onAutoCompleteClick(item)}><Text>{item}</Text></li>))}
</ul>
)}
</div> </div>
) )
} }
@ -175,6 +183,7 @@ export default class Input extends React.Component<Props, States> {
const div = this.parentRef.current const div = this.parentRef.current
if (!div) {return} if (!div) {return}
const result = !(div.offsetTop - window.scrollY >= window.innerHeight / 2) const result = !(div.offsetTop - window.scrollY >= window.innerHeight / 2)
console.log(result, div, this.state.isInFirstPartOfScreen)
if (this.state.isInFirstPartOfScreen !== result) { if (this.state.isInFirstPartOfScreen !== result) {
this.setState({isInFirstPartOfScreen: result}) this.setState({isInFirstPartOfScreen: result})
} }

View File

@ -27,13 +27,16 @@ a
} }
/* Track */ /* Track */
::-webkit-scrollbar-corner
::-webkit-scrollbar-track ::-webkit-scrollbar-track
background $foregroundLight background $foregroundLight
transition $transition
@media (prefers-color-scheme dark) @media (prefers-color-scheme dark)
background $foregroundDark background $foregroundDark
::-webkit-scrollbar-thumb ::-webkit-scrollbar-thumb
background: darken($foregroundLight, 16%) background: darken($foregroundLight, 16%)
transition $transition
@media (prefers-color-scheme dark) @media (prefers-color-scheme dark)
background lighten($foregroundDark, 16%) background lighten($foregroundDark, 16%)
&:hover &:hover

View File

@ -64,6 +64,7 @@
], ],
"exclude": [ "exclude": [
"node_modules", "node_modules",
"build" "build",
"*.stories.tsx"
] ]
} }

1620
yarn.lock

File diff suppressed because it is too large Load Diff