Skip to content

Commit

Permalink
feat: add icon and button to input
Browse files Browse the repository at this point in the history
  • Loading branch information
Virtute90 committed Jun 28, 2024
1 parent 8e9a84a commit 8ce6589
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 205 deletions.
38 changes: 27 additions & 11 deletions src/Input/Input.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import isNumber from 'is-number';
import React, {
InputHTMLAttributes,
ElementType,
Ref,
InputHTMLAttributes,
ReactNode,
Ref,
useCallback,
useState,
useEffect,
useRef,
useEffect
useState
} from 'react';
import isNumber from 'is-number';

import { InputContainer } from './InputContainer';
import { Icon } from '../Icon/Icon';
import { getTag, getFormControlClass, getClasses, getValidationTextControlClass, useFocus } from './utils';
import classNames from 'classnames';
import type { CSSModule } from 'reactstrap/types/lib/utils';
import { Icon } from '../Icon/Icon';
import { notifyDeprecation } from '../utils';
import classNames from 'classnames';
import { InputContainer } from './InputContainer';
import { getClasses, getFormControlClass, getTag, getValidationTextControlClass, useFocus } from './utils';

// taken from reactstrap types
type InputType =
Expand Down Expand Up @@ -101,6 +101,14 @@ export interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
static?: boolean;
/** Quando attivo rimuove il componente contenitore dell'Input. Utile per un controllo maggiore dello styling */
noWrapper?: boolean;
/** Indica che il componente ha un bottone a destra rispetto all'input */
hasButtonRight?: boolean;
/** Componente per il bottone */
buttonRight?: ReactNode;
/** Indica che il componente ha una icona a sinistra rispetto all'input */
hasIconLeft?: boolean;
/** Componente per l'icona */
iconLeft?: ReactNode;
testId?: string;
}

