Skip to content
Merged
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
21 changes: 21 additions & 0 deletions .changeset/odd-taxis-do.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
"@uifabricshared/theming-ramp": patch
"@fluentui-react-native/android-theme": patch
"@fluentui-react-native/default-theme": patch
"@fluentui-react-native/theming-utils": patch
"@fluentui-react-native/experimental-shimmer": patch
"@fluentui-react-native/theme-tokens": patch
"@fluentui-react-native/checkbox": patch
"@fluentui-react-native/apple-theme": patch
"@fluentui-react-native/theme-types": patch
"@fluentui-react-native/tablist": patch
"@fluentui-react-native/avatar": patch
"@fluentui-react-native/button": patch
"@fluentui-react-native/switch": patch
"@fluentui-react-native/badge": patch
"@fluentui-react-native/menu": patch
"@fluentui-react-native/theme": patch
"@fluentui-react-native/design": patch
---

Move platform theming utilities into the design package, update usage in the repo to use the new source"
2 changes: 2 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ yarn format:check # Check formatting without writing
```bash
yarn lint-repo # Repo-wide structural lint (scripts/src/tasks/lintRepo.ts)
yarn lint-lockfile # Validate the Yarn lockfile
yarn lage test-links # Validate links in repository Markdown files
yarn check-publishing # Validate package publishing configuration
yarn change # Create a change file for the current branch
yarn change:check # Verify required change files exist
Expand All @@ -85,6 +86,7 @@ The task pipeline is defined in `lage.config.mjs`:
- `buildci` is the aggregate CI alias (lint-repo, check-publishing, build, test, lint)
- Lage caches task outputs; add `--no-cache` to bypass caching and `--verbose` for detailed output
- After a major rework (e.g. moving packages, large refactors, or renaming exports), run `yarn lage test --no-cache` from the root once to force every test to re-run without relying on stale cached results. This also resets the Lage cache, so subsequent plain `yarn lage test` runs will work incrementally again.
- Before checking in moved or renamed files, run `yarn lage test-links` and update any repository links that still reference the old paths.

### Package-Level Commands

Expand Down
1 change: 0 additions & 1 deletion apps/tester-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@
"@fluentui-react-native/theme": "workspace:*",
"@fluentui-react-native/theme-tokens": "workspace:*",
"@fluentui-react-native/themed-stylesheet": "workspace:*",
"@fluentui-react-native/theming-utils": "workspace:*",
"@fluentui-react-native/tooltip": "workspace:*",
"@fluentui-react-native/vibrancy-view": "workspace:*",
"@fluentui-react-native/win32-theme": "workspace:*",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { globalTokens } from '@fluentui-react-native/theme-tokens';
import type { Theme } from '@fluentui-react-native/design/theming';
import { useTheme } from '@fluentui-react-native/design/theming';
import { themedStyleSheet } from '@fluentui-react-native/themed-stylesheet';
import { getCurrentAppearance } from '@fluentui-react-native/theming-utils';
import { getCurrentAppearance } from '@fluentui-react-native/design/theming';
import { createOfficeAliasTokens } from '@fluentui-react-native/win32-theme';
import type { SvgProps } from 'react-native-svg';
import Svg, { G, Path } from 'react-native-svg';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { Text } from '@fluentui/react-native';
import { HOMEPAGE_CORNERRADIUS_TESTPAGE } from '@fluentui-react-native/e2e-testing';
import { useFluentTheme } from '@fluentui-react-native/framework';
import { Stack } from '@fluentui-react-native/stack';
import { getCurrentAppearance } from '@fluentui-react-native/theming-utils';
import { getCurrentAppearance } from '@fluentui-react-native/design/theming';

import { stackStyle } from '../Common/styles';
import type { TestSection, PlatformStatus } from '../Test';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import type { Theme } from '@fluentui-react-native/framework';
import { useFluentTheme } from '@fluentui-react-native/framework';
import { Stack } from '@fluentui-react-native/stack';
import { themedStyleSheet } from '@fluentui-react-native/themed-stylesheet';
import { getCurrentAppearance } from '@fluentui-react-native/theming-utils';
import { getCurrentAppearance } from '@fluentui-react-native/design/theming';

import { stackStyle } from '../Common/styles';
import type { TestSection, PlatformStatus } from '../Test';
Expand Down
3 changes: 0 additions & 3 deletions apps/tester-core/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,6 @@
{
"path": "../../packages/framework/themed-stylesheet/tsconfig.json"
},
{
"path": "../../packages/theming/theming-utils/tsconfig.json"
},
{
"path": "../../packages/experimental/Tooltip/tsconfig.json"
},
Expand Down
6 changes: 3 additions & 3 deletions docs/pages/Theming/CustomTheme.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ There are two ways to make a custom theme: you can tack onto an existing one usi

### Extending an existing `ThemeReference`

We have a concept of `ThemeRecipes` which allow for layering of partial theme objects to create the ultimately desired theme. `ThemeRecipes` are functions which take a `Theme` and spit out a [`PartialTheme`](../../../packages/agentic-design/src/theming/Theme.types.ts), which is then deep merged into the base theme object.
We have a concept of `ThemeRecipes` which allow for layering of partial theme objects to create the ultimately desired theme. `ThemeRecipes` are functions which take a `Theme` and spit out a [`PartialTheme`](../../../packages/agentic-design/src/theming/types/Theme.types.ts), which is then deep merged into the base theme object.

You can extend one of our default themes by creating a `ThemeReference` using the default theme as the base theme, and then add your customization as a `ThemeRecipe`:

Expand Down Expand Up @@ -46,7 +46,7 @@ There's two ways to customize a FURN theme's properties:

### Changing theme tokens directly

Theme tokens can be overridden directly. You can specify different values for theme entries and add to the set of colors. You can see what can be overridden by looking at the [Theme type definition](../../../packages/agentic-design/src/theming/Theme.types.ts).
Theme tokens can be overridden directly. You can specify different values for theme entries and add to the set of colors. You can see what can be overridden by looking at the [Theme type definition](../../../packages/agentic-design/src/theming/types/Theme.types.ts).

This approach is useful if you need the customizations to be applied to all components.

Expand Down Expand Up @@ -161,7 +161,7 @@ interface Theme {
}
```

