Skip to content
Snippets Groups Projects
Commit 791cb43d authored by OZGCloud's avatar OZGCloud
Browse files

Merge remote-tracking branch 'origin/master' into OZG-6477-collaborations-anzeigen

# Conflicts:
#	alfa-client/package-lock.json
#	alfa-client/package.json
parents 4947e9b2 4fbd21db
No related branches found
No related tags found
No related merge requests found
pipeline {
agent {
node {
label 'ozgcloud-jenkins-build-agent'
label 'ozgcloud-jenkins-build-agent-jdk21-node20'
}
}
......@@ -11,7 +11,8 @@ pipeline {
SNAPSHOT_REGEX = /\d+.\d+.\d+-SNAPSHOT/
FAILED_STAGE = ""
SH_SUCCESS_STATUS_CODE = 0
FORCE_COLOR = 0
NO_COLOR = 1
}
options {
......
......@@ -51,7 +51,7 @@ describe('TooltipDirective', () => {
describe('createTooltip', () => {
beforeEach(() => {
directive.viewContainerRef.createComponent = jest.fn().mockReturnValue({ location: { nativeElement: {} } });
directive.setDescribedBy = jest.fn();
directive.setAriaDescribedBy = jest.fn();
directive.setTooltipProperties = jest.fn();
});
......@@ -67,10 +67,10 @@ describe('TooltipDirective', () => {
expect(directive.elementRef.nativeElement.appendChild).toHaveBeenCalled();
});
it('should set aria described by attribute to parent', () => {
it('should set aria-describedby attribute to parent', () => {
directive.createTooltip();
expect(directive.setDescribedBy).toHaveBeenCalled();
expect(directive.setAriaDescribedBy).toHaveBeenCalled();
});
it('should set tooltip properties', () => {
......@@ -136,7 +136,7 @@ describe('TooltipDirective', () => {
});
});
describe('setDescribedBy', () => {
describe('setAriaDescribedBy', () => {
beforeEach(() => {
directive.getFocusableElement = jest.fn();
directive.renderer.setAttribute = jest.fn();
......@@ -144,31 +144,31 @@ describe('TooltipDirective', () => {
});
it('should check if parent element focusable', () => {
directive.setDescribedBy();
directive.setAriaDescribedBy();
expect(directive.interactivityChecker.isFocusable).toHaveBeenCalled();
});
it('should get focusable element if parent not focusable', () => {
directive.setDescribedBy();
directive.setAriaDescribedBy();
expect(directive.getFocusableElement).toHaveBeenCalled();
});
it('should set describedby attribute', () => {
directive.setDescribedBy();
it('should set aria-describedby attribute', () => {
directive.setAriaDescribedBy();
expect(directive.renderer.setAttribute).toHaveBeenCalled();
});
});
describe('removeDescribedBy', () => {
describe('removeAriaDescribedBy', () => {
beforeEach(() => {
directive.renderer.removeAttribute = jest.fn();
});
it('should remove describedby attribute', () => {
directive.removeDescribedBy();
it('should remove aria-describedby attribute', () => {
directive.removeAriaDescribedBy();
expect(directive.renderer.removeAttribute).toHaveBeenCalled();
});
......@@ -197,7 +197,7 @@ describe('TooltipDirective', () => {
describe('destroy', () => {
beforeEach(() => {
directive.componentRef = mockComponentRef;
directive.removeDescribedBy = jest.fn();
directive.removeAriaDescribedBy = jest.fn();
});
it('should set component ref to null', () => {
......@@ -206,10 +206,10 @@ describe('TooltipDirective', () => {
expect(directive.componentRef).toBeNull();
});
it('should remove describedby attribute', () => {
it('should remove aria-describedby attribute', () => {
directive.destroy();
expect(directive.removeDescribedBy).toHaveBeenCalled();
expect(directive.removeAriaDescribedBy).toHaveBeenCalled();
});
it('should set focusable element to null', () => {
......
import { isEscapeKey } from '@alfa-client/tech-shared';
import { isEscapeKey, isNotNull } from '@alfa-client/tech-shared';
import { InteractivityChecker } from '@angular/cdk/a11y';
import {
ComponentRef,
......@@ -11,9 +11,11 @@ import {
Renderer2,
ViewContainerRef,
} from '@angular/core';
import { uniqueId } from 'lodash-es';
import { isNull, uniqueId } from 'lodash-es';
import { TooltipComponent } from './tooltip.component';
const OUTLINE_INDENT = 4; // Outline offset (2) + outline width (2)
@Directive({
selector: '[tooltip]',
standalone: true,
......@@ -37,15 +39,17 @@ export class TooltipDirective implements OnDestroy {
@HostListener('mouseenter')
@HostListener('focusin')
createTooltip(): void {
if (this.componentRef === null) {
if (isNotNull(this.componentRef)) {
return;
}
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.setDescribedBy();
this.setAriaDescribedBy();
this.setTooltipProperties(attachedToFocused);
}
}
@HostListener('mouseleave')
@HostListener('window:scroll')
......@@ -62,16 +66,18 @@ export class TooltipDirective implements OnDestroy {
}
setTooltipProperties(attachedToFocused = false): void {
if (this.componentRef !== null) {
if (isNull(this.componentRef)) {
return;
}
const { left, right, bottom } = this.elementRef.nativeElement.getBoundingClientRect();
this.componentRef.instance.left = (right + left) / 2;
this.componentRef.instance.top = attachedToFocused ? bottom + 4 : bottom;
this.componentRef.instance.top = attachedToFocused ? bottom + OUTLINE_INDENT : bottom;
this.componentRef.instance.text = this.tooltip;
this.componentRef.instance.id = this.tooltipId;
}
}
setDescribedBy(): void {
setAriaDescribedBy(): void {
const nativeElement: HTMLElement = this.elementRef.nativeElement;
this.tooltipId = uniqueId('tooltip');
this.focusableElement =
......@@ -79,7 +85,7 @@ export class TooltipDirective implements OnDestroy {
this.renderer.setAttribute(this.focusableElement, 'aria-describedby', this.tooltipId);
}
removeDescribedBy(): void {
removeAriaDescribedBy(): void {
this.renderer.removeAttribute(this.focusableElement, 'aria-describedby');
}
......@@ -88,11 +94,13 @@ export class TooltipDirective implements OnDestroy {
}
destroy(): void {
if (this.componentRef !== null) {
if (isNull(this.componentRef)) {
return;
}
this.componentRef.destroy();
this.componentRef = null;
this.removeDescribedBy();
this.removeAriaDescribedBy();
this.focusableElement = null;
}
}
}
This diff is collapsed.
......@@ -47,7 +47,7 @@
"cypress:open-admin": "npx cypress open --project apps/admin-e2e",
"workspace-generator": "nx workspace-generator",
"storybook": "nx storybook design-system",
"ci-storybook": "nx storybook build design-system && nx container design-system"
"ci-storybook": "nx build-storybook design-system && nx container design-system"
},
"private": true,
"dependencies": {
......@@ -114,10 +114,10 @@
"@nx/web": "19.8.8",
"@nx/workspace": "19.8.8",
"@schematics/angular": "18.2.8",
"@storybook/addon-essentials": "^8.3.5",
"@storybook/addon-interactions": "^8.3.5",
"@storybook/angular": "^8.3.5",
"@storybook/core-server": "^8.3.5",
"@storybook/addon-essentials": "^8.4.2",
"@storybook/addon-interactions": "^8.4.2",
"@storybook/angular": "^8.4.2",
"@storybook/core-server": "^8.4.2",
"@swc-node/register": "~1.9.1",
"@swc/core": "~1.5.7",
"@swc/helpers": "~0.5.11",
......@@ -156,7 +156,7 @@
"prettier-plugin-organize-imports": "^4.1.0",
"prettier-plugin-tailwindcss": "^0.6.8",
"sonarqube-scanner": "^4.2.5",
"storybook": "^8.3.5",
"storybook": "^8.4.2",
"tailwind-merge": "^2.5.4",
"tailwindcss": "^3.4.14",
"ts-jest": "^29.1.0",
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment