Skip to content

Commit 7fcea55

Browse files
committed
feat: New TextInput component
1 parent 0d8c596 commit 7fcea55

File tree

4 files changed

+940
-0
lines changed

4 files changed

+940
-0
lines changed
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
import { Meta, Title, Story, Source } from '@storybook/blocks';
2+
import * as TextInputStories from './TextInput.stories';
3+
4+
<Meta title="Components/TextInput" of={TextInputStories} />
5+
6+
<Title>TextInput</Title>
7+
8+
```ts
9+
import TextInput from '@jackdomleo7/vue3-library/components/TextInput/TextInput.vue';
10+
```
11+
12+
## `v-model`
13+
14+
You can bind any string value to the `v-model` prop. This is a two-way binding, so any changes to the input will update the bound value, and vice versa.
15+
16+
```ts
17+
import { ref } from 'vue';
18+
19+
const value = ref('');
20+
```
21+
22+
```html
23+
<TextInput v-model="value" />
24+
```
25+
26+
## Props
27+
28+
### Root Class
29+
30+
- Prop: `rootClass`
31+
- Type: `string`
32+
- Default: `undefined`
33+
34+
Classes to add directly to the root element's `class` attribute.
35+
36+
### Root Style
37+
38+
- Prop: `rootStyle`
39+
- Type: `string`
40+
- Default: `undefined`
41+
42+
Styles to add directly to the root element's `style` attribute.
43+
44+
### ID
45+
46+
- Prop: `id`
47+
- Type: `string`
48+
- Required: `true`
49+
50+
The `id` of the `<input/>` and the `for` of the `<label/>` element. This may also be used in various ARIA attributes.
51+
52+
### Type
53+
54+
- Prop: `type`
55+
- Type: `"text"|"email"|"tel"|"url"|"password"|"search"`
56+
- Default: `"text"`
57+
- Extends: [`<input type />`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#input_types)
58+
59+
The type of the `<input/>` element. This component restricts the type to those that are string-based (excluding dates).
60+
61+
`type="text"`
62+
<Story of={TextInputStories.TypeText} />
63+
<br/>
64+
`type="email"`
65+
<Story of={TextInputStories.TypeEmail} />
66+
<br/>
67+
`type="url"`
68+
<Story of={TextInputStories.TypeUrl} />
69+
<br/>
70+
`type="tel"`
71+
<Story of={TextInputStories.TypeTel} />
72+
<br/>
73+
`type="password"`
74+
<Story of={TextInputStories.TypePassword} />
75+
<br/>
76+
`type="search"`
77+
<Story of={TextInputStories.TypeSearch} />
78+
79+
### Status
80+
81+
- Prop: `status`
82+
- Type: `"error"|"success"`
83+
- Default: `undefined`
84+
85+
The validation status of the input.
86+
87+
<Story of={TextInputStories.StatusSuccess} />
88+
<br/>
89+
<Story of={TextInputStories.StatusError} />
90+
91+
### Hidden Label
92+
93+
- Prop: `hiddenLabel`
94+
- Type: `boolean`
95+
- Default: `false`
96+
97+
If you want to hide the label, you will still need to set a label (for accessibility), but you can then set this prop to `true` to hide the label visually.
98+
99+
Only to be used where the context of its use is clear.
100+
101+
<Story of={TextInputStories.HiddenLabel} />
102+
103+
### Character Count
104+
105+
- Prop: `characterCount`
106+
- Type: `"ascending"|"descending"`
107+
- Default: `undefined`
108+
109+
Whether to show the character count.
110+
111+
When `characterCount="ascending"`, the character count will be an incremental counter that counts up from 0.
112+
113+
<Story of={TextInputStories.CharacterCountAscendingNoLimit} />
114+
<br/>
115+
116+
When `characterCount="ascending"` **and** a `maxlength` value has been set, the character count will be shown as `0/{maxlength}` up to the `maxlength` value.
117+
118+
<Story of={TextInputStories.CharacterCountAscending} />
119+
<br/>
120+
121+
When `characterCount="descending"` **and** a `maxlength` value has been set, the character count will be shown as `{maxlength} characters remaining` down to `0`.
122+
123+
<Story of={TextInputStories.CharacterCountDescending} />
124+
<br/>
125+
126+
When `characterCount="descending"` **without** a `maxlength` value, no counter will show because there is no limit to count down from.
127+
128+
### Fallthrough Attributes
129+
130+
Any non-prop attributes and any event listeners will fallthrough to the `<input/>` element. This means you can use any native HTML attributes that are valid for an `<input/>` element with the `type` specified. Below are just some examples.
131+
132+
#### Disabled
133+
134+
```html
135+
<TextInput disabled />
136+
```
137+
138+
<Story of={TextInputStories.Disabled} />
139+
<br/>
140+
141+
#### Readonly
142+
143+
```html
144+
<TextInput readonly />
145+
```
146+
147+
<Story of={TextInputStories.Readonly} />
148+
<br/>
149+
150+
#### Required
151+
152+
```html
153+
<TextInput required />
154+
```
155+
156+
<Story of={TextInputStories.Required} />
157+
<br/>
158+
159+
#### Minlength
160+
161+
```html
162+
<TextInput minlength />
163+
```
164+
165+
<Story of={TextInputStories.Minlength} />
166+
<br/>
167+
168+
#### Maxlength
169+
170+
```html
171+
<TextInput maxlength />
172+
```
173+
174+
<Story of={TextInputStories.Maxlength} />
175+
176+
## Slots
177+
178+
### Error
179+
180+
- Slot: `error`
181+
182+
Recommended to use with `status="error"`.
183+
184+
Single error.
185+
186+
<Story of={TextInputStories.SingleError} />
187+
<br/>
188+
189+
Multiple errors.
190+
191+
<Story of={TextInputStories.MultipleErrors} />
192+
193+
### Description
194+
195+
- Slot: `description`
196+
197+
<Story of={TextInputStories.WithDescription} />
198+
199+
## Behaviour
200+
201+
### Width
202+
203+
This component will take up the full width of the parent component by default. You can use the `rootClass` or `rootStyle` props to set a custom width.
204+
205+
## Accessibility
206+
207+
This component uses native HTML behaviour for `<input />` elements. This means that it will be keyboard navigable and screen reader friendly out of the box.
208+
209+
`aria-describedby` is added to the `<input />` element when the `description` and/or the `error` slots are used to associate this content with the input.

0 commit comments

Comments
 (0)