Skip to content

Commit ec2bbd3

Browse files
authored
Merge pull request #365 from Sqrcz/feature/improved-input-component-flexibility
Feature: Improved FwbInput component flexibility
2 parents 8cf7c5c + 6286957 commit ec2bbd3

File tree

10 files changed

+215
-143
lines changed

10 files changed

+215
-143
lines changed

docs/components/input.md

Lines changed: 54 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
<script setup>
22
import FwbInputExample from './input/examples/FwbInputExample.vue'
3-
import FwbInputExampleSize from './input/examples/FwbInputExampleSize.vue'
43
import FwbInputExampleDisabled from './input/examples/FwbInputExampleDisabled.vue'
54
import FwbInputExampleHelper from './input/examples/FwbInputExampleHelper.vue'
6-
import FwbInputExampleBlockClasses from './input/examples/FwbInputExampleBlockClasses.vue'
75
import FwbInputExamplePrefix from './input/examples/FwbInputExamplePrefix.vue'
8-
import FwbInputExampleSuffix from './input/examples/FwbInputExampleSuffix.vue'
96
import FwbInputExampleRequired from './input/examples/FwbInputExampleRequired.vue'
7+
import FwbInputExampleSize from './input/examples/FwbInputExampleSize.vue'
8+
import FwbInputExampleStyling from './input/examples/FwbInputExampleStyling.vue'
9+
import FwbInputExampleSuffix from './input/examples/FwbInputExampleSuffix.vue'
1010
import FwbInputExampleValidation from './input/examples/FwbInputExampleValidation.vue'
1111
</script>
1212

