diff --git a/alfa-client/libs/common/src/lib/accessibility-button/accessibility-button.component.spec.ts b/alfa-client/libs/common/src/lib/accessibility-button/accessibility-button.component.spec.ts
index ad67dcf8ab0a9414481ab5db68b15534d2799751..8b150294c1af567bef737ca8909cae78eb9081fd 100644
--- a/alfa-client/libs/common/src/lib/accessibility-button/accessibility-button.component.spec.ts
+++ b/alfa-client/libs/common/src/lib/accessibility-button/accessibility-button.component.spec.ts
@@ -1,4 +1,6 @@
 import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { LinkComponent, TooltipDirective } from '@ods/system';
+import { MockComponent, MockDirective } from 'ng-mocks';
 import { AccessibilityButtonComponent } from './accessibility-button.component';
 
 describe('AccessibilityButtonComponent', () => {
@@ -7,7 +9,7 @@ describe('AccessibilityButtonComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      imports: [AccessibilityButtonComponent],
+      imports: [AccessibilityButtonComponent, MockComponent(LinkComponent), MockDirective(TooltipDirective)],
     }).compileComponents();
 
     fixture = TestBed.createComponent(AccessibilityButtonComponent);
diff --git a/alfa-client/libs/design-system/src/lib/tooltip/tooltip.component.ts b/alfa-client/libs/design-system/src/lib/tooltip/tooltip.component.ts
index 51b46d897d0ff01414a77fc37792fb24c1edd1b8..89697eccbb9f006612aa1063acd5a53627a8fefb 100644
--- a/alfa-client/libs/design-system/src/lib/tooltip/tooltip.component.ts
+++ b/alfa-client/libs/design-system/src/lib/tooltip/tooltip.component.ts
@@ -26,7 +26,9 @@ import { Component } from '@angular/core';
 @Component({
   selector: 'ods-tooltip',
   template: `<p
-    class="fixed z-[100] mt-2 -translate-x-1/2 animate-fadeIn cursor-default rounded bg-ozggray-900 px-3 py-2 text-sm text-whitetext before:absolute before:-top-2 before:left-[calc(50%-0.5rem)] before:size-0 before:border-b-[0.5rem] before:border-l-[0.5rem] before:border-r-[0.5rem] before:border-b-ozggray-900 before:border-l-transparent before:border-r-transparent before:content-[''] dark:bg-white dark:before:border-b-white"
+    class="fixed hidden z-[100] mt-2 -translate-x-1/2 animate-fadeIn cursor-default rounded bg-ozggray-900 px-3 py-2 text-sm text-whitetext before:absolute before:-top-2 before:left-[calc(50%-0.5rem)] before:size-0 before:border-b-[0.5rem] before:border-l-[0.5rem] before:border-r-[0.5rem] before:border-b-ozggray-900 before:border-l-transparent before:border-r-transparent before:content-[''] dark:bg-white dark:before:border-b-white"
+    [class.block]="show"
+    [class.hidden]="!show"
     [style.left]="left + 'px'"
     [style.top]="top + 'px'"
     [attr.id]="id"
@@ -42,5 +44,6 @@ export class TooltipComponent {
   text: string = '';
   left: number = 0;
   top: number = 0;
+  show: boolean = false;
   id: string;
 }
diff --git a/alfa-client/libs/design-system/src/lib/tooltip/tooltip.directive.spec.ts b/alfa-client/libs/design-system/src/lib/tooltip/tooltip.directive.spec.ts
index 25ae440cf0e5e90d427386862f00cd41abce9eb4..e39f39af4d4342b92c643cb8156c7c49ed77fcd2 100644
--- a/alfa-client/libs/design-system/src/lib/tooltip/tooltip.directive.spec.ts
+++ b/alfa-client/libs/design-system/src/lib/tooltip/tooltip.directive.spec.ts
@@ -45,7 +45,7 @@ describe('TooltipDirective', () => {
     location: null,
     hostView: null,
     injector: null,
-    instance: { id: '', left: 0, top: 0, text: '' },
+    instance: { id: '', left: 0, top: 0, text: '', show: false },
   };
 
   beforeEach((): void => {
@@ -74,8 +74,7 @@ describe('TooltipDirective', () => {
   describe('createTooltip', () => {
     beforeEach(() => {
       directive.viewContainerRef.createComponent = jest.fn().mockReturnValue({ location: { nativeElement: {} } });
-      directive.setAriaDescribedBy = jest.fn();
-      directive.setTooltipProperties = jest.fn();
+      directive.setAriaLabeledBy = jest.fn();
     });
 
     it('should create tooltip component', () => {
@@ -90,37 +89,50 @@ describe('TooltipDirective', () => {
       expect(directive.elementRef.nativeElement.appendChild).toHaveBeenCalled();
     });
 
-    it('should set aria-describedby attribute to parent', () => {
+    it('should set aria-labeledby attribute to parent', () => {
       directive.createTooltip();
 
-      expect(directive.setAriaDescribedBy).toHaveBeenCalled();
+      expect(directive.setAriaLabeledBy).toHaveBeenCalled();
+    });
+  });
+
+  describe('showTooltip', () => {
+    beforeEach(() => {
+      directive.setTooltipProperties = jest.fn();
+      directive.elementRef.nativeElement.contains = jest.fn().mockReturnValue(true);
+    });
+
+    it('should check if element focused', () => {
+      directive.showTooltip();
+
+      expect(directive.elementRef.nativeElement.contains).toHaveBeenCalled();
     });
 
     it('should set tooltip properties', () => {
-      directive.createTooltip();
+      directive.showTooltip();
 
-      expect(directive.setTooltipProperties).toHaveBeenCalled();
+      expect(directive.setTooltipProperties).toHaveBeenCalledWith(true);
     });
   });
 
-  describe('destroyTooltip', () => {
-    it('should destroy tooltip', () => {
-      directive.destroy = jest.fn();
+  describe('hideTooltip', () => {
+    it('should hide tooltip', () => {
+      directive.hide = jest.fn();
 
-      directive.destroyTooltip();
+      directive.hideTooltip();
 
-      expect(directive.destroy).toHaveBeenCalled();
+      expect(directive.hide).toHaveBeenCalled();
     });
   });
 
   describe('onKeydown', () => {
-    it('should destroy tooltip if escape key pressed', () => {
-      directive.destroy = jest.fn();
+    it('should hide tooltip if escape key pressed', () => {
+      directive.hide = jest.fn();
       const escapeEvent: KeyboardEvent = { ...new KeyboardEvent('esc'), key: 'Escape' };
 
       directive.onKeydown(escapeEvent);
 
-      expect(directive.destroy).toHaveBeenCalled();
+      expect(directive.hide).toHaveBeenCalled();
     });
   });
 
@@ -149,6 +161,7 @@ describe('TooltipDirective', () => {
         left: 500,
         text: 'I am tooltip',
         top: 1000,
+        show: true,
       });
     });
 
@@ -159,7 +172,7 @@ describe('TooltipDirective', () => {
     });
   });
 
-  describe('setAriaDescribedBy', () => {
+  describe('setAriaLabeledBy', () => {
     beforeEach(() => {
       directive.getFocusableElement = jest.fn();
       directive.renderer.setAttribute = jest.fn();
@@ -167,31 +180,31 @@ describe('TooltipDirective', () => {
     });
 
     it('should check if parent element focusable', () => {
-      directive.setAriaDescribedBy();
+      directive.setAriaLabeledBy();
 
       expect(directive.interactivityChecker.isFocusable).toHaveBeenCalled();
     });
 
     it('should get focusable element if parent not focusable', () => {
-      directive.setAriaDescribedBy();
+      directive.setAriaLabeledBy();
 
       expect(directive.getFocusableElement).toHaveBeenCalled();
     });
 
-    it('should set aria-describedby attribute', () => {
-      directive.setAriaDescribedBy();
+    it('should set aria-labeledby attribute', () => {
+      directive.setAriaLabeledBy();
 
       expect(directive.renderer.setAttribute).toHaveBeenCalled();
     });
   });
 
-  describe('removeAriaDescribedBy', () => {
+  describe('removeAriaLabeledBy', () => {
     beforeEach(() => {
       directive.renderer.removeAttribute = jest.fn();
     });
 
-    it('should remove aria-describedby attribute', () => {
-      directive.removeAriaDescribedBy();
+    it('should remove aria-labeledby attribute', () => {
+      directive.removeAriaLabeledBy();
 
       expect(directive.renderer.removeAttribute).toHaveBeenCalled();
     });
@@ -217,10 +230,22 @@ describe('TooltipDirective', () => {
     });
   });
 
+  describe('hide', () => {
+    beforeEach(() => {
+      directive.componentRef = Object.assign(mockComponentRef, { instance: { ...mockComponentRef.instance, show: true } });
+    });
+
+    it('should hide component', () => {
+      directive.hide();
+
+      expect(directive.componentRef.instance.show).toBeFalsy;
+    });
+  });
+
   describe('destroy', () => {
     beforeEach(() => {
       directive.componentRef = mockComponentRef;
-      directive.removeAriaDescribedBy = jest.fn();
+      directive.removeAriaLabeledBy = jest.fn();
     });
 
     it('should set component ref to null', () => {
@@ -229,10 +254,10 @@ describe('TooltipDirective', () => {
       expect(directive.componentRef).toBeNull();
     });
 
-    it('should remove aria-describedby attribute', () => {
+    it('should remove aria-labeledby attribute', () => {
       directive.destroy();
 
-      expect(directive.removeAriaDescribedBy).toHaveBeenCalled();
+      expect(directive.removeAriaLabeledBy).toHaveBeenCalled();
     });
 
     it('should set focusable element to null', () => {
diff --git a/alfa-client/libs/design-system/src/lib/tooltip/tooltip.directive.ts b/alfa-client/libs/design-system/src/lib/tooltip/tooltip.directive.ts
index f624d583427930c3a5fbb8cf5c42d85c1c43f0bb..09d7958f93cd817c6cc8fba64f329e9684902c1c 100644
--- a/alfa-client/libs/design-system/src/lib/tooltip/tooltip.directive.ts
+++ b/alfa-client/libs/design-system/src/lib/tooltip/tooltip.directive.ts
@@ -31,6 +31,7 @@ import {
   inject,
   Input,
   OnDestroy,
+  OnInit,
   Renderer2,
   ViewContainerRef,
 } from '@angular/core';
@@ -43,7 +44,7 @@ const OUTLINE_INDENT = 4; // Outline offset (2) + outline width (2)
   selector: '[tooltip]',
   standalone: true,
 })
-export class TooltipDirective implements OnDestroy {
+export class TooltipDirective implements OnInit, OnDestroy {
   @Input() tooltip: string = '';
 
   componentRef: ComponentRef<TooltipComponent> = null;
@@ -55,22 +56,19 @@ export class TooltipDirective implements OnDestroy {
   public renderer: Renderer2 = inject(Renderer2);
   public interactivityChecker: InteractivityChecker = inject(InteractivityChecker);
 
+  ngOnInit(): void {
+    this.createTooltip();
+  }
+
   ngOnDestroy(): void {
     this.destroy();
   }
 
   @HostListener('mouseenter')
   @HostListener('focusin')
-  createTooltip(): void {
-    if (isNotNull(this.componentRef)) {
-      return;
-    }
-
+  showTooltip(): void {
     const nativeElement: HTMLElement = this.elementRef.nativeElement;
     const attachedToFocused: boolean = nativeElement.contains(document.activeElement);
-    this.componentRef = this.viewContainerRef.createComponent(TooltipComponent);
-    nativeElement.appendChild(this.componentRef.location.nativeElement);
-    this.setAriaDescribedBy();
     this.setTooltipProperties(attachedToFocused);
   }
 
@@ -78,15 +76,26 @@ export class TooltipDirective implements OnDestroy {
   @HostListener('window:scroll')
   @HostListener('focusout')
   @HostListener('window:resize')
-  destroyTooltip(): void {
-    this.destroy();
+  hideTooltip(): void {
+    this.hide();
   }
 
   @HostListener('keydown', ['$event'])
   onKeydown(e: KeyboardEvent): void {
     if (isEscapeKey(e)) {
-      this.destroy();
+      this.hide();
+    }
+  }
+
+  createTooltip(): void {
+    if (isNotNull(this.componentRef)) {
+      return;
     }
+
+    const nativeElement: HTMLElement = this.elementRef.nativeElement;
+    this.componentRef = this.viewContainerRef.createComponent(TooltipComponent);
+    nativeElement.appendChild(this.componentRef.location.nativeElement);
+    this.setAriaLabeledBy();
   }
 
   setTooltipProperties(attachedToFocused = false): void {
@@ -99,24 +108,33 @@ export class TooltipDirective implements OnDestroy {
     this.componentRef.instance.top = attachedToFocused ? bottom + OUTLINE_INDENT : bottom;
     this.componentRef.instance.text = this.tooltip;
     this.componentRef.instance.id = this.tooltipId;
+    this.componentRef.instance.show = true;
   }
 
-  setAriaDescribedBy(): void {
+  setAriaLabeledBy(): void {
     const nativeElement: HTMLElement = this.elementRef.nativeElement;
     this.tooltipId = uniqueId('tooltip');
     this.focusableElement =
       this.interactivityChecker.isFocusable(nativeElement) ? nativeElement : this.getFocusableElement(nativeElement);
-    this.renderer.setAttribute(this.focusableElement, 'aria-describedby', this.tooltipId);
+    this.renderer.setAttribute(this.focusableElement, 'aria-labeledby', this.tooltipId);
   }
 
-  removeAriaDescribedBy(): void {
-    this.renderer.removeAttribute(this.focusableElement, 'aria-describedby');
+  removeAriaLabeledBy(): void {
+    this.renderer.removeAttribute(this.focusableElement, 'aria-labeledby');
   }
 
   getFocusableElement(element: HTMLElement): HTMLElement {
     return element.querySelector('a[href], button, input, textarea, select, details, [tabindex]:not([tabindex="-1"])');
   }
 
+  hide(): void {
+    if (isNull(this.componentRef)) {
+      return;
+    }
+
+    this.componentRef.instance.show = false;
+  }
+
   destroy(): void {
     if (isNull(this.componentRef)) {
       return;
@@ -124,7 +142,7 @@ export class TooltipDirective implements OnDestroy {
 
     this.componentRef.destroy();
     this.componentRef = null;
-    this.removeAriaDescribedBy();
+    this.removeAriaLabeledBy();
     this.focusableElement = null;
   }
 }