Skip to content
Open
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import React from 'react';
import { Button, Tooltip, TooltipPosition } from '@patternfly/react-core';
import {
Table,
Tbody,
Thead,
Tr,
Th,
Td
} from '@patternfly/react-table';
import RhUiArrowCircleUpIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-arrow-circle-up-icon';
import RhUiNotificationFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-notification-fill-icon';
import RhUiSettingsIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-settings-icon';
import RhUiCopyIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-copy-icon';
import RhUiDownloadIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-download-icon';
import RhUiEllipsisVerticalIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-ellipsis-vertical-icon';
import RhUiEditIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-edit-icon';
import RhUiSearchIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-search-icon';
import RhUiZoomOutIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-zoom-out-icon';
import RhUiZoomInIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-zoom-in-icon';
import RhUiSyncIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-sync-icon';
import RhUiTrashIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-trash-icon';
import RhUiExportIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-export-icon';
import RhUiTaskIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-task-icon';

const REACT_LABEL = 'React name';

const ROWS = [
{ Icon: RhUiArrowCircleUpIcon, name: 'rh-ui-arrow-circle-up', reactName: 'RhUiArrowCircleUpIcon', tooltip: 'Upgrade', note: '' },
{ Icon: RhUiNotificationFillIcon, name: 'rh-ui-notification-fill', reactName: 'RhUiNotificationFillIcon', tooltip: 'Notifications', note: '' },
{ Icon: RhUiSettingsIcon, name: 'rh-ui-settings', reactName: 'RhUiSettingsIcon', tooltip: 'Settings', note: '' },
{ Icon: RhUiCopyIcon, name: 'rh-ui-copy', reactName: 'RhUiCopyIcon', tooltip: 'Copy', note: '' },
{ Icon: RhUiDownloadIcon, name: 'rh-ui-download', reactName: 'RhUiDownloadIcon', tooltip: 'Download', note: '' },
{ Icon: RhUiEllipsisVerticalIcon, name: 'rh-ui-ellipsis-vertical', reactName: 'RhUiEllipsisVerticalIcon', tooltip: 'More options', note: '' },
{ Icon: RhUiEditIcon, name: 'rh-ui-edit', reactName: 'RhUiEditIcon', tooltip: 'Edit', note: '' },
{ Icon: RhUiSearchIcon, name: 'rh-ui-search', reactName: 'RhUiSearchIcon', tooltip: 'Search', note: '' },
{ Icon: RhUiZoomOutIcon, name: 'rh-ui-zoom-out', reactName: 'RhUiZoomOutIcon', tooltip: 'Zoom out', note: '' },
{ Icon: RhUiZoomInIcon, name: 'rh-ui-zoom-in', reactName: 'RhUiZoomInIcon', tooltip: 'Zoom in', note: '' },
{ Icon: RhUiSyncIcon, name: 'rh-ui-sync', reactName: 'RhUiSyncIcon', tooltip: 'Sync', note: 'Choose the best fit for your scenario.' },
{ Icon: RhUiTrashIcon, name: 'rh-ui-trash', reactName: 'RhUiTrashIcon', tooltip: 'Delete', note: '' },
{ Icon: RhUiExportIcon, name: 'rh-ui-export', reactName: 'RhUiExportIcon', tooltip: 'Export', note: '' },
{ Icon: RhUiTaskIcon, name: 'rh-ui-task', reactName: 'RhUiTaskIcon', tooltip: 'Tasks', note: '' }
];

