-
Notifications
You must be signed in to change notification settings - Fork 9
fix(IconHelp): stable sizing and alignment, add stories and guideline #1115
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| import { Meta, Canvas } from '@storybook/addon-docs/blocks'; | ||
| import * as Stories from './iconhelp.stories'; | ||
|
|
||
| <Meta name="Guideline" of={Stories} /> | ||
|
|
||
| # IconHelp | ||
|
|
||
| `IconHelp` is a small info icon that reveals a tooltip on hover or focus. Use it to provide secondary information without overloading the interface. | ||
|
|
||
| <Canvas of={Stories.Simple} sourceState="none" /> | ||
|
|
||
| ## When to use it | ||
|
|
||
| Reach for `IconHelp` whenever a user might have to **guess** what a label, value or concept means. If the wording is not self-explanatory and there is no room — or no need — to spell it out in the layout, an `IconHelp` should be considered. | ||
|
|
||
| Typical cases: | ||
|
|
||
| - A label or a settings name that uses a domain term (`Object lock`, `Replication policy`, `RPO`). | ||
| - A value whose meaning is not transparent (`Governance`, `Compliance`, `Standard` storage class). | ||
| - A column header, badge, or status that benefits from a one-line definition. | ||
|
|
||
| ## When not to use it | ||
|
|
||
| - **Don't use it as the only way to convey critical information.** A tooltip is hidden by default — anything required to complete a task must remain visible (helper text, error message, inline description). | ||
| - **Don't stack multiple `IconHelp` next to each other.** If a section needs that much explanation, write a short paragraph or link to documentation instead. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Two parts of this bullet need clarification. "Write a short paragraph" — where? Name the concrete pattern: a description paragraph below the section heading, an "Link to documentation" has the same gap: how is the link surfaced? Inline in the layout? As an
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rewrote the bullet in e009220 to name concrete patterns: a description paragraph under the section heading, or an |
||
| - **Don't replace good labels with an `IconHelp`.** Fix the label first; add help only when the term itself cannot be made clearer. | ||
| - **Don't put long content inside the tooltip.** Keep it to one or two short sentences. For longer explanations, use a dedicated documentation page. | ||
|
|
||
| ## Explaining values in a key/value list | ||
|
|
||
| In summary or detail pages, attach an `IconHelp` only to the values whose meaning is not obvious. Leave plain values (a name, an email, an ID) without one. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggest updating this sentence and adding a
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done in e009220. The section now spells out both sides — key-side when the label itself is opaque ( |
||
|
|
||
| <Canvas of={Stories.InKeyValueList} sourceState="none" /> | ||
|
|
||
| ## In a form | ||
|
|
||
| In forms, `FormGroup` already exposes a `labelHelpTooltip` prop that renders an `IconHelp` next to the field label — you don't need to add one manually. Use it to clarify: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The section is missing the key decision rule: use helper text when the information is needed to complete the task, because it is always visible. Without this distinction, consumers have no clear signal for when to reach for
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added in e009220. "In a form" now opens with the decision rule: helper text (via |
||
|
|
||
| - **What the field represents** — e.g. _"The name other users will see on your profile."_ | ||
| - **The accepted format or validation rule** — e.g. _"Must be 3–32 characters, letters and digits only."_ | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove this bullet. Format and validation rules ("Must be 3–32 characters, letters and digits only") are needed to complete the task, so they belong in always-visible helper text, not a tooltip. This contradicts the rule two bullets above: "don't use IconHelp as the only way to convey critical information".
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Even if we are not super strict in the UI, it should be strict in the design system. |
||
| - **The impact of the value** — e.g. _"Enabling versioning keeps a copy of every overwrite or delete."_ | ||
|
|
||
| ## Placement | ||
|
|
||
| The tooltip defaults to `right`. Pick another placement only when `right` is clipped by the container or overlaps important content. | ||
|
|
||
| <Canvas of={Stories.WithPlacement} sourceState="none" /> | ||
|
|
||
| ## Accessibility | ||
|
|
||
| - Always pass an `aria-label` that describes _what the tooltip explains_, not just `"Help"`. Example: `aria-label="More info about replication policy"`. | ||
| - The icon renders as a real `<button>`, so it is reachable by keyboard (`Tab`) and the tooltip opens on focus. | ||
| - The tooltip content is the visible text — keep it informative and complete on its own. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| import React from 'react'; | ||
| import { IconHelp } from '../../src/lib/components/iconhelper/IconHelper'; | ||
| import { Text } from '../../src/lib/components/text/Text.component'; | ||
| import { Stack } from '../../src/lib/spacing'; | ||
| import { Wrapper } from '../common'; | ||
|
|
||
| export default { | ||
| title: 'Components/IconHelp', | ||
| component: IconHelp, | ||
| decorators: [(story: () => React.ReactNode) => <Wrapper>{story()}</Wrapper>], | ||
| }; | ||
|
|
||
| export const Simple = { | ||
| name: 'Simple', | ||
| render: () => ( | ||
| <Text> | ||
| Replication policy{' '} | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is debatable, I don't know if it's a spacing component or if it's managed with a space. |
||
| <IconHelp | ||
| tooltipMessage="Defines how objects are replicated across locations." | ||
| aria-label="More info about replication policy" | ||
| /> | ||
| </Text> | ||
| ), | ||
| }; | ||
|
|
||
| export const WithPlacement = { | ||
| name: 'Tooltip placement', | ||
| render: () => ( | ||
| <Stack direction="vertical" gap="r24"> | ||
| <Text> | ||
| Placement <b>top</b>{' '} | ||
| <IconHelp | ||
| placement="top" | ||
| tooltipMessage="Appears above the icon." | ||
| aria-label="Top tooltip" | ||
| /> | ||
| </Text> | ||
| <Text> | ||
| Placement <b>right</b> (default){' '} | ||
| <IconHelp | ||
| placement="right" | ||
| tooltipMessage="Appears to the right of the icon." | ||
| aria-label="Right tooltip" | ||
| /> | ||
| </Text> | ||
| <Text> | ||
| Placement <b>bottom</b>{' '} | ||
| <IconHelp | ||
| placement="bottom" | ||
| tooltipMessage="Appears below the icon." | ||
| aria-label="Bottom tooltip" | ||
| /> | ||
| </Text> | ||
| <Text> | ||
| Placement <b>left</b>{' '} | ||
| <IconHelp | ||
| placement="left" | ||
| tooltipMessage="Appears to the left of the icon." | ||
| aria-label="Left tooltip" | ||
| /> | ||
| </Text> | ||
| </Stack> | ||
| ), | ||
| }; | ||
|
|
||
| const KeyValueRow = ({ | ||
| label, | ||
| value, | ||
| helpMessage, | ||
| helpAriaLabel, | ||
| }: { | ||
| label: string; | ||
| value: React.ReactNode; | ||
| helpMessage?: React.ReactNode; | ||
| helpAriaLabel?: string; | ||
| }) => ( | ||
| <div | ||
| style={{ | ||
| display: 'grid', | ||
| gridTemplateColumns: '200px 1fr', | ||
| alignItems: 'baseline', | ||
| gap: '16px', | ||
| padding: '6px 0', | ||
| }} | ||
| > | ||
| <Text color="textSecondary">{label}</Text> | ||
| <Text> | ||
| {value} | ||
| {helpMessage && ( | ||
| <> | ||
| {' '} | ||
| <IconHelp | ||
| tooltipMessage={helpMessage} | ||
| aria-label={helpAriaLabel ?? `More info about ${label}`} | ||
| /> | ||
| </> | ||
| )} | ||
| </Text> | ||
| </div> | ||
| ); | ||
|
|
||
| export const InKeyValueList = { | ||
| name: 'Explaining values', | ||
| render: () => ( | ||
| <div style={{ maxWidth: 560 }}> | ||
| <KeyValueRow label="Bucket name" value="prod-customer-assets" /> | ||
| <KeyValueRow | ||
| label="Versioning" | ||
| value="Enabled" | ||
| helpMessage="Once enabled, every overwrite or delete keeps the previous version." | ||
| /> | ||
| <KeyValueRow | ||
| label="Object lock" | ||
| value="Governance" | ||
| helpMessage="Governance mode allows privileged users to change retention; Compliance mode does not." | ||
| /> | ||
| <KeyValueRow | ||
| label="Storage class" | ||
| value="Standard" | ||
| helpMessage="Affects durability, latency and pricing of stored objects." | ||
| /> | ||
| <KeyValueRow label="Region" value="us-east-1" /> | ||
| </div> | ||
| ), | ||
| }; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The intro should be a single descriptive sentence, per the guideline writing convention in CLAUDE.md. The second sentence ("Use it to provide secondary information without overloading the interface") is a usage recommendation and belongs in "When to use it".
Suggested intro:
`IconHelp` is an inline icon button that reveals a tooltip on hover or focus.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Applied as suggested in e009220. Intro is now
IconHelp` is an inline icon button that reveals a tooltip on hover or focus.and the usage recommendation moved into the opening line of "When to use it".