diff --git a/lib/components/Button/ButtonIcon.vue b/lib/components/Button/ButtonIcon.vue index 188edd95..c5468225 100644 --- a/lib/components/Button/ButtonIcon.vue +++ b/lib/components/Button/ButtonIcon.vue @@ -265,7 +265,15 @@ const props = withDefaults(defineProps(), { type: 'button', loadingDuration: '1s', tooltipPlacement: 'top', - tooltipDelay: () => ({ show: 0, hide: 0 }) + tooltipDelay: () => ({ show: 0, hide: 0 }), + // Vue defaults an absent `Boolean`-typed prop to `false` unless a default + // is given explicitly. Left unset, that silently forwards `pressed: false` + // to BButton, which switches it into toggle-button mode: it then flips its + // own internal `pressed`/`.active` state on every click, regardless of + // this component's `variant`, and never flips it back. Declaring the + // default as `undefined` here keeps `pressed` genuinely unset for callers + // that don't pass it, so BButton stays a plain (non-toggle) button. + pressed: undefined }) const emit = defineEmits(['click:icon-right']) diff --git a/package.json b/package.json index 5c030bbc..f5f4cb88 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "@storybook/preset-scss": "^1.0.3", "@vueuse/core": "^14.0.0", "bootstrap": "^5.3.8", - "bootstrap-vue-next": "0.45.8", + "bootstrap-vue-next": "1.0.1", "canvas": "^3.2.0", "clipboard": "^2.0.11", "d3-array": "^3.2.4", diff --git a/tests/unit/components/Button/ButtonIcon.spec.ts b/tests/unit/components/Button/ButtonIcon.spec.ts new file mode 100644 index 00000000..3c43bba1 --- /dev/null +++ b/tests/unit/components/Button/ButtonIcon.spec.ts @@ -0,0 +1,34 @@ +import { mount } from '@vue/test-utils' +import { describe, expect, it } from 'vitest' +import ButtonIcon from '@/components/Button/ButtonIcon.vue' + +describe('ButtonIcon.vue', () => { + it('is a Vue instance', () => { + const wrapper = mount(ButtonIcon) + expect(wrapper.vm).toBeTruthy() + }) + + it('does not turn into a toggle button when `pressed` is not passed', async () => { + const wrapper = mount(ButtonIcon, { props: { label: 'Toggle' } }) + const button = wrapper.get('button') + + expect(button.attributes('aria-pressed')).toBeUndefined() + + await button.trigger('click') + + expect(button.attributes('aria-pressed')).toBeUndefined() + expect(button.classes()).not.toContain('active') + }) + + it('still behaves as a toggle button when `pressed` is explicitly passed', async () => { + const wrapper = mount(ButtonIcon, { props: { label: 'Toggle', pressed: false } }) + const button = wrapper.get('button') + + expect(button.attributes('aria-pressed')).toBe('false') + + await button.trigger('click') + + expect(button.attributes('aria-pressed')).toBe('true') + expect(button.classes()).toContain('active') + }) +}) diff --git a/yarn.lock b/yarn.lock index 9dd64261..8f6a8cc6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -513,7 +513,7 @@ resolved "https://registry.yarnpkg.com/@exodus/bytes/-/bytes-1.15.1.tgz#b13bc464ca162c17abf0837fb3a11aeab79e45d1" integrity sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q== -"@floating-ui/core@^1.7.5", "@floating-ui/core@^1.8.0": +"@floating-ui/core@^1.8.0": version "1.8.0" resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.8.0.tgz#d01c0bbea02e4a57f6fd7d5de6fc2c5c7dca40e1" integrity sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ== @@ -533,7 +533,7 @@ resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.12.tgz#afefe785949f16ac4cdd1e695935a321572dd56a" integrity sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww== -"@floating-ui/vue@2.0.1": +"@floating-ui/vue@2.0.1", "@floating-ui/vue@^2.0.1": version "2.0.1" resolved "https://registry.yarnpkg.com/@floating-ui/vue/-/vue-2.0.1.tgz#987976853159255ce8be3a39239706192228485c" integrity sha512-043dyEKD9TDSfz080YH2vobubgg+NIo/9Fw4RAl7sEMpD8Am1DNrrSTl/GpMBjyGHoD/FbJY2QLawY+HSQsEIA== @@ -541,7 +541,7 @@ "@floating-ui/dom" "^1.8.0" "@floating-ui/utils" "^0.2.12" -"@floating-ui/vue@^1.1.11", "@floating-ui/vue@^1.1.6": +"@floating-ui/vue@^1.1.6": version "1.1.11" resolved "https://registry.yarnpkg.com/@floating-ui/vue/-/vue-1.1.11.tgz#94fb1e62f6e157f91258a315a78b17079dd260e3" integrity sha512-HzHKCNVxnGS35r9fCHBc3+uCnjw9IWIlCPL683cGgM9Kgj2BiAl8x1mS7vtvP6F9S/e/q4O6MApwSHj8hNLGfw== @@ -2060,7 +2060,7 @@ js-beautify "^1.14.9" vue-component-type-helpers "^3.0.0" -"@vueuse/core@^14.0.0", "@vueuse/core@^14.1.0", "@vueuse/core@^14.2.1": +"@vueuse/core@^14.0.0", "@vueuse/core@^14.1.0": version "14.4.0" resolved "https://registry.yarnpkg.com/@vueuse/core/-/core-14.4.0.tgz#a841da6b3c7d548bdeed5bf611e73f3de62d20fa" integrity sha512-X4WHz1HlCzCBoYXesUkifzzWBAcZgXG8Fi5iNPQg/epdzOB3gu8Fawj3hvuwYR1nGcXGnvxwYYcUC/71++svtQ== @@ -2069,11 +2069,30 @@ "@vueuse/metadata" "14.4.0" "@vueuse/shared" "14.4.0" +"@vueuse/core@~14.2.1": + version "14.2.1" + resolved "https://registry.yarnpkg.com/@vueuse/core/-/core-14.2.1.tgz#b5cf36a07b4ea973381e18523ad0ed6ddc98a5be" + integrity sha512-3vwDzV+GDUNpdegRY6kzpLm4Igptq+GA0QkJ3W61Iv27YWwW/ufSlOfgQIpN6FZRMG0mkaz4gglJRtq5SeJyIQ== + dependencies: + "@types/web-bluetooth" "^0.0.21" + "@vueuse/metadata" "14.2.1" + "@vueuse/shared" "14.2.1" + +"@vueuse/metadata@14.2.1": + version "14.2.1" + resolved "https://registry.yarnpkg.com/@vueuse/metadata/-/metadata-14.2.1.tgz#bd3338a565c2f651b9d18ac0f8825aa6077ee461" + integrity sha512-1ButlVtj5Sb/HDtIy1HFr1VqCP4G6Ypqt5MAo0lCgjokrk2mvQKsK2uuy0vqu/Ks+sHfuHo0B9Y9jn9xKdjZsw== + "@vueuse/metadata@14.4.0": version "14.4.0" resolved "https://registry.yarnpkg.com/@vueuse/metadata/-/metadata-14.4.0.tgz#a2508499b803bac14775a9c9b852b8738fc16f98" integrity sha512-swx/255R6JyHZFJhx845iz5CRWDZdCfvkZOpACWc5+c5WHcG24mv8gUT1WIdFQaHt6dq79rvILd9QnCWiyVm9g== +"@vueuse/shared@14.2.1": + version "14.2.1" + resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-14.2.1.tgz#829a271147937f6b105bb1422d3171e6142f47ba" + integrity sha512-shTJncjV9JTI4oVNyF1FQonetYAiTBd+Qj7cY89SWbXSkx7gyhrgtEdF2ZAVWS1S3SHlaROO6F2IesJxQEkZBw== + "@vueuse/shared@14.4.0", "@vueuse/shared@^14.1.0": version "14.4.0" resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-14.4.0.tgz#4e89813c7859d153d48c03d74bff78739f96723b" @@ -2257,15 +2276,15 @@ boolbase@^1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== -bootstrap-vue-next@0.45.8: - version "0.45.8" - resolved "https://registry.yarnpkg.com/bootstrap-vue-next/-/bootstrap-vue-next-0.45.8.tgz#af2d688bc488a930dfd757b7be7d4a5c809c9916" - integrity sha512-D4Lntb6z7cVttLrOYCUy7joCZMYnl6lkKbOFJSxHKc0pNFsnduvp9PQs47FQwPWyq5HxTk3twcsyRdB0eWDAoA== +bootstrap-vue-next@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/bootstrap-vue-next/-/bootstrap-vue-next-1.0.1.tgz#802fbee875fe6ac51a02f4b2ed999d7d27acdd60" + integrity sha512-3qIPlwy1T4nWwWTk1a9jHC7k60N94N1ZvF8sLqH6oIGWKsWa5wrDNxUiHRgApoF/aUjhXu3bjZqo/W7Fn0xi4w== dependencies: - "@floating-ui/core" "^1.7.5" - "@floating-ui/vue" "^1.1.11" - "@vueuse/core" "^14.2.1" - reka-ui "^2.9.2" + "@floating-ui/core" "^1.8.0" + "@floating-ui/vue" "^2.0.1" + "@vueuse/core" "~14.2.1" + reka-ui "^2.10.3" bootstrap@^5.3.8: version "5.3.8" @@ -4327,10 +4346,10 @@ redent@^3.0.0: indent-string "^4.0.0" strip-indent "^3.0.0" -reka-ui@^2.9.2: - version "2.10.1" - resolved "https://registry.yarnpkg.com/reka-ui/-/reka-ui-2.10.1.tgz#af51db13cf753668385639900f0e01e99c386f44" - integrity sha512-drcOQ4rQtDYAcGCsyQBqQg8QQ+H3B+zDaMJU0h8KPEPMa7g9BHu3zcOi4OB39XJSWizceFoNO0Z9tctSGLOXqg== +reka-ui@^2.10.3: + version "2.10.4" + resolved "https://registry.yarnpkg.com/reka-ui/-/reka-ui-2.10.4.tgz#2a0ee3ecec1464c74645c53ec4ab33b1cc638e2b" + integrity sha512-kbS5GAbkHkYj0EVKAg5ZPEPndhBjeUFSa1Aq5m5ftQwyHnB1v5tw8X6fcwfKH/ry3StPXblMWM1DW82MVS71cw== dependencies: "@floating-ui/dom" "^1.6.13" "@floating-ui/vue" "^1.1.6"