Skip to content

Commit 409fa95

Browse files
johnleiderKaelWD
andauthored
feat(VField/VInput): add new props icon-color and glow (#21076)
resolves #17763 Co-authored-by: Kael <[email protected]>
1 parent 44be603 commit 409fa95

File tree

8 files changed

+58
-7
lines changed

8 files changed

+58
-7
lines changed

packages/api-generator/src/locale/en/VField.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
"clearIcon": "The icon used when the **clearable** prop is set to true.",
77
"dirty": "Manually apply the dirty state styling.",
88
"disabled": "Removes the ability to click or target the input.",
9+
"glow": "Makes prepend/append icons full opacity when the field is focused.",
910
"error": "Puts the input in a manual error state.",
1011
"flat": "Removes box shadow when using a variant with elevation.",
12+
"iconColor": "Sets the color of the prepend/append icons.",
1113
"id": "Sets the DOM id on the component.",
1214
"persistentClear": "Always show the clearable icon when the input is dirty (By default it only shows on hover).",
1315
"prependInnerIcon": "Creates a [v-icon](/api/v-icon/) component in the **prepend-inner** slot.",

packages/api-generator/src/locale/en/VInput.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
{
22
"props": {
33
"backgroundColor": "Changes the background-color of the input.",
4+
"baseColor": "Sets the color of the input when it is not focused.",
45
"centerAffix": "Vertically align **appendInner**, **prependInner**, **clearIcon** and **label** in the center.",
56
"direction": "Changes the direction of the input.",
67
"hideDetails": "Hides hint and validation errors. When set to `auto` messages will be rendered only if there's a message (hint, error message, counter value etc) to display.",
78
"hideSpinButtons": "Hides spin buttons on the input when type is set to `number`.",
89
"dense": "Reduces the input height.",
10+
"glow": "Makes prepend/append icons full opacity when the input is focused.",
911
"height": "Sets the height of the input.",
1012
"hint": "Displays hint text below the input when focused. Force this always open with the [persistent-hint](#props-persistent-hint) property.",
13+
"iconColor": "Sets the color of the prepend/append icons.",
1114
"id": "Sets the DOM id on the component.",
1215
"loading": "Displays linear progress bar. Can either be a String which specifies which color is applied to the progress bar (any material color or theme color - **primary**, **secondary**, **success**, **info**, **warning**, **error**) or a Boolean which uses the component **color** (set by color prop - if it's supported by the component) or the primary color.",
1316
"persistentHint": "Forces [hint](#props-hint) to always be visible.",

packages/docs/src/data/new-in.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,18 @@
1414
"text": "3.2.0"
1515
}
1616
},
17+
"VField": {
18+
"props": {
19+
"iconColor": "3.8.0",
20+
"glow": "3.8.0"
21+
}
22+
},
23+
"VInput": {
24+
"props": {
25+
"iconColor": "3.8.0",
26+
"glow": "3.8.0"
27+
}
28+
},
1729
"VListItem": {
1830
"props": {
1931
"baseColor": "3.3.0"

packages/vuetify/src/components/VField/VField.sass

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,8 @@
213213
opacity: var(--v-medium-emphasis-opacity)
214214

215215
.v-field--disabled &,
216-
.v-field--error &
216+
.v-field--error &,
217+
.v-field--glow.v-field--focused &
217218
> .v-icon
218219
opacity: 1
219220

packages/vuetify/src/components/VField/VField.tsx

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,10 @@ export const makeVFieldProps = propsFactory({
7070
type: Boolean,
7171
default: null,
7272
},
73+
glow: Boolean,
7374
error: Boolean,
7475
flat: Boolean,
76+
iconColor: [Boolean, String],
7577
label: String,
7678
persistentClear: Boolean,
7779
prependInnerIcon: IconValue,
@@ -145,13 +147,19 @@ export const VField = genericComponent<new <T>(
145147
const floatingLabelRef = ref<VFieldLabel>()
146148
const controlRef = ref<HTMLElement>()
147149
const isPlainOrUnderlined = computed(() => ['plain', 'underlined'].includes(props.variant))
148-
149-
const { backgroundColorClasses, backgroundColorStyles } = useBackgroundColor(toRef(props, 'bgColor'))
150-
const { textColorClasses, textColorStyles } = useTextColor(computed(() => {
150+
const color = computed(() => {
151151
return props.error || props.disabled ? undefined
152152
: isActive.value && isFocused.value ? props.color
153153
: props.baseColor
154-
}))
154+
})
155+
const iconColor = computed(() => {
156+
if (!props.iconColor) return undefined
157+
158+
return props.iconColor === true ? color.value : props.iconColor
159+
})
160+
161+
const { backgroundColorClasses, backgroundColorStyles } = useBackgroundColor(toRef(props, 'bgColor'))
162+
const { textColorClasses, textColorStyles } = useTextColor(color)
155163

156164
watch(isActive, val => {
157165
if (hasFloatingLabel.value) {
@@ -235,6 +243,7 @@ export const VField = genericComponent<new <T>(
235243
'v-field--disabled': props.disabled,
236244
'v-field--dirty': props.dirty,
237245
'v-field--error': props.error,
246+
'v-field--glow': props.glow,
238247
'v-field--flat': props.flat,
239248
'v-field--has-background': !!props.bgColor,
240249
'v-field--persistent-clear': props.persistentClear,
@@ -274,6 +283,7 @@ export const VField = genericComponent<new <T>(
274283
<InputIcon
275284
key="prepend-icon"
276285
name="prependInner"
286+
color={ iconColor.value }
277287
/>
278288
)}
279289

@@ -359,6 +369,7 @@ export const VField = genericComponent<new <T>(
359369
<InputIcon
360370
key="append-icon"
361371
name="appendInner"
372+
color={ iconColor.value }
362373
/>
363374
)}
364375
</div>

packages/vuetify/src/components/VInput/InputIcon.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ type Listeners<T extends {}, U = keyof T> = U extends `onClick:${infer V extends
2626
export function useInputIcon<T extends {}, K extends names = Listeners<T>> (props: T & InputIconProps<K>) {
2727
const { t } = useLocale()
2828

29-
function InputIcon ({ name }: { name: Extract<names, K> }) {
29+
function InputIcon ({ name, color }: { name: Extract<names, K>, color?: string }) {
3030
const localeKey = {
3131
prepend: 'prependAction',
3232
prependInner: 'prependAction',
@@ -54,6 +54,7 @@ export function useInputIcon<T extends {}, K extends names = Listeners<T>> (prop
5454
aria-label={ label }
5555
onClick={ listener }
5656
onKeydown={ onKeydown }
57+
color={ color }
5758
/>
5859
)
5960
}

packages/vuetify/src/components/VInput/VInput.sass

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@
6161
opacity: var(--v-medium-emphasis-opacity)
6262

6363
.v-input--disabled &,
64-
.v-input--error &
64+
.v-input--error &,
65+
.v-input--glow.v-input--focused &
6566
> .v-icon,
6667
.v-messages
6768
opacity: 1

packages/vuetify/src/components/VInput/VInput.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,14 @@ export interface VInputSlot {
4040
export const makeVInputProps = propsFactory({
4141
id: String,
4242
appendIcon: IconValue,
43+
baseColor: String,
4344
centerAffix: {
4445
type: Boolean,
4546
default: true,
4647
},
48+
color: String,
49+
glow: Boolean,
50+
iconColor: [Boolean, String],
4751
prependIcon: IconValue,
4852
hideDetails: [Boolean, String] as PropType<boolean | 'auto'>,
4953
hideSpinButtons: Boolean,
@@ -137,6 +141,18 @@ export const VInput = genericComponent<new <T>(
137141
validate,
138142
}))
139143

144+
const color = computed(() => {
145+
return props.error || props.disabled ? undefined
146+
: props.focused ? props.color
147+
: props.baseColor
148+
})
149+
150+
const iconColor = computed(() => {
151+
if (!props.iconColor) return undefined
152+
153+
return props.iconColor === true ? color.value : props.iconColor
154+
})
155+
140156
const messages = computed(() => {
141157
if (props.errorMessages?.length || (!isPristine.value && errorMessages.value.length)) {
142158
return errorMessages.value
@@ -163,6 +179,8 @@ export const VInput = genericComponent<new <T>(
163179
`v-input--${props.direction}`,
164180
{
165181
'v-input--center-affix': props.centerAffix,
182+
'v-input--focused': props.focused,
183+
'v-input--glow': props.glow,
166184
'v-input--hide-spin-buttons': props.hideSpinButtons,
167185
},
168186
densityClasses.value,
@@ -184,6 +202,7 @@ export const VInput = genericComponent<new <T>(
184202
<InputIcon
185203
key="prepend-icon"
186204
name="prepend"
205+
color={ iconColor.value }
187206
/>
188207
)}
189208
</div>
@@ -201,6 +220,7 @@ export const VInput = genericComponent<new <T>(
201220
<InputIcon
202221
key="append-icon"
203222
name="append"
223+
color={ iconColor.value }
204224
/>
205225
)}
206226

0 commit comments

Comments
 (0)