Skip to content

Commit ea24e97

Browse files
authored
feat: Add S2 ActionBar component (#7446)
* feat: Add S2 ActionBar component * Move animation hooks into @react-aria/utils * Use auto static color and only accept action buttons as children * i hate you yarn 4 * skip codemod for now * Remove z-index so menus are on top * Update close button colors to match action button confirmed with design in slack * Review comments
1 parent 4b97149 commit ea24e97

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+812
-222
lines changed

packages/@react-aria/utils/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929
"clsx": "^2.0.0"
3030
},
3131
"peerDependencies": {
32-
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
32+
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1",
33+
"react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
3334
},
3435
"publishConfig": {
3536
"access": "public"
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* Copyright 2020 Adobe. All rights reserved.
3+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License. You may obtain a copy
5+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
*
7+
* Unless required by applicable law or agreed to in writing, software distributed under
8+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9+
* OF ANY KIND, either express or implied. See the License for the specific language
10+
* governing permissions and limitations under the License.
11+
*/
12+
13+
import {flushSync} from 'react-dom';
14+
import {RefObject, useCallback, useRef, useState} from 'react';
15+
import {useLayoutEffect} from './useLayoutEffect';
16+
17+
export function useEnterAnimation(ref: RefObject<HTMLElement | null>, isReady: boolean = true) {
18+
let [isEntering, setEntering] = useState(true);
19+
useAnimation(ref, isEntering && isReady, useCallback(() => setEntering(false), []));
20+
return isEntering && isReady;
21+
}
22+
23+
export function useExitAnimation(ref: RefObject<HTMLElement | null>, isOpen: boolean) {
24+
// State to trigger a re-render after animation is complete, which causes the element to be removed from the DOM.
25+
// Ref to track the state we're in, so we don't immediately reset isExiting to true after the animation.
26+
let [isExiting, setExiting] = useState(false);
27+
let [exitState, setExitState] = useState('idle');
28+
29+
// If isOpen becomes false, set isExiting to true.
30+
if (!isOpen && ref.current && exitState === 'idle') {
31+
isExiting = true;
32+
setExiting(true);
33+
setExitState('exiting');
34+
}
35+
36+
// If we exited, and the element has been removed, reset exit state to idle.
37+
if (!ref.current && exitState === 'exited') {
38+
setExitState('idle');
39+
}
40+
41+
useAnimation(
42+
ref,
43+
isExiting,
44+
useCallback(() => {
45+
setExitState('exited');
46+
setExiting(false);
47+
}, [])
48+
);
49+
50+
return isExiting;
51+
}
52+
53+
function useAnimation(ref: RefObject<HTMLElement | null>, isActive: boolean, onEnd: () => void) {
54+
let prevAnimation = useRef<string | null>(null);
55+
if (isActive && ref.current) {
56+
// This is ok because we only read it in the layout effect below, immediately after the commit phase.
57+
// We could move this to another effect that runs every render, but this would be unnecessarily slow.
58+
// We only need the computed style right before the animation becomes active.
59+
// eslint-disable-next-line rulesdir/pure-render
60+
prevAnimation.current = window.getComputedStyle(ref.current).animation;
61+
}
62+
63+
useLayoutEffect(() => {
64+
if (isActive && ref.current) {
65+
// Make sure there's actually an animation, and it wasn't there before we triggered the update.
66+
let computedStyle = window.getComputedStyle(ref.current);
67+
if (computedStyle.animationName && computedStyle.animationName !== 'none' && computedStyle.animation !== prevAnimation.current) {
68+
let onAnimationEnd = (e: AnimationEvent) => {
69+
if (e.target === ref.current) {
70+
element.removeEventListener('animationend', onAnimationEnd);
71+
flushSync(() => {onEnd();});
72+
}
73+
};
74+
75+
let element = ref.current;
76+
element.addEventListener('animationend', onAnimationEnd);
77+
return () => {
78+
element.removeEventListener('animationend', onAnimationEnd);
79+
};
80+
} else {
81+
onEnd();
82+
}
83+
}
84+
}, [ref, isActive, onEnd]);
85+
}

packages/@react-aria/utils/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,4 @@ export {useDeepMemo} from './useDeepMemo';
4343
export {useFormReset} from './useFormReset';
4444
export {useLoadMore} from './useLoadMore';
4545
export {CLEAR_FOCUS_EVENT, FOCUS_EVENT, UPDATE_ACTIVEDESCENDANT} from './constants';
46+
export {useEnterAnimation, useExitAnimation} from './animation';

packages/@react-spectrum/s2/intl/ar-AE.json

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
{
2-
"breadcrumbs.more": "المزيد من العناصر",
2+
"actionbar.actions": "الإجراءات",
3+
"actionbar.actionsAvailable": "الإجراءات المتاحة.",
4+
"actionbar.clearSelection": "إزالة التحديد",
5+
"actionbar.selected": "{count, plural, =0 {غير محدد} other {# محدد}}",
6+
"actionbar.selectedAll": "تم تحديد الكل",
37
"button.pending": "قيد الانتظار",
48
"contextualhelp.help": "مساعدة",
59
"contextualhelp.info": "معلومات",
@@ -24,5 +28,6 @@
2428
"tag.actions": "الإجراءات",
2529
"tag.hideButtonLabel": "إظهار أقل",
2630
"tag.noTags": "بدون",
27-
"tag.showAllButtonLabel": "عرض الكل ({tagCount, number})"
28-
}
31+
"tag.showAllButtonLabel": "عرض الكل ({tagCount, number})",
32+
"breadcrumbs.more": "المزيد من العناصر"
33+
}