<font size=1>(Taken from the [`Theme` type definition](../../../packages/agentic-design/src/theming/Theme.types.ts).)</font>
<font size=1>(Taken from the [`Theme` type definition](../../../packages/agentic-design/src/theming/types/Theme.types.ts).)</font>

NOTE: If you would prefer to customize one instance of a FURN component instead, use [the customize API](../../../packages/framework/composition/README.md).

Expand Down
2 changes: 1 addition & 1 deletion docs/pages/Theming/Tokens/Basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export const defaultNotificationTokens: TokenSettings<NotificationTokens, Theme>

Notes about alias color tokens:

- Different platforms can have different sets of alias tokens; however, the entire set of alias tokens are all defined in the same interface. See [Color.types.ts](https://github.com/microsoft/fluentui-react-native/blob/main/packages/agentic-design/src/theming/Color.types.ts#L861) for this interface and which platforms define which alias tokens.
- Different platforms can have different sets of alias tokens; however, the entire set of alias tokens are all defined in the same interface. See [Color.types.ts](../../../../packages/agentic-design/src/theming/types/Color.types.ts#L861) for this interface and which platforms define which alias tokens.
- As a result, if an alias token is referenced that does not exist for that platform, there won't be any compile-time or run-time errors. Instead, the color shown will default to black.

Special case: if accessing a specific color, you can find it in the `globalTokens.color` property.
Expand Down
3 changes: 1 addition & 2 deletions lage.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,7 @@ const config = {
* Prebuild is a pre-build step that can either modify the source code or generate additional files in the project.
*/
dependsOn: ['^prebuild'],
inputs: ['**/*', '!node_modules/**/*', '!dist/**/*', '!lib/**/*', '!lib-commonjs/**/*'],
outputs: ['lib/**/*', 'src/**/*'],
cache: false,
},
'root-prebuild': {
cache: false,
Expand Down
10 changes: 9 additions & 1 deletion packages/agentic-design/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"@fluentui-react-native/design-tokens-win32": "catalog:",
"@fluentui-react-native/design-tokens-windows": "catalog:",
"@fluentui-react-native/scripts": "workspace:*",
"@office-iss/react-native-win32": "^0.81.0",
"@react-native-community/cli": "^20.0.0",
"@react-native-community/cli-platform-android": "^20.0.0",
"@react-native-community/cli-platform-ios": "^20.0.0",
Expand All @@ -70,20 +71,25 @@
"react": "19.1.4",
"react-native": "^0.81.6",
"react-native-macos": "^0.81.0",
"react-native-windows": "^0.81.0",
"react-test-renderer": "19.1.4"
},
"peerDependencies": {
"@types/react": "~18.2.0 || ~19.0.0 || ~19.1.4",
"react": "18.2.0 || 19.0.0 || 19.1.4",
"react-native": "^0.73.0 || ^0.74.0 || ^0.78.0 || ^0.81.6",
"react-native-macos": "^0.73.0 || ^0.74.0 || ^0.78.0 || ^0.81.0"
"react-native-macos": "^0.73.0 || ^0.74.0 || ^0.78.0 || ^0.81.0",
"react-native-windows": "^0.73.0 || ^0.74.0 || ^0.78.0 || ^0.81.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"react-native-macos": {
"optional": true
},
"react-native-windows": {
"optional": true
}
},
"furn": {
Expand All @@ -95,6 +101,8 @@
"capabilities": [
"core-dev-only",
"core-macos-dev-only",
"core-windows-dev-only",
"core-win32-dev-only",
"react-test-renderer"
]
},
Expand Down
2 changes: 1 addition & 1 deletion packages/agentic-design/src/theming/context.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';

import type { Theme } from './Theme.types';
import type { Theme } from './types/Theme.types';

export const ThemeContext = React.createContext<Theme>(undefined);
export const useTheme = () => React.useContext(ThemeContext);
11 changes: 6 additions & 5 deletions packages/agentic-design/src/theming/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ export type {
PaletteTextColors,
PartialPalette,
ThemeColorDefinition,
} from './Color.types';
export type { ShadowValue, ShadowToken, BaseShadowAliasTokens, ThemeShadowDefinition, PartialShadowDefinition } from './Shadow.types';
export type { AppearanceOptions, PartialTheme, Spacing, Theme, ThemeOptions } from './Theme.types';
} from './types/Color.types';
export type { ShadowValue, ShadowToken, BaseShadowAliasTokens, ThemeShadowDefinition, PartialShadowDefinition } from './types/Shadow.types';
export type { AppearanceOptions, PartialTheme, Spacing, Theme, ThemeOptions } from './types/Theme.types';
export type {
FontDynamicTypeRamp,
FontFamilies,
Expand All @@ -27,10 +27,11 @@ export type {
Variant,
VariantValue,
Variants,
} from './Typography.types';
} from './types/Typography.types';
export { ThemeContext, useTheme } from './context';
export type { OfficePalette } from './palette.types';
export type { OfficePalette } from './types/palette.types';
export { ThemeProvider } from './ThemeProvider';
export type { ThemeProviderProps } from './ThemeProvider';
export { ThemeReference } from './themeReference';
export type { OnThemeChange, ThemeRecipe, ThemeTransform } from './themeReference';
export { getCurrentAppearance, isHighContrast, setIsHighContrast } from './platformUtils';
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Appearance } from 'react-native';

