Skip to content

Commit 5684405

Browse files
authored
feat(b-form-spinbutton): add slots for increment and decrement button content (closes #4958) (#4963)
Co-authored-by: Jacob Müller
1 parent d481365 commit 5684405

File tree

5 files changed

+68
-9
lines changed

5 files changed

+68
-9
lines changed

src/components/form-spinbutton/_spinbutton.scss

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
pointer-events: none;
4949
}
5050

51-
&:hover:not(:disabled) > div {
51+
&:hover:not(:disabled) > div > .b-icon {
5252
transform: scale(1.25);
5353
}
5454
}

src/components/form-spinbutton/form-spinbutton.js

+23-5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { toString } from '../../utils/string'
99
import identity from '../../utils/identity'
1010
import KeyCodes from '../../utils/key-codes'
1111
import idMixin from '../../mixins/id'
12+
import normalizeSlotMixin from '../../mixins/normalize-slot'
1213
import { BIconPlus, BIconDash } from '../../icons/icons'
1314

1415
// --- Constants ---
@@ -47,7 +48,7 @@ const defaultInteger = (value, defaultValue = null) => {
4748
// @vue/component
4849
export const BFormSpinbutton = /*#__PURE__*/ Vue.extend({
4950
name: NAME,
50-
mixins: [idMixin],
51+
mixins: [idMixin, normalizeSlotMixin],
5152
inheritAttrs: false,
5253
props: {
5354
value: {
@@ -439,11 +440,12 @@ export const BFormSpinbutton = /*#__PURE__*/ Vue.extend({
439440
const hasValue = !isNull(value)
440441
const formatter = isFunction(this.formatterFn) ? this.formatterFn : this.defaultFormatter
441442

442-
const makeButton = (stepper, label, IconCmp, keyRef, shortcut, btnDisabled) => {
443+
const makeButton = (stepper, label, IconCmp, keyRef, shortcut, btnDisabled, slotName) => {
443444
const $icon = h(IconCmp, {
444445
props: { scale: this.hasFocus ? 1.5 : 1.25 },
445446
attrs: { 'aria-hidden': 'true' }
446447
})
448+
const scope = { hasFocus: this.hasFocus }
447449
const handler = evt => {
448450
if (!isDisabled && !isReadonly) {
449451
evt.preventDefault()
@@ -476,12 +478,28 @@ export const BFormSpinbutton = /*#__PURE__*/ Vue.extend({
476478
touchstart: handler
477479
}
478480
},
479-
[h('div', {}, [$icon])]
481+
[h('div', {}, [this.normalizeSlot(slotName, scope) || $icon])]
480482
)
481483
}
482484
// TODO: Add button disabled state when `wrap` is `false` and at value max/min
483-
const $increment = makeButton(this.stepUp, this.labelIncrement, BIconPlus, 'inc', 'ArrowUp')
484-
const $decrement = makeButton(this.stepDown, this.labelDecrement, BIconDash, 'dec', 'ArrowDown')
485+
const $increment = makeButton(
486+
this.stepUp,
487+
this.labelIncrement,
488+
BIconPlus,
489+
'inc',
490+
'ArrowUp',
491+
false,
492+
'increment'
493+
)
494+
const $decrement = makeButton(
495+
this.stepDown,
496+
this.labelDecrement,
497+
BIconDash,
498+
'dec',
499+
'ArrowDown',
500+
false,
501+
'decrement'
502+
)
485503

486504
let $hidden = h()
487505
if (this.name && !isDisabled) {

src/components/form-spinbutton/package.json

+26
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,32 @@
9999
"description": "Number of steps to jump by once the `repeat-threshold` has been reached. Must be a positive integer. This value is also used for the page up and down keys"
100100
}
101101
],
102+
"slots": [
103+
{
104+
"name": "increment",
105+
"version": "2.8.0",
106+
"description": "Custom content to place in the increment button",
107+
"scope": [
108+
{
109+
"prop": "hasFocus",
110+
"type": "Boolean",
111+
"description": "`true` when the spinbutton has focus"
112+
}
113+
]
114+
},
115+
{
116+
"name": "decrement",
117+
"version": "2.8.0",
118+
"description": "Custom content to place in the decrement button",
119+
"scope": [
120+
{
121+
"prop": "hasFocus",
122+
"type": "Boolean",
123+
"description": "`true` when the spinbutton has focus"
124+
}
125+
]
126+
}
127+
],
102128
"events": [
103129
{
104130
"event": "input",

src/components/form-timepicker/README.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,7 @@ In the following simple example, we are placing the timepicker (button only mode
236236
button-only
237237
right
238238
show-seconds
239-
:hour12="false"
240-
locale="en-US"
239+
locale="en"
241240
aria-controls="example-input"
242241
></b-form-timepicker>
243242
</b-input-group-append">

src/components/time/time.js

+17-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import idMixin from '../../mixins/id'
1717
import normalizeSlotMixin from '../../mixins/normalize-slot'
1818
// Sub components used
1919
import { BFormSpinbutton } from '../form-spinbutton/form-spinbutton'
20-
import { BIconCircleFill } from '../../icons/icons'
20+
import { BIconCircleFill, BIconChevronUp } from '../../icons/icons'
2121

2222
// --- Constants ---
2323

@@ -288,6 +288,21 @@ export const BTime = /*#__PURE__*/ Vue.extend({
288288
return this.timeFormatter(createDate(Date.UTC(0, 0, 1, hours, minutes, seconds)))
289289
}
290290
return this.labelNoTimeSelected || ' '
291+
},
292+
spinScopedSlots() {
293+
const h = this.$createElement
294+
return {
295+
increment: ({ hasFocus }) =>
296+
h(BIconChevronUp, {
297+
props: { scale: hasFocus ? 1.5 : 1.25 },
298+
attrs: { 'aria-hidden': 'true' }
299+
}),
300+
decrement: ({ hasFocus }) =>
301+
h(BIconChevronUp, {
302+
props: { flipV: true, scale: hasFocus ? 1.5 : 1.25 },
303+
attrs: { 'aria-hidden': 'true' }
304+
})
305+
}
291306
}
292307
},
293308
watch: {
@@ -467,6 +482,7 @@ export const BTime = /*#__PURE__*/ Vue.extend({
467482
min: 0,
468483
...spinbuttonProps
469484
},
485+
scopedSlots: this.spinScopedSlots,
470486
on: {
471487
// We use `change` event to minimize SR verbosity
472488
// As the spinbutton will announce each value change

0 commit comments

Comments
 (0)