packages/@react-spectrum/s2/intl/bg-BG.json

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
{
2-
"breadcrumbs.more": "Още елементи",
2+
"actionbar.actions": "Действия",
3+
"actionbar.actionsAvailable": "Налични действия.",
4+
"actionbar.clearSelection": "Изчистване на избора",
5+
"actionbar.selected": "{count, plural, =0 {Няма избрани} one {# избран} other {# избрани}}",
6+
"actionbar.selectedAll": "Всички избрани",
37
"button.pending": "недовършено",
48
"contextualhelp.help": "Помощ",
59
"contextualhelp.info": "Информация",
@@ -24,5 +28,6 @@
2428
"tag.actions": "Действия",
2529
"tag.hideButtonLabel": "Показване на по-малко",
2630
"tag.noTags": "Нито един",
27-
"tag.showAllButtonLabel": "Показване на всички ({tagCount, number})"
28-
}
31+
"tag.showAllButtonLabel": "Показване на всички ({tagCount, number})",
32+
"breadcrumbs.more": "Още елементи"
33+
}

packages/@react-spectrum/s2/intl/cs-CZ.json

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
{
2-
"breadcrumbs.more": "Více položek",
2+
"actionbar.actions": "Akce",
3+
"actionbar.actionsAvailable": "Dostupné akce.",
4+
"actionbar.clearSelection": "Vymazat výběr",
5+
"actionbar.selected": "Vybráno: { count }",
6+
"actionbar.selectedAll": "Vybráno vše",
37
"button.pending": "čeká na vyřízení",
48
"contextualhelp.help": "Nápověda",
59
"contextualhelp.info": "Informace",
@@ -24,5 +28,6 @@
2428
"tag.actions": "Akce",
2529
"tag.hideButtonLabel": "Zobrazit méně",
2630
"tag.noTags": "Žádný",
27-
"tag.showAllButtonLabel": "Zobrazit vše ({tagCount, number})"
28-
}
31+
"tag.showAllButtonLabel": "Zobrazit vše ({tagCount, number})",
32+
"breadcrumbs.more": "Více položek"
33+
}