import type { AppearanceOptions, ThemeOptions } from '@fluentui-react-native/design/theming';
import type { AppearanceOptions, Theme, ThemeOptions } from './types/Theme.types';

export function getCurrentAppearance(appearance: ThemeOptions['appearance'], fallback: AppearanceOptions): AppearanceOptions {
if (appearance === undefined || appearance === null) {
Expand All @@ -9,3 +9,11 @@ export function getCurrentAppearance(appearance: ThemeOptions['appearance'], fal

return appearance === 'dynamic' ? (Appearance && Appearance.getColorScheme()) || fallback : appearance;
}

export function setIsHighContrast(_isHighContrast: boolean) {
// High contrast state is managed externally on platforms other than macOS.
}

export function isHighContrast(_theme?: Theme): boolean {
return false;
}
13 changes: 13 additions & 0 deletions packages/agentic-design/src/theming/platformUtils.macos.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { Theme } from './types/Theme.types';

export { getCurrentAppearance } from './platformUtils.defaults';

let isHighContrastEnabled = false;

export function setIsHighContrast(isHighContrast: boolean) {
isHighContrastEnabled = isHighContrast;
}

export function isHighContrast(_theme?: Theme): boolean {
return isHighContrastEnabled;
}
1 change: 1 addition & 0 deletions packages/agentic-design/src/theming/platformUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { getCurrentAppearance, isHighContrast, setIsHighContrast } from './platformUtils.defaults';
7 changes: 7 additions & 0 deletions packages/agentic-design/src/theming/platformUtils.win32.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { Theme } from './types/Theme.types';

export { getCurrentAppearance, setIsHighContrast } from './platformUtils.defaults';

export function isHighContrast(theme?: Theme): boolean {
return theme?.name === 'HighContrast';
}
26 changes: 26 additions & 0 deletions packages/agentic-design/src/theming/platformUtils.windows.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Appearance } from 'react-native';
import { AppTheme } from 'react-native-windows';

import type { AppearanceOptions, Theme, ThemeOptions } from './types/Theme.types';

export { setIsHighContrast } from './platformUtils.defaults';

export function getCurrentAppearance(appearance: ThemeOptions['appearance'], fallback: AppearanceOptions): AppearanceOptions {
if (appearance === undefined) {
return fallback;
}

if (appearance === 'dynamic') {
if (!AppTheme || !Appearance) {
return fallback;
}

return AppTheme.isHighContrast ? 'highContrast' : Appearance.getColorScheme();
}

return appearance;
}

export function isHighContrast(_theme?: Theme): boolean {
return AppTheme.isHighContrast;
}
2 changes: 1 addition & 1 deletion packages/agentic-design/src/tokens/flex.types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ColorValue, TextStyle, ViewStyle, DimensionValue } from 'react-native';
import type { ShadowToken } from '../theming/Shadow.types';
import type { ShadowToken } from '../theming/types/Shadow.types';

