Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions futurenhs.app/assets/scss/_imports.scss
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
@import 'modules/notification-banner/notification-banner';
@import 'modules/group-privacy/group-privacy';
@import 'modules/group-teaser/group-teaser';
@import 'modules/multi-input/multi-input';

@import 'objects/objects';
@import 'utilities/utilities';
15 changes: 9 additions & 6 deletions futurenhs.app/assets/scss/modules/button/_button.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
.c-button {
@extend %nhsuk-button;

&--alt {
@extend %nhsuk-button;
background-color: $blue;
}
&--disabled {
@extend %nhsuk-button;
filter: grayscale(100%);
}
&--outline {
@extend %toggle-button;
}
Expand All @@ -18,11 +26,6 @@
}

&--themeable {
@extend %nhsuk-button-themeable
@extend %nhsuk-button-themeable;
}

}

.c-button-outline {
@extend %toggle-button;
}
18 changes: 18 additions & 0 deletions futurenhs.app/assets/scss/modules/multi-input/_multi-input.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.c-multi-input {
&-enter-button {
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top: 0;
right: 0;
height: 100%;
background: rgba(0, 0, 0, 0);
background-color: $green;
border: none;
&--disabled,
&--pressed {
filter: grayscale(100%) brightness(200%);
}
}
}
2 changes: 1 addition & 1 deletion futurenhs.app/components/blocks/KeyLinksBlock/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { useCsrf } from '@helpers/hooks/useCsrf'
import { Heading } from '@components/layouts/Heading'
import { LayoutColumnContainer } from '@components/layouts/LayoutColumnContainer'
import { LayoutColumn } from '@components/layouts/LayoutColumn'
import { Form } from '@components/forms/Form'
import { Form } from '@components/old_forms/Form'
import { SVGIcon } from '@components/generic/SVGIcon'
import { Theme } from '@appTypes/theme'
import { FormConfig } from '@appTypes/form'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useFormConfig } from '@helpers/hooks/useForm'
import { formTypes } from '@constants/forms'
import { FormConfig } from '@appTypes/form'
import { useCsrf } from '@helpers/hooks/useCsrf'
import { Form } from '@components/forms/Form'
import { Form } from '@components/old_forms/Form'

export const PendingMemberActions: (props: Props) => JSX.Element = ({
acceptAction,
Expand Down
2 changes: 1 addition & 1 deletion futurenhs.app/components/blocks/Reply/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useState, useRef, useEffect } from 'react'
import classNames from 'classnames'

import { formTypes } from '@constants/forms'
import { Form } from '@components/forms/Form'
import { Form } from '@components/old_forms/Form'
import { Accordion } from '@components/generic/Accordion'
import { SVGIcon } from '@components/generic/SVGIcon'
import forms from '@config/form-configs/index'
Expand Down
2 changes: 1 addition & 1 deletion futurenhs.app/components/blocks/TextContentBlock/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Heading } from '@components/layouts/Heading'
import { RichText } from '@components/generic/RichText'
import { LayoutColumnContainer } from '@components/layouts/LayoutColumnContainer'
import { LayoutColumn } from '@components/layouts/LayoutColumn'
import { Form } from '@components/forms/Form'
import { Form } from '@components/old_forms/Form'
import { formTypes } from '@constants/forms'
import { FormConfig } from '@appTypes/form'
import { CmsContentBlock } from '@appTypes/contentBlock'
Expand Down
46 changes: 46 additions & 0 deletions futurenhs.app/components/forms/Input.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { VMessage } from '@helpers/validation'
import { ReactNode } from 'react'

export interface Props extends React.HTMLProps<HTMLInputElement> {
validation?: Array<VMessage>
label?: string
hint?: string
children?: ReactNode
}

export const Input = ({
validation,
label,
hint,
children,
...inputProps
}: Props) => {
const isError = validation && validation.some((v) => v.error === true)
const classNames = {
input: `nhsuk-input nhsuk-u-width-full
${isError ? 'nhsuk-input--error ' : null}
${inputProps.className ?? ''}`,
hint: `nhsuk-hint ${isError ? 'nhsuk-input--error' : null}`,
wrapper: `nhsuk-form-group ${
isError ? 'nhsuk-form-group--error' : null
}`,
}

// const onChange = (e) => {}

return (
<div className={classNames.wrapper}>
{!!hint && <span className={classNames.hint}>{hint}</span>}
{!!label && <label className="nhsuk-label">{label}</label>}
{!!isError && (
<span className="nhsuk-error-message">
{validation[0].message}
</span>
)}
<div style={{ position: 'relative' }}>
{children}
<input {...inputProps} className={classNames.input} />
</div>
</div>
)
}
106 changes: 0 additions & 106 deletions futurenhs.app/components/forms/Input/index.tsx

