@vodafone_de/brix-components 17.1.0 → 17.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -19,7 +19,7 @@ import Heading from "../Heading/index.js";
19
19
  import { h as headingAlignCenter } from "../../props-GrMT6XLD.js";
20
20
  import { t as tertiaryAppearance } from "../../ButtonAppearances-BEMZJMeh.js";
21
21
  import { t as textHeadingXs } from "../../HeadingSize-O__w72MO.js";
22
- import { notifyConsentChange } from "../../hooks/useThirdPartyConsent/index.js";
22
+ import { requestConsentFocus, notifyConsentChange } from "../../hooks/useThirdPartyConsent/index.js";
23
23
  const ConsentMessageBackgroundStyled = styled.div.withConfig({
24
24
  displayName: "ConsentMessageBackgroundStyled",
25
25
  componentId: "sc-gbn604-0"
@@ -120,13 +120,15 @@ const ConsentMessage = ({
120
120
  (window._dfq || (window._dfq = [])).push(["consent show", {
121
121
  page: "settings",
122
122
  callback: (result) => {
123
- var _a, _b;
123
+ var _a;
124
+ const consentDenied = false === result.permissions.externalContent;
125
+ if (!consentDenied) {
126
+ requestConsentFocus(focusOnConsent);
127
+ }
124
128
  notifyConsentChange();
125
- if (false === result.permissions.externalContent) {
129
+ if (consentDenied) {
126
130
  (_a = document.getElementById(buttonId)) == null ? void 0 : _a.focus();
127
- return;
128
131
  }
129
- (_b = document.getElementById(focusOnConsent)) == null ? void 0 : _b.focus();
130
132
  }
131
133
  }]);
132
134
  } catch (e) {
@@ -29,7 +29,8 @@ export interface ConsentMessageProps extends BrixComponentProps, Omit<HTMLAttrib
29
29
  */
30
30
  button: string;
31
31
  /**
32
- * CSS selector or ID of the element to focus after consent is granted.
32
+ * ID of the element that receives focus after consent is granted.
33
+ * Focus moves as soon as that element is rendered.
33
34
  */
34
35
  focusOnConsent: string;
35
36
  /**
@@ -5,7 +5,7 @@ import { useEffect, useState } from "react";
5
5
  import ConsentMessage from "../ConsentMessage/index.js";
6
6
  import { S as ScreenreaderOnly } from "../../index-Dgu9iIhb.js";
7
7
  import { s as spacingMd } from "../../Spacing-Dj-qX3Z5.js";
8
- import { useThirdPartyConsent } from "../../hooks/useThirdPartyConsent/index.js";
8
+ import { useThirdPartyConsent, useConsentFocus } from "../../hooks/useThirdPartyConsent/index.js";
9
9
  import styled from "styled-components";
10
10
  import { v as viewport } from "../../index-CG4uiVbZ.js";
11
11
  import { getBorderColor } from "../../foundations/token/getBorderColor/index.js";
@@ -95,6 +95,7 @@ const GoogleMap = ({
95
95
  const [map, setMap] = useState(null);
96
96
  const id = `maps-${props.uid}`;
97
97
  const screenreaderId = `screenreader-${props.uid}`;
98
+ useConsentFocus(screenreaderId, consent);
98
99
  children = children || defaultBasicMap;
99
100
  useEffect(() => {
100
101
  if (!map) {
@@ -2,7 +2,7 @@
2
2
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
3
3
  import ConsentMessage from "../ConsentMessage/index.js";
4
4
  import { S as ScreenreaderOnly } from "../../index-Dgu9iIhb.js";
5
- import { useThirdPartyConsent } from "../../hooks/useThirdPartyConsent/index.js";
5
+ import { useThirdPartyConsent, useConsentFocus } from "../../hooks/useThirdPartyConsent/index.js";
6
6
  import styled from "styled-components";
7
7
  import { translateLayoutPropsToCss } from "../../foundations/layout/index.js";
8
8
  import { getBorderRadius } from "../../foundations/token/getBorderRadius/index.js";
@@ -80,6 +80,7 @@ const YouTubeVideo = ({
80
80
  }) => {
81
81
  const consent = useThirdPartyConsent();
82
82
  const id = `youtube-${props.uid}`;
83
+ useConsentFocus(id, consent);
83
84
  return /* @__PURE__ */ jsx(YouTubeVideoStyled, { ...props, roundedCorners, children: !consent ? /* @__PURE__ */ jsx(ConsentMessage, { ...consentMessage, focusOnConsent: id, variant: consentVariantVideo }) : /* @__PURE__ */ jsxs(Fragment, { children: [
84
85
  /* @__PURE__ */ jsx(ScreenreaderOnly, { id, tabIndex: -1, children: consentSuccessText }),
85
86
  /* @__PURE__ */ jsx(YouTubeVideoIframeStyled, { src: getYouTubeUrl({
@@ -21,6 +21,17 @@ export declare const checkThirdPartyConsentStorage: () => boolean;
21
21
  * This should be called whenever the consent storage is updated.
22
22
  */
23
23
  export declare const notifyConsentChange: () => void;
24
+ /**
25
+ * Requests focus for `targetId`, either right away or once `useConsentFocus` sees it mounted.
26
+ * Supersedes a request that is still pending.
27
+ */
28
+ export declare const requestConsentFocus: (targetId: string) => void;
29
+ /**
30
+ * Completes the focus handover started by a ConsentMessage once the consented content is
31
+ * mounted, so focus stays inside the surrounding context (for example a Tray). Without a
32
+ * pending request nothing happens, so an already consented page load never moves focus.
33
+ */
34
+ export declare const useConsentFocus: (targetId: string, consent: boolean) => void;
24
35
  /**
25
36
  * The useThirdPartyConsent hook is a custom React Hook designed to
26
37
  * track and respond to changes in a user's third-party consent status,
@@ -1,4 +1,4 @@
1
- import { useState, useEffect } from "react";
1
+ import { useEffect, useState } from "react";
2
2
  const CONSENT_CHANGE_EVENT = "brix-consent-change";
3
3
  const consentStorageItemName = "adv_fcData";
4
4
  const consentStorageFeature = "permissions";
@@ -31,6 +31,38 @@ const checkThirdPartyConsentStorage = () => {
31
31
  const notifyConsentChange = () => {
32
32
  window.dispatchEvent(new CustomEvent(CONSENT_CHANGE_EVENT));
33
33
  };
34
+ let requestedConsentFocusId = null;
35
+ const focusRequestedConsentTarget = (targetId) => {
36
+ const target = document.getElementById(targetId);
37
+ if (!target) {
38
+ return;
39
+ }
40
+ requestedConsentFocusId = null;
41
+ target.focus();
42
+ };
43
+ const requestConsentFocus = (targetId) => {
44
+ requestedConsentFocusId = targetId;
45
+ focusRequestedConsentTarget(targetId);
46
+ };
47
+ const clearConsentFocusRequest = () => {
48
+ requestedConsentFocusId = null;
49
+ };
50
+ const useConsentFocus = (targetId, consent) => {
51
+ useEffect(() => {
52
+ if (!consent) {
53
+ return;
54
+ }
55
+ if (requestedConsentFocusId !== targetId) {
56
+ return;
57
+ }
58
+ focusRequestedConsentTarget(targetId);
59
+ return () => {
60
+ if (requestedConsentFocusId === targetId) {
61
+ clearConsentFocusRequest();
62
+ }
63
+ };
64
+ }, [consent, targetId]);
65
+ };
34
66
  const useThirdPartyConsent = () => {
35
67
  const [consent, setConsent] = useState(false);
36
68
  useEffect(() => {
@@ -54,5 +86,7 @@ export {
54
86
  consentStorageItemName,
55
87
  consentStorageKey,
56
88
  notifyConsentChange,
89
+ requestConsentFocus,
90
+ useConsentFocus,
57
91
  useThirdPartyConsent
58
92
  };
package/dist/index.js CHANGED
@@ -117,7 +117,7 @@ import { translateLayoutPropsToCss } from "./foundations/layout/index.js";
117
117
  import { gridColSpans } from "./foundations/GridConfig/index.js";
118
118
  import { GlobalStyle, cssReset } from "./foundations/GlobalStyle/index.js";
119
119
  import { u } from "./index-DlENLqPq.js";
120
- import { CONSENT_CHANGE_EVENT, checkThirdPartyConsentStorage, consentStorageFeature, consentStorageItemName, consentStorageKey, notifyConsentChange, useThirdPartyConsent } from "./hooks/useThirdPartyConsent/index.js";
120
+ import { CONSENT_CHANGE_EVENT, checkThirdPartyConsentStorage, consentStorageFeature, consentStorageItemName, consentStorageKey, notifyConsentChange, requestConsentFocus, useConsentFocus, useThirdPartyConsent } from "./hooks/useThirdPartyConsent/index.js";
121
121
  import { useReducedMotion } from "./hooks/useReducedMotion/index.js";
122
122
  import { DefaultPicture, PictureContext, PictureProvider, filterAspectRatioFromSources, filterImagePropsToPictureComponentImageProps, usePictureComponent } from "./hooks/usePictureComponent/index.js";
123
123
  import { useMediaQuery } from "./hooks/useMediaQuery/index.js";
@@ -539,6 +539,7 @@ export {
539
539
  i12 as priceSizes,
540
540
  p2 as primaryBadgeAppearance,
541
541
  reducedMotionQuery,
542
+ requestConsentFocus,
542
543
  r as richTextContentfulTags,
543
544
  s2 as secondaryBadgeAppearance,
544
545
  c5 as successBadgeAppearance,
@@ -553,6 +554,7 @@ export {
553
554
  t3 as tertiaryBadgeAppearance,
554
555
  t7 as textListTags,
555
556
  translateLayoutPropsToCss,
557
+ useConsentFocus,
556
558
  useFocusWithin,
557
559
  useForcedColors,
558
560
  useImageComponent,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vodafone_de/brix-components",
3
3
  "description": "Brix is the digital design system for vodafone.de",
4
- "version": "17.1.0",
4
+ "version": "17.1.1",
5
5
  "exports": {
6
6
  "./package.json": "./package.json",
7
7
  ".": {