type FontWeight = TextStyle['fontWeight'];
type FontSize = TextStyle['fontSize'];
Expand Down
1 change: 0 additions & 1 deletion packages/components/Avatar/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
"@fluentui-react-native/framework": "workspace:*",
"@fluentui-react-native/framework-base": "workspace:*",
"@fluentui-react-native/icon": "workspace:*",
"@fluentui-react-native/theming-utils": "workspace:*",
"@fluentui-react-native/tokens": "workspace:*",
"@fluentui-react-native/use-styling": "workspace:*",
"unicode-segmenter": "^0.14.4"
Expand Down
2 changes: 1 addition & 1 deletion packages/components/Avatar/src/AvatarTokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
fontWeightRegular,
fontWeightSemibold,
} from '@fluentui-react-native/design/tokens/global';
import { isHighContrast } from '@fluentui-react-native/theming-utils';
import { isHighContrast } from '@fluentui-react-native/design/theming';
import type { TokenSettings } from '@fluentui-react-native/use-styling';

import type { AvatarTokens } from '.';
Expand Down
2 changes: 1 addition & 1 deletion packages/components/Avatar/src/AvatarTokens.win32.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
fontWeightRegular,
fontWeightSemibold,
} from '@fluentui-react-native/design/tokens/global';
import { isHighContrast } from '@fluentui-react-native/theming-utils';
import { isHighContrast } from '@fluentui-react-native/design/theming';
import type { TokenSettings } from '@fluentui-react-native/use-styling';

