Skip to content

Commit

Permalink
feat: Modal and Input improvements (#530)
Browse files Browse the repository at this point in the history
  • Loading branch information
dogmar authored Oct 23, 2023
1 parent dbc0bd9 commit cdf4dea
Show file tree
Hide file tree
Showing 6 changed files with 202 additions and 120 deletions.
1 change: 1 addition & 0 deletions src/components/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ function ButtonRef(
animationName={pulse ? pulseKeyframes : undefined}
boxShadow={pulse ? '0 0 7px 2px #fff1' : undefined}
_hover={{ animationPlayState: 'paused' }}
type="button"
{...props}
/>
)
Expand Down
110 changes: 64 additions & 46 deletions src/components/Input.tsx
Original file line number Diff line number Diff line change
@@ -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'
Expand Down Expand Up @@ -95,68 +95,86 @@ 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'
: (props as any).small
? '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 (
<ExtendTheme theme={themeExtension}>
<HonorableInput
ref={ref}
endIcon={
<>
{showClearButton && props.value && (
<ClearButton
onClick={() => {
const input = inputRef?.current
hasEndIcon && (
<>
{showClearButton && props.value && (
<ClearButton
onClick={() => {
const input = inputRef?.current

if (input) {
simulateInputChange(input, '')
}
}}
/>
)}
{endIcon || suffix ? (
<>
{endIcon}
{suffix && <PrefixSuffix>{suffix}</PrefixSuffix>}
</>
) : undefined}
</>
if (input) {
simulateInputChange(input, '')
}
}}
/>
)}
{endIcon || suffix ? (
<>
{endIcon}
{suffix && <PrefixSuffix>{suffix}</PrefixSuffix>}
</>
) : undefined}
</>
)
}
startIcon={
startIcon || prefix || titleContent ? (
hasStartIcon ? (
<>
{(titleContent && (
<InputTitleContent
Expand Down
126 changes: 72 additions & 54 deletions src/components/Modal.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import { type ReactNode, type Ref, forwardRef, useEffect } from 'react'
import {
Div,
Flex,
H1,
Modal as HonorableModal,
type ModalProps,
} from 'honorable'
import { Flex, H1, Modal as HonorableModal, type ModalProps } from 'honorable'
import PropTypes from 'prop-types'

import styled, { type StyledComponentPropsWithRef } from 'styled-components'

import { type ColorKey, type SeverityExt } from '../types'

import useLockedBody from '../hooks/useLockedBody'
Expand Down Expand Up @@ -37,6 +33,8 @@ type ModalPropsType = Omit<ModalProps, 'size'> & {
actions?: ReactNode
severity?: ModalSeverity
lockBody?: boolean
asForm?: boolean
formProps?: StyledComponentPropsWithRef<'form'>
[x: string]: unknown
}

Expand Down Expand Up @@ -73,17 +71,38 @@ const sizeToWidth = {
large: 608,
} as const satisfies Record<ModalSize, number>

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<any>
Expand All @@ -97,6 +116,8 @@ function ModalRef(
setBodyLocked(lockBody && open)
}, [lockBody, open, setBodyLocked])

console.log('formprops', formProps)

return (
<HonorableModal
open={open}
Expand All @@ -108,55 +129,52 @@ function ModalRef(
maxWidth={sizeToWidth[size]}
{...props}
>
<Div
margin="large"
marginBottom={actions ? 0 : 'large'}
body1
<ModalSC
as={asForm ? 'form' : undefined}
{...(asForm ? formProps : {})}
>
{!!header && (
<Flex
ref={ref}
align="center"
justify="start"
marginBottom="large"
gap="xsmall"
>
{HeaderIcon && (
<HeaderIcon
marginTop={-2} // optically center icon
color={iconColorKey}
/>
)}
<H1
overline
color="text-xlight"
<ModalContentSC $hasActions={!!actions}>
{!!header && (
<Flex
ref={ref}
align="center"
justify="start"
marginBottom="large"
gap="xsmall"
>
{HeaderIcon && (
<HeaderIcon
marginTop={-2} // optically center icon
color={iconColorKey}
/>
)}
<H1
overline
color="text-xlight"
>
{header}
</H1>
</Flex>
)}
{children}
</ModalContentSC>
{!!actions && (
<ModalActionsSC>
<Flex
background="linear-gradient(180deg, transparent 0%, fill-one 100%);"
height={16}
/>
<Flex
padding="large"
align="center"
justify="flex-end"
backgroundColor="fill-one"
>
{header}
</H1>
</Flex>
{actions}
</Flex>
</ModalActionsSC>
)}
{children}
</Div>
{!!actions && (
<Flex
position="sticky"
direction="column"
bottom="0"
>
<Flex
background="linear-gradient(180deg, transparent 0%, fill-one 100%);"
height={16}
/>
<Flex
padding="large"
align="center"
justify="flex-end"
backgroundColor="fill-one"
>
{actions}
</Flex>
</Flex>
)}
</ModalSC>
</HonorableModal>
)
}
Expand Down
46 changes: 32 additions & 14 deletions src/stories/Input.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,28 @@ export default {
component: Input,
}

function InputSet(props: any) {
return (
<Flex
direction="column"
gap="small"
>
<Input {...props} />
<Input
startIcon={<MagnifyingGlassIcon />}
endIcon={
<CaretDownIcon
size={10}
mt={0.333}
mx="3px"
/>
}
{...props}
/>
</Flex>
)
}

function Template(args: any) {
const [inputVal, setInputVal] = useState('')

Expand All @@ -28,21 +50,17 @@ function Template(args: any) {
<Flex
direction="column"
maxWidth="400px"
gap="large"
>
<Input {...props} />
<Div marginTop="medium">
<Input
startIcon={<MagnifyingGlassIcon />}
endIcon={
<CaretDownIcon
size={10}
mt={0.333}
mx="3px"
/>
}
{...props}
/>
</Div>
<InputSet
{...props}
large
/>
<InputSet {...props} />
<InputSet
{...props}
small
/>
</Flex>
)
}
Expand Down
Loading

0 comments on commit cdf4dea

Please sign in to comment.