Skip to content

Commit 516f278

Browse files
committed
feat(MdField): create password toggle
1 parent 12bf9a5 commit 516f278

File tree

10 files changed

+171
-60
lines changed

10 files changed

+171
-60
lines changed

docs/app/pages/Components/Input/Input.vue

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
<example src="./examples/ErrorsMessages.vue" />
33
<example src="./examples/Counters.vue" />
44
<example src="./examples/Icons.vue" />
5+
<example src="./examples/InlineActions.vue" />
56

67
<template>
78
<page-container centered :title="$t('pages.input.title')">
@@ -30,7 +31,13 @@
3031
<div class="page-container-section">
3132
<h2>Icons and Clear button</h2>
3233

33-
<code-example title="Outside, inline and clear" :component="examples['icons']" />
34+
<code-example title="Outside and inline icons" :component="examples['icons']" />
35+
</div>
36+
37+
<div class="page-container-section">
38+
<h2>Inline Actions</h2>
39+
40+
<code-example title="Clear and password" :component="examples['inline-actions']" />
3441
</div>
3542
</page-container>
3643
</template>

docs/app/pages/Components/Input/examples/Icons.vue

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,6 @@
2424
<md-input />
2525
<md-icon>attach_money</md-icon>
2626
</md-field>
27-
28-
<md-field md-clearable>
29-
<label>Cleareable</label>
30-
<md-input v-model="initial" />
31-
</md-field>
3227
</div>
3328
</template>
3429

@@ -40,9 +35,6 @@
4035

4136
<script>
4237
export default {
43-
name: 'Icons',
44-
data: () => ({
45-
initial: 'Initial Value'
46-
})
38+
name: 'Icons'
4739
}
4840
</script>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<template>
2+
<div>
3+
<md-field md-clearable>
4+
<label>Cleareable</label>
5+
<md-input v-model="initial" />
6+
</md-field>
7+
8+
<md-field>
9+
<label>Password toggle</label>
10+
<md-input type="password" v-model="password" />
11+
</md-field>
12+
13+
<md-field :md-toggle-password="false">
14+
<label>Password field without toggle</label>
15+
<md-input type="password" v-model="password" />
16+
</md-field>
17+
</div>
18+
</template>
19+
20+
<style lang="scss" scoped>
21+
.md-field:last-child {
22+
margin-bottom: 40px;
23+
}
24+
</style>
25+
26+
<script>
27+
export default {
28+
name: 'Icons',
29+
data: () => ({
30+
initial: 'Initial Value',
31+
password: 'mysecurepassword'
32+
})
33+
}
34+
</script>

src/components/MdField/MdField.vue

Lines changed: 52 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,33 @@
44

55
<span class="md-count" v-if="hasCounter">{{ valueLength }} / {{ state.maxlength }}</span>
66

7-
<transition name="md-clear" appear>
8-
<md-button tabindex="-1" class="md-icon-button md-dense md-clear" @click="clearInput" v-if="hasValue && mdClearable">
7+
<transition name="md-input-action" appear>
8+
<md-button tabindex="-1" class="md-icon-button md-dense md-input-action md-clear" @click="clearInput" v-if="hasValue && mdClearable">
99
<md-clear-icon />
1010
</md-button>
1111
</transition>
12+
13+
<transition name="md-input-action" appear>
14+
<md-button tabindex="-1" class="md-icon-button md-dense md-input-action md-toggle-password" @click="togglePassword" v-if="hasPasswordToggle">
15+
<md-password-off-icon v-if="state.togglePassword" />
16+
<md-password-on-icon v-else />
17+
</md-button>
18+
</transition>
1219
</div>
1320
</template>
1421

