From cdf4dea8eec380e7edfb7233e172164d303169aa Mon Sep 17 00:00:00 2001 From: Klink <85062+dogmar@users.noreply.github.com> Date: Mon, 23 Oct 2023 08:02:31 -0700 Subject: [PATCH] feat: Modal and Input improvements (#530) --- src/components/Button.tsx | 1 + src/components/Input.tsx | 110 ++++++++++++++++------------- src/components/Modal.tsx | 126 +++++++++++++++++++--------------- src/stories/Input.stories.tsx | 46 +++++++++---- src/stories/Modal.stories.tsx | 12 +++- src/theme.tsx | 27 ++++++-- 6 files changed, 202 insertions(+), 120 deletions(-) diff --git a/src/components/Button.tsx b/src/components/Button.tsx index a50e601e..e115589f 100644 --- a/src/components/Button.tsx +++ b/src/components/Button.tsx @@ -23,6 +23,7 @@ function ButtonRef( animationName={pulse ? pulseKeyframes : undefined} boxShadow={pulse ? '0 0 7px 2px #fff1' : undefined} _hover={{ animationPlayState: 'paused' }} + type="button" {...props} /> ) diff --git a/src/components/Input.tsx b/src/components/Input.tsx index 1922b90e..6e83175b 100644 --- a/src/components/Input.tsx +++ b/src/components/Input.tsx @@ -1,4 +1,4 @@ -import { ExtendTheme, Input as HonorableInput, mergeTheme } from 'honorable' +import { ExtendTheme, Input as HonorableInput } from 'honorable' import type { InputProps as HonorableInputProps } from 'honorable' import { type ComponentProps, type ReactNode, forwardRef, useRef } from 'react' import styled from 'styled-components' @@ -95,7 +95,46 @@ const Input = forwardRef( ...(inputProps ?? {}), ref: mergeRefs([inputRef, ...(inputProps?.ref ? [inputProps.ref] : [])]), } - let themeExtension: any = {} + const themeExtension: any = { + Input: { + Root: [ + { + paddingLeft: 0, + paddingRight: 0, + }, + ], + InputBase: [ + { + paddingLeft: prefix + ? 'xsmall' + : titleContent + ? startIcon + ? 'xsmall' + : 'small' + : 'medium', + paddingRight: suffix + ? 'xsmall' + : showClearButton || endIcon + ? 'xsmall' + : 'medium', + }, + ], + StartIcon: [ + { + ...startEndStyles, + paddingLeft: prefix || titleContent ? 0 : 'medium', + marginRight: 0, + }, + ], + EndIcon: [ + { + ...startEndStyles, + paddingRight: suffix || showClearButton ? 0 : 'medium', + marginLeft: 0, + }, + ], + }, + } const parentFillLevel = useFillLevel() const size = (props as any).large ? 'large' @@ -103,60 +142,39 @@ const Input = forwardRef( ? 'small' : 'medium' - if (suffix || showClearButton) { - themeExtension = mergeTheme(themeExtension, { - Input: { - Root: [{ paddingRight: 0 }], - EndIcon: [ - { ...startEndStyles, ...{ paddingLeft: 'xsmall', gap: 0 } }, - ], - }, - }) - } - if (prefix || titleContent) { - themeExtension = mergeTheme(themeExtension, { - Input: { - Root: [{ paddingLeft: 0 }], - StartIcon: [ - { - ...startEndStyles, - ...{ - paddingRight: titleContent && !startIcon ? 'small' : 'xsmall', - }, - }, - ], - }, - }) - } inputProps = mergeProps(useFormField()?.fieldProps ?? {}, inputProps) + const hasEndIcon = (showClearButton && props.value) || endIcon || suffix + const hasStartIcon = startIcon || prefix || titleContent return ( - {showClearButton && props.value && ( - { - const input = inputRef?.current + hasEndIcon && ( + <> + {showClearButton && props.value && ( + { + const input = inputRef?.current - if (input) { - simulateInputChange(input, '') - } - }} - /> - )} - {endIcon || suffix ? ( - <> - {endIcon} - {suffix && {suffix}} - - ) : undefined} - + if (input) { + simulateInputChange(input, '') + } + }} + /> + )} + {endIcon || suffix ? ( + <> + {endIcon} + {suffix && {suffix}} + + ) : undefined} + + ) } startIcon={ - startIcon || prefix || titleContent ? ( + hasStartIcon ? ( <> {(titleContent && ( & { actions?: ReactNode severity?: ModalSeverity lockBody?: boolean + asForm?: boolean + formProps?: StyledComponentPropsWithRef<'form'> [x: string]: unknown } @@ -73,17 +71,38 @@ const sizeToWidth = { large: 608, } as const satisfies Record +const ModalSC = styled.div((_) => ({ + position: 'relative', +})) + +const ModalContentSC = styled.div<{ $hasActions: boolean }>( + ({ theme, $hasActions }) => ({ + margin: theme.spacing.large, + marginBottom: $hasActions ? 0 : theme.spacing.large, + ...theme.partials.text.body1, + }) +) + +const ModalActionsSC = styled.div((_) => ({ + display: 'flex', + position: 'sticky', + flexDirection: 'column', + bottom: '0', +})) + function ModalRef( { children, header, actions, - form = false, open = false, + form = false, size = form ? 'large' : 'medium', onClose, severity, lockBody = true, + asForm = false, + formProps = {}, ...props }: ModalPropsType, ref: Ref @@ -97,6 +116,8 @@ function ModalRef( setBodyLocked(lockBody && open) }, [lockBody, open, setBodyLocked]) + console.log('formprops', formProps) + return ( -
- {!!header && ( - - {HeaderIcon && ( - - )} -

+ {!!header && ( + + {HeaderIcon && ( + + )} +

+ {header} +

+
+ )} + {children} + + {!!actions && ( + + + - {header} -

-
+ {actions} + + )} - {children} -
- {!!actions && ( - - - - {actions} - - - )} +
) } diff --git a/src/stories/Input.stories.tsx b/src/stories/Input.stories.tsx index 169357e0..e5fa8fe8 100644 --- a/src/stories/Input.stories.tsx +++ b/src/stories/Input.stories.tsx @@ -13,6 +13,28 @@ export default { component: Input, } +function InputSet(props: any) { + return ( + + + } + endIcon={ + + } + {...props} + /> + + ) +} + function Template(args: any) { const [inputVal, setInputVal] = useState('') @@ -28,21 +50,17 @@ function Template(args: any) { - -
- } - endIcon={ - - } - {...props} - /> -
+ + +
) } diff --git a/src/stories/Modal.stories.tsx b/src/stories/Modal.stories.tsx index c00b6095..ed9a0bdd 100644 --- a/src/stories/Modal.stories.tsx +++ b/src/stories/Modal.stories.tsx @@ -1,7 +1,7 @@ -import { Button, Div, H3, P } from 'honorable' +import { Div, H3, P } from 'honorable' import { useState } from 'react' -import { Card, FormField, Input, Modal } from '..' +import { Button, Card, FormField, Input, Modal } from '..' import { SEVERITIES } from '../components/Modal' export default { @@ -43,6 +43,7 @@ function Template(args: any) { Cancel