packages/@react-spectrum/s2/intl/da-DK.json

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
{
2-
"breadcrumbs.more": "Flere elementer",
2+
"actionbar.actions": "Handlinger",
3+
"actionbar.actionsAvailable": "Tilgængelige handlinger.",
4+
"actionbar.clearSelection": "Ryd markering",
5+
"actionbar.selected": "{count, plural, =0 {Ingen valgt} other {# valgt}}",
6+
"actionbar.selectedAll": "Alle valgt",
37
"button.pending": "afventende",
48
"contextualhelp.help": "Hjælp",
59
"contextualhelp.info": "Oplysninger",
@@ -16,13 +20,14 @@
1620
"picker.placeholder": "Vælg…",
1721
"slider.maximum": "Maksimum",
1822
"slider.minimum": "Minimum",
19-
"table.loading": "Indlæser...",
20-
"table.loadingMore": "Indlæser flere...",
23+
"table.loading": "Indlæser ...",
24+
"table.loadingMore": "Indlæser flere ...",
2125
"table.resizeColumn": "Tilpas størrelse på kolonne",
2226
"table.sortAscending": "Sorter stigende",
2327
"table.sortDescending": "Sorter faldende",
2428
"tag.actions": "Handlinger",
2529
"tag.hideButtonLabel": "Vis mindre",
2630
"tag.noTags": "Ingen",
27-
"tag.showAllButtonLabel": "Vis alle ({tagCount, number})"
28-
}
31+
"tag.showAllButtonLabel": "Vis alle ({tagCount, number})",
32+
"breadcrumbs.more": "Flere elementer"
33+
}

packages/@react-spectrum/s2/intl/de-DE.json

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
{
2-
"breadcrumbs.more": "Weitere Elemente",
2+
"actionbar.actions": "Aktionen",
3+
"actionbar.actionsAvailable": "Aktionen verfügbar.",
4+
"actionbar.clearSelection": "Auswahl löschen",
5+
"actionbar.selected": "{count, plural, =0 {Nichts ausgewählt} one {# ausgewählt} other {# ausgewählt}}",
6+
"actionbar.selectedAll": "Alles ausgewählt",
37
"button.pending": "Ausstehend",
48
"contextualhelp.help": "Hilfe",
59
"contextualhelp.info": "Informationen",
@@ -24,5 +28,6 @@
2428
"tag.actions": "Aktionen",
2529
"tag.hideButtonLabel": "Weniger zeigen",
2630
"tag.noTags": "Keine",
27-
"tag.showAllButtonLabel": "Alle anzeigen ({tagCount, number})"
28-
}
31+
"tag.showAllButtonLabel": "Alle anzeigen ({tagCount, number})",
32+
"breadcrumbs.more": "Weitere Elemente"
33+
}

packages/@react-spectrum/s2/intl/el-GR.json

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
{
2-
"breadcrumbs.more": "Περισσότερα στοιχεία",
2+
"actionbar.actions": "Ενέργειες",
3+
"actionbar.actionsAvailable": "Υπάρχουν διαθέσιμες ενέργειες.",
4+
"actionbar.clearSelection": "Εκκαθάριση επιλογής",
5+
"actionbar.selected": "{count, plural, =0 {Δεν επιλέχθηκε κανένα} one {# επιλεγμένο} other {# επιλεγμένα}}",
6+
"actionbar.selectedAll": "Επιλέχθηκαν όλα",
37
"button.pending": "σε εκκρεμότητα",
48
"contextualhelp.help": "Βοήθεια",
59
"contextualhelp.info": "Πληροφορίες",
@@ -24,5 +28,6 @@
2428
"tag.actions": "Ενέργειες",
2529
"tag.hideButtonLabel": "Εμφάνιση λιγότερων",
2630
"tag.noTags": "Κανένα",
27-
"tag.showAllButtonLabel": "Εμφάνιση όλων ({tagCount, number})"
28-
}
31+
"tag.showAllButtonLabel": "Εμφάνιση όλων ({tagCount, number})",
32+
"breadcrumbs.more": "Περισσότερα στοιχεία"
33+
}

packages/@react-spectrum/s2/intl/en-US.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
{
2+
"actionbar.clearSelection": "Clear selection",
3+
"actionbar.selected": "{count, plural, =0 {None selected} other {# selected}}",
4+
"actionbar.selectedAll": "All selected",
5+
"actionbar.actions": "Actions",
6+
"actionbar.actionsAvailable": "Actions available.",
27
"button.pending": "pending",
38
"contextualhelp.info": "Information",
49
"contextualhelp.help": "Help",

0 commit comments

Comments
 (0)