useResizeObserver
Returns the ref object containing the current "width" and "height" properties.
Sets up a ResizeObserver which attaches to the provided template ref when the component is mounted.
This composable only supports horizontal writing directions (left to right or right to left), not vertical writing directions (e.g. top to bottom).
Usage
Set a template ref on the target element that you want the ResizeObserver to watch. The ref
attribute provides a direct reference to the element and allows us to interact with the DOM element.
<template>
<div ref="dialogBody"></div>
</template>
Pass the template ref to the composable.
const dialogBody = ref(null); // dialog content
const bodyDimensions = useResizeObserver( dialogBody );
Full example
In this example, the component has three sections: header, body, and footer. And we want to determine whether or not to show border dividers between the three sections.
The composable gets the current height of the body. If the body's client height is smaller than the body's scroll height then a CSS class is dynamically added to show the border dividers.
<template>
<div class="cdx-docs-container" :class="rootClasses">
<header>
<h1 class="cdx-docs-title">Title</h1>
</header>
<p ref="bodyContent" class="cdx-docs-body">
This is the body content.This is the body content.This is the body
content.This is the body content.This is the body content.This is the body
content.This is the body content.This is the body content.This is the body
content.This is the body content.This is the body content.This is the body
content.This is the body content.This is the body content.This is the body
content.This is the body content.This is the body content.This is the body
content.This is the body content.This is the body content.This is the body
content.This is the body content.This is the body content.This is the body
content.This is the body content.This is the body content.This is the body
content.This is the body content.This is the body content.This is the body
content.This is the body content.This is the body content.This is the body
content.This is the body content.This is the body content.This is the body
content.This is the body content.This is the body content.This is the body
content.
</p>
<footer class="cdx-docs-footer">
<cdx-button>Continue</cdx-button>
</footer>
</div>
</template>
<script>
import { defineComponent, ref, computed, watch } from 'vue';
import { CdxButton, useResizeObserver } from '@wikimedia/codex';
export default defineComponent({
components: { CdxButton },
setup() {
const bodyContent = ref(null);
const bodyDimensions = useResizeObserver( bodyContent );
const currentBodyHeight = computed( () => bodyDimensions.value.height ?? 0 );
const showDividers = ref( false );
const rootClasses = computed( () => {
return {
'cdx-docs-container--dividers': showDividers.value
};
} );
// Determine if content dividers should be displayed for overflowing content
watch( currentBodyHeight, () => {
if ( bodyContent.value ) {
showDividers.value = bodyContent.value.clientHeight < bodyContent.value.scrollHeight;
}
} );
return {
bodyContent,
rootClasses
}
}
});
</script>
<style>
@import ( reference ) '@wikimedia/codex-design-tokens/theme-wikimedia-ui.less';
/* MediaWiki imports Codex design tokens differently
https://www.mediawiki.org/wiki/Codex#Using_Codex_design_tokens */
.cdx-docs-container {
height: @size-half;
border: @border-base;
}
.cdx-docs-title {
margin-top: @spacing-25;
margin-bottom: @spacing-25;
margin-left: @spacing-50;
}
.cdx-docs-body {
height: @size-400;
margin-left: @spacing-50;
padding-top: @spacing-75;
padding-bottom: @spacing-75;
overflow: auto;
font-size: @font-size-medium;
}
.cdx-docs-footer {
padding-top: @spacing-75;
& button {
margin-left: @spacing-50;
}
}
header {
.cdx-docs-container--dividers & {
border-bottom: @border-subtle;
}
}
footer {
.cdx-docs-container--dividers & {
border-top: @border-subtle;
}
}
</style>