export const TooltipIconReferenceTable = () => {
const [copiedReactName, setCopiedReactName] = React.useState(null);

return (
<Table aria-label="Icon tooltip reference" variant="compact">
<Thead>
<Tr>
<Th>Icon</Th>
<Th>Name</Th>
<Th>{REACT_LABEL}</Th>
<Th>Tooltip content</Th>
<Th>Note</Th>
</Tr>
</Thead>
<Tbody>
{ROWS.map((row) => {
const Icon = row.Icon;
return (
<Tr key={row.reactName}>
<Td dataLabel="Icon">
<Tooltip content={row.tooltip} position={TooltipPosition.right}>
<Button variant="plain" aria-label={`Suggested tooltip label: ${row.tooltip}`}>
<Icon />
</Button>
</Tooltip>
</Td>
<Td dataLabel="Name" modifier="fitContent">
{row.name}
</Td>
<Td dataLabel={REACT_LABEL} modifier="fitContent">
<Tooltip
trigger="mouseenter focus click"
content={<div>{copiedReactName === row.reactName ? 'Copied' : 'Copy React name'}</div>}
position={TooltipPosition.left}
exitDelay={copiedReactName === row.reactName ? 1000 : 100}
onTooltipHidden={() => {
if (copiedReactName === row.reactName) {
setCopiedReactName(null);
}
}}
>
<span
style={{ cursor: 'pointer' }}
role="button"
tabIndex={0}
aria-label={`Copy ${row.reactName} to clipboard`}
onClick={() => {
navigator.clipboard.writeText(row.reactName);
setCopiedReactName(row.reactName);
}}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
navigator.clipboard.writeText(row.reactName);
setCopiedReactName(row.reactName);
}
}}
>
{row.reactName}
</span>
</Tooltip>
</Td>
<Td dataLabel="Tooltip content">{row.tooltip}</Td>
<Td dataLabel="Note">{row.note || null}</Td>
</Tr>
);
})}
</Tbody>
</Table>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,22 @@ section: content-design
subsection: writing-guides
---

import ArrowCircleUpIcon from '@patternfly/react-icons/dist/esm/icons/arrow-circle-up-icon';
import BellIcon from '@patternfly/react-icons/dist/esm/icons/bell-icon';
import CogIcon from '@patternfly/react-icons/dist/esm/icons/cog-icon';
import CopyIcon from '@patternfly/react-icons/dist/esm/icons/copy-icon';
import DownloadIcon from '@patternfly/react-icons/dist/esm/icons/download-icon';
import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon';
import PencilAltIcon from '@patternfly/react-icons/dist/esm/icons/pencil-alt-icon';
import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon';
import SearchMinusIcon from '@patternfly/react-icons/dist/esm/icons/search-minus-icon';
import SearchPlusIcon from '@patternfly/react-icons/dist/esm/icons/search-plus-icon';
import SyncAltIcon from '@patternfly/react-icons/dist/esm/icons/sync-alt-icon';
import TrashIcon from '@patternfly/react-icons/dist/esm/icons/trash-icon';
import ExportIcon from '@patternfly/react-icons/dist/esm/icons/export-icon';
import TaskIcon from '@patternfly/react-icons/dist/esm/icons/task-icon';
import QuestionCircleIcon from '@patternfly/react-icons/dist/esm/icons/question-circle-icon';
import { Button, Icon, Tooltip, Split, SplitItem } from '@patternfly/react-core'
import RhUiSettingsIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-settings-icon';
import RhUiCopyIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-copy-icon';
import RhUiSearchIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-search-icon';
import RhUiQuestionMarkCircleIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-question-mark-circle-icon';
import { Button, Tooltip, Split, SplitItem } from '@patternfly/react-core'
import { TooltipIconReferenceTable } from './TooltipIconReferenceTable.jsx';

A **tooltip** is a message box that is shown when a UI element, like a button or an icon, is in a hover state. They contain short descriptions that offer additional information to help users better understand elements within a UI.

<Split>
<SplitItem>
<Tooltip content={"This is a tooltip. It contains useful information that solves all your problems."} aria="describedby" >
<Button>I'm a button with a tooltip!</Button>
</Tooltip>
</SplitItem>
</Split>

When writing tooltips, follow these general recommendations:

Expand All @@ -36,7 +30,7 @@ When writing tooltips, follow these general recommendations:
| Don't repeat information that is already available in the UI. | Do write content that is succinct, clear, and effective. |
| Don't use tooltips for critical information. | Do use tooltips for additional, non-essential information. |
| Don't end sentence fragments in a period. | Do end full sentences in a period. |
| Don’t place tooltips on question-circle icons (<QuestionCircleIcon />). Instead, use a [popover](/components/popover). | Do follow [our tooltip development accessibility guidelines](/components/tooltip/accessibility) to ensure that tooltip content is available to all users.|
| Don’t place tooltips on question-mark icons (<RhUiQuestionMarkCircleIcon />). Instead, use a [popover](/components/popover). | Do follow [our tooltip development accessibility guidelines](/components/tooltip/accessibility) to ensure that tooltip content is available to all users.|