@@ -104,33 +104,6 @@ const name = ref('')
104104
</script>
105105
```
106106

107-
## Extra CSS classes
108-
109-
Sometimes it is required to add some customization to the input or the input wrapper.
110-
By default, `class` attribute is bound to the input element. To customize the input wrapper you can use the `block-classes` property.
111-
It accepts the values as the `class` attribute
112-
113-
<fwb-input-example-block-classes />
114-
```vue
115-
<template>
116-
<fwb-input
117-
v-model="name"
118-
label="First name"
119-
placeholder="enter your first name"
120-
required
121-
class="bg-green-200"
122-
block-classes="border-2 border-green-500 p-2 rounded-lg"
123-
/>
124-
</template>
125-
126-
<script setup>
127-
import { ref } from 'vue'
128-
import { FwbInput } from 'flowbite-vue'
129-
130-
const name = ref('')
131-
</script>
132-
```
133-
134107
## Slot - Helper
135108

136109
<fwb-input-example-helper />
@@ -218,22 +191,26 @@ const query = ref('')
218191
```vue
219192
<template>
220193
<fwb-input
221-
v-model="email"
194+
v-model="name"
195+
label="Your name"
196+
placeholder="Success input"
222197
required
223-
placeholder="enter your email address"
224-
label="Email"
225198
validation-status="success"
226-
/>
199+
>
200+
<template #validationMessage>
201+
<span class="font-medium">Well done!</span> Some success message.
202+
</template>
203+
</fwb-input>
227204
<hr class="mt-4 border-0">
228205
<fwb-input
229-
v-model="email"
206+
v-model="name"
207+
label="Your name"
208+
placeholder="Error input"
230209
required
231-
placeholder="enter your email address"
232-
label="Email"
233210
validation-status="error"
234211
>
235212
<template #validationMessage>
236-
Please enter a valid email address
213+
<span class="font-medium">Oh, snapp!</span> Some error message.
237214
</template>
238215
</fwb-input>
239216
</template>
@@ -242,6 +219,44 @@ const query = ref('')
242219
import { ref } from 'vue'
243220
import { FwbInput } from 'flowbite-vue'
244221
245-
const email = ref('')
222+
const name = ref('')
246223
</script>
247224
```
225+
226+
## Styling Inputs
227+
228+
Use dedicated props to pass classes to individual elements.
229+
230+
231+
<fwb-input-example-styling />
232+
```vue
233+
<template>
234+
<fwb-input
235+
v-model="name"
236+
class="p-2 border border-black rounded-none text-a italic"
237+
input-class="p-0 text-center text-gray-700 dark:text-gray-200"
238+
label-class="text-center p-2 m-0 text-gray-900 dark:text-gray-200"
239+
label="First name"
240+
placeholder="enter your first name"
241+
wrapper-class="bg-gray-100 dark:bg-gray-800"
242+
/>
243+
</template>
244+
245+
<script setup>
246+
import { ref } from 'vue'
247+
import { FwbInput } from 'flowbite-vue'
248+
249+
const name = ref('')
250+
</script>
251+
```
252+
253+
254+
## Input component API
255+
256+
### FwbInput Props
257+
| Name | Type | Default | Description |
258+
| ------------ | ---------------- | ------- | ------------------------------------------------------------ |
259+
| wrapperClass | String \| Object | `''` | Added to main component wrapper |
260+
| labelClass | String \| Object | `''` | Added to `<label>` element. |
261+
| class | String \| Object | `''` | Added to wrapper around `<input>` element and prefix/suffix. |
262+
| inputClass | String \| Object | `''` | Added to `<input>` element. |

docs/components/input/examples/FwbInputExampleDisabled.vue

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
<template>
2-
<fwb-input
3-
v-model="name"
4-
disabled
5-
label="First name"
6-
placeholder="enter your first name"
7-
/>
2+
<div class="vp-raw">
3+
<fwb-input
4+
v-model="name"
5+
disabled
6+
label="First name"
7+
placeholder="enter your first name"
8+
/>
9+
</div>
810
</template>
911

1012
<script lang="ts" setup>

docs/components/input/examples/FwbInputExampleHelper.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
<template #helper>
99
We'll never share your details. Read our
1010
<fwb-a
11-
href="#"
1211
color="text-blue-600 dark:text-blue-500"
12+
href="#"
1313
>
1414
Privacy Policy
1515
</fwb-a>.

docs/components/input/examples/FwbInputExampleBlockClasses.vue renamed to docs/components/input/examples/FwbInputExampleStyling.vue

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22
<div class="vp-raw">
33
<fwb-input
44
v-model="name"
5+
class="p-2 border border-gray-900 rounded-none"
6+
input-class="p-0 text-center text-gray-700 dark:text-gray-200"
7+
label-class="text-center p-2 m-0 text-gray-900 dark:text-gray-200 italic"
58
label="First name"
69
placeholder="enter your first name"
7-
class="bg-green-200 dark:bg-green-700"
8-
block-classes="border-2 border-green-500 p-2 rounded-lg"
10+
wrapper-class="bg-gray-100 dark:bg-gray-800"
911
/>
1012
</div>
1113
</template>
Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,26 @@
11
<template>
22
<div class="vp-raw">
33
<fwb-input
4-
v-model="email"
4+
v-model="name"
5+
label="Your name"
6+
placeholder="Success input"
57
required
6-
placeholder="enter your email address"
7-
label="Email"
88
validation-status="success"
9-
/>
9+
>
10+
<template #validationMessage>
11+
<span class="font-medium">Well done!</span> Some success message.
12+
</template>
13+
</fwb-input>
1014
<hr class="mt-4 border-0">
1115
<fwb-input
12-
v-model="email"
16+
v-model="name"
17+
label="Your name"
18+
placeholder="Error input"
1319
required
14-
placeholder="enter your email address"
15-
label="Email"
1620
validation-status="error"
1721
>
1822
<template #validationMessage>
19-
Please enter a valid email address
23+
<span class="font-medium">Oh, snapp!</span> Some error message.
2024
</template>
2125
</fwb-input>
2226
</div>
@@ -27,5 +31,5 @@ import { ref } from 'vue'
2731
2832
import { FwbInput } from '../../../../src/index'
2933
30-
const email = ref('')
34+
const name = ref('')
3135
</script>

src/components/FwbInput/FwbInput.vue

Lines changed: 31 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
<template>
2-
<div :class="blockClasses">
2+
<div :class="wrapperClass">
33
<label
44
v-if="label"
5-
:class="labelClasses"
5+
:class="labelClass"
66
>{{ label }}</label>
7-
<div
8-
class="relative flex items-center"
9-
:class="[inputBlockClasses]"
10-
>
7+
<div :class="inputWrapperClass">
118
<div
129
v-if="$slots.prefix"
1310
class="ms-2 flex shrink-0 items-center"
@@ -17,11 +14,11 @@
1714
<input
1815
v-bind="$attrs"
1916
v-model="model"
17+
:autocomplete="autocomplete"
18+
:class="inputClass"
2019
:disabled="disabled"
21-
:type="type"
2220
:required="required"
23-
:autocomplete="autocomplete"
24-
:class="[inputClasses]"
21+
:type="type"
2522
>
2623
<div
2724
v-if="$slots.suffix"
@@ -32,69 +29,69 @@
3229
</div>
3330
<p
3431
v-if="$slots.validationMessage"
35-
:class="validationWrapperClasses"
32+
:class="validationMessageClass"
3633
>
3734
<slot name="validationMessage" />
3835
</p>
3936
<p
4037
v-if="$slots.helper"
41-
class="mt-2 text-sm text-gray-500 dark:text-gray-400"
38+
:class="helperMessageClass"
4239
>
4340
<slot name="helper" />
4441
</p>
4542
</div>
4643
</template>
4744

4845
<script lang="ts" setup>
49-
import { useVModel } from '@vueuse/core'
50-
import { twMerge } from 'tailwind-merge'
51-
import { computed, toRefs } from 'vue'
46+
47+
import { toRefs } from 'vue'
5248
5349
import { useInputClasses } from './composables/useInputClasses'
54-
import {
55-
type CommonAutoFill,
56-
type InputSize,
57-
type InputType,
58-
type ValidationStatus,
59-
validationStatusMap,
60-
} from './types'
50+
51+
import type { CommonAutoFill, InputSize, InputType, ValidationStatus } from './types'
6152
6253
interface InputProps {
54+
autocomplete?: CommonAutoFill
55+
class?: string | Record<string, boolean>
6356
disabled?: boolean
57+
inputClass?: string | Record<string, boolean>
6458
label?: string
59+
labelClass?: string | Record<string, boolean>
6560
modelValue?: string | number
6661
required?: boolean
6762
size?: InputSize
6863
type?: InputType
69-
autocomplete?: CommonAutoFill
7064
validationStatus?: ValidationStatus
71-
blockClasses?: string | string[] | Record<string, unknown>
65+
wrapperClass?: string | Record<string, boolean>
7266
}
7367
7468
defineOptions({
7569
inheritAttrs: false,
7670
})
7771
7872
const props = withDefaults(defineProps<InputProps>(), {
73+
autocomplete: 'off',
74+
class: '',
7975
disabled: false,
76+
inputClass: '',
8077
label: '',
78+
labelClass: '',
8179
modelValue: '',
8280
required: false,
8381
size: 'md',
8482
type: 'text',
85-
autocomplete: 'off',
8683
validationStatus: undefined,
87-
blockClasses: undefined,
84+
wrapperClass: '',
8885
})
8986
90-
const model = useVModel(props, 'modelValue')
91-
92-
const { inputClasses, inputBlockClasses, labelClasses } = useInputClasses(toRefs(props))
93-
94-
const validationWrapperClasses = computed(() => twMerge(
95-
'mt-2 text-sm',
96-
props.validationStatus === validationStatusMap.Success ? 'text-green-600 dark:text-green-500' : '',
97-
props.validationStatus === validationStatusMap.Error ? 'text-red-600 dark:text-red-500' : '',
87+
const model = defineModel({ type: String })
9888
99-
))
89+
const {
90+
wrapperClass,
91+
helperMessageClass,
92+
validationMessageClass,
93+
labelClass,
94+
inputWrapperClass,
95+
inputClass,
96+
} = useInputClasses(toRefs(props))
10097
</script>

0 commit comments

Comments
 (0)