The Icon
component provides a symbol, graphic or image that represents an application, a capability, or some other concept or specific entity with meaning for the user.
The following section documents variants of the component that currently exist in Fabric and identifies variants that exist in other component libraries but don't currently exist in Fabric, documenting which component libraries have those variants.
Font icons
Image icons
Block icons
- In Gestalt
Bordered icons
- In Semantic UI
- In Stardust
Circular icons
- In Semantic UI
- In Stardust
Corner icons
- In Semantic UI
Focusable icons
- In Chakra UI
Group icons
- In Semantic UI
Inverted icons
- In Semantic UI
Outlined vs filled icons via props
- In Ant Design
Rotated icons
- In Ant Design
- In Semantic UI
- In Stardust
Spinning/Loading icons
- In Ant Design
- In Semantic UI
Two tone icons
- In Ant Design
- In Atlaskit
The following section documents links to different UI libraries implementations of Icons, while also providing a code sandbox with a side by side implementation of them for comparison.
-
- Look for the
Icons
section in theForms
page
- Look for the
The following section documents the properties that will become part of the new component, as well as the process for mitigating all changes when moving from Fabric and Stardust to Fluent UI.
TODO: Consult the prop wizard to derive consistently defined props.
Name | Type | Default value | Description |
---|
Name | Type | Default value | Description |
---|---|---|---|
ariaHidden |
boolean |
false |
Indicates whether the element is exposed to an accessibility API. |
ariaLabel |
string |
Defines a string value that labels the current element. | |
ariaLabelledby |
string |
Identifies the element (or elements) that labels the current element. | |
as |
string |
Defines a component that should be used as the root element of the Icon . |
|
className |
string |
Defines an additional classname to provide on the root of the Icon . |
|
name |
string |
Defines the name of the pre-registered Icon to use. If the string is empty, a placeholder blank space of the same width will be rendered. |
|
role |
string |
Defines the accessibility role of the Icon . |
|
title |
string |
Specifies extra information about the Icon . |
None at the moment.
https://developer.microsoft.com/en-us/fabric#/controls/web/icon
Name | Type | Notes |
---|---|---|
ariaLabel |
string |
|
iconName |
string |
Should we rename this to just be name ? |
iconType |
IconType |
Already deprecated. |
imageErrorAs |
React.ComponentType<IImageProps> |
Should be removed duo to unnecessary complexity and infrequent use. |
imageProps |
IImageProps |
Should not be part of base Icon . Should be considered for ImageIcon variant. |
styles |
IStyleFunctionOrObject<IIconStyleProps, IIconStyles> |
Should be deprecated in favor of recomposition. |
theme |
ITheme |
Should not show up in the public props contract. |
Name | Type | Notes |
---|---|---|
accessibility |
Accessibility |
Why would a user need this prop? |
bordered |
boolean |
Should this prop be provided or is this just a matter that could be solved via styling and recomposition? |
circular |
boolean |
Should this prop be provided or is this just a matter that could be solved via styling and recomposition? |
disabled |
boolean |
Does it make sense for an Icon to be disabled if it is not an interactive component. |
name |
string |
|
outline |
boolean |
Should this prop be provided or is this just a matter that could be solved via styling and recomposition? |
rotate |
number |
Should this prop be provided or is this just a matter that could be solved via styling and recomposition? |
size |
SizeValue |
Should this prop be provided or is this just a matter that could be solved via styling and recomposition? |
xSpacing |
IconXSpacing |
Should this prop be provided or is this just a matter that could be solved via styling and recomposition? |
Name | Action to take/taken | Property transitioned? | Breaking change? | Codemod/Shim created? |
---|---|---|---|---|
ariaLabel |
TBD | ❌ | ❌ | ❌ |
iconName |
TBD | ❌ | ❌ | ❌ |
iconType |
Removing as it is already deprecated. | ☑ | No, because prop is already deprecated. | ❌ |
imageErrorAs |
TBD | ❌ | ❌ | ❌ |
imageProps |
TBD | ❌ | ❌ | ❌ |
styles |
TBD | ❌ | ❌ | ❌ |
theme |
TBD | ❌ | ❌ | ❌ |
Name | Action to take/taken | Property transitioned? | Breaking change? | Codemod/Shim created? |
---|---|---|---|---|
accessibility |
TBD | ❌ | ❌ | ❌ |
bordered |
TBD | ❌ | ❌ | ❌ |
circular |
TBD | ❌ | ❌ | ❌ |
disabled |
TBD | ❌ | ❌ | ❌ |
name |
TBD | ❌ | ❌ | ❌ |
outline |
TBD | ❌ | ❌ | ❌ |
rotate |
TBD | ❌ | ❌ | ❌ |
size |
TBD | ❌ | ❌ | ❌ |
xSpacing |
TBD | ❌ | ❌ | ❌ |
The following section documents the DOM structure for the component from different component library examples and then suggests a recommended DOM taking into consideration common patterns between the libraries reviewed.
<i aria-label="icon: home" class="anticon anticon-home">
<svg
viewBox="64 64 896 896"
focusable="false"
class=""
data-icon="home"
width="1em"
height="1em"
fill="currentColor"
aria-hidden="true"
>
<path
d="M946.5 505L560.1 118.8l-25.9-25.9a31.5 31.5 0 0 0-44.4 0L77.5 505a63.9 63.9 0 0 0-18.8 46c.4 35.2 29.7 63.3 64.9 63.3h42.5V940h691.8V614.3h43.4c17.1 0 33.2-6.7 45.3-18.8a63.6 63.6 0 0 0 18.7-45.3c0-17-6.7-33.1-18.8-45.2zM568 868H456V664h112v204zm217.9-325.7V868H632V640c0-22.1-17.9-40-40-40H432c-22.1 0-40 17.9-40 40v228H238.1V542.3h-96l370-369.7 23.1 23.1L882 542.3h-96.1z"
></path>
</svg>
</i>
- Only supports SVG icons.
<span class="sc-gzVnrw fihEGT" aria-label="HomeIcon">
<svg width="24" height="24" viewBox="0 0 24 24" focusable="false" role="presentation">
<path
d="M10 19v-4.5a2 2 0 1 1 4 0V19h4a1 1 0 0 0 1-1v-7.831l-6.293-6.296a1 1 0 0 0-1.414 0L5 10.169V18a1 1 0 0 0 1 1h4zm11-6.83V18a3 3 0 0 1-3 3H6a3 3 0 0 1-3-3v-5.83l-.04.04c-.39.39-1.03.39-1.42 0-.39-.39-.39-1.03 0-1.42l8.339-8.331a3 3 0 0 1 4.242 0l8.339 8.331c.39.39.39 1.03 0 1.42-.39.39-1.03.39-1.42 0l-.04-.04z"
fill="currentColor"
></path>
</svg>
</span>
- Only supports SVG icons.
- To use provided icons you need to import built-in icon directly (i.e.
BookIcon
).
<svg data-baseweb="icon" viewBox="0 0 24 24" class="by bz c0 k2 kt">
<title>Arrow Up</title>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M11.2929 6.29289C11.6834 5.90237 12.3166 5.90237 12.7071 6.29289L16.7071 10.2929C17.0976 10.6834 17.0976 11.3166 16.7071 11.7071C16.3166 12.0976 15.6834 12.0976 15.2929 11.7071L13 9.41421V17C13 17.5523 12.5523 18 12 18C11.4477 18 11 17.5523 11 17V9.41421L8.70711 11.7071C8.31658 12.0976 7.68342 12.0976 7.29289 11.7071C6.90237 11.3166 6.90237 10.6834 7.29289 10.2929L11.2929 6.29289Z"
></path>
</svg>
- Only supports SVG icons.
- To use provided icons you need to import built-in icon directly (i.e.
ArrowUp
).
<svg viewBox="0 0 14 14" focusable="false" role="presentation" class="css-h7g82p">
<path
fill="currentColor"
d="M2.20731,0.0127209 C2.1105,-0.0066419 1.99432,-0.00664663 1.91687,0.032079 C0.871279,0.438698 0.212942,1.92964 0.0580392,2.95587 C-0.426031,6.28627 2.20731,9.17133 4.62766,11.0689 C6.77694,12.7534 10.9012,15.5223 13.3409,12.8503 C13.6507,12.5211 14.0186,12.037 13.9993,11.553 C13.9412,10.7397 13.186,10.1588 12.6051,9.71349 C12.1598,9.38432 11.2304,8.47427 10.6495,8.49363 C10.1267,8.51299 9.79754,9.05515 9.46837,9.38432 L8.88748,9.96521 C8.79067,10.062 7.55145,9.24878 7.41591,9.15197 C6.91248,8.8228 6.4284,8.45491 6.00242,8.04829 C5.57644,7.64167 5.18919,7.19632 4.86002,6.73161 C4.7632,6.59607 3.96933,5.41495 4.04678,5.31813 C4.04678,5.31813 4.72448,4.58234 4.91811,4.2919 C5.32473,3.67229 5.63453,3.18822 5.16982,2.45243 C4.99556,2.18135 4.78257,1.96836 4.55021,1.73601 C4.14359,1.34875 3.73698,0.942131 3.27227,0.612963 C3.02055,0.419335 2.59457,0.0708094 2.20731,0.0127209 Z"
></path>
</svg>
- Only supports SVG icons.
- Icons are and can be added as part of the theme.
<i data-icon-name="CompassNW" role="presentation" aria-hidden="true" class="ms-Icon root-38 css-176 css-144"></i>
<i data-icon-name="onedrive-svg" role="presentation" aria-hidden="true" class="ms-Icon root-38 css-144">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0,0,2048,2048">
<g fill="#1B559B">
<path
d="M 1860 1196 q 53 10 94 37 q 18 12 35 29 q 16 16 30 40 q 13 23 21 53 q 8 30 8 68 q 0 37 -10 75 q -11 38 -34 69 q -23 31 -58 51 q -36 20 -86 20 h -1079 q -78 0 -131 -24 q -54 -25 -87 -65 q -34 -40 -49 -91 q -15 -52 -15 -107 q 0 -46 12 -81 q 11 -35 31 -61 q 19 -27 43 -45 q 24 -19 50 -31 q 60 -29 136 -35 q 0 -1 4 -26 q 3 -25 16 -61 q 12 -37 36 -80 q 24 -43 64 -79 q 39 -37 98 -61 q 59 -25 141 -25 q 57 0 103 15 q 45 15 81 38 q 35 23 62 52 q 26 28 44 55 q 18 -10 42 -18 q 20 -7 48 -12 q 27 -6 60 -6 q 40 0 91 15 q 50 14 94 48 q 44 33 75 88 q 30 55 30 136 m -1463 174 q 0 53 10 99 q 10 46 29 86 h -170 q -52 0 -100 -23 q -48 -23 -85 -61 q -37 -38 -59 -87 q -22 -50 -22 -104 q 0 -49 11 -87 q 10 -38 27 -66 q 17 -29 39 -49 q 21 -21 44 -35 q 53 -33 121 -41 q -1 -9 -1 -18 q -1 -9 -1 -17 q 0 -72 27 -134 q 27 -63 73 -110 q 45 -47 106 -74 q 60 -27 127 -27 q 36 0 66 7 q 29 6 51 14 q 25 10 45 21 q 27 -48 65 -89 q 37 -41 84 -71 q 46 -30 101 -47 q 55 -17 115 -17 q 39 0 80 8 q 41 7 83 24 q 72 28 121 71 q 49 42 81 90 q 32 47 49 94 q 16 46 22 82 q -23 2 -43 5 q -21 3 -40 8 q -66 -69 -148 -104 q -82 -36 -177 -36 q -76 0 -136 17 q -60 17 -106 45 q -47 28 -81 64 q -34 36 -58 75 q -24 38 -39 76 q -15 37 -23 67 q -51 12 -102 38 q -52 26 -93 68 q -42 42 -67 101 q -26 59 -26 137"
></path>
</g>
</svg>
</i>
<div role="presentation" aria-hidden="true" class="ms-Icon root-38 ms-Icon-imageContainer image-40 one-149">
<div class="ms-Image oneImage-266">
<img
src="https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/office-ui-fabric-react-assets/icon-one.png"
class="ms-Image-image is-loaded ms-Image-image--portrait is-fadeIn image-264"
/>
</div>
</div>
- Requires icon initialization and uses global registration.
<svg class="gUZ pBj U9O kVc" height="16" width="16" viewBox="0 0 24 24" aria-label="Pin" role="img">
<path
d="M18 13.5c0-2.22-1.21-4.15-3-5.19V2.45A2.5 2.5 0 0 0 17 0H7a2.5 2.5 0 0 0 2 2.45v5.86c-1.79 1.04-3 2.97-3 5.19h5v8.46L12 24l1-2.04V13.5h5z"
></path>
</svg>
- Only supports SVG icons.
- Renders by default as a block, and not an inline, element.
<span class="material-icons MuiIcon-root" aria-hidden="true">add_circle</span>
<svg class="MuiSvgIcon-root" focusable="false" viewBox="0 0 24 24" aria-hidden="true" role="presentation">
<path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"></path>
</svg>
None.
<i aria-hidden="true" class="users icon">::before</i>
- Only supports font icons.
- Can support icon groups and icon superpositions with the second item in the corner.
<span class="ui-icon ck cb ca" role="img" aria-hidden="true">
<svg class="em ct cu en cw" viewBox="8 8 16 16" role="presentation" focusable="false">
<g class="ui-icon__outline eo">
<path
d="M23.6968,12.0403c-0.1836-0.0786-0.3975-0.04-0.542,0.0981l-2.5317,2.4165C20.2212,14.9382,20,15.4514,20,16 c0,0.5483,0.2212,1.0615,0.623,1.4448l2.5317,2.4167C23.2495,19.9521,23.374,20,23.5,20c0.0664,0,0.1333-0.0132,0.1968-0.0403 C23.8809,19.8809,24,19.7002,24,19.5v-7C24,12.2998,23.8809,12.1191,23.6968,12.0403z M23,18.3315l-1.6865-1.6099v-0.0002 C21.1113,16.5286,21,16.2725,21,16s0.1113-0.5286,0.3135-0.7217L23,13.6685V18.3315z"
></path>
<path
d="M17.5,11H9.8193c-0.7056,0-1.3232,0.5393-1.4692,1.2822C8.1177,13.4619,8,14.7129,8,16s0.1177,2.5381,0.3501,3.7173 C8.4961,20.4607,9.1138,21,9.8193,21H17.5c0.8271,0,1.5-0.6729,1.5-1.5v-7C19,11.6729,18.3271,11,17.5,11z M18,19.5 c0,0.2756-0.2241,0.5-0.5,0.5H9.8193c-0.2285,0-0.4341-0.2-0.4878-0.4756C9.1113,18.4082,9,17.2224,9,16 s0.1113-2.4082,0.3315-3.5249C9.3853,12.2,9.5908,12,9.8193,12H17.5c0.2759,0,0.5,0.2244,0.5,0.5V19.5z"
></path>
</g>
<g class="ui-icon__filled">
<path
d="M23.6968,12.0403c-0.1841-0.0786-0.3975-0.04-0.542,0.0981l-2.5317,2.4165C20.2212,14.9382,20,15.4514,20,16 c0,0.5483,0.2212,1.0615,0.623,1.4448l2.5317,2.4167C23.2495,19.9521,23.374,20,23.5,20c0.0664,0,0.1333-0.0132,0.1968-0.0403 C23.8809,19.8809,24,19.7002,24,19.5v-7C24,12.2998,23.8809,12.1191,23.6968,12.0403z"
></path>
<path
d="M17.5,11H9.8193c-0.7056,0-1.3232,0.5393-1.4692,1.2822C8.1177,13.4619,8,14.7129,8,16s0.1177,2.5381,0.3501,3.7173 C8.4961,20.4607,9.1138,21,9.8193,21H17.5c0.8271,0,1.5-0.6729,1.5-1.5v-7C19,11.6729,18.3271,11,17.5,11z"
></path>
</g>
</svg>
</span>
- Allows for both font and SVG icons but only has SVG icons built-in.
After looking at all the component libraries above and taking into consideration common patterns the following DOM is recommended.
<span class="root" aria-hidden="true">{fontIconName}</span>
TODO: Discuss need to shim back to Fabric with
as=i
because of different tag being used in order to not break styling.
From the recommended DOM above we can indicate which slots are going to be required:
Name | Considerations |
---|---|
root |
TODO: I really think we should have
ImageIcon
as a separate component, maybe via recomposition, to have a very simple and fast baseIcon
. TODO: Do we want a specificSvgIcon
apart from theImageIcon
variant? This seems like one of the most used examples.
Aria spec: There's no aria spec available for icons.
The following section describes the different states in which a Icon
can be throughout the course of interaction with it.
An Icon
has only one state, its default state. The Icon
is not an interactive component and it's used only for representational purposes.
None.
There is no keyboard interaction that occurs with the Icon
.
There is no cursor interaction that occurs with the Icon
.
There is no touch interaction that occurs with the Icon
.
- Should not be tabbable nor focusable and should have
aria-hidden
applied to it by default.
All accessibility concerns would come from user manipulation of the component, so they would be a concern solely for the user and not for the component creator.
The Icon
component uses react-texture
to provide a recomposable implementation that has no runtime performance penalties. The BaseIcon
implementation can be used to provide new slots
and default props
without the application of additional styling:
const FooIcon = BaseIcon.compose({
tokens: {},
styles: {},
slots: {}
});
render () {
<FooIcon name="Home" />
}
Fabric uses global registration for its icons which needs a call to an initialization function to be used. Below are wiki and code references into this process:
- Wiki page
- Icon font generation tool
- Main
initializeIcons
function - Icon registration utilities
- Icon component
Stardust registers icons in the theme, with all default icons being SVGs but also supporting font icons via:
type ObjectOrFunc<TResult, TArg = {}> = ((arg: TArg) => TResult) | TResult;
type FontIconSpec = ObjectOrFunc<{
content: string;
fontFamily: string;
}>;
Below are wiki and code references into this process:
- SVG icon processing
- Instructions on adding new SVG Icon
- Font icon registration into the theme (fontAwesome theme example)
- Font vs SVG icon rendering
- Icon styles as part of theme component styles
- Merging icons as part of theme
- TODO: Decide on recommended thing to do. Leaning towards Stardust approach but worried about perf implications regarding icon definitions.
- TODO: Discuss how to handle font loading if we put icons in the theme.
- Should font loading also be part of the theme?
- Has to be loaded somehow and is ok for the majority of customers to automatically load them, but some customers need to prevent this loading from MSFT CDNs.
1 per slot 1 per state, tagged on root
Tokens represent the general look and feel of the various visual slots. Tokens feed into the styling at the right times in the right slot.
Regarding naming conventions, use a camelCased name following this format:
{slot}{property}{state (or none for default)}
. For example:thumbSizeHovered
.Common property names:
size
,background
,color
,borderRadius
Common states:
hovered
,pressed
,focused
,checked
,checkedHovered
,disabled
Name | Considerations |
---|---|
color |
|
fontSize |
|
fontWeight |
TODO: Example use cases
TODO: If this component represents a selected value, how will that be used in an HTML form? Is there a code example to illustrate?
TODO: Is it possible this component could be rendered in a focus zone? If so, should the focus model change in that case?