Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions UNRELEASED.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Use [the changelog guidelines](https://git.io/polaris-changelog-guidelines) to f

- Moved icons to a separate npm package ([#686](https://github.com/Shopify/polaris-react/pull/686))
- Added `oneHalf` and `oneThird` props to `Layout` component ([#724](https://github.com/Shopify/polaris-react/pull/724))
- Added `helpText` prop to ActionList items ([#777](https://github.com/Shopify/polaris-react/pull/777))

### Bug fixes

Expand Down
51 changes: 51 additions & 0 deletions src/components/ActionList/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,57 @@ class ActionListExample extends React.Component {
}
```

### Action list with help text

Use help text when the normal Verb noun syntax for the actions does not provide sufficient context for the merchant.

```jsx
class ActionListExample extends React.Component {
state = {
active: true,
};

togglePopover = () => {
this.setState(({active}) => {
return {active: !active};
});
};

render() {
const activator = (
<Button onClick={this.togglePopover}>More actions</Button>
);

return (
<div style={{height: '250px'}}>
<Popover
active={this.state.active}
activator={activator}
onClose={this.togglePopover}
>
<ActionList
sections={[
{
items: [
{
content: 'Blog posts',
helpText: 'Manage your blog articles',
},
{
content: 'Blogs',
helpText: 'Manage blogs published to your Online Store',
},
],
},
]}
/>
</Popover>
</div>
);
}
}
```

---

## Related components
Expand Down
13 changes: 12 additions & 1 deletion src/components/ActionList/components/Item/Item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Scrollable from '../../../Scrollable';
import Icon from '../../../Icon';
import UnstyledLink from '../../../UnstyledLink';
import Badge from '../../../Badge';
import TextStyle from '../../../TextStyle';

import * as styles from '../../ActionList.scss';

Expand All @@ -15,6 +16,7 @@ export default function Item({
id,
badge,
content,
helpText,
url,
onAction,
icon,
Expand Down Expand Up @@ -51,7 +53,16 @@ export default function Item({
);
}

const contentMarkup = ellipsis && content ? `${content}…` : content;
const contentText = ellipsis && content ? `${content}…` : content;

const contentMarkup = helpText ? (
<div>
<div>{contentText}</div>
<TextStyle variation="subdued">{helpText}</TextStyle>
</div>
) : (
contentText
);

const badgeMarkup = badge && (
<span className={styles.BadgeWrapper}>
Expand Down
6 changes: 6 additions & 0 deletions src/components/ActionList/components/Item/tests/Item.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as React from 'react';
import {mountWithAppProvider} from 'test-utilities';
import {UnstyledLink} from 'components';
import Item from '../Item';
import TextStyle from '../../../../TextStyle';

describe('<Item />', () => {
it('adds a style property when the image prop is present', () => {
Expand Down Expand Up @@ -36,4 +37,9 @@ describe('<Item />', () => {
const item = mountWithAppProvider(<Item ellipsis />);
expect(item.text()).toBe('');
});

it('renders helpText when the helpText prop is defined', () => {
const item = mountWithAppProvider(<Item helpText="Foo" />);
expect(item.find(TextStyle).text()).toBe('Foo');
});
});
3 changes: 2 additions & 1 deletion src/components/ActionList/components/Section/Section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,12 @@ export default function Section({
};
};
const actionMarkup = section.items.map(
({content, onAction, ...item}, index) => {
({content, helpText, onAction, ...item}, index) => {
return (
<Item
key={`${content}-${index}`}
content={content}
helpText={helpText}
role={actionRole}
onAction={handleAction(onAction)}
{...item}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,27 @@ describe('<Section />', () => {
).toBe('Import file');
});

it('passes helpText to Item', () => {
const section = mountWithAppProvider(
<Section
hasMultipleSections
section={{
items: [
{content: 'Import file', helpText: 'Foo', onAction: noop},
{content: 'Export file', helpText: 'Bar', onAction: noop},
],
}}
/>,
);

expect(
section
.find(Item)
.first()
.prop('helpText'),
).toBe('Foo');
});

it('passes the onActionAnyItem callback to Item', () => {
const spy = jest.fn();
const section = mountWithAppProvider(
Expand Down
2 changes: 2 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ export interface ActionListItemDescriptor
BadgeAction,
DestructableAction,
AppBridgeAction {
/** Additional hint text to display with item */
helpText?: string;
/** Image source */
image?: string;
/** Add an ellipsis suffix to action content */
Expand Down