diff --git a/ui/packages/consul-ui/app/components/providers/dimension/index.hbs b/ui/packages/consul-ui/app/components/providers/dimension/index.hbs
new file mode 100644
index 0000000000..4d36322965
--- /dev/null
+++ b/ui/packages/consul-ui/app/components/providers/dimension/index.hbs
@@ -0,0 +1,4 @@
+
+ {{on-window 'resize' this.handleWindowResize}}
+ {{yield (hash data=this.data)}}
+
\ No newline at end of file
diff --git a/ui/packages/consul-ui/app/components/providers/dimension/index.js b/ui/packages/consul-ui/app/components/providers/dimension/index.js
new file mode 100644
index 0000000000..ebf47545d3
--- /dev/null
+++ b/ui/packages/consul-ui/app/components/providers/dimension/index.js
@@ -0,0 +1,53 @@
+import Component from '@glimmer/component';
+import { tracked } from '@glimmer/tracking';
+import { action } from '@ember/object';
+import { inject as service } from '@ember/service';
+import { ref } from 'ember-ref-bucket';
+import { htmlSafe } from '@ember/template';
+
+export default class DimensionsProvider extends Component {
+ @service dom;
+ @ref('element') element;
+
+ @tracked height;
+
+ get data() {
+ const { height, fillRemainingHeightStyle } = this;
+
+ return {
+ height,
+ fillRemainingHeightStyle,
+ };
+ }
+
+ get fillRemainingHeightStyle() {
+ return htmlSafe(`height: ${this.height}px;`);
+ }
+
+ get bottomBoundary() {
+ return this.args.bottomBoundary || this.footer;
+ }
+
+ get footer() {
+ return document.querySelector('footer[role="contentinfo"]');
+ }
+
+ get viewport() {
+ return this.dom.viewport();
+ }
+
+ @action measureDimensions(element) {
+ const { viewport, bottomBoundary } = this;
+
+ const height =
+ viewport.innerHeight - (element.getBoundingClientRect().top + bottomBoundary.clientHeight);
+
+ this.height = height;
+ }
+
+ @action handleWindowResize() {
+ const { element } = this;
+
+ this.measureDimensions(element);
+ }
+}