Skip to content

Commit 72ffba9

Browse files
authored
feat(form-file): Add focus styling for custom-file input (bootstrap-vue#1033)
* feat(form-file): Add focus styling for custom-file input * Update form-file.vue * [form-file] Remove wrapper div when in plain mode * add sizing to plain file input Unfortunately there doesn't appear to be an option to size the custom-file input. * Update form-file.vue
1 parent dd5ddb0 commit 72ffba9

File tree

1 file changed

+83
-24
lines changed

1 file changed

+83
-24
lines changed

lib/components/form-file.vue

Lines changed: 83 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,39 @@
11
<template>
2-
<!-- Normally this should be a <label> but IE borks out on it. Awaiting fix from MSFT -->
3-
<div :class="[custom?'custom-file':null, state?`is-${state}`:null]"
2+
<input v-if="plain"
3+
type="file"
4+
:id="safeId()"
5+
ref="input"
6+
:class="['form-control-file', sizeFormClass, stateClass]"
7+
:name="name"
8+
:disabled="disabled"
9+
:required="required"
10+
:capture="capture || null"
11+
:aria-required="required ? 'true' : null"
12+
:accept="accept || null"
13+
:multiple="multiple"
14+
:webkitdirectory="directory"
15+
@change="onFileChange">
16+
<div v-else
17+
:class="['custom-file', 'w-100', stateClass]"
418
:id="safeId('_BV_file_outer_')"
5-
@dragover.stop.prevent="dragover"
6-
>
19+
@dragover.stop.prevent="dragover">
20+
<!-- Normally this div should be label, but IE borks out if label has a file input inside. Awaiting fix from MSFT -->
721

8-
<!-- Drop Here Target -->
9-
<span class="drop-here"
10-
v-if="dragging && custom"
11-
@dragover.stop.prevent="dragover"
12-
@drop.stop.prevent="drop"
13-
@dragleave.stop.prevent="dragging=false"
14-
:data-drop="dropLabel"
15-
></span>
22+
<!-- Drop Here Target, set as label so it can be associated with input -->
23+
<label v-if="dragging"
24+
:for="safeId()"
25+
:data-drop="dropLabel"
26+
class="drop-here"
27+
@dragover.stop.prevent="dragover"
28+
@drop.stop.prevent="drop"
29+
@dragleave.stop.prevent="dragging=false"
30+
></label>
1631

1732
<!-- Real Form input -->
1833
<input type="file"
1934
:id="safeId()"
2035
ref="input"
21-
:class="[custom?'custom-file-input':'form-control-file', stateClass]"
36+
:class="['custom-file-input', 'w-100', stateClass, hasFocus?'focus':'']"
2237
:name="name"
2338
:disabled="disabled"
2439
:required="required"
@@ -27,23 +42,55 @@
2742
:accept="accept || null"
2843
:multiple="multiple"
2944
:webkitdirectory="directory"
30-
:aria-describedby="custom ? safeId('_BV_file_control_') : null"
31-
@change="onFileChange"
32-
>
45+
:aria-describedby="safeId('_BV_file_control_')"
46+
@focusin="focusHandler"
47+
@focusout="focusHandler"
48+
@change="onFileChange">
3349

3450
<!-- Overlay Labels -->
35-
<span :class="['custom-file-control',dragging?'dragging':null]"
36-
:id="safeId('_BV_file_control_')"
37-
:data-choose="computedChooseLabel"
38-
:data-selected="selectedLabel"
39-
v-if="custom"
40-
></span>
51+
<!-- this is normally a <span> but we use <label> here so we can associate it with the input -->
52+
<label :id="safeId('_BV_file_control_')"
53+
:for="safeId()"
54+
:class="['custom-file-control', dragging?'dragging':null]"
55+
:data-choose="computedChooseLabel"
56+
:data-selected="selectedLabel"
57+
></label>
4158

4259
</div>
4360
</template>
4461

4562
<style scoped>
46-
/* Are these classes needed??? bootstrap.css contains similar ones */
63+
/* Custom-file focus styling */
64+
/* regular focus styling */
65+
.custom-file-input.focus ~ .custom-file-control,
66+
.custom-file-input:focus ~ .custom-file-control {
67+
color: #495057;
68+
background-color: #fff;
69+
border-color: #80bdff;
70+
outline: none;
71+
}
72+
73+
/* Invalid focus styling */
74+
.custom-file-input.is-invalid.focus ~ .custom-file-control,
75+
.custom-file-input.is-invalid:focus ~ .custom-file-control,
76+
.was-validated .custom-file-input:invalid.focus ~ .custom-file-control,
77+
.was-validated .custom-file-input:invalid:focus ~ .custom-file-control {
78+
-webkit-box-shadow: 0 0 0 .2rem rgba(220,53,69,.25);
79+
box-shadow: 0 0 0 .2rem rgba(220,53,69,.25);
80+
border-color: #dc3545;
81+
}
82+
83+
/* valid focus styling */
84+
.custom-file-input.is-valid.focus ~ .custom-file-control,
85+
.custom-file-input.is-valid:focus ~ .custom-file-control,
86+
.was-validated .custom-file-input:valid.focus ~ .custom-file-control,
87+
.was-validated .custom-file-input:valid:focus ~ .custom-file-control {
88+
-webkit-box-shadow: 0 0 0 .2rem rgba(40,167,69,.25);
89+
box-shadow: 0 0 0 .2rem rgba(40,167,69,.25);
90+
border-color: #28a745;
91+
}
92+
93+
/* Drag/Drop handling */
4794
.custom-file-control {
4895
overflow: hidden;
4996
}
@@ -95,7 +142,8 @@
95142
data() {
96143
return {
97144
selectedFile: null,
98-
dragging: false
145+
dragging: false,
146+
hasFocus: false
99147
};
100148
},
101149
props: {
@@ -177,6 +225,17 @@
177225
}
178226
},
179227
methods: {
228+
handleFocus(evt) {
229+
// Boostrap v4.beta doesn't have focus styling for custom file input
230+
// Firefox has a borked '[type=file]:focus ~ sibling' selector, so we add
231+
// A 'focus' class to get around this bug
232+
if (this.plain || evt.type === 'focusout') {
233+
this.hasFocus = false;
234+
} else {
235+
// Add focus styling for custom file input
236+
this.hasFocus = true;
237+
}
238+
},
180239
reset() {
181240
try {
182241
// Wrapped in try in case IE < 11 craps out

0 commit comments

Comments
 (0)