1522
<script>
1623
import MdComponent from 'core/MdComponent'
1724
import MdClearIcon from 'core/Icons/MdClearIcon'
25+
import MdPasswordOffIcon from 'core/Icons/MdPasswordOffIcon'
26+
import MdPasswordOnIcon from 'core/Icons/MdPasswordOnIcon'
1827
1928
export default new MdComponent({
2029
name: 'MdField',
2130
components: {
22-
MdClearIcon
31+
MdClearIcon,
32+
MdPasswordOffIcon,
33+
MdPasswordOnIcon
2334
},
2435
provide: {
2536
state: {}
@@ -30,9 +41,14 @@
3041
mdCounter: {
3142
type: Boolean,
3243
default: true
44+
},
45+
mdTogglePassword: {
46+
type: Boolean,
47+
default: true
3348
}
3449
},
3550
data: () => ({
51+
showPassword: false,
3652
state: {
3753
value: null,
3854
focused: false,
@@ -42,13 +58,18 @@
4258
textarea: false,
4359
autogrow: false,
4460
maxlength: null,
61+
password: null,
62+
togglePassword: false,
4563
clear: false
4664
}
4765
}),
4866
computed: {
4967
hasCounter () {
5068
return this.mdCounter && this.state.maxlength
5169
},
70+
hasPasswordToggle () {
71+
return this.mdTogglePassword && this.state.password
72+
},
5273
hasValue () {
5374
return this.state.value && this.state.value.length > 0
5475
},
@@ -69,8 +90,9 @@
6990
'md-has-value': this.state.value && this.state.value.length > 0,
7091
'md-has-placeholder': this.state.placeholder,
7192
'md-has-textarea': this.state.textarea,
93+
'md-has-password': this.state.password,
7294
'md-autogrow': this.state.autogrow
73-
/* 'md-has-password': this.state.mdHasPassword,
95+
/* ,
7496
'md-has-select': this.state.mdHasSelect,
7597
'md-has-file': this.state.hasFile,
7698
*/
@@ -82,6 +104,9 @@
82104
this.state.clear = true
83105
await this.$nextTick()
84106
this.state.clear = false
107+
},
108+
async togglePassword () {
109+
this.state.togglePassword = !this.state.togglePassword
85110
}
86111
},
87112
created () {
@@ -158,15 +183,6 @@
158183
transition: $md-transition-stand;
159184
transition-property: font-size, color;
160185
}
161-
162-
~ .md-icon:not(.md-icon-delete) {
163-
margin-left: 12px;
164-
165-
&:after {
166-
right: 0;
167-
left: auto;
168-
}
169-
}
170186
}
171187
172188
.md-textarea {
@@ -198,6 +214,26 @@
198214
right: 0;
199215
}
200216
217+
.md-input-action {
218+
width: 24px;
219+
min-width: 24px;
220+
height: 24px;
221+
margin: 0;
222+
position: absolute;
223+
top: 20px;
224+
right: 0;
225+
transition: $md-transition-default;
226+
227+
&.md-input-action-enter-active,
228+
&.md-input-action-leave-active {
229+
opacity: 0;
230+
}
231+
232+
&.md-input-action-enter-to {
233+
opacity: 1;
234+
}
235+
}
236+
201237
> .md-icon {
202238
margin: 4px auto;
203239
position: relative;
@@ -376,19 +412,15 @@
376412
}
377413
378414
&.md-has-password {
379-
&.md-focused .md-toggle-password {
380-
color: rgba(#000, .54);
381-
}
382-
383415
.md-toggle-password {
384416
margin: 0;
385417
position: absolute;
386418
right: 0;
387419
bottom: -2px;
388-
color: rgba(#000, .38);
389420
390-
.md-ink-ripple {
391-
color: rgba(#000, .87);
421+
svg {
422+
width: 22px;
423+
height: 22px;
392424
}
393425
}
394426
}
@@ -399,24 +431,6 @@
399431
}
400432
401433
.md-clear {
402-
width: 24px;
403-
min-width: 24px;
404-
height: 24px;
405-
margin: 0;
406-
position: absolute;
407-
top: 20px;
408-
right: 0;
409-
transition: $md-transition-default;
410-
411-
&.md-clear-enter-active,
412-
&.md-clear-leave-active {
413-
opacity: 0;
414-
}
415-
416-
&.md-clear-enter-to {
417-
opacity: 1;
418-
}
419-
420434
svg {
421435
width: 17px;
422436
height: 17px;

src/components/MdField/MdFieldMixin.js

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@ import MdUuid from 'core/MdUuid'
33
export default {
44
props: {
55
value: [String, Number],
6-
type: {
7-
type: String,
8-
default: 'text'
9-
},
106
id: {
117
type: String,
128
default: 'md-field-' + MdUuid()
@@ -31,10 +27,7 @@ export default {
3127
watch: {
3228
clear (clear) {
3329
if (clear) {
34-
this.$el.value = ''
35-
this.content = ''
36-
this.setStateValue()
37-
this.$emit('input', '')
30+
this.clearField()
3831
}
3932
},
4033
placeholder () {
@@ -51,6 +44,12 @@ export default {
5144
}
5245
},
5346
methods: {
47+
clearField () {
48+
this.$el.value = ''
49+
this.content = ''
50+
this.setStateValue()
51+
this.$emit('input', '')
52+
},
5453
setStateValue () {
5554
this.state.value = this.content
5655
},

src/components/MdField/MdInput/MdInput.vue

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,43 @@
1616
1717
export default new MdComponent({
1818
name: 'MdInput',
19-
mixins: [MdFieldMixin]
19+
mixins: [MdFieldMixin],
20+
props: {
21+
type: {
22+
type: String,
23+
default: 'text'
24+
}
25+
},
26+
computed: {
27+
toggleType () {
28+
return this.state.togglePassword
29+
}
30+
},
31+
watch: {
32+
type (type) {
33+
this.setPassword()
34+
},
35+
toggleType (toggle) {
36+
if (toggle) {
37+
this.setTypeText()
38+
} else {
39+
this.setTypePassword()
40+
}
41+
}
42+
},
43+
methods: {
44+
setPassword () {
45+
this.state.password = this.type === 'password'
46+
},
47+
setTypePassword () {
48+
this.$el.type = 'password'
49+
},
50+
setTypeText () {
51+
this.$el.type = 'text'
52+
}
53+
},
54+
created () {
55+
this.setPassword()
56+
}
2057
})
2158
</script>

src/components/MdField/MdTextarea/MdTextarea.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template>
22
<textarea
3-
v-bind="{ type, id, disabled, required, placeholder, readonly, maxlength }"
3+
v-bind="{ id, disabled, required, placeholder, readonly, maxlength }"
44
v-model="content"
55
class="md-textarea"
66
@focus="onFocus"

src/components/MdField/theme.scss

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
}
2020

2121
.md-clear {
22-
background-color: rgba(#000, .26);
22+
background-color: rgba(#000, .2);
2323
}
2424

2525
&.md-focused,
@@ -66,7 +66,7 @@
6666
}
6767

6868
.md-clear {
69-
background-color: rgba(#fff, .26);
69+
background-color: rgba(#fff, .2);
7070
}
7171

7272
&.md-focused,

src/core/Icons/MdPasswordOffIcon.vue

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<template>
2+
<md-icon class="md-icon-image">
3+
<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
4+
<path d="M0 0h24v24H0zm0 0h24v24H0zm0 0h24v24H0zm0 0h24v24H0z" fill="none"/>
5+
<path d="M12 7c2.76 0 5 2.24 5 5 0 .65-.13 1.26-.36 1.83l2.92 2.92c1.51-1.26 2.7-2.89 3.43-4.75-1.73-4.39-6-7.5-11-7.5-1.4 0-2.74.25-3.98.7l2.16 2.16C10.74 7.13 11.35 7 12 7zM2 4.27l2.28 2.28.46.46C3.08 8.3 1.78 10.02 1 12c1.73 4.39 6 7.5 11 7.5 1.55 0 3.03-.3 4.38-.84l.42.42L19.73 22 21 20.73 3.27 3 2 4.27zM7.53 9.8l1.55 1.55c-.05.21-.08.43-.08.65 0 1.66 1.34 3 3 3 .22 0 .44-.03.65-.08l1.55 1.55c-.67.33-1.41.53-2.2.53-2.76 0-5-2.24-5-5 0-.79.2-1.53.53-2.2zm4.31-.78l3.15 3.15.02-.16c0-1.66-1.34-3-3-3l-.17.01z"/>
6+
</svg>
7+
</md-icon>
8+
</template>
9+
10+
<script>
11+
export default {
12+
name: 'MdPasswordOffIcon'
13+
}
14+
</script>

0 commit comments

Comments
 (0)