Skip to content

Commit

Permalink
feat: Add name property to form-related fields (#512) (#511)
Browse files Browse the repository at this point in the history
### Changes made 
- All form-related fields, such as checkbox, radio button, input, and
select, have been updated with a new optional property called name to be
usable in projects that require form handling.
- The `text` property in the `Input` component has been renamed to
`value` because it is more related to its meaning (the input's value).
- Added new functions for events such as `onClick`, `onChange`, and
`onBlur` on imputable components for better extensibility.

---

### My pull request is for
- [ ] A bugfix
- [ ] A new component
- [x] An existing component update
- [ ] Dependencies version update

### Also, it complies with the following
- [x] Updated unit tests that reach at least 90% of code coverage.
- [x] Updated interfaces, types, tuples, and enums for the impacted
component/s

---

### Screenshots
N/A
  • Loading branch information
NicolasOmar authored Dec 10, 2024
2 parents 428545f + 9d890b2 commit 83a700a
Show file tree
Hide file tree
Showing 12 changed files with 122 additions and 50 deletions.
2 changes: 1 addition & 1 deletion eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import reactRefresh from 'eslint-plugin-react-refresh'
import tseslint from 'typescript-eslint'

export default tseslint.config(
{ ignores: ['dist', 'storybook-static'] },
{ ignores: ['dist', 'storybook-static', 'coverage'] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ['**/*.{ts,tsx}'],
Expand Down
10 changes: 8 additions & 2 deletions src/components/atoms/Checkbox/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@ const CheckBox: React.FC<CheckBoxProps> = ({
style = null,
containerStyle = null,
content = null,
name,
isDisabled = null,
onChange = null
onClick,
onChange,
onBlur
}) => {
const checkboxContainerClasses = parseClasses([
'checkbox',
Expand Down Expand Up @@ -48,10 +51,13 @@ const CheckBox: React.FC<CheckBoxProps> = ({
<input
data-testid={checkboxTestId}
type='checkbox'
name={name}
className={cssClasses ?? undefined}
style={style ?? undefined}
disabled={isDisabled ?? false}
onChange={onChange ?? undefined}
onClick={onClick}
onChange={onChange}
onBlur={onBlur}
/>
{content}
</label>
Expand Down
11 changes: 8 additions & 3 deletions src/components/atoms/File/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,17 @@ const File: React.FC<FileProps> = ({
style = null,
containerStyle = null,
fileName = null,
name,
uploadIcon = { iconLabel: 'upload' },
uploadText = 'Choose a file…',
buttonOnRight = false,
isFullWidth = false,
isBoxed = false,
color = null,
size = null,
onClick = null
onClick,
onChange,
onBlur
}) => {
const fileContainerClasses = parseClasses([
'file',
Expand Down Expand Up @@ -62,10 +65,12 @@ const File: React.FC<FileProps> = ({
<input
data-testid={fileInputTestId}
type='file'
name='resume'
name={name}
className={fileInputClasses}
style={style ?? undefined}
onClick={onClick ?? undefined}
onClick={onClick}
onChange={onChange}
onBlur={onBlur}
/>
<span className='file-cta'>
{uploadIcon ? <Icon {...uploadIcon} /> : null}
Expand Down
2 changes: 1 addition & 1 deletion src/components/atoms/Input/index.mocks.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"placeholder": "Here the user will see this until you type something"
},
"withText": {
"text": "Welcome to reactive-bulma"
"value": "Welcome to reactive-bulma"
},
"redColored": {
"color": "is-danger"
Expand Down
2 changes: 1 addition & 1 deletion src/components/atoms/Input/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ describe('Input', () => {

test('Should render with a text value', () => {
const testValue = '150'
const basicProps = { ...basicExample, text: testValue } as InputProps
const basicProps = { ...basicExample, value: testValue } as InputProps

render(<Input {...basicProps} />)
const testInputWithText = screen.getByTestId(basicTestId)
Expand Down
16 changes: 10 additions & 6 deletions src/components/atoms/Input/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ const Input: React.FC<InputProps> = ({
cssClasses = null,
style = null,
type,
text = null,
value = null,
name,
placeholder = null,
isDisabled = false,
isReadonly = false,
Expand All @@ -18,8 +19,9 @@ const Input: React.FC<InputProps> = ({
isRounded = null,
isHovered = null,
isFocused = null,
onClick = null,
onChange = null
onClick,
onChange,
onBlur
}) => {
const inputClasses = parseClasses([
'input',
Expand All @@ -42,13 +44,15 @@ const Input: React.FC<InputProps> = ({
data-testid={inputTestId}
type={type}
placeholder={placeholder ?? undefined}
defaultValue={text ?? undefined}
defaultValue={value ?? undefined}
name={name}
disabled={isDisabled}
readOnly={isReadonly}
className={inputClasses}
style={style ?? undefined}
onClick={onClick ?? undefined}
onChange={onChange ?? undefined}
onClick={onClick}
onChange={onChange}
onBlur={onBlur}
/>
)
}
Expand Down
38 changes: 26 additions & 12 deletions src/components/atoms/RadioButton/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react'
import React, { useMemo } from 'react'
// TYPES & INTERFACES
import {
RadioButtonItemProps,
Expand All @@ -15,7 +15,9 @@ const renderRadioButton = (config: RadioButtonItemProps, index: number) => {
isChecked = false,
isDisabled = false,
style = null,
onChange
onClick,
onChange,
onBlur
} = config
const radioButtonTestId = testId ?? `test-radio-button-item-${index}`

Expand All @@ -31,7 +33,9 @@ const renderRadioButton = (config: RadioButtonItemProps, index: number) => {
name={name}
defaultChecked={isChecked}
disabled={isDisabled}
onClick={onClick}
onChange={onChange}
onBlur={onBlur}
/>
{label}
</label>
Expand All @@ -44,7 +48,9 @@ const RadioButton: React.FC<RadioButtonProps> = ({
containerStyle = null,
options,
name,
onChange = null
onClick,
onChange,
onBlur
}) => {
const radioButtonContainerClasses = parseClasses([
'control',
Expand All @@ -57,22 +63,30 @@ const RadioButton: React.FC<RadioButtonProps> = ({
parsedClasses: radioButtonContainerClasses
})

return (
<section
data-testid={radioButtonContainerTestId}
className={radioButtonContainerClasses}
style={containerStyle ?? undefined}
>
{options.map((_option, i) =>
const renderRadioButtons = useMemo(
() =>
options.map((_option, i) =>
renderRadioButton(
{
..._option,
name,
onChange: onChange ?? undefined
onClick,
onChange,
onBlur
},
i
)
)}
),
[options, name, onClick, onChange, onBlur]
)

return (
<section
data-testid={radioButtonContainerTestId}
className={radioButtonContainerClasses}
style={containerStyle ?? undefined}
>
{renderRadioButtons}
</section>
)
}
Expand Down
10 changes: 8 additions & 2 deletions src/components/atoms/Select/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,17 @@ const Select: React.FC<SelectProps> = ({
style = null,
containerStyle = null,
options = [],
name,
showOptions = 1,
isMultiple = false,
color = null,
size = null,
isRounded = null,
isHovered = null,
isFocused = null,
onClick = null
onClick,
onChange,
onBlur
}) => {
const containerSelectClasses = parseClasses([
'select',
Expand Down Expand Up @@ -49,6 +52,7 @@ const Select: React.FC<SelectProps> = ({
data-testid={selectTestId}
className={cssClasses ?? undefined}
style={style ?? undefined}
name={name}
multiple={isMultiple}
size={showOptions}
>
Expand All @@ -57,7 +61,9 @@ const Select: React.FC<SelectProps> = ({
data-testid={`${selectTestId}-option-${i}`}
key={id.toString()}
defaultChecked={selected ?? false}
onClick={onClick ?? undefined}
onClick={onClick}
onChange={onChange}
onBlur={onBlur}
>
{name}
</option>
Expand Down
2 changes: 1 addition & 1 deletion src/components/atoms/TextArea/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe('TextArea', () => {

test('Should render with a value', () => {
const testValue = '150'
const basicProps = { text: testValue } as TextAreaProps
const basicProps = { value: testValue } as TextAreaProps

render(<TextArea {...basicProps} />)
const testAreaWithText = screen.getByText(testValue)
Expand Down
6 changes: 4 additions & 2 deletions src/components/atoms/TextArea/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ const TextArea: React.FC<TextAreaProps> = ({
testId = null,
cssClasses = null,
style = null,
text = null,
value = null,
name,
cols = null,
rows = null,
isDisabled = false,
Expand Down Expand Up @@ -50,7 +51,8 @@ const TextArea: React.FC<TextAreaProps> = ({
return (
<textarea
data-testid={textAreaTestId}
defaultValue={text ?? undefined}
defaultValue={value ?? undefined}
name={name}
cols={cols ?? undefined}
rows={rows ?? undefined}
disabled={isDisabled}
Expand Down
45 changes: 27 additions & 18 deletions src/interfaces/atomProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import React from 'react'
import {
ElementProps,
ComposedElementProps,
ClickeableProps
ClickeableProps,
NamedInputProps,
InteractiveProps,
InteractiveOnChangeProps
} from './commonProps'
// TYPES & INTERFACES
import {
Expand Down Expand Up @@ -173,11 +176,14 @@ export interface IconProps extends ComposedElementProps {
position?: RightLeftAlignType
}

export interface InputProps extends ElementProps, ClickeableProps {
export interface InputProps
extends ElementProps,
InteractiveProps,
NamedInputProps {
/** `Attribute` `Required` What type of input will be used */
type: InputType
/** `Attribute` The value that will be shown on the input */
text?: string
value?: string
/** `Attribute` The text that will be shown if the user does not type any value */
placeholder?: string
/** `Attribute` Will disable the input */
Expand All @@ -194,8 +200,6 @@ export interface InputProps extends ElementProps, ClickeableProps {
isHovered?: boolean
/** `Styling` Will add a specific border when the input is focused by the user */
isFocused?: boolean
/** `Function` Reffers to each time the user press a key. Alone does not nothing, but can be reused for other components */
onChange?: () => void
}

export interface TextAreaProps extends Omit<InputProps, 'isRounded' | 'type'> {
Expand All @@ -218,7 +222,10 @@ export interface SelectOption {
selected?: boolean
}

export interface SelectProps extends ComposedElementProps, ClickeableProps {
export interface SelectProps
extends ComposedElementProps,
InteractiveProps,
NamedInputProps {
/** `Attribute` Indicates the options contained on the select */
options?: SelectOption[]
/** `Attribute` Indicates how many options will be shown at first glance (before looking for the whole list */
Expand All @@ -237,7 +244,10 @@ export interface SelectProps extends ComposedElementProps, ClickeableProps {
isFocused?: boolean
}

export interface FileProps extends ComposedElementProps, ClickeableProps {
export interface FileProps
extends ComposedElementProps,
InteractiveProps,
NamedInputProps {
/** `Attribute` The name of the file to be uploaded */
fileName?: string
/** `Attribute` The icon displayed in file's button" */
Expand All @@ -256,36 +266,35 @@ export interface FileProps extends ComposedElementProps, ClickeableProps {
size?: ElementSizeType
}

export interface CheckBoxProps extends ComposedElementProps {
export interface CheckBoxProps
extends ComposedElementProps,
InteractiveOnChangeProps,
NamedInputProps {
/** `Attribute` Sets checkbox's text that will be shown next to its control */
content?: ChildrenType
/** `Attribute` Will disable the checkbox */
isDisabled?: boolean
/** `Function` Click function, alone does not nothing, but can be reused for other components */
onChange?: () => void
}

export interface RadioButtonItemProps
extends Pick<ElementProps, 'testId' | 'style'> {
extends Pick<ElementProps, 'testId' | 'style'>,
InteractiveOnChangeProps,
NamedInputProps {
/** `Attribute` `Required` Sets checkbox's text*/
label: string
/** `Attribute` Sets the name that will relate this checkbox with the others */
name?: string
/** `Attribute` Shows the checkbox as checked or unchecked */
isChecked?: boolean
/** `Attribute` Will disable the checkbox */
isDisabled?: boolean
/** `Function` Click function, alone does not nothing, but can be reused for other components */
onChange?: () => void
}

export interface RadioButtonProps extends ComposedElementProps {
export interface RadioButtonProps
extends ComposedElementProps,
InteractiveOnChangeProps {
/** `Attribute` `Required` Indicates the options contained to be selected */
options: RadioButtonItemProps[]
/** `Attribute` `Required` Sets the name that will relate this checkbox with the others */
name: string
/** `Function` Click function, alone does not nothing, but can be reused for other components */
onChange?: () => void
}

export interface BreadcrumbItemProps
Expand Down
Loading

0 comments on commit 83a700a

Please sign in to comment.