wave-ui 1.52.0 → 1.53.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,15 +13,10 @@ component(
13
13
  //- Left label.
14
14
  template(v-if="labelPosition === 'left'")
15
15
  label.w-input__label.w-input__label--left.w-form-el-shakable(
16
- v-if="$slots.default"
16
+ v-if="$slots.default || label"
17
17
  :for="`w-input--${_uid}`"
18
- :class="validationClasses")
19
- slot
20
- label.w-input__label.w-input__label--left.w-form-el-shakable(
21
- v-else-if="label"
22
- :for="`w-input--${_uid}`"
23
- :class="validationClasses"
24
- v-html="label")
18
+ :class="labelClasses")
19
+ slot {{ label }}
25
20
 
26
21
  //- Input wrapper.
27
22
  .w-input__input-wrap(:class="inputWrapClasses")
@@ -81,15 +76,10 @@ component(
81
76
 
82
77
  template(v-if="labelPosition === 'inside' && showLabelInside")
83
78
  label.w-input__label.w-input__label--inside.w-form-el-shakable(
84
- v-if="$slots.default"
85
- :for="`w-input--${_uid}`"
86
- :class="validationClasses")
87
- slot
88
- label.w-input__label.w-input__label--inside.w-form-el-shakable(
89
- v-else-if="label"
79
+ v-if="$slots.default || label"
90
80
  :for="`w-input--${_uid}`"
91
- v-html="label"
92
- :class="validationClasses")
81
+ :class="labelClasses")
82
+ slot {{ label }}
93
83
  w-icon.w-input__icon.w-input__icon--inner-right(
94
84
  v-if="innerIconRight"
95
85
  tag="label"
@@ -117,15 +107,10 @@ component(
117
107
  //- Right label.
118
108
  template(v-if="labelPosition === 'right'")
119
109
  label.w-input__label.w-input__label--right.w-form-el-shakable(
120
- v-if="$slots.default"
121
- :for="`w-input--${_uid}`"
122
- :class="validationClasses")
123
- slot
124
- label.w-input__label.w-input__label--right.w-form-el-shakable(
125
- v-else-if="label"
110
+ v-if="$slots.default || label"
126
111
  :for="`w-input--${_uid}`"
127
- :class="validationClasses"
128
- v-html="label")
112
+ :class="labelClasses")
113
+ slot {{ label }}
129
114
  </template>
130
115
 
131
116
  <script>
@@ -146,12 +131,12 @@ export default {
146
131
  labelPosition: { type: String, default: 'inside' },
147
132
  innerIconLeft: { type: String },
148
133
  innerIconRight: { type: String },
149
- // When label is inside, allows to move the label above on focus or when filled.
150
- staticLabel: { type: Boolean },
134
+ staticLabel: { type: Boolean }, // When label is inside, fix the label above.
151
135
  placeholder: { type: String },
152
136
  color: { type: String, default: 'primary' },
153
- progressColor: { type: String },
154
137
  bgColor: { type: String },
138
+ labelColor: { type: String, default: 'primary' },
139
+ progressColor: { type: String },
155
140
  minlength: { type: [Number, String] },
156
141
  maxlength: { type: [Number, String] },
157
142
  step: { type: [Number, String] },
@@ -237,7 +222,7 @@ export default {
237
222
  },
238
223
 
239
224
  overallFilesProgress () {
240
- const progress = this.inputFiles.reduce((total, file) => total + file.progress, 0)
225
+ const progress = +this.inputFiles.reduce((total, file) => total + file.progress, 0)
241
226
  const total = progress / this.inputFiles.length
242
227
  this.$emit('update:overallProgress', this.inputFiles.length ? total : undefined)
243
228
 
@@ -269,15 +254,9 @@ export default {
269
254
  }
270
255
  },
271
256
 
272
- validationClasses () {
273
- return this.isFocused && {
274
- [this.valid === false ? 'error' : this.color]: this.color || this.valid === false
275
- }
276
- },
277
-
278
257
  inputWrapClasses () {
279
258
  return {
280
- [this.valid === false ? 'error' : this.color]: this.color || this.valid === false,
259
+ [this.valid === false ? this.validationColor : this.color]: this.color || this.valid === false,
281
260
  [`${this.bgColor}--bg`]: this.bgColor,
282
261
  'w-input__input-wrap--file': this.type === 'file',
283
262
  'w-input__input-wrap--round': this.round,
@@ -635,8 +614,6 @@ $inactive-color: #777;
635
614
  .w-input--filled.w-input--floating-label.w-input--inner-icon-left & {left: 0;}
636
615
  // Chrome & Safari - Must remain in a separated rule as Firefox discard the whole rule seeing -webkit-.
637
616
  .w-input--floating-label.w-input--inner-icon-left .w-input__input:-webkit-autofill & {left: 0;}
638
-
639
- .w-input--focused & {color: currentColor;}
640
617
  }
641
618
  }
642
619
  </style>
@@ -88,6 +88,14 @@ export default {
88
88
  // alignRight, noPosition, zIndex, activator.
89
89
  },
90
90
 
91
+ provide () {
92
+ return {
93
+ // If a detachable is used inside a w-menu without an appendTo, default to the menu element
94
+ // instead of the w-app.
95
+ detachableDefaultRoot: () => this.$refs.detachable?.$el || this.$refs.detachable || null
96
+ }
97
+ },
98
+
91
99
  emits: ['input', 'update:modelValue', 'open', 'close'],
92
100
 
93
101
  data: () => ({
@@ -1,7 +1,9 @@
1
1
  <template lang="pug">
2
2
  transition(:name="transitionName" appear)
3
3
  .w-notification(v-if="show" :class="classes" :style="styles")
4
- w-alert.white--bg(v-bind="alertProps" @input="$emit('update:modelValue', false);$emit('input', false)")
4
+ w-alert.white--bg(
5
+ v-bind="alertProps"
6
+ @input="$emit('update:modelValue', false);$emit('input', false)")
5
7
  slot
6
8
  </template>
7
9
 
@@ -1,9 +1,9 @@
1
1
  <template lang="pug">
2
- transition(name="fade" appear @after-leave="onClosed")
2
+ transition(name="fade" appear @after-leave="onClose")
3
3
  .w-overlay(
4
4
  v-if="showOverlay"
5
- v-show="value"
6
- :style="(value && styles) || null"
5
+ ref="overlay"
6
+ :style="styles || null"
7
7
  @keydown.escape.stop="onClick"
8
8
  @click="onClick"
9
9
  v-focus
@@ -25,7 +25,15 @@ export default {
25
25
  persistentNoAnimation: { type: Boolean }
26
26
  },
27
27
 
28
- emits: ['input', 'update:modelValue', 'click', 'close', 'closed'],
28
+ provide () {
29
+ return {
30
+ // If a detachable is used inside a w-overlay without an appendTo, default to the overlay element
31
+ // instead of the w-app.
32
+ detachableDefaultRoot: () => this.$refs.overlay || null
33
+ }
34
+ },
35
+
36
+ emits: ['input', 'update:modelValue', 'click', 'before-close', 'close'],
29
37
 
30
38
  data: () => ({
31
39
  persistentAnimate: false,
@@ -60,21 +68,19 @@ export default {
60
68
  setTimeout(() => (this.persistentAnimate = false), 150) // Must match CSS animation duration.
61
69
  }
62
70
  else if (!this.persistent) {
63
- this.$emit('update:modelValue', false)
64
- this.$emit('input', false)
65
- this.$emit('close')
71
+ this.showOverlay = false
72
+ this.$emit('before-close')
66
73
  }
67
74
 
68
75
  this.$emit('click', e)
69
76
  },
70
77
 
71
- // Wait until the end of the closing transition to unmount the components it contains.
72
- // This way, in case of w-select in w-dialog, the w-select will only remove its activator
73
- // element from the DOM once the dialog is completely closed.
74
- // https://github.com/antoniandre/wave-ui/issues/82
75
- onClosed () {
76
- this.showOverlay = false
77
- this.$emit('closed')
78
+ // Wait until the end of the closing transition (v-show) to completely unmount (v-if).
79
+ // The onClose method is called twice from the transition: once for the v-show, and once for the v-if.
80
+ onClose () {
81
+ this.$emit('update:modelValue', false)
82
+ this.$emit('input', false)
83
+ this.$emit('close') // Only emit once.
78
84
  }
79
85
  },
80
86
 
@@ -84,7 +90,7 @@ export default {
84
90
 
85
91
  watch: {
86
92
  value (bool) {
87
- if (bool) this.showOverlay = true
93
+ if (this.showOverlay !== bool) this.showOverlay = bool
88
94
  }
89
95
  }
90
96
  }
@@ -20,16 +20,20 @@ component(
20
20
  :aria-checked="inputValue || 'false'"
21
21
  role="radio")
22
22
  template(v-if="hasLabel && labelOnLeft")
23
- label.w-radio__label.w-form-el-shakable.pr2(v-if="$slots.default" :for="`w-radio--${_uid}`")
24
- slot
25
- label.w-radio__label.w-form-el-shakable.pr2(v-else-if="label" :for="`w-radio--${_uid}`" v-html="label")
23
+ label.w-radio__label.w-form-el-shakable.pr2(
24
+ v-if="$slots.default || label"
25
+ :for="`w-radio--${_uid}`"
26
+ :class="labelClasses")
27
+ slot {{ label }}
26
28
  .w-radio__input(
27
29
  @click="$refs.input.focus();$refs.input.click()"
28
30
  :class="this.color")
29
31
  template(v-if="hasLabel && !labelOnLeft")
30
- label.w-radio__label.w-form-el-shakable.pl2(v-if="$slots.default" :for="`w-radio--${_uid}`")
31
- slot
32
- label.w-radio__label.w-form-el-shakable.pl2(v-else-if="label" :for="`w-radio--${_uid}`" v-html="label")
32
+ label.w-radio__label.w-form-el-shakable.pl2(
33
+ v-if="$slots.default || label"
34
+ :for="`w-radio--${_uid}`"
35
+ :class="labelClasses")
36
+ slot {{ label }}
33
37
  </template>
34
38
 
35
39
  <script>
@@ -48,6 +52,7 @@ export default {
48
52
  label: { type: String },
49
53
  labelOnLeft: { type: Boolean },
50
54
  color: { type: String, default: 'primary' },
55
+ labelColor: { type: String, default: 'primary' },
51
56
  noRipple: { type: Boolean }
52
57
  // Props from mixin: name, disabled, readonly, required, tabindex, validators.
53
58
  // Computed from mixin: inputName, isDisabled & isReadonly.
@@ -15,26 +15,16 @@ component(
15
15
  @focus="$emit('focus', $event)"
16
16
  :name="inputName"
17
17
  :value="item.value === value"
18
- :label="item.label"
19
- :label-on-left="labelOnLeft"
20
- :color="item.color"
18
+ v-bind="{ label: item.label, color: item.color, labelOnLeft, labelColor }"
21
19
  :disabled="isDisabled || null"
22
20
  :readonly="isReadonly || null"
23
21
  :class="{ mt1: !inline && i }")
24
22
  slot(
25
- v-if="$scopedSlots[`item.${i + 1}`]"
26
- :name="`item.${i + 1}`"
23
+ v-if="$slots[`item.${i + 1}`] || $slots.item"
24
+ :name="$slots[`item.${i + 1}`] ? `item.${i + 1}` : 'item'"
27
25
  :item="getOriginalItem(item)"
28
26
  :index="i + 1"
29
- :checked="item.value === value"
30
- v-html="item.label")
31
- slot(
32
- v-else-if="$scopedSlots.item"
33
- name="item"
34
- :item="getOriginalItem(item)"
35
- :index="i + 1"
36
- :checked="item.value === value"
37
- v-html="item.label")
27
+ :checked="item.value === value")
38
28
  </template>
39
29
 
40
30
  <script>
@@ -52,7 +42,8 @@ export default {
52
42
  itemValueKey: { type: String, default: 'value' },
53
43
  itemColorKey: { type: String, default: 'color' }, // Support a different color per item.
54
44
  inline: { type: Boolean },
55
- color: { type: String, default: 'primary' }
45
+ color: { type: String, default: 'primary' },
46
+ labelColor: { type: String, default: 'primary' }
56
47
  // Props from mixin: name, disabled, readonly, required, validators.
57
48
  // Computed from mixin: inputName, isDisabled & isReadonly.
58
49
  },
@@ -9,24 +9,19 @@ component(
9
9
  :class="classes")
10
10
  template(v-if="labelPosition === 'left'")
11
11
  label.w-select__label.w-select__label--left.w-form-el-shakable(
12
- v-if="$slots.default"
13
- :for="`w-select--${_uid}`")
14
- slot
15
- label.w-select__label.w-select__label--left.w-form-el-shakable(
16
- v-else-if="label"
12
+ v-if="$slots.default || label"
17
13
  :for="`w-select--${_uid}`"
18
- v-html="label")
14
+ :class="labelClasses")
15
+ slot {{ label }}
19
16
 
20
17
  w-menu(
21
18
  v-model="showMenu"
22
19
  :menu-class="`w-select__menu ${menuClass || ''}`"
23
20
  transition="slide-fade-down"
24
- :append-to="(menuProps || {}).appendTo !== undefined ? (menuProps || {}).appendTo : '.w-app'"
21
+ :append-to="(menuProps || {}).appendTo !== undefined ? (menuProps || {}).appendTo : undefined"
25
22
  align-left
26
23
  custom
27
24
  min-width="activator"
28
- @mousedown="isFocused = true, selectingItem = true"
29
- @mouseup="isFocused = true, selectingItem = false"
30
25
  v-bind="menuProps || {}")
31
26
  template(#activator="{ on }")
32
27
  //- Input wrapper.
@@ -69,15 +64,10 @@ component(
69
64
  :name="inputName + (multiple ? '[]' : '')")
70
65
  template(v-if="labelPosition === 'inside' && showLabelInside")
71
66
  label.w-select__label.w-select__label--inside.w-form-el-shakable(
72
- v-if="$slots.default"
73
- :for="`w-select--${_uid}`"
74
- :class="isFocused && { [valid === false ? 'error' : color]: color || valid === false }")
75
- slot
76
- label.w-select__label.w-select__label--inside.w-form-el-shakable(
77
- v-else-if="label"
67
+ v-if="$slots.default || label"
78
68
  :for="`w-select--${_uid}`"
79
- v-html="label"
80
- :class="isFocused && { [valid === false ? 'error' : color]: color || valid === false }")
69
+ :class="labelClasses")
70
+ slot {{ label }}
81
71
  w-icon.w-select__icon.w-select__icon--inner-right(
82
72
  v-if="innerIconRight"
83
73
  tag="label"
@@ -113,13 +103,10 @@ component(
113
103
 
114
104
  template(v-if="labelPosition === 'right'")
115
105
  label.w-select__label.w-select__label--right.w-form-el-shakable(
116
- v-if="$slots.default"
117
- :for="`w-select--${_uid}`")
118
- slot
119
- label.w-select__label.w-select__label--right.w-form-el-shakable(
120
- v-else-if="label"
106
+ v-if="$slots.default || label"
121
107
  :for="`w-select--${_uid}`"
122
- v-html="label")
108
+ :class="labelClasses")
109
+ slot {{ label }}
123
110
  </template>
124
111
 
125
112
  <script>
@@ -150,8 +137,9 @@ export default {
150
137
  itemClass: { type: String },
151
138
  menuClass: { type: String },
152
139
  color: { type: String, default: 'primary' }, // Applies to all the items.
153
- selectionColor: { type: String, default: 'primary' }, // Applies to the selected items only.
154
140
  bgColor: { type: String }, // Applies to all the items.
141
+ labelColor: { type: String, default: 'primary' },
142
+ selectionColor: { type: String, default: 'primary' }, // Applies to the selected items only.
155
143
  outline: { type: Boolean },
156
144
  round: { type: Boolean },
157
145
  shadow: { type: Boolean },
@@ -175,7 +163,6 @@ export default {
175
163
  showMenu: false,
176
164
  menuMinWidth: 0,
177
165
  isFocused: false,
178
- selectingItem: false,
179
166
  selectionWrapRef: undefined
180
167
  }),
181
168
 
@@ -213,7 +200,7 @@ export default {
213
200
  'w-select--disabled': this.isDisabled,
214
201
  'w-select--readonly': this.isReadonly,
215
202
  [`w-select--${this.hasValue ? 'filled' : 'empty'}`]: true,
216
- 'w-select--focused': (this.isFocused || this.selectingItem) && !this.isReadonly,
203
+ 'w-select--focused': (this.isFocused || this.showMenu) && !this.isReadonly,
217
204
  'w-select--dark': this.dark,
218
205
  'w-select--floating-label': this.hasLabel && this.labelPosition === 'inside' && !this.staticLabel,
219
206
  'w-select--no-padding': !this.outline && !this.bgColor && !this.shadow && !this.round,
@@ -579,8 +566,6 @@ export default {
579
566
  .w-select--filled.w-select--floating-label.w-select--inner-icon-left & {left: 0;}
580
567
  // Chrome & Safari - Must remain in a separated rule as Firefox discard the whole rule seeing -webkit-.
581
568
  .w-select--floating-label.w-select--inner-icon-left .w-select__select:-webkit-autofill & {left: 0;}
582
-
583
- .w-select--focused &, .w-select--open & {color: currentColor;}
584
569
  }
585
570
 
586
571
  // Menu.
@@ -5,15 +5,17 @@ component(
5
5
  v-bind="formRegister && { validators, inputValue: rangeValueScaled, disabled: isDisabled, readonly: isReadonly }"
6
6
  :valid.sync="valid"
7
7
  @reset="rangeValuePercent = 0;updateRangeValueScaled()"
8
- wrap
8
+ :wrap="formRegister || null"
9
9
  :class="wrapperClasses")
10
10
  label.w-slider__label.w-slider__label--left.w-form-el-shakable(
11
11
  v-if="$slots['label-left']"
12
- :for="`button--${_uid}`")
12
+ :for="`button--${_uid}`"
13
+ :class="labelClasses")
13
14
  slot(name="label-left")
14
15
  label.w-slider__label.w-slider__label--left.w-form-el-shakable(
15
16
  v-else-if="labelLeft"
16
17
  :for="`button--${_uid}`"
18
+ :class="labelClasses"
17
19
  v-html="labelLeft")
18
20
  .w-slider__track-wrap
19
21
  .w-slider__track(
@@ -39,6 +41,7 @@ component(
39
41
  :disabled="isDisabled || null"
40
42
  :readonly="isReadonly || null"
41
43
  :aria-readonly="isReadonly ? 'true' : 'false'"
44
+ :tabindex="isDisabled || isReadonly ? -1 : null"
42
45
  @keydown.left="onKeyDown($event, -1)"
43
46
  @keydown.right="onKeyDown($event, 1)"
44
47
  @focus="$emit('focus', $event)"
@@ -64,11 +67,13 @@ component(
64
67
  style="left: 100%") {{ this.maxVal }}
65
68
  label.w-slider__label.w-slider__label--right.w-form-el-shakable(
66
69
  v-if="$slots['label-right']"
67
- :for="`button--${_uid}`")
70
+ :for="`button--${_uid}`"
71
+ :class="labelClasses")
68
72
  slot(name="label-right")
69
73
  label.w-slider__label.w-slider__label--right.w-form-el-shakable(
70
74
  v-else-if="labelRight"
71
75
  :for="`button--${_uid}`"
76
+ :class="labelClasses"
72
77
  v-html="labelRight")
73
78
  </template>
74
79
 
@@ -83,6 +88,7 @@ export default {
83
88
  value: { type: Number, default: 0 },
84
89
  color: { type: String, default: 'primary' },
85
90
  bgColor: { type: String },
91
+ labelColor: { type: String, default: 'primary' },
86
92
  stepLabels: { type: [Boolean, Array] },
87
93
  thumbLabel: { type: [Boolean, String] }, // One of true, false, 'droplet'.
88
94
  thumbLabelClass: { type: String },
@@ -378,16 +384,17 @@ export default {
378
384
  &:before, &:after {
379
385
  content: '';
380
386
  position: absolute;
387
+ border-radius: inherit;
388
+ @include default-transition;
381
389
  }
390
+ // Colored border on thumb when hover and active - but with a transparency.
382
391
  &:before {
383
392
  left: 0;
384
393
  right: 0;
385
394
  top: 0;
386
395
  bottom: 0;
387
396
  opacity: 0.5;
388
- border-radius: inherit;
389
397
  border: 1px solid currentColor;
390
- @include default-transition;
391
398
  }
392
399
  &:hover:before, &:focus:before {opacity: 0.7;}
393
400
  &:active:before, .w-slider--dragging &:before {
@@ -398,13 +405,17 @@ export default {
398
405
  .w-slider--disabled &:before,
399
406
  .w-slider--readonly &:before {box-shadow: none;opacity: 0.4;}
400
407
 
401
- // For fat fingers.
408
+ // The outline when focused, but also a bigger reactive zone for fat fingers when not.
402
409
  &:after {
403
- left: -6px;
404
- right: -6px;
405
- top: -6px;
406
- bottom: -6px;
410
+ left: -2 * $base-increment;
411
+ right: -2 * $base-increment;
412
+ top: -2 * $base-increment;
413
+ bottom: -2 * $base-increment;
414
+ opacity: 0;
415
+ background-color: currentColor;
407
416
  }
417
+ &:focus:after {opacity: 0.15;}
418
+ .w-slider--dragging &:after, &:active:after {opacity: 0.1;transform: scale(1.2);}
408
419
  }
409
420
 
410
421
  // Thumb label.
@@ -22,17 +22,25 @@ component(
22
22
  :aria-checked="isOn || 'false'"
23
23
  role="switch")
24
24
  template(v-if="hasLabel && labelOnLeft")
25
- label.w-switch__label.w-form-el-shakable(v-if="$slots.default" :for="`w-switch--${_uid}`")
26
- slot
27
- label.w-switch__label.w-form-el-shakable(v-else-if="label" :for="`w-switch--${_uid}`" v-html="label")
25
+ label.w-switch__label.w-switch__label--left.w-form-el-shakable(
26
+ v-if="$slots.default || label"
27
+ :for="`w-switch--${_uid}`"
28
+ :class="labelClasses")
29
+ slot {{ label }}
28
30
  .w-switch__input(
29
31
  @click="$refs.input.focus();$refs.input.click()"
30
32
  v-on="$listeners"
31
33
  :class="inputClasses")
34
+ .w-switch__track(v-if="$slots.track")
35
+ slot(name="track")
36
+ .w-switch__thumb(v-if="$slots.thumb")
37
+ slot(name="thumb")
32
38
  template(v-if="hasLabel && !labelOnLeft")
33
- label.w-switch__label.w-form-el-shakable(v-if="$slots.default" :for="`w-switch--${_uid}`")
34
- slot
35
- label.w-switch__label.w-form-el-shakable(v-else-if="label" :for="`w-switch--${_uid}`" v-html="label")
39
+ label.w-switch__label.w-switch__label--right.w-form-el-shakable(
40
+ v-if="$slots.default || label"
41
+ :for="`w-switch--${_uid}`"
42
+ :class="labelClasses")
43
+ slot {{ label }}
36
44
  </template>
37
45
 
38
46
  <script>
@@ -47,6 +55,7 @@ export default {
47
55
  label: { type: String, default: '' },
48
56
  labelOnLeft: { type: Boolean },
49
57
  color: { type: String, default: 'primary' },
58
+ labelColor: { type: String, default: 'primary' },
50
59
  thin: { type: Boolean },
51
60
  noRipple: { type: Boolean }
52
61
  // Props from mixin: name, disabled, readonly, required, tabindex, validators.
@@ -77,6 +86,8 @@ export default {
77
86
  'w-switch--disabled': this.isDisabled,
78
87
  'w-switch--readonly': this.isReadonly,
79
88
  'w-switch--ripple': this.ripple.start,
89
+ 'w-switch--custom-thumb': this.$slots.thumb,
90
+ 'w-switch--custom-track': this.$slots.track,
80
91
  'w-switch--rippled': this.ripple.end
81
92
  }
82
93
  },
@@ -186,8 +197,18 @@ $disabled-color: #ddd;
186
197
  }
187
198
  }
188
199
 
189
- // Thumb.
190
- &__input:after {
200
+ // Track slot, if any.
201
+ &__track {
202
+ position: absolute;
203
+ left: 100%;
204
+ padding: 0 4px;
205
+ transform: translateX(-100%);
206
+ @include default-transition;
207
+ }
208
+ .w-switch--on &__track {left: 0;transform: translateX(0);}
209
+
210
+ // Thumb: show either the thumb slot if any, or :after otherwise.
211
+ &__thumb, &__input:after {
191
212
  content: '';
192
213
  position: absolute;
193
214
  left: 0;
@@ -196,22 +217,28 @@ $disabled-color: #ddd;
196
217
  height: $small-form-el-size;
197
218
  background-color: #fff;
198
219
  border-radius: 100%;
220
+ text-align: center;
199
221
  @include default-transition;
200
222
 
201
223
  .w-switch[class^="bdrs"] &, .w-switch[class*=" bdrs"] & {border-radius: inherit;}
202
224
 
203
- :checked ~ & {transform: translateX(100%);}
225
+ .w-switch--on & {left: 100%;transform: translateX(-100%);}
204
226
 
205
227
  .w-switch--thin & {
206
228
  top: - round(0.15 * $small-form-el-size);
207
229
  transform: scale(1.1);
208
230
  box-shadow: $box-shadow;
209
231
  }
210
- .w-switch--thin :checked ~ & {
211
- transform: translateX(100%) scale(1.1);
232
+ .w-switch--thin.w-switch--on & {
233
+ transform: translateX(-100%) scale(1.1);
212
234
  background-color: currentColor;
213
235
  }
214
236
  }
237
+ &--custom-thumb &__input:after {display: none;}
238
+ &__thumb > * {
239
+ width: inherit;
240
+ height: inherit;
241
+ }
215
242
 
216
243
  // The focus outline & ripple on switch activation.
217
244
  &__input:before {
@@ -223,11 +250,12 @@ $disabled-color: #ddd;
223
250
  height: $small-form-el-size;
224
251
  background-color: currentColor;
225
252
  border-radius: 100%;
226
- transform: translateX(100%) scale(0);
227
253
  opacity: 0;
228
254
  pointer-events: none;
229
255
  transition: 0.25s ease-in-out;
230
256
 
257
+ :checked ~ & {transform: translateX(-100%) scale(0);left: 100%;}
258
+
231
259
  .w-switch[class^="bdrs"] &, .w-switch[class*=" bdrs"] & {border-radius: inherit;}
232
260
  .w-switch--thin & {top: - round(0.15 * $small-form-el-size);}
233
261
  }
@@ -242,14 +270,14 @@ $disabled-color: #ddd;
242
270
  opacity: 0.2;
243
271
  }
244
272
  :focus:checked ~ &__input:before {
245
- transform: translateX(100%) scale(1.8);
273
+ transform: translateX(-100%) scale(1.8);
246
274
  }
247
275
 
248
276
  // After ripple reset to default state, then remove the class via js and the
249
277
  // `:focus ~ &__input:before` will re-transition to normal focused outline.
250
278
  &--rippled &__input:before {
251
279
  transition: none;
252
- transform: translateX(100%) scale(0);
280
+ transform: translateX(-100%) scale(0);
253
281
  opacity: 0;
254
282
  }
255
283
 
@@ -264,7 +292,7 @@ $disabled-color: #ddd;
264
292
  }
265
293
 
266
294
  @keyframes w-switch-ripple {
267
- 0% {opacity: 0.8;transform: translateX(100%) scale(1);background-color: currentColor;} // Start with visible ripple.
268
- 100% {opacity: 0;transform: translateX(100%) scale(2.8);} // Propagate ripple to max radius and fade out.
295
+ 0% {opacity: 0.8;transform: translateX(-100%) scale(1);background-color: currentColor;} // Start with visible ripple.
296
+ 100% {opacity: 0;transform: translateX(-100%) scale(2.8);} // Propagate ripple to max radius and fade out.
269
297
  }
270
298
  </style>
@@ -65,6 +65,7 @@ export default {
65
65
  titleClass: { type: String },
66
66
  activeClass: { type: String, default: 'primary' },
67
67
  noSlider: { type: Boolean },
68
+ pillSlider: { type: Boolean },
68
69
  sliderColor: { type: String, default: 'primary' },
69
70
  contentClass: { type: String },
70
71
  transition: { type: [String, Boolean], default: '' },
@@ -122,6 +123,7 @@ export default {
122
123
  return {
123
124
  'w-tabs--card': this.card,
124
125
  'w-tabs--no-slider': this.noSlider,
126
+ 'w-tabs--pill-slider': this.pillSlider,
125
127
  'w-tabs--fill-bar': this.fillBar,
126
128
  'w-tabs--init': this.init
127
129
  }
@@ -252,11 +254,11 @@ export default {
252
254
  &__bar {
253
255
  position: relative;
254
256
  display: flex;
255
- // align-items: center;
256
257
  overflow-x: auto;
257
258
 
258
259
  &--center {justify-content: center;}
259
260
  &--right {justify-content: flex-end;}
261
+ .w-tabs--pill-slider & {padding-left: $base-increment;}
260
262
 
261
263
  .w-tabs--card &:after {
262
264
  content: '';
@@ -310,6 +312,7 @@ export default {
310
312
  &:active:before {opacity: 0.08;}
311
313
  &--disabled:before {display: none;}
312
314
  }
315
+ &--pill-slider &__bar-item:before {display: none;}
313
316
 
314
317
  // Bar Extra.
315
318
  // ------------------------------------------------------
@@ -330,6 +333,13 @@ export default {
330
333
  background-color: currentColor;
331
334
  transition: $transition-duration ease-in-out;
332
335
  }
336
+ &--pill-slider &__slider {
337
+ opacity: 0.1;
338
+ bottom: 15%;
339
+ height: 70%;
340
+ border-radius: 99em;
341
+ }
342
+
333
343
  &--init &__slider {transition: none;}
334
344
 
335
345
  // Content.