Expand Down Expand Up @@ -128,6 +136,10 @@ export const Input = ({
size,
testId,
noWrapper = false,
hasButtonRight,
buttonRight,
hasIconLeft,
iconLeft,
...attributes
}: InputProps) => {
const [isHidden, setHidden] = useState(true);
Expand Down Expand Up @@ -249,7 +261,11 @@ export const Input = ({
label,
validationTextClass,
validationText,
wrapperClass
wrapperClass,
hasButtonRight,
buttonRight,
hasIconLeft,
iconLeft
};

if (noWrapper) {
Expand Down Expand Up @@ -399,4 +415,4 @@ export const Input = ({
}

return <Tag {...rest} {...extraAttributes} className={inputClasses} {...sharedAttributes} data-testid={testId} />;
};
};
33 changes: 33 additions & 0 deletions src/Input/InputContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ export interface InputContainerProps extends HTMLAttributes<HTMLElement> {
id: string | undefined;
infoId: string | undefined;
infoText: string | undefined;
/** Indica che il componente ha un bottone a destra rispetto all'input */
hasButtonRight?: boolean;
/** Componente per il bottone */
buttonRight?: ReactNode;
/** Indica che il componente ha una icona a sinistra rispetto all'input */
hasIconLeft?: boolean;
/** Componente per l'icona */
iconLeft?: ReactNode;
testId?: string;
}

Expand All @@ -24,8 +32,33 @@ export const InputContainer: FC<InputContainerProps> = ({
validationTextClass,
validationText,
wrapperClass,
hasButtonRight,
buttonRight,
hasIconLeft,
iconLeft,
children
}) => {

if (hasButtonRight || hasIconLeft) {
return (
<div className={wrapperClass} data-testid={testId}>
<div className='input-group'>
{hasIconLeft && <span className='input-group-text'>{iconLeft}</span>}
<label htmlFor={id} className={activeClass + ' ' + extraLabelClass}>
{label}
</label>
{children}
{infoText && (
<small id={infoId} className='form-text'>
{infoText}
</small>
)}
<div className={validationTextClass}>{validationText}</div>
{hasButtonRight && <div className='input-group-append'>{buttonRight}</div>}
</div>
</div>
);
}
return (
<div className={wrapperClass} data-testid={testId}>
<label htmlFor={id} className={activeClass + ' ' + extraLabelClass}>
Expand Down
130 changes: 30 additions & 100 deletions stories/Components/Form/Input.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Meta, StoryObj } from "@storybook/react";
// @ts-ignore per il momento questo modulo non ha types
import Autocomplete from "accessible-autocomplete/react"; // Reference to https://www.npmjs.com/package/accessible-autocomplete
import React, { useState } from "react";
import { FormGroup, Icon, Input, TextArea } from "../../../src";
import { Button, FormGroup, Icon, Input, TextArea } from "../../../src";

const meta: Meta<typeof Input> = {
title: "Documentazione/Form/Input",
Expand Down Expand Up @@ -44,107 +44,37 @@ export const UtilizzoDiPlaceholderELabel: Story = {
)
};

const InputConIconaOBottoniHooks = () => {
const [isFocused1, toggleFocus1] = useState(false);
const [isFocused2, toggleFocus2] = useState(false);
const [isFocused3, toggleFocus3] = useState(false);

const toggleFocusLabel1 = () => toggleFocus1(true);
// @ts-ignore: ignore types for now
const toggleBlurLabel1 = (e) => {
if (e.target.value === "") {
toggleFocus1(!isFocused1);
}
};
const toggleFocusLabel2 = () => toggleFocus2(true);
// @ts-ignore: ignore types for now
const toggleBlurLabel2 = (e) => {
if (e.target.value === "") {
toggleFocus2(!isFocused2);
}
};
const toggleFocusLabel3 = () => toggleFocus3(true);
// @ts-ignore: ignore types for no}w
const toggleBlurLabel3 = (e) => {
if (e.target.value === "") {
toggleFocus3(!isFocused3);
}
};
return (
<div>
<div className="form-group">
<div className="input-group">
<span className="input-group-text">
<Icon icon="it-pencil" aria-hidden size="sm" />
</span>
<label htmlFor="input-group-1" className={isFocused1 ? "active" : ""}>
Con Etichetta
</label>
<input
type="text"
className={isFocused1 ? "form-control focus--mouse" : "form-control"}
onFocus={toggleFocusLabel1}
onBlur={toggleBlurLabel1}
id="input-group-1"
name="input-group-1"
/>
</div>
</div>
<div className="form-group">
<div className="input-group">
<span className="input-group-text">
<Icon icon="it-pencil" color="danger" aria-hidden size="sm" />
</span>
<label htmlFor="input-group-2" className="active">
Con Etichetta e placeholder
</label>
<input
type="text"
className={isFocused2 ? "form-control focus--mouse" : "form-control"}
onFocus={toggleFocusLabel2}
onBlur={toggleBlurLabel2}
id="input-group-2"
name="input-group-2"
placeholder="Lorem Ipsum"
/>
</div>
</div>
<div className="form-group">
<div className="input-group">
<span className="input-group-text">
<Icon icon="it-pencil" color="primary" aria-hidden size="sm" />
</span>
<label htmlFor="input-group-3" className={isFocused3 ? "active" : ""}>
Con Etichetta e bottone di tipo primary
</label>
<input
type="text"
className={isFocused3 ? "form-control focus--mouse" : "form-control"}
onFocus={toggleFocusLabel3}
onBlur={toggleBlurLabel3}
id="input-group-3"
name="input-group-3"
/>
<div className="input-group-append">
<button className="btn btn-primary" type="button" id="button-3">
Invio
</button>
</div>
</div>
</div>
</div>
);
};

export const InputConIconaOBottoni: Story = {
render: () => {
return <InputConIconaOBottoniHooks />
},
parameters: {
docs: {
canvas: { sourceState: "none" },
},
},
return (
<>
<Input
id='exampleInputIcon'
label='Campo di tipo testuale'
type='text'
hasIconLeft
iconLeft={<Icon icon='it-pencil' aria-hidden size='sm' />}
/>
<Input
id='exampleInputIconDanger'
label='Con etichetta e placeholder'
placeholder='Lorem Ipsum'
type='text'
hasIconLeft
iconLeft={<Icon icon='it-pencil' aria-hidden color='danger' size='sm' />}
/>
<Input
id='exampleInputButton'
label='Con etichetta e bottone di tipo primary'
type='text'
hasIconLeft
iconLeft={<Icon icon='it-pencil' color='primary' aria-hidden size='sm' />}
hasButtonRight
buttonRight={<Button color='primary'>Invio</Button>}
/>
</>
)
}
}


Expand Down
94 changes: 0 additions & 94 deletions stories/Documentation/Form/Input.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -43,100 +43,6 @@ In caso di necessità, è anche possibile utilizzare un ulteriore contenuto test

<Canvas of={InputStories.InputConIconaOBottoni} />

#### Codice

```tsx
const [isFocused1, toggleFocus1] = useState(false);
const [isFocused2, toggleFocus2] = useState(false);
const [isFocused3, toggleFocus3] = useState(false);

const toggleFocusLabel1 = () => toggleFocus1(true);
// @ts-ignore: ignore types for now
const toggleBlurLabel1 = (e) => {
if (e.target.value === '') {
toggleFocus1(!isFocused1);
}
};
const toggleFocusLabel2 = () => toggleFocus2(true);
// @ts-ignore: ignore types for now
const toggleBlurLabel2 = (e) => {
if (e.target.value === '') {
toggleFocus2(!isFocused2);
}
};
const toggleFocusLabel3 = () => toggleFocus3(true);
// @ts-ignore: ignore types for no}w
const toggleBlurLabel3 = (e) => {
if (e.target.value === '') {
toggleFocus3(!isFocused3);
}
};
return (
<div>
<div className='form-group'>
<div className='input-group'>
<span className='input-group-text'>
<Icon icon='it-pencil' aria-hidden size='sm' />
</span>
<label htmlFor='input-group-1' className={isFocused1 ? 'active' : ''}>
Con Etichetta
</label>
<input
type='text'
className={isFocused1 ? 'form-control focus--mouse' : 'form-control'}
onFocus={toggleFocusLabel1}
onBlur={toggleBlurLabel1}
id='input-group-1'
name='input-group-1'
/>
</div>
</div>
<div className='form-group'>
<div className='input-group'>
<span className='input-group-text'>
<Icon icon='it-pencil' color='danger' aria-hidden size='sm' />
</span>
<label htmlFor='input-group-2' className='active'>
Con Etichetta e placeholder
</label>
<input
type='text'
className={isFocused2 ? 'form-control focus--mouse' : 'form-control'}
onFocus={toggleFocusLabel2}
onBlur={toggleBlurLabel2}
id='input-group-2'
name='input-group-2'
placeholder='Lorem Ipsum'
/>
</div>
</div>
<div className='form-group'>
<div className='input-group'>
<span className='input-group-text'>
<Icon icon='it-pencil' color='primary' aria-hidden size='sm' />
</span>
<label htmlFor='input-group-3' className={isFocused3 ? 'active' : ''}>
Con Etichetta e bottone di tipo primary
</label>
<input
type='text'
className={isFocused3 ? 'form-control focus--mouse' : 'form-control'}
onFocus={toggleFocusLabel3}
onBlur={toggleBlurLabel3}
id='input-group-3'
name='input-group-3'
/>
<div className='input-group-append'>
<button className='btn btn-primary' type='button' id='button-3'>
Invio
</button>
</div>
</div>
</div>
</div>
);
```

## Input password

Per rendere più semplice l’inserimento della password, l’elemento è stato dotato di un visualizzatore dei caratteri digitati.
Expand Down

0 comments on commit 8ce6589

Please sign in to comment.