-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs: Adds a page to help find v9 icons for v0 migration (#25185)
* docs: Adds a page to help find v9 icons for v0 migration Uses the icon mapping in https://github.com/YuanboXue-Amber/style-transform-tool/blob/master/apps/web/src/lib/iconMapping.json by @YuanboXue to create migration documentation for v0 icons. * virtualize * make list longer * fix types * pr suggestions * link to officla icon docs * revert peresona
- Loading branch information
Showing
8 changed files
with
2,426 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
102 changes: 102 additions & 0 deletions
102
...public-docsite-v9/src/Concepts/Migration/FromV0/Components/IconCatalog/ComparisonTile.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
import * as React from 'react'; | ||
import { DismissRegular, InfoRegular } from '@fluentui/react-icons'; | ||
import { makeStyles, shorthands, tokens, Button, mergeClasses, Tooltip } from '@fluentui/react-components'; | ||
import { V0IconComponent, V9IconComponent } from './types'; | ||
|
||
const useIconTileStyles = makeStyles({ | ||
root: { | ||
position: 'relative', | ||
display: 'flex', | ||
flexDirection: 'column', | ||
alignItems: 'center', | ||
...shorthands.padding('5px', '0px'), | ||
...shorthands.gap('10px'), | ||
...shorthands.border(tokens.strokeWidthThin, 'solid', tokens.colorNeutralStroke1), | ||
maxHeight: '105px', | ||
':hover': { | ||
backgroundColor: tokens.colorNeutralBackground2Hover, | ||
}, | ||
}, | ||
|
||
badge: { | ||
position: 'absolute', | ||
top: '5px', | ||
right: '10px', | ||
}, | ||
|
||
warning: { | ||
color: tokens.colorPaletteDarkOrangeBackground3, | ||
}, | ||
|
||
success: { | ||
color: tokens.colorPaletteGreenBackground3, | ||
}, | ||
|
||
v0: { | ||
width: '16px', | ||
height: '16px', | ||
}, | ||
|
||
v9: { | ||
width: '20px', | ||
height: '20px', | ||
}, | ||
|
||
tile: { | ||
display: 'flex', | ||
flexDirection: 'column', | ||
justifyContent: 'center', | ||
alignItems: 'center', | ||
...shorthands.gap('2px'), | ||
}, | ||
|
||
buttonReset: { | ||
resize: 'horizontal', | ||
boxSizing: 'content-box', | ||
backgroundColor: 'inherit', | ||
color: 'inherit', | ||
fontFamily: 'inherit', | ||
fontSize: 'inherit', | ||
lineHeight: 'normal', | ||
...shorthands.overflow('visible'), | ||
...shorthands.padding(0), | ||
...shorthands.borderStyle('none'), | ||
WebkitAppearance: 'button', | ||
textAlign: 'unset', | ||
}, | ||
}); | ||
|
||
interface IComparisonTileProps { | ||
V0Icon: V0IconComponent; | ||
V9Icon?: V9IconComponent; | ||
} | ||
|
||
export const ComparisonTile: React.FC<IComparisonTileProps> = ({ V0Icon, V9Icon }) => { | ||
const noV9Icon = !V9Icon; | ||
|
||
const tooltipWarningContent = <ul>{noV9Icon && <li>No equivalent icon available</li>}</ul>; | ||
|
||
const styles = useIconTileStyles(); | ||
return ( | ||
<div className={styles.root} role="listitem"> | ||
<Tooltip relationship="description" content={noV9Icon ? tooltipWarningContent : 'Good to go!'}> | ||
<Button | ||
appearance="subtle" | ||
className={mergeClasses(styles.badge, noV9Icon ? styles.warning : styles.success)} | ||
icon={<InfoRegular />} | ||
shape="circular" | ||
/> | ||
</Tooltip> | ||
<div className={styles.tile}> | ||
<div className={styles.v0}>{<V0Icon outline />}</div> | ||
<div>{V0Icon.displayName}</div> | ||
</div> | ||
<div className={styles.tile}> | ||
<div className={styles.v9}> | ||
{V9Icon ? <V9Icon fontSize={20} /> : <DismissRegular color="red" fontSize={21} />} | ||
</div> | ||
<div>{V9Icon ? V9Icon.displayName : 'Not Available'}</div> | ||
</div> | ||
</div> | ||
); | ||
}; |
111 changes: 111 additions & 0 deletions
111
apps/public-docsite-v9/src/Concepts/Migration/FromV0/Components/IconCatalog/IconCatalog.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
import * as React from 'react'; | ||
import { Provider, teamsV2Theme } from '@fluentui/react-northstar'; | ||
import * as v0Icons from '@fluentui/react-icons-northstar'; | ||
import * as v9Icons from '@fluentui/react-icons'; | ||
import { makeStyles, Input, Switch, Label } from '@fluentui/react-components'; | ||
import type { InputProps, SwitchProps } from '@fluentui/react-components'; | ||
import { iconMapping as rawMapping } from './iconMapping'; | ||
import { IconGrid } from './IconGrid'; | ||
import { useDebounce } from './useDebounce'; | ||
import { V0IconComponent, V9IconComponent } from './types'; | ||
|
||
const useStyles = makeStyles({ | ||
searchPanel: { | ||
display: 'flex', | ||
alignItems: 'center', | ||
justifyContent: 'space-between', | ||
marginBottom: '10px', | ||
marginTop: '20px', | ||
}, | ||
|
||
switch: { | ||
display: 'flex', | ||
alignItems: 'center', | ||
}, | ||
}); | ||
|
||
const _mapping = rawMapping | ||
.map(entry => { | ||
const v0IconName = `${entry.v0}`; | ||
const v9IconName = `${entry.v9}Regular`; | ||
const V0Icon = ((v0Icons as unknown) as Record<string, V0IconComponent>)[v0IconName]; | ||
const V9Icon = ((v9Icons as unknown) as Record<string, V9IconComponent | undefined>)[v9IconName]; | ||
|
||
if (!V0Icon) { | ||
return null; | ||
} | ||
|
||
return { | ||
v9Search: entry.v9?.toLowerCase(), | ||
v0Search: entry.v0.toLowerCase(), | ||
V0Icon, | ||
V9Icon, | ||
}; | ||
}) | ||
.filter(Boolean); | ||
const mapping = _mapping.filter(Boolean) as Array<NonNullable<typeof _mapping[number]>>; | ||
|
||
const IconCatalogInner: React.FC = () => { | ||
const styles = useStyles(); | ||
const [searchTerm, setSearchTerm] = React.useState<string | undefined>(undefined); | ||
const [searchV0, setSearchV0] = React.useState(true); | ||
|
||
const updateSearch = React.useCallback( | ||
(newSearchTerm: string) => { | ||
setSearchTerm(newSearchTerm.toLowerCase()); | ||
}, | ||
[setSearchTerm], | ||
); | ||
|
||
const updateSearchDebounced = useDebounce(updateSearch, 220); | ||
|
||
const entries = React.useMemo( | ||
() => | ||
mapping.filter(entry => { | ||
if (!searchTerm) { | ||
return true; | ||
} | ||
|
||
if (searchV0) { | ||
return entry.v0Search.includes(searchTerm); | ||
} | ||
|
||
return entry.v9Search?.includes(searchTerm); | ||
}), | ||
[searchTerm, searchV0], | ||
); | ||
|
||
const onInputChange: InputProps['onChange'] = React.useCallback((e, { value }) => updateSearchDebounced(value), [ | ||
updateSearchDebounced, | ||
]); | ||
const onSwitchChange: SwitchProps['onChange'] = React.useCallback((e, { checked }) => setSearchV0(checked), []); | ||
|
||
return ( | ||
<> | ||
<div> | ||
<div className={styles.searchPanel}> | ||
<Input | ||
aria-label={`Search across ${mapping.length} icons`} | ||
placeholder={`Search across ${mapping.length} icons`} | ||
onChange={onInputChange} | ||
/> | ||
<div className={styles.switch}> | ||
<Label htmlFor="searchToggle">{searchV0 ? 'Searching Northstar icons ' : 'Searching V9 icons'}</Label> | ||
<Switch id="searchToggle" checked={searchV0} onChange={onSwitchChange} /> | ||
</div> | ||
</div> | ||
</div> | ||
<div role="status">{entries.length} icon entries</div> | ||
<IconGrid entries={entries} /> | ||
</> | ||
); | ||
}; | ||
|
||
// Simply hoists the northstar provider above the catalog to avoid unnecessarily | ||
// re-rendering the provider. | ||
const northstarTheme = { ...teamsV2Theme, staticStyles: [] }; | ||
export const IconCatalog: React.FC = () => ( | ||
<Provider theme={northstarTheme}> | ||
<IconCatalogInner /> | ||
</Provider> | ||
); |
42 changes: 42 additions & 0 deletions
42
apps/public-docsite-v9/src/Concepts/Migration/FromV0/Components/IconCatalog/IconGrid.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import * as React from 'react'; | ||
import { FixedSizeList as List } from 'react-window'; | ||
import type { ListChildComponentProps } from 'react-window'; | ||
import { ComparisonTile as ComparisonTileBase } from './ComparisonTile'; | ||
import { V0IconComponent, V9IconComponent } from './types'; | ||
|
||
const ComparisonTile = React.memo(ComparisonTileBase); | ||
|
||
interface IIconGridProps { | ||
entries: { | ||
V0Icon: V0IconComponent; | ||
V9Icon?: V9IconComponent; | ||
}[]; | ||
} | ||
|
||
const ROW_SIZE = 3; | ||
|
||
interface IRowProps extends ListChildComponentProps { | ||
data: IIconGridProps['entries']; | ||
} | ||
|
||
const Row = ({ index, style, data }: IRowProps) => { | ||
const start = index * ROW_SIZE; | ||
const items = data.slice(start, start + 3); | ||
return ( | ||
<div style={style}> | ||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 10 }}> | ||
{items.map(({ V0Icon, V9Icon }) => ( | ||
<ComparisonTile key={V0Icon.displayName} V0Icon={V0Icon} V9Icon={V9Icon} /> | ||
))} | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export const IconGrid: React.FC<IIconGridProps> = ({ entries }) => { | ||
return ( | ||
<List width="100%" itemCount={entries.length / ROW_SIZE} height={600} itemData={entries} itemSize={110}> | ||
{Row} | ||
</List> | ||
); | ||
}; |
Oops, something went wrong.