Skip to content

Commit a1f2e7d

Browse files
feat(MenuItem): Added description to MenuItem (#1543)
[Local playroom](http://localhost:9000/#?code=N4Igxg9gJgpiBcIA8BZGA7ArgHXQAgLwCcNYiAVAQyIHMYAXAXmAApgSAzAGjwnQAUSAZyEBfAJR5GAPjwtchRXiTkImMAAtKAIwA2MYjA7NOo3gOFDmfQTBGjpCpc4DyABwx4Athhz5nygD0qupaejCO-gTiok4EJOhkaFjMbJw8YLqUIgBylD4SUrLyUUpIUACWAG6GxuxGZpnZQnk%2BzE25%2BTAOcQEEqL4AkvQwXr19ilnaMLqM2CAA4kSYbhDz4xMEsEJgRBVu9BV8cyAAoiIGNMureJRgOpR4o3gAjACseBoQRNnrpZsEGyWVKSGR4YCiWL-AKBSIA5TJTDDUYbTZTGYnJYrCB4SD4TQwMAAa20EAAHn94Yptrt9odjvNzkJLtccXcHk8vK8Pl8fkJKVSCHj6EQILpyABPDwnAnE0kUkCoiayokwKBKvpAuxWVig2QQqHw2EawgDLDIsbQtE6DGM3QVLwVdDUPBXbECwU0vYHI7oE7neiPO5gCoAZ-w6BxzLwbkwaoM2y0YBgRA9VO2IvUhyqMBNzi1IhBRXBkLzeGNVrKiItZcmNtm8wAIhUhDp9OrFZW%2Bl66b6TjkcZUhKt0BVwrdeZQ0-Ch221bXCAWdSw9SXDQCK30kIFKlU4YQYrhYSBREA): <img width="1334" height="750" alt="image" src="https://github.com/user-attachments/assets/fb860242-fb47-47cf-858d-64517408cc6a" /> accessibility check: <img width="1919" height="851" alt="Captura de pantalla 2026-05-05 a las 13 17 22" src="https://github.com/user-attachments/assets/a8f6db62-7f35-4784-996b-e35132bc088e" /> ticket: https://jira.tid.es/browse/WEB-2410 [figma](https://www.figma.com/design/a1pgrI7Wg41iyXWU8ETqlU/%F0%9F%94%B8-Menu-Specs?node-id=36-1496&p=f&t=a2dK3pQQwwfCJhMT-0): <img width="1173" height="570" alt="image" src="https://github.com/user-attachments/assets/c7dbaeb6-fb5a-4bc6-8255-a8b4f9f61764" /> <img width="1158" height="501" alt="image" src="https://github.com/user-attachments/assets/ee6d67a5-ef60-4fee-8d04-5d6223d720b2" />
1 parent a5ddd59 commit a1f2e7d

6 files changed

Lines changed: 49 additions & 9 deletions

File tree

playroom/snippets.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ const menuSnippet = {
2727
renderMenu={({ ref, className }) => (
2828
<div ref={ref} className={className}>
2929
<MenuSection>
30-
<MenuItem label="option 1" onPress={() => {}} />
30+
<MenuItem label="option 1" description="Description for option 1" onPress={() => {}} />
3131
<MenuItem
3232
label="option 2"
33+
description="Description for option 2"
3334
onPress={() => setState("option 2", !getState("option 2", false))}
3435
controlType="checkbox"
3536
checked={getState("option 2", false)}
51.5 KB
Loading

src/__screenshot_tests__/menu-screenshot-test.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,17 @@ test('Menu is rendered inside a datacard', async () => {
9292
await (await screen.findByRole('button')).click();
9393
expect(await page.screenshot()).toMatchImageSnapshot();
9494
});
95+
96+
test('Menu with item description', async () => {
97+
const page = await openStoryPage({
98+
id: 'components-menu--default',
99+
device: 'MOBILE_IOS',
100+
viewport,
101+
args: {
102+
description: true,
103+
},
104+
});
105+
106+
await (await screen.findByRole('button')).click();
107+
expect(await page.screenshot()).toMatchImageSnapshot();
108+
});

src/__stories__/menu-story.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ type MenuArgs = {
2525
verticalPosition: 'top' | 'bottom';
2626
icon: boolean;
2727
checkbox: boolean;
28+
description: boolean;
2829
};
2930

3031
export const Default: StoryComponent<MenuArgs> = ({
@@ -33,6 +34,7 @@ export const Default: StoryComponent<MenuArgs> = ({
3334
verticalPosition,
3435
icon,
3536
checkbox,
37+
description,
3638
}) => {
3739
const {alert} = useDialog();
3840
const [valuesState, setValuesState] = React.useState<ReadonlyArray<number>>([]);
@@ -85,6 +87,11 @@ export const Default: StoryComponent<MenuArgs> = ({
8587
<MenuItem
8688
key={optionIndex}
8789
label={`Option ${optionIndex + 1}`}
90+
description={
91+
description
92+
? `Description for option ${optionIndex + 1}`
93+
: undefined
94+
}
8895
onPress={(item) => {
8996
if (checkbox) {
9097
setValues(item);
@@ -124,6 +131,7 @@ Default.args = {
124131
verticalPosition: 'top',
125132
icon: false,
126133
checkbox: true,
134+
description: false,
127135
};
128136
Default.argTypes = {
129137
horizontalPosition: {

src/menu.css.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,12 @@ export const itemContent = style({
126126
alignItems: 'center',
127127
});
128128

129+
export const itemTextContent = style({
130+
display: 'flex',
131+
flexDirection: 'column',
132+
gap: 2,
133+
});
134+
129135
export const iconContainer = style({
130136
display: 'flex',
131137
paddingRight: 8,

src/menu.tsx

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {Portal} from './portal';
1010
import Box from './box';
1111
import Inline from './inline';
1212
import Touchable from './touchable';
13-
import {Text3} from './text';
13+
import {Text2, Text3} from './text';
1414
import {vars} from './skins/skin-contract.css';
1515
import Divider from './divider';
1616
import Checkbox from './checkbox';
@@ -53,6 +53,7 @@ const getItemIndexInMenu = (menu: HTMLElement | null, item: HTMLElement | null):
5353

5454
interface MenuItemBaseProps {
5555
label: string;
56+
description?: string;
5657
Icon?: (props: IconProps) => JSX.Element;
5758
destructive?: boolean;
5859
disabled?: boolean;
@@ -80,6 +81,7 @@ export const MenuItem = ({
8081
onPress,
8182
controlType,
8283
checked,
84+
description,
8385
dataAttributes,
8486
}: MenuItemProps): JSX.Element => {
8587
const {focusedItem, setFocusedItem, closeMenu, isMenuOpen} = useMenuContext();
@@ -93,6 +95,19 @@ export const MenuItem = ({
9395

9496
const menuItemDataAttributes = {testid: 'MenuItem', ...dataAttributes};
9597

98+
const renderTextContent = (id?: string) => (
99+
<div id={id} className={styles.itemTextContent}>
100+
<Text3 regular color={contentColor}>
101+
{label}
102+
</Text3>
103+
{description && (
104+
<Text2 regular color={vars.colors.textSecondary}>
105+
{description}
106+
</Text2>
107+
)}
108+
</div>
109+
);
110+
96111
const renderContent = () =>
97112
controlType === 'checkbox' ? (
98113
<Checkbox
@@ -108,7 +123,7 @@ export const MenuItem = ({
108123
disabled={disabled}
109124
role="menuitemcheckbox"
110125
dataAttributes={menuItemDataAttributes}
111-
render={({controlElement}) => (
126+
render={({controlElement, labelId}) => (
112127
<Box paddingX={8} paddingY={12}>
113128
<Inline space="between" alignItems="center">
114129
<div className={styles.itemContent}>
@@ -117,9 +132,7 @@ export const MenuItem = ({
117132
<Icon size={24} color={contentColor} />
118133
</div>
119134
)}
120-
<Text3 regular color={contentColor}>
121-
{label}
122-
</Text3>
135+
{renderTextContent(labelId)}
123136
</div>
124137
<Box paddingLeft={16}>{controlElement}</Box>
125138
</Inline>
@@ -146,9 +159,7 @@ export const MenuItem = ({
146159
<Icon size={24} color={contentColor} />
147160
</div>
148161
)}
149-
<Text3 regular color={contentColor}>
150-
{label}
151-
</Text3>
162+
{renderTextContent()}
152163
</div>
153164
</Box>
154165
</Touchable>

0 commit comments

Comments
 (0)