</div>

Expand All @@ -51,33 +45,18 @@ For example:

<Split>
<SplitItem>
<Tooltip content={"Settings"} aria="labelledby"> <Button variant="plain" aria-label="More information about settings"> <CogIcon /></Button> </Tooltip>
<Tooltip content={"Settings"} aria="labelledby"> <Button variant="plain" aria-label="More information about settings"> <RhUiSettingsIcon /></Button> </Tooltip>
</SplitItem>
<SplitItem>
<Tooltip content={"Copy"} aria="labelledby"> <Button variant="plain" aria-label="Copy"> <CopyIcon /></Button> </Tooltip>
<Tooltip content={"Copy"} aria="labelledby"> <Button variant="plain" aria-label="Copy"> <RhUiCopyIcon /></Button> </Tooltip>
</SplitItem>
<SplitItem>
<Tooltip content={"Search"} aria="labelledby"> <Button variant="plain" aria-label="Search"> <SearchIcon /></Button> </Tooltip>
<Tooltip content={"Search"} aria="labelledby"> <Button variant="plain" aria-label="Search"> <RhUiSearchIcon /></Button> </Tooltip>
</SplitItem>
</Split>

In PatternFly, there are commonly used icons that hold universal meanings. These should always use the same tooltip description, as shown in the following table:

|**Icon** | **Name** | **Tooltip content** | **Note** |
|------------|-----------|-----------|---- |
| <ArrowCircleUpIcon /> | fa-arrow-circle-up | Upgrade |
| <BellIcon /> | fa-bell | Notifications |
| <CogIcon /> | fa-cog | Settings |
| <CopyIcon /> | fa-copy | Copy |
| <DownloadIcon /> | fa-download | Download |
| <EllipsisVIcon /> | fa-ellipsis-v | More options |
| <PencilAltIcon /> | fa-pencil-alt | Edit |
| <SearchIcon /> | fa-search | Search |
| <SearchMinusIcon /> | fa-search-minus | Search minus |
| <SearchPlusIcon /> | fa-search-plus | Search plus |
| <SyncAltIcon /> | fa-sync-alt | Sync, Refresh, or Running | Choose the best fit for your scenario.|
| <TrashIcon /> | fa-trash | Delete |
| <ExportIcon /> | pficon-export | Export |
| <TaskIcon /> | pficon-task | Tasks |
<TooltipIconReferenceTable />

You can learn more about the usage of these icons in our [design foundations.](/foundations-and-styles/iconography)
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,21 @@ import {
} from '@patternfly/react-table';
import { iconsData } from './icons';
import { saveAs } from 'file-saver';
import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon';
import * as iconUnicodes from '@patternfly/patternfly/assets/icons/iconUnicodes.json';
import RhUiSearchIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-search-icon';

const REACT_COLUMN_LABEL = 'React name';

