Skip to content

Commit

Permalink
feat(input): improve input styles
Browse files Browse the repository at this point in the history
  • Loading branch information
andresz1 committed Jun 15, 2023
1 parent 73b24d3 commit 8d14d4b
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 56 deletions.
42 changes: 9 additions & 33 deletions packages/components/input/src/Input.styles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,34 +17,30 @@ export const inputStyles = cva(
{
variants: {
intent: {
unstyled: [''],
none: [''],
neutral: ['border-sm', 'focus:ring-1', 'focus:border-outline-high', 'ring-outline-high'],
success: ['border-sm', 'focus:ring-1', 'border-success', 'ring-success'],
alert: ['border-sm', 'focus:ring-1', 'border-alert', 'ring-alert'],
error: ['border-sm', 'focus:ring-1', 'border-error', 'ring-error'],
},
isHovered: {
true: [],
false: [],
},
isDisabled: {
true: ['bg-on-surface/dim-5', 'text-on-surface/dim-3', 'cursor-not-allowed'],
false: ['bg-surface', 'text-on-surface'],
},
isLeftElementVisible: {
true: [],
true: ['pl-3xl'],
false: [],
},
isRightElementVisible: {
true: [],
true: ['pr-3xl'],
false: [],
},
isLeftAddonVisible: {
true: ['border-l-none', 'rounded-l-none'],
true: ['pl-md', 'border-l-none', 'rounded-l-none'],
false: ['rounded-l-lg'],
},
isRightAddonVisible: {
true: ['border-r-none', 'rounded-r-none'],
true: ['pr-md', 'border-r-none', 'rounded-r-none'],
false: ['rounded-r-lg'],
},
},
Expand All @@ -55,40 +51,20 @@ export const inputStyles = cva(
class: 'border-outline',
},
{
isLeftElementVisible: false,
isLeftAddonVisible: false,
class: 'pl-lg',
intent: 'neutral',
isDisabled: false,
class: 'hover:border-outline-high',
},
{
isLeftElementVisible: false,
isLeftAddonVisible: true,
class: 'pl-md',
},
{
isLeftElementVisible: true,
isLeftAddonVisible: false,
class: 'pl-3xl',
class: 'pl-lg',
},
{
isRightElementVisible: false,
isRightAddonVisible: false,
class: 'pr-lg',
},
{
isRightElementVisible: false,
isRightAddonVisible: true,
class: 'pr-md',
},
{
isRightElementVisible: true,
isRightAddonVisible: false,
class: 'pr-3xl',
},
{
intent: 'neutral',
isDisabled: false,
class: 'hover:border-outline-high',
},
],
}
)
Expand Down
9 changes: 4 additions & 5 deletions packages/components/input/src/Input.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useFormFieldState } from '@spark-ui/form-field'
import { ComponentPropsWithoutRef, forwardRef, PropsWithChildren } from 'react'
import { ComponentPropsWithoutRef, forwardRef } from 'react'

import { inputStyles, InputStylesProps } from './Input.styles'
import { useInputGroup } from './InputGroupContext'
Expand All @@ -16,16 +16,15 @@ export interface InputProps
> {}

