Skip to canvas
Proton Design System
/
Introduction
Changelog
Colors
Icons
Layers Management
Responsive
Sass Css Variables
Typography
Alert
Autocomplete
Badge
ButtonGroup
Checkbox
Collapsible
Copy
CountrySelect
DateInput
Details
Dropdown
Dropzone
EllipsisLoader
Errors
Icon
InputButton
InputFieldSkip to canvas
InputFieldStacked
LabelStack
Logo
Meter
MiddleEllipsis
Modal
Notification
Price
Progress
Promotion Button
QuickSettings
Radio
Scale
Select
Spotlight
Table
Tabs
Toggle
TopBanner
TotpInput
VideoInstructions
Avatar
Banner
Button
Card
CircleLoader
DashboardCard
Donut
Href
InlineLinkButton
Input
Kbd
NotificationDot
Pill
ProtonLoader
Scroll
Slider
Stepper
UserAvatar
VerticalSteps
Vr
Border
Border Radius
Colors
Columns
Cursor
Divide
ExpandClickArea
Gap
HidingDisablingContent
InteractiveFocusHelper
Lists
Margin
Opacity
OpacityOnHover
Padding
Position
Print
Ratio Container
Responsive
Scroll
Shadow
Sizing
Transforms
Typography
  1. Recently opened
  2. InputFieldcomponents
  3. Back to componentsESC
  4. Clear history
