Private
Public Access
1
0

feat: Fluent UI Outlook Lite + connections mockup

This commit is contained in:
2026-04-14 18:52:25 +00:00
parent 1199eff6c3
commit dfa4010406
34820 changed files with 1003813 additions and 205 deletions

View File

@@ -0,0 +1,142 @@
# Build-Time Import Transforms
You can keep root-level barrel imports and leverage build-time transforms to automatically rewrite them to optimized atomic imports — no source code changes required.
These transforms rewrite imports from:
```tsx
import { AccessTime24Filled } from '@fluentui/react-icons';
```
To the optimized atomic import for your chosen target:
```tsx
// SVG (standard)
import { AccessTime24Filled } from '@fluentui/react-icons/svg/access-time';
// SVG sprites
import { AccessTime24Filled } from '@fluentui/react-icons/svg-sprite/access-time';
// Font icons
import { AccessTime24Filled } from '@fluentui/react-icons/fonts/access-time';
// Base API (SVG)
import { AccessTime24Filled } from '@fluentui/react-icons/base/svg/access-time';
// Base API (SVG sprites)
import { AccessTime24Filled } from '@fluentui/react-icons/base/svg-sprite/access-time';
// Base API (fonts)
import { AccessTime24Filled } from '@fluentui/react-icons/base/fonts/access-time';
```
The examples below use `svg` as the target path. Replace it with the appropriate path for your setup from the list above.
## Babel
Add [babel-plugin-transform-imports](https://www.npmjs.com/package/babel-plugin-transform-imports) with the following setup.
Copy the following helper into your project (e.g. as `fluent-icons-transform.js`):
```js
// @filename fluent-icons-transform.js
/**
* Resolves a @fluentui/react-icons import name to its atomic module path.
* @param {string} importName - The named export being imported.
* @param {string} [target='svg'] - The target subpath (e.g. 'svg', 'svg-sprite', 'fonts',
* 'base/svg', 'base/svg-sprite', 'base/fonts').
* @returns {string} The resolved module path.
*/
function resolveFluentIconImport(importName, target = 'svg') {
if (importName === 'useIconContext' || importName === 'IconDirectionContextProvider') {
return '@fluentui/react-icons/providers';
}
const match = importName.match(/^(.+?)(\d+)?(Regular|Filled|Light|Color)$/);
if (!match) {
return '@fluentui/react-icons/utils';
}
return `@fluentui/react-icons/${target}/${kebabCase(match[1])}`;
}
function kebabCase(str) {
return str.replace(/[a-z\d](?=[A-Z])|[a-zA-Z](?=\d)|[A-Z](?=[A-Z][a-z])/g, '$&-').toLowerCase();
}
module.exports = { resolveFluentIconImport };
```
Then use it in your Babel config:
```js
// @filename .babelrc.js
const { resolveFluentIconImport } = require('./fluent-icons-transform');
module.exports = {
presets: [
// ... your preset configuration
],
plugins: [
[
'transform-imports',
{
'@fluentui/react-icons': {
// Change the second argument to match your target:
// 'svg' | 'svg-sprite' | 'fonts' | 'base/svg' | 'base/svg-sprite' | 'base/fonts'
transform: (importName) => resolveFluentIconImport(importName, 'svg'),
preventFullImport: false,
skipDefaultConversion: true,
},
},
],
],
};
```
## SWC
Add [@swc/plugin-transform-imports](https://www.npmjs.com/package/@swc/plugin-transform-imports) with the following setup.
Replace every `svg` segment in the target paths below with your chosen target (`svg`, `svg-sprite`, `fonts`, `base/svg`, `base/svg-sprite`, or `base/fonts`):
```jsonc
// @filename .swcrc
{
"jsc": {
"experimental": {
"plugins": [
[
"@swc/plugin-transform-imports",
{
"@fluentui/react-icons": {
"transform": [
// Transform provider imports to /providers
["^(useIconContext|IconDirectionContextProvider)$", "@fluentui/react-icons/providers"],
// Transform icon imports to /{target}/{icon-name}
// (.+?) lazily captures the icon base name (may contain digits,
// e.g. "Space3D", "Rotate315Right"), (\d+)? greedily strips any
// trailing all-digit segment (size suffixes like 16/20/24, but
// also level indicators like Battery0) — this mirrors the
// normalizeBaseName logic used by the generation pipeline.
// {{ kebabCase }} on group 1 mirrors lodash.kebabCase.
[
"(.+?)(\\d+)?(Regular|Filled|Light|Color)$",
"@fluentui/react-icons/svg/{{ kebabCase memberMatches.[1] }}",
],
// Fallback: all other exports are utilities
[".*", "@fluentui/react-icons/utils"],
],
"preventFullImport": false,
"skipDefaultConversion": true,
"handleDefaultImport": false,
"handleNamespaceImport": false,
},
},
],
],
},
},
}
```

View File

@@ -0,0 +1,13 @@
# Preview Features
> **⚠️ Alpha** — these features are available as alpha prereleases only.
>
> Install via `npm i @fluentui/react-icons@alpha`
## [Atomic API (SVG Sprites)](./svg-sprites.md)
SVG sprites offer smaller bundles, faster renders, and zero runtime overhead.
## [Base API](./base.md)
A drop-in replacement for the standard API that removes the CSS-in-JS runtime — provides data-attribute selectors for styling behaviour with opt-in pre-defined vanilla CSS.

View File

@@ -0,0 +1,184 @@
# Base API
> **⚠️ Alpha** — this feature is available as an alpha prerelease only.
>
> Install via `npm i @fluentui/react-icons@prerelease`
The Base API is a drop-in replacement for the standard icon API that removes the CSS-in-JS runtime dependency. It provides `data-*` attribute selectors for styling behaviour with opt-in pre-defined vanilla CSS — making it suitable for any React setup, including those without a CSS-in-JS runtime.
## Benefits
- **No CSS-in-JS runtime** — removes the CSS-in-JS dependency entirely; styling is handled by an opt in plain CSS file or in user-land
- **Smaller JavaScript bundles** — icon styling code is moved from JS to a static CSS file
- **Framework-agnostic styling** — works in any environment that can load a CSS file (Vite, Next.js, Remix, etc.)
- **Same API surface** — `createFluentIcon`, `bundleIcon`, `useIconState`, and all constants work identically to the standard API
- **Migration-friendly** — works with both existing codebases (via build-time transforms) and greenfield projects (via direct imports)
## How it works
The standard API uses Griffel's `makeStyles` / `mergeClasses` to inject CSS rules at runtime. The base API replaces this with HTML `data-*` attributes and a shipped CSS file (`base.css`) that targets them:
| Concern | Standard (Griffel) | Base (CSS) |
| --------------------- | ----------------------------------- | -------------------------------------------------------------------------- |
| Base icon layout | `useRootStyles()` → atomic classes | `[data-fui-icon] { display: inline; line-height: 0 }` |
| High-contrast mode | `@media (forced-colors)` in JS | `@media (forced-colors) { [data-fui-icon] { forced-color-adjust: auto } }` |
| RTL directional flip | `transform: scaleX(-1)` via Griffel | `[data-fui-icon-rtl] { transform: scaleX(-1) }` |
| bundleIcon visibility | Generated show/hide classes | `[data-fui-icon-hidden] { display: none }` |
| Font icon family | Griffel styles per variant | `[data-fui-icon-font="filled"] { font-family: '...' }` |
## CSS Setup
You **must** import the base CSS file — this is the key difference from the standard API, which injects styles at runtime.
**For SVG icons and SVG sprites:**
```ts
import '@fluentui/react-icons/base/base.css';
```
**For font icons** (additionally):
```ts
import '@fluentui/react-icons/base/base-fonts.css';
import '@fluentui/react-icons/base/base.css';
```
> **Note:** `base-fonts.css` contains `@font-face` declarations with relative paths to the font files (`.woff2`, `.woff`, `.ttf`). Your bundler (webpack, Vite, esbuild) will resolve these into the dependency graph automatically, enabling font subsetting plugins to process them.
> **Tip 💡:** It's highly recommended to enable our [`react-icons-font-subsetting-webpack-plugin`](https://www.npmjs.com/package/@fluentui/react-icons-font-subsetting-webpack-plugin) to get same fonts "tree-shaking" perf boost
## Usage
### SVG Icons
Base SVG icons are grouped by icon kind and exposed via `@fluentui/react-icons/base/svg/{icon-group}`:
```tsx
import '@fluentui/react-icons/base/base.css';
import {
AccessTime20Filled,
AccessTime24Filled,
AccessTime20Regular,
} from '@fluentui/react-icons/base/svg/access-time';
import { Add16Filled, Add20Filled } from '@fluentui/react-icons/base/svg/add';
function MyComponent() {
return (
<>
<AccessTime20Filled />
<Add16Filled />
</>
);
}
```
### SVG Sprites
Base SVG sprites work the same way as standard SVG sprites but without Griffel:
```tsx
import '@fluentui/react-icons/base/base.css';
import { AccessTime20Filled, AccessTime24Filled } from '@fluentui/react-icons/base/svg-sprite/access-time';
import { Add16Filled } from '@fluentui/react-icons/base/svg-sprite/add';
function MyComponent() {
return (
<>
<AccessTime20Filled />
<Add16Filled />
</>
);
}
```
> **Same-origin requirement:** Sprite files must be served from the same origin as your application. See the [SVG Sprites same-origin section](./svg-sprites.md#same-origin-requirement) for details.
### Font Icons
Base font icons require both CSS files — `base.css` for base styles and `base-fonts.css` for `@font-face` declarations:
```tsx
import '@fluentui/react-icons/base/base-fonts.css';
import '@fluentui/react-icons/base/base.css';
import { Airplane20Filled, Airplane24Regular } from '@fluentui/react-icons/base/fonts/airplane';
function MyComponent() {
return <Airplane20Filled />;
}
```
### Utilities
The base entry point (`@fluentui/react-icons/base`) re-exports all core utilities:
```tsx
import {
// Icon factories
createFluentIcon,
bundleIcon,
// Core hook
useIconState,
// CSS class name constants (for consumer targeting)
iconClassName, // 'fui-Icon'
iconFilledClassName, // 'fui-Icon-filled'
iconRegularClassName, // 'fui-Icon-regular'
iconLightClassName, // 'fui-Icon-light'
iconColorClassName, // 'fui-Icon-color'
fontIconClassName, // 'fui-Icon-font'
// Data attribute constants
DATA_FUI_ICON, // 'data-fui-icon'
DATA_FUI_ICON_RTL, // 'data-fui-icon-rtl'
DATA_FUI_ICON_HIDDEN, // 'data-fui-icon-hidden'
DATA_FUI_ICON_FONT, // 'data-fui-icon-font'
// Context
IconDirectionContextProvider,
useIconContext,
// Class name helper
cx,
} from '@fluentui/react-icons/base';
```
The `bundleIcon` function works identically to the standard API:
```tsx
import '@fluentui/react-icons/base/base.css';
import { bundleIcon } from '@fluentui/react-icons/base';
import { AccessTimeFilled } from '@fluentui/react-icons/base/svg/access-time';
import { AccessTimeRegular } from '@fluentui/react-icons/base/svg/access-time';
const AccessTime = bundleIcon(AccessTimeFilled, AccessTimeRegular);
function MyComponent() {
return <AccessTime filled aria-label="Access time" />;
}
```
## TypeScript Configuration
**IMPORTANT**: TypeScript users must use `moduleResolution: "bundler"` (or `"node16"`/`"nodenext"`) in their `tsconfig.json` to properly resolve the base atomic exports:
```json
{
"compilerOptions": {
"moduleResolution": "bundler"
}
}
```
## Build-Time Transform
You can keep root-level barrel imports and leverage build transforms to adopt the base API without modifying your source code. This works for both existing codebases migrating to base approach and greenfield projects.
Use `base/svg` as the target path (or `base/svg-sprite` for sprites, `base/fonts` for font icons).
> **Note:** You still need to manually add the CSS import (`import '@fluentui/react-icons/base/base.css'`) to your application entry point — build transforms only rewrite component imports.
👉 **[Build-Time Transform setup (Babel & SWC) →](../build-transforms.md)**

View File

@@ -0,0 +1,158 @@
# Atomic API (SVG Sprites)
> **⚠️ Alpha** — this feature is available as an alpha prerelease only.
>
> Install via `npm i @fluentui/react-icons@prerelease`
## Benefits
- Smaller bundles, faster renders, zero runtime overhead, and no migration cost.
- If you use icons at scale, sprites can be considered the new default.
**📦 Bundle size wins**
With sprites, icons are deduplicated at the app level:
- The size savings increase with every additional icon you use
- Each icon definition exists only once for the entire application
- Icon code is removed from your JS bundles entirely
**⚡ Performance by design**
- Every icon exists once, outside of JS
- React re-renders are effectively noops for icons
- Browsers give you an aggressive, free SVG storage cache, making repeated icon usage extremely cheap
## How it works
Each icon component renders a lightweight `<svg><use href="/path/to/sprite.svg#icon-id" /></svg>` element. The actual icon paths live inside an external `.sprite.svg` file that the browser fetches, caches, and reuses across every render and page navigation. This completely removes icon rendering cost from your JavaScript bundle and React tree.
## Same-origin requirement
> **Important:** Browsers block cross-origin SVG `<use href="...">` references due to security constraints — this is **not** a CORS header issue and cannot be solved by adding `Access-Control-Allow-Origin` headers alone.
The sprite files **must be served from the same origin** as your application. There are two straightforward ways to achieve this:
**Option 1 — Serve from your own static assets (recommended)**
Copy the sprite files into your application's public/static folder and reference them from your own domain. The [Webpack Subsetting Plugin](#webpack-plugin) handles this automatically at build time.
**Option 2 — Reverse proxy**
If the sprites are hosted on a CDN or separate server, configure your reverse proxy to forward requests under a same-origin path to that upstream. Example Nginx config:
```nginx
# Proxy /sprites/ requests to the CDN while appearing same-origin to the browser
location /sprites/ {
proxy_pass https://your-cdn.example.com/sprites/;
proxy_cache_valid 200 30d;
add_header Cache-Control "public, max-age=2592000, immutable";
}
```
After proxying, sprite URLs like `/sprites/access-time.sprite.svg` resolve from the same origin and the browser security restriction is lifted.
## Usage
### Direct API usage
Atomic SVG sprites, similarly to Atomic SVGs, are grouped by icon kind and exposed via `@fluentui/react-icons/svg-sprite/{icon-group}`.
```ts
// Import individual icon variants from atomic icon groups
import {
AccessTime20Filled,
AccessTime24Filled,
AccessTime20Regular,
} from '@fluentui/react-icons/svg-sprite/access-time';
import { Add16Filled, Add20Filled } from '@fluentui/react-icons/svg-sprite/add';
```
### TypeScript Configuration
**IMPORTANT**: TypeScript users must use `moduleResolution: "bundler"` (or `"node16"`/`"nodenext"`) in their `tsconfig.json` to properly resolve these sprite exports:
```json
{
"compilerOptions": {
"moduleResolution": "bundler"
}
}
```
### Build-Time Transform
You can keep root-level barrel imports and leverage build transforms to start using the new atomic sprites API.
Use `svg-sprite` as the target path.
👉 **[Build-Time Transform setup (Babel & SWC) →](../build-transforms.md)**
## Tooling
### Webpack
Enable static asset processing for SVG files so the bundler emits them as separate URL-addressed resources:
```js
const config = {
module: {
rules: [
{
test: /\.svg$/,
type: 'asset/resource',
},
],
},
};
```
### Vite
Vite handles static assets out of the box. Ensure SVG files are **not** processed by any SVG-to-component plugin (such as `vite-plugin-svgr`) for sprite files, or scope such plugins to exclude `.sprite.svg`:
```js
// vite.config.ts
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [
// If you use vite-plugin-svgr, exclude sprite files:
// svgr({ include: /(?<!\.sprite)\.svg$/ }),
],
// Sprite .svg files are served as static URLs automatically — no extra config needed.
});
```
### Webpack Plugin
> **⚠️ Alpha** — this package is available as an alpha prerelease only.
>
> Install via `npm i @fluentui/react-icons-svg-sprite-subsetting-webpack-plugin@prerelease`
To leverage performance benefits to the fullest, use the Webpack SvgSprite Subsetting Plugin. It analyzes your application's actual icon usage at build time and strips unused icon definitions from the sprite files — ensuring only icons your app references are shipped.
[Learn more about `react-icons-svg-sprite-subsetting-webpack-plugin`](https://www.npmjs.com/package/@fluentui/react-icons-svg-sprite-subsetting-webpack-plugin)
```js
const {
default: FluentUIReactIconsSvgSpriteSubsettingPlugin,
} = require('@fluentui/react-icons-svg-sprite-subsetting-webpack-plugin');
const config = {
plugins: [
new FluentUIReactIconsSvgSpriteSubsettingPlugin({
/**
* 'atomic' (recommended) — one sprite file per icon group (e.g. access-time.sprite.svg).
* Best for HTTP/2 servers; browsers fetch only the groups your app actually uses and
* cache each group independently.
*
* 'merged' — all icons combined into a single sprite file.
* Useful when your app uses a large portion of the icon set and you prefer a single
* network request over many smaller ones.
*/
mode: 'atomic', // or 'merged'
}),
],
};
```