Skip to content

Commit 3d22ee0

Browse files
authored
Merge pull request #19 from microcipcip/feature/useScrollbarWidth
feat(useScrollbarWidth): Adding useScrollbarWidth function
2 parents 8f3fa45 + 5abcf19 commit 3d22ee0

8 files changed

+165
-0
lines changed

Diff for: README.md

+2
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ Vue.use(VueCompositionAPI)
9292
[![Demo](https://img.shields.io/badge/demo-🚀-yellow.svg)](https://microcipcip.github.io/vue-use-kit/?path=/story/sensors-usesize--demo)
9393
- [`useScroll`](./src/functions/useScroll/stories/useScroll.md) — tracks an HTML element's scroll position.
9494
[![Demo](https://img.shields.io/badge/demo-🚀-yellow.svg)](https://microcipcip.github.io/vue-use-kit/?path=/story/sensors-usescroll--demo)
95+
- [`useScrollbarWidth`](./src/functions/useScrollbarWidth/stories/useScrollbarWidth.md) — gets current browser's scrollbar width.
96+
[![Demo](https://img.shields.io/badge/demo-🚀-yellow.svg)](https://microcipcip.github.io/vue-use-kit/?path=/story/sensors-usescrollbarwidth--demo)
9597
- [`useSearchParams`](./src/functions/useSearchParams/stories/useSearchParams.md) — tracks browser's location search params.
9698
[![Demo](https://img.shields.io/badge/demo-🚀-yellow.svg)](https://microcipcip.github.io/vue-use-kit/?path=/story/sensors-usesearchparams--demo)
9799
- [`useWindowSize`](./src/functions/useWindowSize/stories/useWindowSize.md) — tracks `Window` scroll position.

Diff for: src/functions/useScrollbarWidth/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './useScrollbarWidth'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<template>
2+
<table class="table is-fullwidth">
3+
<thead>
4+
<tr>
5+
<th>Prop</th>
6+
<th>Value</th>
7+
</tr>
8+
</thead>
9+
<tbody>
10+
<tr>
11+
<td>scrollbarWidth</td>
12+
<td>{{ scrollbarWidth }}px</td>
13+
</tr>
14+
</tbody>
15+
</table>
16+
</template>
17+
18+
<script lang="ts">
19+
import Vue from 'vue'
20+
import { useScrollbarWidth } from '@src/vue-use-kit'
21+
22+
export default Vue.extend({
23+
name: 'UseScrollbarWidthDemo',
24+
setup() {
25+
const { scrollbarWidth } = useScrollbarWidth()
26+
return { scrollbarWidth }
27+
}
28+
})
29+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# useScrollbarWidth
2+
3+
Vue function that gets current browser's scrollbar width.
4+
5+
## Reference
6+
7+
```typescript
8+
function useScrollbarWidth(
9+
runOnMount?: boolean
10+
): {
11+
scrollbarWidth: Ref<number>
12+
getScrollbarWidth: () => void
13+
}
14+
```
15+
16+
### Parameters
17+
18+
- `runOnMount: boolean` whether to get scrollbar width on mount, `true` by default
19+
20+
### Returns
21+
22+
- `scrollbarWidth: Ref<number>` the scrollbar width
23+
- `getScrollbarWidth: Function` the function to call to get the scrollbar width
24+
25+
## Usage
26+
27+
```html
28+
<template>
29+
<div>
30+
scrollbarWidth: {{ scrollbarWidth }}px
31+
</div>
32+
</template>
33+
34+
<script lang="ts">
35+
import Vue from 'vue'
36+
import { useScrollbarWidth } from 'vue-use-kit'
37+
38+
export default Vue.extend({
39+
name: 'UseScrollbarWidthDemo',
40+
setup() {
41+
const { scrollbarWidth } = useScrollbarWidth()
42+
return { scrollbarWidth }
43+
}
44+
})
45+
</script>
46+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { storiesOf } from '@storybook/vue'
2+
import path from 'path'
3+
import StoryTitle from '@src/helpers/StoryTitle.vue'
4+
import UseScrollbarWidthDemo from './UseScrollbarWidthDemo.vue'
5+
6+
const functionName = 'useScrollbarWidth'
7+
const functionPath = path.resolve(__dirname, '..')
8+
const notes = require(`./${functionName}.md`).default
9+
10+
const basicDemo = () => ({
11+
components: { StoryTitle, demo: UseScrollbarWidthDemo },
12+
template: `
13+
<div class="container">
14+
<story-title
15+
function-path="${functionPath}"
16+
source-name="${functionName}"
17+
demo-name="UseScrollbarWidthDemo.vue"
18+
>
19+
<template v-slot:title></template>
20+
<template v-slot:intro></template>
21+
</story-title>
22+
<demo />
23+
</div>`
24+
})
25+
26+
storiesOf('sensors|useScrollbarWidth', module)
27+
.addParameters({ notes })
28+
.add('Demo', basicDemo)
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { mount } from '@src/helpers/test'
2+
import { useScrollbarWidth } from '@src/vue-use-kit'
3+
4+
afterEach(() => {
5+
jest.clearAllMocks()
6+
})
7+
8+
const testComponent = (onMount = true) => ({
9+
template: `
10+
<div>
11+
<div id="scrollbarWidth">{{ scrollbarWidth }}</div>
12+
<button id="getScrollbarWidth" @click="getScrollbarWidth"></button>
13+
</div>
14+
`,
15+
setup() {
16+
const { scrollbarWidth, getScrollbarWidth } = useScrollbarWidth(onMount)
17+
return { scrollbarWidth, getScrollbarWidth }
18+
}
19+
})
20+
21+
describe('useScrollbarWidth', () => {
22+
it('should return a scrollbarWidth as a numeric value', async () => {
23+
const wrapper = mount(testComponent())
24+
await wrapper.vm.$nextTick()
25+
expect(wrapper.find('#scrollbarWidth').text()).toBe('0')
26+
})
27+
})

Diff for: src/functions/useScrollbarWidth/useScrollbarWidth.ts

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { ref, onMounted, Ref } from '@src/api'
2+
3+
export function useScrollbarWidth(runOnMount = true) {
4+
const scrollbarWidth = ref(0)
5+
6+
const getScrollbarWidth = () => {
7+
// https://stackoverflow.com/a/13382873/974107
8+
// Creating invisible container
9+
const outer = document.createElement('div')
10+
outer.style.visibility = 'hidden'
11+
outer.style.overflow = 'scroll' // forcing scrollbar to appear
12+
outer.style.msOverflowStyle = 'scrollbar' // needed for WinJS apps
13+
document.body.appendChild(outer)
14+
15+
// Creating inner element and placing it in the container
16+
const inner = document.createElement('div')
17+
outer.appendChild(inner)
18+
19+
// Calculating difference between container's full width and the child width
20+
const scrollbarWidthValue = outer.offsetWidth - inner.offsetWidth
21+
22+
// Removing temporary elements from the DOM
23+
if (outer.parentNode) outer.parentNode.removeChild(outer)
24+
25+
scrollbarWidth.value = scrollbarWidthValue
26+
}
27+
28+
onMounted(() => runOnMount && getScrollbarWidth())
29+
30+
return { scrollbarWidth, getScrollbarWidth }
31+
}

Diff for: src/vue-use-kit.ts

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export * from './functions/useOrientation'
1818
export * from './functions/useSize'
1919
export * from './functions/useSearchParams'
2020
export * from './functions/useScroll'
21+
export * from './functions/useScrollbarWidth'
2122
export * from './functions/useWindowSize'
2223
// Animations
2324
export * from './functions/useIntervalFn'

0 commit comments

Comments
 (0)