import type { AvatarTokens } from '.';
Expand Down
3 changes: 0 additions & 3 deletions packages/components/Avatar/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@
{
"path": "../../../scripts/tsconfig.json"
},
{
"path": "../../theming/theming-utils/tsconfig.json"
},
{
"path": "../../utils/tokens/tsconfig.json"
},
Expand Down
1 change: 0 additions & 1 deletion packages/components/Badge/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
"@fluentui-react-native/framework-base": "workspace:*",
"@fluentui-react-native/icon": "workspace:*",
"@fluentui-react-native/text": "workspace:*",
"@fluentui-react-native/theming-utils": "workspace:*",
"@fluentui-react-native/tokens": "workspace:*",
"@fluentui-react-native/use-styling": "workspace:*"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isHighContrast } from '@fluentui-react-native/theming-utils';
import { isHighContrast } from '@fluentui-react-native/design/theming';
import type { PresenceBadgeTokens } from './PresenceBadge.types';
import type { Theme } from '@fluentui-react-native/design/theming';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
size20,
sizeNone,
} from '@fluentui-react-native/design/tokens/global';
import { isHighContrast } from '@fluentui-react-native/theming-utils';
import { isHighContrast } from '@fluentui-react-native/design/theming';

import type { PresenceBadgeTokens } from './PresenceBadge.types';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
size20,
sizeNone,
} from '@fluentui-react-native/design/tokens/global';
import { isHighContrast } from '@fluentui-react-native/theming-utils';
import { isHighContrast } from '@fluentui-react-native/design/theming';
import { getBadgeColor } from './PresenceBadge.helpers';

import type { PresenceBadgeTokens } from './PresenceBadge.types';
Expand Down
3 changes: 0 additions & 3 deletions packages/components/Badge/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@
{
"path": "../Text/tsconfig.json"
},
{
"path": "../../theming/theming-utils/tsconfig.json"
},
{
"path": "../../utils/tokens/tsconfig.json"
},
Expand Down
1 change: 0 additions & 1 deletion packages/components/Button/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
"@fluentui-react-native/pressable": "workspace:*",
"@fluentui-react-native/styling-utils": "workspace:*",
"@fluentui-react-native/text": "workspace:*",
"@fluentui-react-native/theming-utils": "workspace:*",
"@fluentui-react-native/tokens": "workspace:*",
"@fluentui-react-native/use-styling": "workspace:*",
"@uifabricshared/foundation-composable": "workspace:*",
Expand Down
2 changes: 1 addition & 1 deletion packages/components/Button/src/ButtonColorTokens.macos.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Theme } from '@fluentui-react-native/framework';
import { isHighContrast } from '@fluentui-react-native/theming-utils';
import { isHighContrast } from '@fluentui-react-native/design/theming';
import type { TokenSettings } from '@fluentui-react-native/use-styling';

import type { ButtonTokens } from './Button.types';
Expand Down
2 changes: 1 addition & 1 deletion packages/components/Button/src/ButtonColorTokens.win32.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { PlatformColor } from 'react-native';

import type { Theme } from '@fluentui-react-native/framework';
import { isHighContrast } from '@fluentui-react-native/theming-utils';
import { isHighContrast } from '@fluentui-react-native/design/theming';
import type { TokenSettings } from '@fluentui-react-native/use-styling';

import type { ButtonTokens } from './Button.types';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { PlatformColor } from 'react-native';

import type { Theme } from '@fluentui-react-native/framework';
import { isHighContrast } from '@fluentui-react-native/theming-utils';
import { isHighContrast } from '@fluentui-react-native/design/theming';
import type { TokenSettings } from '@fluentui-react-native/use-styling';

import type { ButtonTokens } from './Button.types';
Expand Down
Loading
Loading