Skip to sidebar
1import { useState } from 'react'; 2 3import { Button } from '@proton/atoms'; 4import { 5 Checkbox, 6 ColorPicker, 7 Icon, 8 InputFieldTwo, 9 Option, 10 PasswordInputTwo, 11 PhoneInput, 12 RadioGroup, 13 SelectTwo, 14 TextAreaTwo, 15 Toggle, 16 TotpInput, 17} from '@proton/components'; 18 19import { getTitle } from '../../helpers/title'; 20import mdx from './InputField.mdx'; 21 22export default { 23 component: InputFieldTwo, 24 title: getTitle(__filename, false), 25 parameters: { 26 docs: { 27 page: mdx, 28 }, 29 }, 30}; 31 32export const Basic = () => ( 33 <InputFieldTwo 34 label="What this input field is about" 35 hint="Any hint on filling this input field" 36 assistiveText="Assistive text explaining how to fill this input field…" 37 placeholder="Ex: example of a correct filling…" 38 title="Help displayed on hovering this input field, and read by screen readers too." 39 prefix={<Icon name="robot" />} 40 /> 41); 42 43const toggles = ['dense', 'bigger', 'unstyled', 'disabled', 'readOnly'] as const; 44 45const adornmentIds = ['none', 'text', 'select', 'icon', 'icons', 'icon button'] as const; 46 47export const Sandbox = () => { 48 const [label, setLabel] = useState<string>('Label'); 49 const [hint, setHint] = useState<string>('Hint'); 50 const [placeholder, setPlaceholder] = useState<string>('Placeholder'); 51 const [assistiveText, setAssistiveText] = useState<string>(''); 52 const [error, setError] = useState<string>(''); 53 const [warning, setWarning] = useState<string>(''); 54 const [selectedSuffixId, setSelectedSuffixId] = useState<string>('none'); 55 const [selectedPrefixId, setSelectedPrefixId] = useState<string>('none'); 56 const [selectedToggles, setSelectedToggles] = useState(toggles.map(() => false)); 57 58 const getAdornment = (id: string) => { 59 if (id === 'text') { 60 return 'text adornment'; 61 } 62 63 if (id === 'icon') { 64 return <Icon name="brand-proton" />; 65 } 66 67 if (id === 'icons') { 68 return ( 69 <> 70 <Icon name="brand-proton-mail" /> 71 <Icon name="brand-proton-calendar" /> 72 </> 73 ); 74 } 75 76 if (id === 'icon button') { 77 return ( 78 <Button 79 onClick={() => { 80 alert('Clicked!'); 81 }} 82 shape="ghost" 83 size="small" 84 icon 85 className="rounded-sm" 86 disabled={selectedToggles[toggles.indexOf('disabled')]} 87 > 88 <Icon name="brand-proton" /> 89 </Button> 90 ); 91 } 92 93 if (id === 'select') { 94 return ( 95 <SelectTwo unstyled value="Item 1" disabled={selectedToggles[toggles.indexOf('disabled')]}> 96 <Option key="1" value="Item 1" title="Item 1"> 97 Item 1 98 </Option> 99 <Option key="2" value="Item 2" title="Item 2"> 100 Item 2 101 </Option> 102 </SelectTwo> 103 ); 104 } 105 }; 106 107 return ( 108 <> 109 <div className="flex flex-1 items-center justify-center border p-7"> 110 <InputFieldTwo 111 label={label} 112 hint={hint} 113 assistiveText={assistiveText} 114 placeholder={placeholder} 115 error={error} 116 warning={warning} 117 prefix={getAdornment(selectedPrefixId)} 118 suffix={getAdornment(selectedSuffixId)} 119 {...selectedToggles.reduce<{ [key: string]: boolean }>((acc, value, i) => { 120 acc[toggles[i]] = value; 121 return acc; 122 }, {})} 123 /> 124 </div> 125 <div className="flex flex-nowrap gap-7 py-7"> 126 <div className="w-1/4"> 127 <InputFieldTwo label="Label" value={label} onValue={setLabel} /> 128 <InputFieldTwo label="Hint" value={hint} onValue={setHint} /> 129 <InputFieldTwo label="Placeholder" value={placeholder} onValue={setPlaceholder} /> 130 </div> 131 <div className="w-1/4"> 132 <InputFieldTwo label="AssistiveText" value={assistiveText} onValue={setAssistiveText} /> 133 <InputFieldTwo label="Error" value={error} onValue={setError} /> 134 <InputFieldTwo label="Warning" value={warning} onValue={setWarning} /> 135 </div> 136 <div> 137 <strong className="block mb-4">Prefix</strong> 138 <RadioGroup 139 name="selected-prefix" 140 value={selectedPrefixId} 141 onChange={setSelectedPrefixId} 142 options={adornmentIds.map((suffix) => ({ value: suffix, label: suffix }))} 143 /> 144 </div> 145 <div> 146 <strong className="block mb-4">Suffix</strong> 147 <RadioGroup 148 name="selected-suffix" 149 value={selectedSuffixId} 150 onChange={setSelectedSuffixId} 151 options={adornmentIds.map((suffix) => ({ value: suffix, label: suffix }))} 152 /> 153 </div> 154 <div> 155 <strong className="block mb-4">Toggles</strong> 156 {toggles.map((prop, i) => { 157 return ( 158 <div className="mb-2"> 159 <Checkbox 160 checked={selectedToggles[i]} 161 onChange={({ target: { checked } }) => { 162 setSelectedToggles( 163 selectedToggles.map((oldValue, otherIndex) => 164 otherIndex === i ? checked : oldValue 165 ) 166 ); 167 }} 168 > 169 {prop} 170 </Checkbox> 171 </div> 172 ); 173 })} 174 </div> 175 </div> 176 </> 177 ); 178}; 179 180export const Intermediate = () => { 181 const [value, setValue] = useState(''); 182 const placeholder = "e.g. 'John Fitzgerald'"; 183 184 return ( 185 <> 186 <InputFieldTwo label="Placeholder" placeholder={placeholder} /> 187 <InputFieldTwo label="Hint" hint={`${value.length}/100`} value={value} onValue={setValue} /> 188 <div className="mb-4"> 189 <InputFieldTwo label="Assistive Text" assistiveText="Your legal surname/s (separated by spaces)" /> 190 </div> 191 <div className="mb-4"> 192 <InputFieldTwo 193 disabled 194 label="Disabled" 195 placeholder={placeholder} 196 assistiveText="Your legal surname/s (separated by spaces)" 197 /> 198 </div> 199 <div className="mb-4"> 200 <InputFieldTwo 201 readOnly 202 label="Readonly field" 203 value="This is a value" 204 placeholder={placeholder} 205 assistiveText="Your legal surname/s (separated by spaces)" 206 /> 207 </div> 208 </> 209 ); 210}; 211 212export const Validation = () => { 213 const sharedInputProps = { 214 placeholder: "e.g. 'John Fitzgerald'", 215 }; 216 217 return ( 218 <> 219 <div className="mb-4"> 220 <InputFieldTwo 221 label="Warning as string" 222 warning="Something's not quite right here" 223 {...sharedInputProps} 224 /> 225 </div> 226 <div className="mb-4"> 227 <InputFieldTwo 228 label="Error as string" 229 error="Something's definitely not right here" 230 {...sharedInputProps} 231 /> 232 </div> 233 <div className="mb-4"> 234 <InputFieldTwo 235 label="Warning as boolean" 236 warning 237 assistiveText="Should be hidden" 238 {...sharedInputProps} 239 /> 240 </div> 241 <div> 242 <InputFieldTwo label="Error as boolean" error assistiveText="Should be hidden" {...sharedInputProps} /> 243 </div> 244 </> 245 ); 246}; 247
248export const Adornments = () => { 249 return ( 250 <> 251 <InputFieldTwo label="Input with icon prefix" prefix={<Icon name="magnifier" />} /> 252 <InputFieldTwo label="Input with text prefix" prefix="Prefix" /> 253 <InputFieldTwo 254 label="Input with icon suffix" 255 placeholder="**** **** **** ****" 256 suffix={<Icon name="credit-card" />} 257 /> 258 <InputFieldTwo label="Input with text suffix" placeholder="username" suffix="@protonmail.com" /> 259 <InputFieldTwo 260 label="Input with select suffix" 261 placeholder="username" 262 suffix={ 263 <SelectTwo unstyled value="pm.me"> 264 <Option key="pm.me" value="pm.me" title="pm.me"> 265 @pm.me 266 </Option> 267 <Option key="protonmail.com" value="protonmail.com" title="protonmail.com"> 268 @protonmail.com 269 </Option> 270 </SelectTwo> 271 } 272 /> 273 </> 274 ); 275};
276 277export const Sizes = () => { 278 const sharedInputProps = { 279 placeholder: "e.g. 'John Fitzgerald'", 280 }; 281 282 return ( 283 <> 284 <InputFieldTwo label="Default" {...sharedInputProps} /> 285 <InputFieldTwo label="Bigger" bigger {...sharedInputProps} /> 286 </> 287 ); 288}; 289 290export const Dense = () => { 291 return ( 292 <> 293 <InputFieldTwo dense label="Warning" warning="I'm a warning" /> 294 <InputFieldTwo dense label="Error" error="I'm an error" /> 295 <InputFieldTwo dense label="Assistive text" assistiveText="I'm invisible" /> 296 <InputFieldTwo dense label="Error with suffix" error="I'm an error" as={PasswordInputTwo} /> 297 </> 298 ); 299}; 300 301export const CustomElements = () => { 302 const [phone, setPhone] = useState(''); 303 const [color, setColor] = useState(''); 304 const [toggleChecked, setToggleChecked] = useState(false); 305 const [checked, setChecked] = useState(false); 306 const [totp, setTotp] = useState(''); 307 308 return ( 309 <> 310 <InputFieldTwo as={PasswordInputTwo} label="Password input" placeholder="Password" /> 311 <InputFieldTwo 312 as={PhoneInput} 313 label="Phone input" 314 placeholder="Phone number" 315 value={phone} 316 onChange={setPhone} 317 /> 318 <InputFieldTwo as={TextAreaTwo} rows={3} label="Text area" placeholder="Placeholder" /> 319 <InputFieldTwo as={SelectTwo} label="Select" placeholder="one"> 320 <Option title="one" value="one" /> 321 <Option title="two" value="two" /> 322 <Option title="three" value="three" /> 323 </InputFieldTwo> 324 <InputFieldTwo 325 as={Toggle} 326 label="Toggle" 327 checked={toggleChecked} 328 onChange={() => setToggleChecked(!toggleChecked)} 329 /> 330 <InputFieldTwo as={Checkbox} label="Checkbox" checked={checked} onChange={() => setChecked(!checked)} /> 331 <InputFieldTwo as={ColorPicker} label="Color picker" color={color} onChange={setColor} /> 332 333 <div style={{ maxWidth: 250 }}> 334 <InputFieldTwo as={TotpInput} label="TOTP input" length={6} value={totp} onValue={setTotp} /> 335 </div> 336 </> 337 ); 338};