From 7b2913d6f9ac1b649c25ba661de87369c5b1acaa Mon Sep 17 00:00:00 2001 From: Max Yinger Date: Thu, 8 Oct 2026 16:43:12 -0600 Subject: [PATCH 1/5] feat(mosaic): animate contact list rows and the primary badge in the user profile Emails and phone numbers in the account section keep the order they were first shown in while the panel is mounted. Each row sits in a grid slot whose track transitions between 1fr and 0fr, with the content fading inside a clip layer anchored to the top. Setting a primary moves the badge, which enters and exits on the motion rules, rather than the rows. A set-primary request marks its row busy; once it outlasts a short delay a spinner shows where the badge will land and the badge change waits for it. Under reduced motion every change is a cut. Adds usePresenceList and useStableOrder to the primitives, and a useContactList hook shared by the email and phone rows. Co-Authored-By: Claude Fable 5.1 --- .changeset/contact-list-rows.md | 2 + packages/mosaic/docs/motion.md | 106 ++++++++ ...ser-profile-contact-list-row.view.test.tsx | 180 ++++++++++++- .../user-profile-email-actions.test.tsx | 80 ++++-- .../use-contact-list.ts | 68 +++++ ...-profile-account-section.markers.stylex.ts | 3 + .../user-profile-account-section.messages.ts | 1 + .../user-profile-account-section.model.ts | 7 +- .../user-profile-account-section.styles.ts | 121 +++++++++ .../user-profile-contact-list-row.view.tsx | 241 ++++++++++++++---- .../user-profile-email-row.view.tsx | 45 ++-- .../user-profile-phone-row.view.tsx | 54 ++-- packages/mosaic/src/primitives/hooks/index.ts | 2 + .../hooks/use-presence-list.test.tsx | 116 +++++++++ .../src/primitives/hooks/use-presence-list.ts | 99 +++++++ .../hooks/use-stable-order.test.tsx | 62 +++++ .../src/primitives/hooks/use-stable-order.ts | 37 +++ .../stories/user-profile-account-section.mdx | 15 ++ .../user-profile-account-section.stories.tsx | 28 +- 19 files changed, 1121 insertions(+), 146 deletions(-) create mode 100644 .changeset/contact-list-rows.md create mode 100644 packages/mosaic/src/features/user-profile/user-profile-account-section/use-contact-list.ts create mode 100644 packages/mosaic/src/features/user-profile/user-profile-account-section/user-profile-account-section.markers.stylex.ts create mode 100644 packages/mosaic/src/features/user-profile/user-profile-account-section/user-profile-account-section.styles.ts create mode 100644 packages/mosaic/src/primitives/hooks/use-presence-list.test.tsx create mode 100644 packages/mosaic/src/primitives/hooks/use-presence-list.ts create mode 100644 packages/mosaic/src/primitives/hooks/use-stable-order.test.tsx create mode 100644 packages/mosaic/src/primitives/hooks/use-stable-order.ts diff --git a/.changeset/contact-list-rows.md b/.changeset/contact-list-rows.md new file mode 100644 index 00000000000..a845151cc84 --- /dev/null +++ b/.changeset/contact-list-rows.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/packages/mosaic/docs/motion.md b/packages/mosaic/docs/motion.md index c3456049e83..cf32a4c75c6 100644 --- a/packages/mosaic/docs/motion.md +++ b/packages/mosaic/docs/motion.md @@ -276,12 +276,118 @@ nothing. The surface keeps its fade and pins the scale (inline text has none to and its entrance delay goes to `instant` as well: it exists to wait for the row, and a row that has snapped open leaves nothing to wait for. +### Rows in a list + +The contact rows in the user profile (`user-profile-contact-list-row.view.tsx`) adopt +the recipe for a `