export const Input = forwardRef<HTMLInputElement, InputProps>(
({ className, intent: intentProp, disabled: disabledProp, ...others }, ref) => {
({ className, intent: intentProp = 'neutral', disabled: disabledProp, ...others }, ref) => {
const field = useFormFieldState()
const group = useInputGroup() || {}

const { isLeftAddonVisible, isRightAddonVisible, isLeftElementVisible, isRightElementVisible } =
group
const { id, name, isInvalid, isRequired, description } = field

const intent = isInvalid ? 'error' : intentProp || 'neutral'
const isDisabled = disabledProp ?? group.isDisabled
const intent = isInvalid && intentProp !== 'none' ? 'error' : intentProp
const isDisabled = group.isDisabled ?? disabledProp

return (
<input
Expand Down
17 changes: 12 additions & 5 deletions packages/components/input/src/InputContainer.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,23 @@ export const inputContainerStyles = cva(
{
variants: {
intent: {
neutral: [
'border-outline',
'peer-hover:border-outline-high',
'peer-focus:border-outline-high',
],
neutral: ['border-outline', 'peer-focus:border-outline-high'],
success: ['border-success'],
alert: ['border-alert'],
error: ['border-error'],
},
isDisabled: {
true: [],
false: [],
},
},
compoundVariants: [
{
intent: 'neutral',
isDisabled: false,
class: 'peer-hover:border-outline-high',
},
],
}
)

Expand Down
6 changes: 4 additions & 2 deletions packages/components/input/src/InputContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ export interface InputContainerProps
}

export const InputContainer = forwardRef<HTMLDivElement, PropsWithChildren<InputContainerProps>>(
({ className, intent, asChild, ...others }, ref) => {
({ className, intent, isDisabled, asChild, ...others }, ref) => {
const Component = asChild ? Slot : 'div'

return <Component ref={ref} className={inputContainerStyles({ intent })} {...others} />
return (
<Component ref={ref} className={inputContainerStyles({ intent, isDisabled })} {...others} />
)
}
)

Expand Down
24 changes: 15 additions & 9 deletions packages/components/input/src/InputGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ export const InputGroup = forwardRef<HTMLDivElement, PropsWithChildren<InputGrou
return element ? (element.type as FC).displayName : ''
}

const findElement = (values: string[]) => {
const findElement = (...values: string[]) => {
return children.find(child => values.includes(getDisplayName(child) || ''))
}

const input = findElement(['Input', 'TextField'])
const left = findElement(['InputGroup.LeftAddon', 'InputGroup.LeftElement'])
const right = findElement(['InputGroup.RightAddon', 'InputGroup.RightElement'])
const input = findElement('Input', 'TextField')
const left = findElement('InputGroup.LeftAddon', 'InputGroup.LeftElement')
const right = findElement('InputGroup.RightAddon', 'InputGroup.RightElement')
const isLeftAddonVisible = getDisplayName(left) === 'InputGroup.LeftAddon'
const isRightAddonVisible = getDisplayName(right) === 'InputGroup.RightAddon'
const isLeftElementVisible = getDisplayName(left) === 'InputGroup.LeftElement'
Expand Down Expand Up @@ -68,22 +68,28 @@ export const InputGroup = forwardRef<HTMLDivElement, PropsWithChildren<InputGrou

{isInput ? (
<>
{cloneElement(input as any, { intent: 'unstyled' })}
<InputContainer intent={intent} />
{cloneElement(input as ReactElement, { intent: 'none' })}

<InputContainer intent={intent} isDisabled={isDisabled} />

{isLeftElementVisible && left}
{right}

{isRightElementVisible && right}
</>
) : (
cloneElement(input as any, {
cloneElement(input as ReactElement, {
intent,
children: (
<>
{isLeftElementVisible && left}
{right}

{isRightElementVisible && right}
</>
),
})
)}

{isRightAddonVisible && right}
</div>
</InputGroupContext.Provider>
)
Expand Down
2 changes: 1 addition & 1 deletion packages/components/input/src/InputLeftAddon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export type InputLeftAddonProps = InputAddonProps

export const InputLeftAddon = forwardRef<HTMLDivElement, InputLeftAddonProps>(
({ className, ...others }, ref) => {
return <InputAddon ref={ref} className={cx(className, 'pl-lg')} {...others} />
return <InputAddon ref={ref} className={cx(className, 'pl-lg rounded-l-lg')} {...others} />
}
)

Expand Down
2 changes: 1 addition & 1 deletion packages/components/input/src/InputRightAddon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export type InputRightAddonProps = InputAddonProps

export const InputRightAddon = forwardRef<HTMLDivElement, InputRightAddonProps>(
({ className, ...others }, ref) => {
return <InputAddon ref={ref} className={cx(className, 'pr-lg')} {...others} />
return <InputAddon ref={ref} className={cx(className, 'pr-lg rounded-r-lg')} {...others} />
}
)

Expand Down

0 comments on commit 8d14d4b

Please sign in to comment.