This file was deleted.

103 changes: 103 additions & 0 deletions futurenhs.app/components/forms/MultiInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { FormEvent, KeyboardEvent, useState } from 'react'
import { Input, Props as InputProps } from './Input'
import { mdiKeyboardReturn } from '@mdi/js'
import { SVGIcon } from '@components/generic/SVGIcon'

interface Props extends InputProps {
getMulti?: (list: Array<string>) => void
}

export const MultiInput = ({ getMulti, ...inputProps }: Props) => {
const { validation } = inputProps
const [multi, setMulti] = useState<Array<string>>([])
const [value, setValue] = useState<string>('')
const [enterPress, setEnterPress] = useState<boolean>(false)

const isError = validation && validation.some((v) => v.error === true)
const hasOnKeyDown = typeof inputProps.onKeyDown === 'function'
const hasOnKeyUp = typeof inputProps.onKeyDown === 'function'
const hasOnChange = typeof inputProps.onChange === 'function'
const hasGetMulti = typeof getMulti === 'function'

const onKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
const enterKey =
(e.keyCode === 13 || e.key.toLowerCase() === 'enter') && !isError

if (enterKey) {
setEnterPress(true)
handleMulti()
}
}

const onKeyUp = (e: KeyboardEvent<HTMLInputElement>) => {
const enterKey =
(e.keyCode === 13 || e.key.toLowerCase() === 'enter') && !isError
if (enterKey) {
setEnterPress(false)
}
}

const onChange = (e: FormEvent<HTMLInputElement>) => {
const el = e.target as HTMLInputElement
setValue(el.value)
}

const handleMulti = () => {
const val = value
const arr = multi
setValue('')
if (val && !arr.includes(val)) {
const newArr = [...arr, val]
setMulti(newArr)
if (hasGetMulti) {
getMulti(newArr)
}
}
}

return (
<div style={{ position: 'relative' }}>
<Input
{...inputProps}
value={value}
onChange={(e) => {
onChange(e)
if (hasOnChange) inputProps.onChange(e)
}}
onKeyDown={(e) => {
onKeyDown(e)
if (hasOnKeyDown) inputProps.onKeyDown(e)
}}
onKeyUp={(e) => {
onKeyUp(e)
if (hasOnKeyUp) inputProps.onKeyUp(e)
}}
>
<button
disabled={isError}
onClick={handleMulti}
className={`c-multi-input-enter-button ${
enterPress
? 'c-multi-input-enter-button--pressed'
: null
} ${
isError ? 'c-multi-input-enter-button--disabled' : null
}`}
>
<SVGIcon color="#fff" material name={mdiKeyboardReturn} />
</button>
</Input>
{multi.map((text, i) => (
<div
key={text + i}
className="c-button--alt u-mr-2 u-mb-2"
onClick={() =>
setMulti(multi.filter((item) => item !== text))
}
>
{text} X
</div>
))}
</div>
)
}
9 changes: 8 additions & 1 deletion futurenhs.app/components/generic/SVGIcon/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export const SVGIcon: (props: Props) => JSX.Element = ({
className,
material,
size = '21px',
color,
}) => {
const fullPath: string = useAssetPath(url)
const xlinkHref: string = fullPath ? `${fullPath}#${name}` : `#${name}`
Expand All @@ -31,6 +32,12 @@ export const SVGIcon: (props: Props) => JSX.Element = ({
<use xlinkHref={xlinkHref} />
</svg>
) : (
<Icon path={name} title={name} size={size} className={className} />
<Icon
path={name}
color={color}
title={name}
size={size}
className={className}
/>
)
}
1 change: 1 addition & 0 deletions futurenhs.app/components/generic/SVGIcon/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export interface Props {
className?: string
material?: true
size?: string
color?: string
}

export interface State {}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Autocomplete from 'accessible-autocomplete/react'

import { getSiteUsersByTerm } from '@services/getSiteUsersByTerm'
import { RichText } from '@components/generic/RichText'
import { RemainingCharacterCount } from '@components/forms/RemainingCharacterCount'
import { RemainingCharacterCount } from '@components/old_forms/RemainingCharacterCount'
import { Option } from '@appTypes/option'
import { Service } from '@appTypes/service'

Expand Down
Loading