export const IconsTable = () => {
const columns = ['Icon', 'Name', 'Style', 'React', 'Usage', 'Unicode'];
const columns = ['Icon', 'Name', 'React', 'Usage'];
const [searchValue, setSearchValue] = React.useState('');
const [isCopied, setCopied] = React.useState(false);
const [sortByIndex, setSortByIndex] = React.useState(1);
const [sortDirection, setSortDirection] = React.useState('asc');
/** Which row’s React name was last copied (for tooltip feedback). */
const [copiedReactName, setCopiedReactName] = React.useState(null);

React.useEffect(() => {
setCopiedReactName(null);
}, [searchValue]);

const getSortParams = columnIndex => ({
sortBy: {
Expand Down Expand Up @@ -62,11 +68,6 @@ export const IconsTable = () => {
saveAs(blob, filename);
};

const clipboardCopyFunc = (event, text) => {
navigator.clipboard.writeText(text.toString());
setCopied(true);
};

const filteredRows = React.useMemo(() => {
return iconsData.filter(icon => {
return icon.Name.toLowerCase().includes(searchValue.toLowerCase()) ||
Expand Down Expand Up @@ -115,24 +116,21 @@ export const IconsTable = () => {
</Toolbar>
<Divider />
<Table
aria-label="Filterable PatternFly icons"
aria-label="Filterable Red Hat UI icons"
variant={'compact'}
id="ws-icons-table"
>
<Thead>
<Tr>
<Th>{columns[0]}</Th>
<Th sort={getSortParams(1)}>{columns[1]}</Th>
<Th>{columns[2]}</Th>
<Th>{columns[3]}</Th>
<Th sort={getSortParams(4)}>{columns[4]}</Th>
<Th modifier="fitContent">{columns[5]}</Th>
<Th>{REACT_COLUMN_LABEL}</Th>
<Th sort={getSortParams(3)}>{columns[3]}</Th>
</Tr>
</Thead>
<Tbody>
{sortedRows.map((icon, index) => {
const Icon = icons[icon.React_name];
const iconUnicode = icon.Unicode || iconUnicodes.default[icon.Name] || '';

return (
<Tr key={index}>
Expand All @@ -148,43 +146,66 @@ export const IconsTable = () => {
</Tooltip>
</Td>
<Td dataLabel={columns[1]} modifier="fitContent">{icon.Name}</Td>
<Td dataLabel={columns[2]}>{icon.Style}</Td>
<Td dataLabel={columns[4]}>{icon.React_name}</Td>
<Td dataLabel={columns[5]}>
{icon.Contextual_usage}
{icon.Extra_context && (
<React.Fragment>
<br/><br/>{icon.Extra_context}
</React.Fragment>
)}
</Td>
<Td dataLabel={columns[6]}>
<Td dataLabel={REACT_COLUMN_LABEL} modifier="fitContent">
<Tooltip
trigger="mouseenter focus click"
content={<div>{isCopied ? 'Copied' : 'Copy'}</div>}
content={<div>{copiedReactName === icon.React_name ? 'Copied' : 'Copy React name'}</div>}
position={TooltipPosition.left}
exitDelay={isCopied ? 1000 : 100}
onTooltipHidden={() => setCopied(false)}
exitDelay={copiedReactName === icon.React_name ? 1000 : 100}
onTooltipHidden={() => {
if (copiedReactName === icon.React_name) {
setCopiedReactName(null);
}
}}
>
<Button
aria-label={`Copy ${icon.Name} icon unicode to clipboard`}
variant="plain"
onClick={(event) => clipboardCopyFunc(event, iconUnicode)}
<span
role="button"
tabIndex={0}
className="ws-icons-react-name-copy"
aria-label={`Copy ${icon.React_name} to clipboard`}
onClick={() => {
navigator.clipboard.writeText(icon.React_name);
setCopiedReactName(icon.React_name);
}}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
navigator.clipboard.writeText(icon.React_name);
setCopiedReactName(icon.React_name);
}
}}
>
{iconUnicode}
</Button>
{icon.React_name}
</span>
</Tooltip>
</Td>
<Td dataLabel={columns[3]}>
{icon.Contextual_usage}
{icon.Extra_context && (
<React.Fragment>
<br/><br/>{icon.Extra_context}
</React.Fragment>
)}
</Td>
</Tr>
)
})}
</Tbody>
</Table>

{filteredRows.length === 0 && (
<EmptyState titleText={`No results found for "${ searchValue }"`} headingLevel="h4" icon={SearchIcon}>
<EmptyStateBody>We couldn't find any icons that matched your search. If none of the icons listed fit
your use case, you may use any additional 'fa' icons within <a href="https://fontawesome.com/icons?d=gallery&amp;m=free">Font Awesome's free set</a>.
<EmptyState titleText={`No results found for "${ searchValue }"`} headingLevel="h4" icon={RhUiSearchIcon}>
<EmptyStateBody>
We couldn't find any icons that matched your search. Try different keywords or browse the full list above.
If you need an icon that isn't listed, you can{' '}
<a
href="https://docs.google.com/forms/d/e/1FAIpQLSde61rTDD4keaZEA3JFzBPbQVJ5EgEkhNapsYoI6ajKCsX4_Q/viewform"
target="_blank"
rel="noopener noreferrer"
>
request a new icon from the Red Hat brand team
</a>
.
</EmptyStateBody>
</EmptyState>
)}
Expand Down
Loading
Loading