Skip to content

Commit 619e4a4

Browse files
runway-github[bot]zone-liveBigshmow
authored
chore(runway): cherry-pick chore: align carousel card heights for accessibility cp-7.78.0 (#30233)
- chore: align carousel card heights for accessibility (#30201) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> ## **Description** Use fluid heights on cards so large system text doesn’t clip. Problem before: fixed heights + large accessibility text scaling = content clipping inside cards. Now: cards and skeletons are fully fluid (no height prop needed). Only ViewMoreCard keeps a height, and only as a min-h directly inline in WhatsHappeningSection, so it sits at the same height as a typical card at normal font scale. How it looks now with huge font: <img height="800" alt="Simulator Screenshot - iPhone 17 Pro - 2026-05-14 at 18 39 46" src="https://github.com/user-attachments/assets/9097c9eb-c49a-45c4-b998-2392c06676dc" /> And normal/default font size: <img height="800" alt="Simulator Screenshot - iPhone 17 Pro - 2026-05-14 at 18 50 02" src="https://github.com/user-attachments/assets/e4a61f2b-425a-44d4-b650-677f288304e0" /> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk UI/layout change to remove fixed card heights; main risk is minor visual regression in carousel alignment across devices/font scales. > > **Overview** > Makes the What’s Happening carousel cards and loading skeletons **fluid-height** by removing the fixed Tailwind height prop (`twHeightClassName`) from `WhatsHappeningCard` and `WhatsHappeningCardSkeleton`, preventing content clipping with large accessibility text. > > Keeps the “View more” tile visually aligned by switching it to a `min-h-[230px]` constraint, and updates the skeleton test to assert the expected 2-line title and 3-line description placeholder configuration. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 00186c9. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Devin Stewart <49423028+Bigshmow@users.noreply.github.com> [a55aeb3](a55aeb3) Co-authored-by: António Regadas <antonio.regadas@consensys.net> Co-authored-by: Devin Stewart <49423028+Bigshmow@users.noreply.github.com>
1 parent e6d22b9 commit 619e4a4

4 files changed

Lines changed: 23 additions & 37 deletions

File tree

app/components/UI/WhatsHappening/WhatsHappeningSection.tsx

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ import { MetaMetricsEvents } from '../../../core/Analytics/MetaMetrics.events';
3737
import { getWhatsHappeningEventProps } from './eventProperties';
3838

3939
const CARD_WIDTH = 280;
40-
const CARD_HEIGHT_CLASS = 'h-[230px]';
40+
const VIEW_MORE_MIN_HEIGHT_CLASS = 'min-h-[230px]';
4141
const GAP = 12;
4242

4343
const SNAP_OFFSETS = Array.from(
@@ -163,12 +163,7 @@ const WhatsHappeningSection = forwardRef<
163163
testID={WhatsHappeningSelectorsIDs.CAROUSEL}
164164
>
165165
{isLoading ? (
166-
SKELETON_KEYS.map((key) => (
167-
<WhatsHappeningCardSkeleton
168-
key={key}
169-
twHeightClassName={CARD_HEIGHT_CLASS}
170-
/>
171-
))
166+
SKELETON_KEYS.map((key) => <WhatsHappeningCardSkeleton key={key} />)
172167
) : (
173168
<>
174169
{items.map((item: WhatsHappeningItem, index: number) => (
@@ -178,12 +173,11 @@ const WhatsHappeningSection = forwardRef<
178173
cardIndex={index}
179174
source={source}
180175
onPress={() => handleCardPress(index)}
181-
twHeightClassName={CARD_HEIGHT_CLASS}
182176
/>
183177
))}
184178
<ViewMoreCard
185179
onPress={handleViewAll}
186-
twClassName={`w-[180px] ${CARD_HEIGHT_CLASS}`}
180+
twClassName={`w-[180px] ${VIEW_MORE_MIN_HEIGHT_CLASS}`}
187181
textVariant={TextVariant.BodyLg}
188182
/>
189183
</>

app/components/UI/WhatsHappening/components/WhatsHappeningCard.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ interface WhatsHappeningCardProps {
3232
cardIndex: number;
3333
source: WhatsHappeningSourceValue;
3434
onPress?: (item: WhatsHappeningItem) => void;
35-
/** Tailwind height class so the carousel can keep all cards visually aligned. */
36-
twHeightClassName?: string;
3735
}
3836

3937
const MAX_VISIBLE_ASSET_ICONS = 3;
@@ -43,7 +41,6 @@ const WhatsHappeningCard: React.FC<WhatsHappeningCardProps> = ({
4341
cardIndex,
4442
source,
4543
onPress,
46-
twHeightClassName = '',
4744
}) => {
4845
const tw = useTailwind();
4946
const formattedDate = useMemo(
@@ -93,7 +90,7 @@ const WhatsHappeningCard: React.FC<WhatsHappeningCardProps> = ({
9390
onPress={handlePress}
9491
activeOpacity={0.7}
9592
style={tw.style(
96-
`w-[280px] ${twHeightClassName} rounded-2xl bg-background-muted overflow-hidden p-4 justify-between gap-3`,
93+
'w-[280px] rounded-2xl bg-background-muted overflow-hidden p-4',
9794
)}
9895
>
9996
<Box gap={3}>
@@ -134,6 +131,7 @@ const WhatsHappeningCard: React.FC<WhatsHappeningCardProps> = ({
134131
alignItems={BoxAlignItems.Center}
135132
justifyContent={BoxJustifyContent.Between}
136133
gap={2}
134+
twClassName="mt-3"
137135
>
138136
{assetLabel && (
139137
<Box

app/components/UI/WhatsHappening/components/WhatsHappeningCardSkeleton.test.tsx

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,35 +3,36 @@ import { screen } from '@testing-library/react-native';
33
import renderWithProvider from '../../../../util/test/renderWithProvider';
44
import WhatsHappeningCardSkeleton from './WhatsHappeningCardSkeleton';
55

6+
const mockLineStack = jest.fn();
7+
68
jest.mock('./whatsHappeningSkeletonShared', () => ({
79
WhatsHappeningSkeletonShimmer: ({
810
children,
911
}: {
1012
children: React.ReactNode;
1113
}) => children,
12-
WhatsHappeningSkeletonLineStack: () => null,
14+
WhatsHappeningSkeletonLineStack: (props: { lineClassNames: string[] }) => {
15+
mockLineStack(props);
16+
return null;
17+
},
1318
}));
1419

1520
describe('WhatsHappeningCardSkeleton', () => {
21+
beforeEach(() => {
22+
mockLineStack.mockClear();
23+
});
24+
1625
it('renders without crashing', () => {
1726
renderWithProvider(<WhatsHappeningCardSkeleton />);
1827
expect(screen.toJSON()).not.toBeNull();
1928
});
2029

21-
it('applies the twHeightClassName when provided', () => {
22-
renderWithProvider(
23-
<WhatsHappeningCardSkeleton twHeightClassName="h-[230px]" />,
24-
);
25-
expect(screen.toJSON()).not.toBeNull();
26-
});
30+
it('renders a two-line title placeholder and a three-line description placeholder', () => {
31+
renderWithProvider(<WhatsHappeningCardSkeleton />);
2732

28-
it('renders correctly without twHeightClassName (default empty string)', () => {
29-
const { toJSON: withoutProp } = renderWithProvider(
30-
<WhatsHappeningCardSkeleton />,
31-
);
32-
const { toJSON: withEmptyProp } = renderWithProvider(
33-
<WhatsHappeningCardSkeleton twHeightClassName="" />,
34-
);
35-
expect(withoutProp()).toEqual(withEmptyProp());
33+
expect(mockLineStack).toHaveBeenCalledTimes(2);
34+
const [titleCall, descriptionCall] = mockLineStack.mock.calls;
35+
expect(titleCall[0].lineClassNames).toHaveLength(2);
36+
expect(descriptionCall[0].lineClassNames).toHaveLength(3);
3637
});
3738
});

app/components/UI/WhatsHappening/components/WhatsHappeningCardSkeleton.tsx

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,13 @@ import {
66
WhatsHappeningSkeletonShimmer,
77
} from './whatsHappeningSkeletonShared';
88

9-
interface WhatsHappeningCardSkeletonProps {
10-
/** Tailwind height class so skeletons match real cards in the carousel. */
11-
twHeightClassName?: string;
12-
}
13-
14-
const WhatsHappeningCardSkeleton: React.FC<WhatsHappeningCardSkeletonProps> = ({
15-
twHeightClassName = '',
16-
}) => {
9+
const WhatsHappeningCardSkeleton: React.FC = () => {
1710
const tw = useTailwind();
1811

1912
return (
2013
<View
2114
style={tw.style(
22-
`w-[280px] ${twHeightClassName} rounded-2xl bg-background-muted overflow-hidden`,
15+
'w-[280px] rounded-2xl bg-background-muted overflow-hidden',
2316
)}
2417
>
2518
<WhatsHappeningSkeletonShimmer>

0 commit comments

Comments
 (0)