Skip to content

Commit

Permalink
Add option to turn on autofocus (#200)
Browse files Browse the repository at this point in the history
* upgrade airgap.js types

* upgrade airgap.js types to right version...

* add autofocus + fix-ish eslint

* bump package version
  • Loading branch information
linh-transcend authored Dec 4, 2024
1 parent 0334a95 commit 8379d69
Show file tree
Hide file tree
Showing 11 changed files with 31 additions and 17 deletions.
10 changes: 5 additions & 5 deletions .pnp.cjs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file not shown.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"url": "https://github.com/transcend-io/consent-manager-ui.git"
},
"homepage": "https://github.com/transcend-io/consent-manager-ui",
"version": "4.22.4",
"version": "4.23.0",
"license": "MIT",
"main": "build/ui",
"files": [
Expand Down Expand Up @@ -51,7 +51,7 @@
"@prettier/sync": "^0.5.2",
"@testing-library/jest-dom": "^6.4.6",
"@testing-library/preact": "^3.2.4",
"@transcend-io/airgap.js-types": "^12.3.0",
"@transcend-io/airgap.js-types": "^12.6.0",
"@transcend-io/type-utils": "^1.5.0",
"@types/jest": "^29.5.12",
"@types/node": "^17.0.45",
Expand Down
4 changes: 3 additions & 1 deletion src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ export function App({
const [currentVariables, handleChangeUiVariables] = useState({});

// Get default view states
const { initialViewStateByPrivacyRegime, dismissedViewState } = config;
const { initialViewStateByPrivacyRegime, dismissedViewState, autofocus } =
config;
const initialViewState =
initialViewStateByPrivacyRegime[
privacyRegime as keyof typeof initialViewStateByPrivacyRegime
Expand All @@ -66,6 +67,7 @@ export function App({
document.activeElement !== document.body
? document.activeElement
: null,
autofocus,
});

// Language setup
Expand Down
1 change: 1 addition & 0 deletions src/components/CompleteOptionsToggles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export function CompleteOptionsToggles({
consentSelection: initialConsentSelections,
defaultPurposeToMessageKey: DEFAULT_PURPOSE_TO_MESSAGE_KEY,
});
// eslint-disable-next-line react-hooks/exhaustive-deps
const purposeToDescription = useMemo(() => airgap.getPurposeTypes(), []);
const purposeToDescriptionKey = useGetPurposeDescriptionKeys({
consentSelection: initialConsentSelections,
Expand Down
1 change: 1 addition & 0 deletions src/components/DoNotSellDisclosure.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export function DoNotSellDisclosure({
useEffect(() => {
handleOptOut(modalOpenAuth);
setIsOptedOut(true);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

// delay UI until opt out happens
Expand Down
7 changes: 5 additions & 2 deletions src/components/Main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,15 @@ export function Main({
const dialogRef = useRef<HTMLDivElement>(null);
useEffect(() => {
if (!isViewStateClosed(viewState) && dialogRef.current) {
const shouldAutofocus = config.autofocus ?? true;

This comment has been minimized.

Copy link
@eligrey

eligrey Dec 6, 2024

Member

@linh-transcend I think we should explicitly look for === 'on' or !== 'off'. The way it's currently implemented, the only way to disable autofocus is with data-autofocus="" which feels a bit awkward

This comment has been minimized.

Copy link
@eligrey

eligrey Dec 6, 2024

Member

in the changelog it says that data-autofocus="false" enables this feature but I don't see how that would work

// This setTimeout was necessary for the api triggered states, (DoNotSell|OptOut)Disclosure
setTimeout(() => {
if (dialogRef.current) initialFocusElement(dialogRef.current);
if (dialogRef.current && shouldAutofocus) {
initialFocusElement(dialogRef.current);
}
}, 0);
}
}, [viewState, dialogRef]);
}, [viewState, dialogRef, config.autofocus]);

// Modal open views
if (!isViewStateClosed(viewState)) {
Expand Down
1 change: 1 addition & 0 deletions src/components/OptOutDisclosure.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export function OptOutDisclosure({
useEffect(() => {
handleOptOut(modalOpenAuth);
setIsOptedOut(true);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

// delay UI until opt out happens
Expand Down
1 change: 1 addition & 0 deletions src/hooks/useGetPurposeDescriptionKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export const useGetPurposeDescriptionKeys = ({
},
defaultPurposeToDescriptionKey as Record<string, DefinedMessage>,
),
// eslint-disable-next-line react-hooks/exhaustive-deps
[consentSelection, defaultPurposeToDescriptionKey],
);

Expand Down
9 changes: 7 additions & 2 deletions src/hooks/useViewState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export function useViewState({
dismissedViewState,
eventTarget,
savedActiveElement,
autofocus,
}: {
/** Which state this consent manager should go to when opened */
initialViewState: InitialViewState;
Expand All @@ -62,6 +63,8 @@ export function useViewState({
eventTarget: EventTarget;
/** Element previously focused before our ui modal was opened */
savedActiveElement: HTMLElement | null;
/** Whether to on last focused element on reopen */
autofocus?: boolean;
}): {
/** The current view state */
viewState: ViewState;
Expand Down Expand Up @@ -134,7 +137,8 @@ export function useViewState({
* very difficult to interact with. We create an element with maximum focus priority and
* focus it so that when we delete it the user will be at the start of the focus order
* just like if they had freshly loaded the page. */
if (savedActiveElement !== null) {
const shouldFocus = autofocus ?? true;
if (savedActiveElement !== null && shouldFocus) {
savedActiveElement.focus();
} else {
const tempInteractiveEl = document.createElement('span');
Expand All @@ -159,7 +163,8 @@ export function useViewState({
break;
}
},
[state, setState, initialViewState, dismissedViewState],
// eslint-disable-next-line react-hooks/exhaustive-deps
[state, setState, initialViewState, dismissedViewState, autofocus],
);

// Now that the viewState has updated, dispatch an event on the `transcend` API / event target
Expand Down
10 changes: 5 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1123,14 +1123,14 @@ __metadata:
languageName: node
linkType: hard

"@transcend-io/airgap.js-types@npm:^12.3.0":
version: 12.3.0
resolution: "@transcend-io/airgap.js-types@npm:12.3.0"
"@transcend-io/airgap.js-types@npm:^12.6.0":
version: 12.6.0
resolution: "@transcend-io/airgap.js-types@npm:12.6.0"
dependencies:
"@transcend-io/type-utils": "npm:^1.2.0"
fp-ts: "npm:^2.16.1"
io-ts: "npm:^2.2.21"
checksum: 10/f7a834296ef20c7415adff5167f0a8c3a629b4fd9fe5cc66988f88641fc2d300f11eedfdac4e55e71a59aa996439a9f93426041977455cde839dbe8445483951
checksum: 10/4d22a5b1b77c3b2d03995f142171d69664df31d6212bd2776762a5aa90cb6f2b0bfe44b8d00f3647be1558dab8080348d7cd6800aeee2d510de6b7aa2699a88a
languageName: node
linkType: hard

Expand All @@ -1155,7 +1155,7 @@ __metadata:
"@prettier/sync": "npm:^0.5.2"
"@testing-library/jest-dom": "npm:^6.4.6"
"@testing-library/preact": "npm:^3.2.4"
"@transcend-io/airgap.js-types": "npm:^12.3.0"
"@transcend-io/airgap.js-types": "npm:^12.6.0"
"@transcend-io/internationalization": "npm:^1.6.0"
"@transcend-io/logger": "npm:^1.1.0"
"@transcend-io/type-utils": "npm:^1.5.0"
Expand Down

0 comments on commit 8379d69

Please sign in to comment.