Ajoute les DateField

wip-johan
Johan Girod 2021-10-18 17:48:55 +02:00
parent 2fb04ded9e
commit 90a55cc285
9 changed files with 59 additions and 74 deletions

View File

@ -1,13 +1,13 @@
import { InputProps } from 'Components/conversation/RuleInput'
import { useCallback, useMemo } from 'react'
import styled from 'styled-components'
import { DateField } from 'DesignSystem/field'
import InputSuggestions from './InputSuggestions'
export default function DateInput({
suggestions,
onChange,
missing,
id,
title,
onSubmit,
required,
value,
@ -19,11 +19,11 @@ export default function DateInput({
}, [value])
// const [currentValue, setCurrentValue] = useState(dateValue)
const handleDateChange = useCallback(
(evt) => {
if (!evt.target.value) {
(value) => {
if (!value) {
return onChange(undefined)
}
const [year, month, day] = evt.target.value.split('-')
const [year, month, day] = value.split('-')
if (+year < 1700) {
return
}
@ -49,10 +49,8 @@ export default function DateInput({
onSecondClick={() => onSubmit?.('suggestion')}
/>
)}
<DateStyledInput
className="ui__ input"
id={id}
type="date"
<DateField
label={title}
defaultValue={missing ? undefined : dateValue}
required={required}
onChange={handleDateChange}
@ -61,9 +59,3 @@ export default function DateInput({
</div>
)
}
const DateStyledInput = styled.input`
font-family: 'Roboto', sans-serif;
text-transform: uppercase;
height: inherit;
`

View File

@ -18,8 +18,8 @@ export default function TextInput({
autoFocus={autoFocus}
type="text"
label={title}
onChange={({ target }) => {
debouncedOnChange(`'${target.value}'`)
onChange={(value) => {
debouncedOnChange(`'${value}'`)
}}
description={description}
{...{

View File

@ -3,7 +3,7 @@ import React, { useCallback, useMemo, useState } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import styled, { css } from 'styled-components'
import { debounce } from '../../../utils'
import { SearchField } from 'DesignSystem/field'
import { TextField } from 'DesignSystem/field'
import { InputProps } from '../RuleInput'
export type ApiCommuneJson = {
@ -184,15 +184,13 @@ export default function Select({ onChange, value, id, missing }: InputProps) {
return (
<div>
<SearchField
<TextField
role="combobox"
errorMessage={noResult && <Trans>Cette commune n'existe pas</Trans>}
type="search"
id={id}
aria-autocomplete="list"
onBlur={submitFocusedElem}
aria-readonly="true"
className="ui__"
onKeyDown={handleKeyDown}
aria-controls="liste-commune"
label={t('Commune ou code postal')}

View File

@ -19,26 +19,14 @@ function SelectComponent({ onChange, onSubmit, options }) {
}, [options])
return (
<>
<input
<TextField
type="search"
css={`
padding: 0.4rem;
margin: 0.2rem 0;
width: 100%;
border: 1px solid var(--lighterTextColor);
border-radius: 0.3rem;
color: inherit;
font-size: inherit;
transition: border-color 0.1s;
position: relative;
:focus {
border-color: var(--color);
}
`}
placeholder={t("Saisissez votre domaine d'activité")}
onChange={(e) => {
let input = e.target.value
errorMessage={
searchResults &&
searchResults.length === 0 && <Trans>Aucun résultat</Trans>
}
onChange={(input) => {
if (input.length < 2) {
setSearchResults(undefined)
return
@ -46,11 +34,6 @@ function SelectComponent({ onChange, onSubmit, options }) {
worker.postMessage({ input })
}}
/>
{searchResults && searchResults.length === 0 && (
<p>
<Trans>Aucun résultat</Trans>
</p>
)}
{searchResults &&
searchResults.map((option) => (

View File

@ -0,0 +1,16 @@
import TextField from './TextField'
import { AriaTextFieldOptions } from '@react-aria/textfield'
export default function DateField(props: AriaTextFieldOptions) {
return (
<TextField
{...props}
css={`
text-transform: uppercase;
`}
type="date"
placeholder="JJ/MM/AAAA"
maxLength={11}
/>
)
}

View File

@ -7,6 +7,7 @@ import {
StyledDescription,
StyledInput,
StyledInputContainer,
StyledErrorMessage,
StyledLabel,
} from './TextField'
import styled from 'styled-components'
@ -14,8 +15,13 @@ import styled from 'styled-components'
export default function SearchField(props: AriaSearchFieldProps) {
const state = useSearchFieldState(props)
const ref = useRef<HTMLInputElement>(null)
const { labelProps, inputProps, descriptionProps, clearButtonProps } =
useSearchField(props, state, ref)
const {
labelProps,
inputProps,
descriptionProps,
errorMessageProps,
clearButtonProps,
} = useSearchField(props, state, ref)
return (
<StyledContainer>
@ -24,6 +30,7 @@ export default function SearchField(props: AriaSearchFieldProps) {
>
<StyledInput
{...(inputProps as InputHTMLAttributes<HTMLInputElement>)}
placeholder={inputProps.placeholder ?? ''}
ref={ref}
/>
<StyledLabel {...labelProps}>{props.label}</StyledLabel>
@ -31,8 +38,13 @@ export default function SearchField(props: AriaSearchFieldProps) {
<StyledClearButton {...clearButtonProps}>×</StyledClearButton>
)}
</StyledInputContainer>
{props.errorMessage && (
<StyledErrorMessage {...errorMessageProps}>
{props.errorMessage}
</StyledErrorMessage>
)}
{props.description && (
<StyledDescription {...descriptionProps} style={{ fontSize: 12 }}>
<StyledDescription {...descriptionProps}>
{props.description}
</StyledDescription>
)}

View File

@ -9,7 +9,6 @@ export default function TextField(props: AriaTextFieldOptions) {
const ref = useRef<HTMLInputElement>(null)
const { labelProps, inputProps, descriptionProps, errorMessageProps } =
useTextField({ ...props, inputElementType: 'input' }, ref)
return (
<StyledContainer>
<StyledInputContainer
@ -17,6 +16,7 @@ export default function TextField(props: AriaTextFieldOptions) {
>
<StyledInput
{...(inputProps as InputHTMLAttributes<HTMLInputElement>)}
placeholder={inputProps.placeholder ?? ''}
ref={ref}
/>
<StyledLabel {...labelProps}>{props.label}</StyledLabel>
@ -53,30 +53,29 @@ export const StyledInput = styled.input`
position: absolute;
padding: calc(${LABEL_HEIGHT} + ${({ theme }) => theme.spacings.xs})
${({ theme }) => theme.spacings.sm} ${({ theme }) => theme.spacings.xs};
transition: color 0.2s;
`
export const StyledLabel = styled.label`
top: 0%;
pointer-events: none;
transform: translateY(0%);
font-size: 0.75rem;
line-height: ${LABEL_HEIGHT};
font-family: ${({ theme }) => theme.fonts.main};
padding: ${({ theme }) => theme.spacings.xs}
${({ theme }) => theme.spacings.sm};
padding: ${({ theme }) => `${theme.spacings.xxs} ${theme.spacings.sm}`};
position: absolute;
will-change: transform top font-size line-height color;
transition: all 0.1s;
`
export const StyledDescription = styled(ExtraSmallBody)`
padding: ${({ theme }) => theme.spacings.xxs}
${({ theme }) => theme.spacings.sm};
padding: ${({ theme }) => `${theme.spacings.xxs} ${theme.spacings.sm}`};
will-change: color;
transition: color 0.2s;
`
const StyledErrorMessage = styled(StyledDescription)`
export const StyledErrorMessage = styled(StyledDescription)`
color: ${({ theme }) => theme.colors.extended.error[400]} !important;
`
@ -103,10 +102,12 @@ export const StyledInputContainer = styled.div<{ error: boolean }>`
color: ${({ theme }) => theme.colors.bases.primary[800]};
}
input:not(:focus):placeholder-shown + ${StyledLabel} {
${StyledInput}:not(:focus):placeholder-shown {
color: transparent;
}
${StyledInput}:not(:focus):placeholder-shown + ${StyledLabel} {
font-size: 1rem;
line-height: 1.5rem;
pointer-events: none;
top: 50%;
transform: translateY(-50%);
}

View File

@ -1,2 +1,3 @@
export { default as TextField } from './TextField'
export { default as SearchField } from './SearchField'
export { default as DateField } from './DateField'

View File

@ -181,26 +181,8 @@ function FormulairePublicodes() {
</Condition>
) : (
<>
<label htmlFor={dottedName}>
{question && (
<span
css={`
margin-top: 0.6rem;
`}
>
{question}
</span>
)}{' '}
</label>
{description && (
<Explicable>
<H3>{title}</H3>
<Markdown source={description} />
</Explicable>
)}
<RuleInput
id={dottedName}
label={question ?? title}
dottedName={dottedName as DottedName}
onChange={(value) => onChange(dottedName, value)}
/>