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
25 changes: 25 additions & 0 deletions .changeset/nine-bees-relate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
"@uifabricshared/foundation-composable": minor
"@fluentui-react-native/themed-stylesheet": minor
"@fluentui-react-native/focus-trap-zone": minor
"@fluentui-react-native/persona-coin": minor
"@fluentui-react-native/menu-button": minor
"@fluentui-react-native/overflow": minor
"@fluentui-react-native/composition": minor
"@fluentui-react-native/use-styling": minor
"@fluentui-react-native/focus-zone": minor
"@fluentui-react-native/experimental-shimmer": minor
"@fluentui-react-native/use-tokens": minor
"@fluentui-react-native/dependency-profiles": minor
"@fluentui-react-native/framework": minor
"@fluentui-react-native/use-slots": minor
"@fluentui-react-native/persona": minor
"@fluentui-react-native/avatar": minor
"@fluentui-react-native/stack": minor
"@fluentui-react-native/menu": minor
"@fluentui-react-native/theme": minor
"@fluentui-react-native/framework-base": minor
"@fluentui-react-native/adapters": minor
---

rework framework rendering to prepare for new component structure
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ The composition framework uses precise types for better type safety:
- `MIGRATION.md` - Migration guide (for V1 components)
- `tsconfig.json`, `babel.config.js`, `jest.config.js`, `eslint.config.js`

**Using Composition Framework**: Use `@fluentui-react-native/composition` for new components. For simpler components without slots/tokens, use the `stagedComponent` pattern from `@fluentui-react-native/use-slot`.
**Using Composition Framework**: Use `@fluentui-react-native/composition` for new components. For simpler components without slots/tokens, use the `stagedComponent` pattern from `@fluentui-react-native/framework-base`.

**JSX Runtime**: All components use the modern automatic JSX runtime:

Expand Down
5 changes: 2 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Tokens help us achieve simpler customization for complex higher order components

This section covers creating and adding a new component package to FluentUI React Native's monorepo. If you are instead working on an existing component and adding a native module, skip to the next two sections.

Most components should use the compose framework as it offers the comprehensive set of patterns like tokens and slots, but if you're creating a simple component that doesn't require those patterns, there's a lighter pattern called [stagedComponent](./packages/framework-base/src/component-patterns/stagedComponent.ts). The stagedComponent pattern splits up the render function into two stages. Stage 1 handles building props and hook calls (best to separate the hook calls from the render tree since they rely on call order). Stage 2 returns the actual element tree, any conditional branching should happen here (Icon is a good example of using stagedCompoenent).
Most components should use the compose framework as it offers the comprehensive set of patterns like tokens and slots, but if you're creating a simple component that doesn't require those patterns, there's a lighter pattern called [stagedComponent](./packages/framework-base/src/component-patterns/phased.ts). The stagedComponent pattern splits up the render function into two stages. Stage 1 handles building props and hook calls (best to separate the hook calls from the render tree since they rely on call order). Stage 2 returns the actual element tree, any conditional branching should happen here (Icon is a good example of using stagedCompoenent).

1. Create a new directory in of these two locations, depending on your component:
- `fluentui-react-native/packages/components/<new-component>`
Expand All @@ -63,8 +63,7 @@ Reach out to Samuel Freiberg with any questions related to E2E testing.
1. Create a `src/` subdirectory in your component directory with a minimum of two files (listed below). You may optionally choose to subdivide your code however you wish; there are plenty of examples in the other components of FluentUI React Native.
1. `index.ts`
- This is the file listed as `main` inside your package.json and simply exports other files.
1. `<new-component>.tsx` - This is the file that will actually define your function component, and compose it into a higher order component with slots, theming, and design tokens. - Note that we need the comment `/** @jsxRuntime classic */
/** @jsx withSlots */` at the top of this file. An explanation can be found in the comment at `packages/experimental/use-slots/src/withSlots.tsx`
1. `<new-component>.tsx` - This is the file that will actually define your function component, and compose it into a higher order component with slots, theming, and design tokens. - Note that we need the comment `/** @jsxImportSource @fluentui-react-native/framework-base */` as the first line of this file. This opts the file into the custom JSX runtime that handles slot rendering; an explanation can be found in `packages/framework-base/src/component-patterns/README.md`. Packages using this pragma must include `@fluentui-react-native/framework-base` in their `devDependencies`.
1. `<new-component>.<types | settings | platform | blah>.tsx` (Optional)
- Optional extra files to subdivide your code however you see fit. You can also add platform specific files as you see fit.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
},
"dependencies": {},
"devDependencies": {
"@fluentui-react-native/framework-base": "workspace:*",
"@fluentui-react-native/scripts": "workspace:*",
"@fluentui-react-native/test-tools": "workspace:*",
"react": "18.2.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
/** @jsxRuntime classic */
/** @jsx withSlots */
/** @jsxImportSource @fluentui-react-native/framework-base */
import * as React from 'react';
import { View } from 'react-native';
import { componentName, ComponentNameType, ComponentNameProps } from './ComponentName.types';
import { TextV1 as Text } from '@fluentui-react-native/text';
import { stylingSettings } from './ComponentName.styling';
import { compose, mergeProps, withSlots, UseSlots } from '@fluentui-react-native/framework';
import { compose, mergeProps, UseSlots } from '@fluentui-react-native/framework';
import { useComponentName } from './useComponentName';
/**
* A function which determines if a set of styles should be applied to the component given the current state and props of the component-name.
Expand Down
28 changes: 14 additions & 14 deletions apps/fluent-tester/macos/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ PODS:
- fast_float (8.0.0)
- FBLazyVector (0.81.2)
- fmt (11.0.2)
- FRNAvatar (0.22.4):
- FRNAvatar (0.22.5):
- MicrosoftFluentUI (= 0.13.1)
- React
- FRNCallout (0.28.4):
- FRNCallout (0.28.5):
- boost
- DoubleConversion
- fast_float
Expand Down Expand Up @@ -36,13 +36,13 @@ PODS:
- ReactCommon/turbomodule/core
- SocketRocket
- Yoga
- FRNCheckbox (0.18.4):
- FRNCheckbox (0.18.5):
- React
- FRNMenuButton (0.14.4):
- FRNMenuButton (0.14.5):
- React
- FRNRadioButton (0.22.4):
- FRNRadioButton (0.22.5):
- React
- FRNVibrancyView (0.4.4):
- FRNVibrancyView (0.4.5):
- React
- glog (0.3.5)
- hermes-engine (0.81.5):
Expand Down Expand Up @@ -137,7 +137,7 @@ PODS:
- fmt (= 11.0.2)
- glog
- RCTDeprecation (0.81.2)
- RCTFocusZone (0.22.4):
- RCTFocusZone (0.22.5):
- React
- RCTRequired (0.81.2)
- RCTTypeSafety (0.81.2):
Expand Down Expand Up @@ -2667,18 +2667,18 @@ SPEC CHECKSUMS:
fast_float: 20817c22759af6ac8d4d67e6e059b8b499953656
FBLazyVector: 0e3076dbb16169b0afc2d701a24a526423b5e76b
fmt: 24e7591456deb60b4a77518f83d9a916ac84223f
FRNAvatar: 586585a440e2b23c9ac872fd1fa2ddb7819cd7bd
FRNCallout: f3234f07e6f49334c0f1de7cb7185494f2915db5
FRNCheckbox: a5afb9bb4e6405d39a30f997f7e69d6e5672533d
FRNMenuButton: e9e49a3afa5eb5ecbe4a36c41047bce763f661c7
FRNRadioButton: 6f7db3424604a413b4cca73c5a22033c79f92d43
FRNVibrancyView: a9cf18fcaee2a7d9f9ea292924ebf1b3acb0a5b2
FRNAvatar: c4baf9356785232c547bb76a9ccd290e94e0fda9
FRNCallout: ee98ce83b788ff3d3716463269560487b787f658
FRNCheckbox: 2e74a528f6328ea79bf9eaa2a1d466dd8f30be4f
FRNMenuButton: bb6913908137c530f1a3af2d8d7d5c6a5fae4e19
FRNRadioButton: adf6b247f1143c9e79f63221405e9b94ef7bef6d
FRNVibrancyView: ccff736e2c309eba2ed56f1b803a0e55b8a3067f
glog: ba31c1afa7dcf1915a109861bccdb4421be6175b
hermes-engine: 9f4dfe93326146a1c99eb535b1cb0b857a3cd172
MicrosoftFluentUI: dde98d8ed3fc306d9ddd0a6f0bc0c1f24fe5275e
RCT-Folly: c803cf33238782d5fd21a5e02d44f64068e0e130
RCTDeprecation: b60b889eafa75f46c3d6be5332681efbb16ad0c7
RCTFocusZone: a6d62c46c530e790479915bc9faa578137e9e2a6
RCTFocusZone: f4199120b2260bc5710359852686307a0f8d8b0e
RCTRequired: 070d7f0ef937e7a93aab20761cef55419f16b5de
RCTTypeSafety: dd2ad1eb0c0c01ba41222d115be141f9a348c636
React: 304df3d34c8c0281fd1fd3a506e69f234095425d
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { View, type ViewStyle } from 'react-native';

import { Text } from '@fluentui/react-native';
import { Shadow, getShadowTokenStyleSet } from '@fluentui-react-native/experimental-shadow';
import { mergeStyles, useFluentTheme } from '@fluentui-react-native/framework';
import { useFluentTheme } from '@fluentui-react-native/framework';
import { mergeStyles } from '@fluentui-react-native/framework-base';
import type { ShadowToken, Theme } from '@fluentui-react-native/theme-types';
import { useTheme } from '@fluentui-react-native/theme-types';
import { themedStyleSheet } from '@fluentui-react-native/themed-stylesheet';
Expand Down
5 changes: 2 additions & 3 deletions docs/pages/Theming/Tokens/UsageWithComponentTokens.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ This page covers how to access color tokens to fill out a component's tokens.
Most components in FURN build a component's styling out of the tokens and theme that are fed into the component. The `compose` framework takes in an object with a `tokens` property, which you can use to define how a component's tokens are filled out. The `tokens` property can be assigned to a function which takes a `Theme` object as an argument and returns an object that is the component's `Token` type. Inside the function, you can access the alias function from the theme as you would if you had the theme inside a component's render function.

```tsx
/** @jsxRuntime classic */
/** @jsx withSlots */
import { Theme, TokenSettings, buildProps, compose, mergeProps, withSlots, UseSlots } from '@fluentui-react-native/framework';
/** @jsxImportSource @fluentui-react-native/framework-base */
import { Theme, TokenSettings, buildProps, compose, mergeProps, UseSlots } from '@fluentui-react-native/framework';
import { fontStyles } from '@fluentui-react-native/tokens';
import { Text } from '@fluentui-react-native/experimental-text';

Expand Down
3 changes: 3 additions & 0 deletions packages/agentic-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
"test": "fluentui-scripts jest",
"update-snapshots": "fluentui-scripts jest -u"
},
"dependencies": {
"@fluentui-react-native/framework-base": "workspace:*"
},
"devDependencies": {
"@babel/core": "catalog:",
"@fluentui-react-native/scripts": "workspace:*",
Expand Down
4 changes: 2 additions & 2 deletions packages/agentic-components/src/components/button/button.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import { Pressable, StyleSheet, Text } from 'react-native';
import type { GestureResponderEvent, StyleProp, ViewStyle } from 'react-native';
import type { FurnJSX } from '@fluentui-react-native/framework-base';

/**
* Props for the simple {@link Button} component.
Expand Down Expand Up @@ -47,7 +47,7 @@ const styles = StyleSheet.create({
/**
* A simple cross-platform button built directly on react-native primitives.
*/
export function Button(props: ButtonProps): React.JSX.Element {
export function Button(props: ButtonProps): FurnJSX.Element {
const { title, onPress, disabled, style } = props;
return (
<Pressable
Expand Down
Empty file.
3 changes: 3 additions & 0 deletions packages/agentic-components/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
"include": ["src"],
"exclude": ["**/*.stories.ts", "**/*.stories.tsx"],
"references": [
{
"path": "../framework-base/tsconfig.json"
},
{
"path": "../../scripts/tsconfig.json"
}
Expand Down
5 changes: 2 additions & 3 deletions packages/components/Avatar/src/Avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { Image, View, Text, Platform } from 'react-native';

import { PresenceBadge } from '@fluentui-react-native/badge';
import type { UseSlots, Slots } from '@fluentui-react-native/framework';
import { compose, mergeProps } from '@fluentui-react-native/framework';
import { compose } from '@fluentui-react-native/framework';
import { mergeProps } from '@fluentui-react-native/framework-base';
import { Icon } from '@fluentui-react-native/icon';
import { Svg, Path } from 'react-native-svg';

Expand Down Expand Up @@ -86,8 +87,6 @@ function renderAvatar(final: AvatarProps, avatarProps: AvatarProps, Slots: Slots
{initials ? (
<Slots.initials accessible={false}>{initials}</Slots.initials>
) : avatarProps.icon ? (
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error - TODO, fix typing error
<Slots.icon {...icon} accessible={false} />
) : (
svgIconsEnabled && (
Expand Down
3 changes: 2 additions & 1 deletion packages/components/Badge/src/Badge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import { View, I18nManager } from 'react-native';

import { Shadow } from '@fluentui-react-native/experimental-shadow';
import type { UseSlots } from '@fluentui-react-native/framework';
import { compose, mergeProps } from '@fluentui-react-native/framework';
import { compose } from '@fluentui-react-native/framework';
import { mergeProps } from '@fluentui-react-native/framework-base';
import { Icon, createIconProps } from '@fluentui-react-native/icon';
import { TextV1 as Text } from '@fluentui-react-native/text';

Expand Down
3 changes: 2 additions & 1 deletion packages/components/Badge/src/CounterBadge/CounterBadge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import { View, I18nManager } from 'react-native';

import { Shadow } from '@fluentui-react-native/experimental-shadow';
import type { UseSlots } from '@fluentui-react-native/framework';
import { compose, mergeProps } from '@fluentui-react-native/framework';
import { compose } from '@fluentui-react-native/framework';
import { mergeProps } from '@fluentui-react-native/framework-base';
import { Icon, createIconProps } from '@fluentui-react-native/icon';
import { TextV1 as Text } from '@fluentui-react-native/text';

Expand Down
3 changes: 2 additions & 1 deletion packages/components/Button/src/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { Platform, Pressable, View } from 'react-native';

import { ActivityIndicator } from '@fluentui-react-native/experimental-activity-indicator';
import type { UseSlots } from '@fluentui-react-native/framework';
import { compose, memoize, mergeProps } from '@fluentui-react-native/framework';
import { compose } from '@fluentui-react-native/framework';
import { memoize, mergeProps } from '@fluentui-react-native/framework-base';
import { Icon, createIconProps } from '@fluentui-react-native/icon';
import type { IPressableState } from '@fluentui-react-native/interactive-hooks';
import { TextV1 as Text } from '@fluentui-react-native/text';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { Platform, Pressable, View } from 'react-native';

import { ActivityIndicator } from '@fluentui-react-native/experimental-activity-indicator';
import type { UseSlots } from '@fluentui-react-native/framework';
import { compose, mergeProps } from '@fluentui-react-native/framework';
import { compose } from '@fluentui-react-native/framework';
import { mergeProps } from '@fluentui-react-native/framework-base';
import { Icon, createIconProps } from '@fluentui-react-native/icon';
import { TextV1 as Text } from '@fluentui-react-native/text';

Expand Down
2 changes: 1 addition & 1 deletion packages/components/Button/src/ExtractStyle.android.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { ViewStyle } from 'react-native';

import { memoize } from '@fluentui-react-native/framework';
import { memoize } from '@fluentui-react-native/framework-base';

/**
* React Native's Pressable does not support curved edges.
Expand Down
3 changes: 2 additions & 1 deletion packages/components/Button/src/FAB/FAB.mobile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { Platform, Pressable, View } from 'react-native';

import { Shadow } from '@fluentui-react-native/experimental-shadow';
import type { UseSlots } from '@fluentui-react-native/framework';
import { compose, mergeProps } from '@fluentui-react-native/framework';
import { compose } from '@fluentui-react-native/framework';
import { mergeProps } from '@fluentui-react-native/framework-base';
import { Icon, createIconProps } from '@fluentui-react-native/icon';
import type { IPressableState } from '@fluentui-react-native/interactive-hooks';
import { TextV1 as Text } from '@fluentui-react-native/text';
Expand Down
3 changes: 2 additions & 1 deletion packages/components/Button/src/ToggleButton/ToggleButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { Platform, Pressable, View } from 'react-native';

import { ActivityIndicator } from '@fluentui-react-native/experimental-activity-indicator';
import type { UseSlots } from '@fluentui-react-native/framework';
import { compose, mergeProps } from '@fluentui-react-native/framework';
import { compose } from '@fluentui-react-native/framework';
import { mergeProps } from '@fluentui-react-native/framework-base';
import { Icon, createIconProps } from '@fluentui-react-native/icon';
import { TextV1 as Text } from '@fluentui-react-native/text';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react';
import type { AccessibilityState } from 'react-native';

import { memoize } from '@fluentui-react-native/framework';
import { memoize } from '@fluentui-react-native/framework-base';
import { useAsToggleWithEvent } from '@fluentui-react-native/interactive-hooks';

import type { ToggleButtonProps, ToggleButtonInfo } from './ToggleButton.types';
Expand Down
3 changes: 2 additions & 1 deletion packages/components/Checkbox/src/Checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import * as React from 'react';
import { Pressable, Platform } from 'react-native';

import type { UseSlots } from '@fluentui-react-native/framework';
import { compose, mergeProps } from '@fluentui-react-native/framework';
import { compose } from '@fluentui-react-native/framework';
import { mergeProps } from '@fluentui-react-native/framework-base';
import { TextV1 as Text } from '@fluentui-react-native/text';
import { Svg, Path } from 'react-native-svg';

Expand Down
2 changes: 1 addition & 1 deletion packages/components/Checkbox/src/useCheckbox.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react';
import type { AccessibilityActionEvent, AccessibilityState } from 'react-native';

import { memoize } from '@fluentui-react-native/framework';
import { memoize } from '@fluentui-react-native/framework-base';
import {
usePressableState,
useKeyProps,
Expand Down
3 changes: 2 additions & 1 deletion packages/components/Chip/src/Chip.mobile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { Children } from 'react';
import { Pressable, I18nManager } from 'react-native';

import type { UseSlots } from '@fluentui-react-native/framework';
import { compose, mergeProps } from '@fluentui-react-native/framework';
import { compose } from '@fluentui-react-native/framework';
import { mergeProps } from '@fluentui-react-native/framework-base';
import { Icon } from '@fluentui-react-native/icon';
import { TextV1 as Text } from '@fluentui-react-native/text';

Expand Down
2 changes: 1 addition & 1 deletion packages/components/Chip/src/useChip.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react';
import type { AccessibilityState } from 'react-native';

import { memoize } from '@fluentui-react-native/framework';
import { memoize } from '@fluentui-react-native/framework-base';
import { createIconProps } from '@fluentui-react-native/icon';
import { usePressableState, useAsToggleWithEvent } from '@fluentui-react-native/interactive-hooks';
import type { InteractionEvent } from '@fluentui-react-native/interactive-hooks';
Expand Down
2 changes: 1 addition & 1 deletion packages/components/Divider/src/Divider.styling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useMemo } from 'react';
import type { ViewProps, ColorValue, StyleProp, ViewStyle } from 'react-native';
import { Platform } from 'react-native';

import { memoize, mergeStyles } from '@fluentui-react-native/framework';
import { memoize, mergeStyles } from '@fluentui-react-native/framework-base';
import type { Theme } from '@fluentui-react-native/framework';
import type { IconPropsV1 as IconProps } from '@fluentui-react-native/icon';
import type { TextProps } from '@fluentui-react-native/text';
Expand Down
3 changes: 2 additions & 1 deletion packages/components/Divider/src/Divider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import React from 'react';
import { View } from 'react-native';
import type { ViewProps } from 'react-native';

import { compressible, useSlot, useFluentTheme, patchTokens } from '@fluentui-react-native/framework';
import { compressible, useFluentTheme, patchTokens } from '@fluentui-react-native/framework';
import { useSlot } from '@fluentui-react-native/framework-base';
import type { UseTokens } from '@fluentui-react-native/framework';
import { IconV1 as Icon } from '@fluentui-react-native/icon';
import type { IconPropsV1 as IconProps } from '@fluentui-react-native/icon';
Expand Down
8 changes: 6 additions & 2 deletions packages/components/FocusTrapZone/src/FocusTrapZone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,12 @@ import { mergeSettings } from '@uifabricshared/foundation-settings';
import type { IFocusTrapZoneProps, IFocusTrapZoneSlotProps, IFocusTrapZoneType } from './FocusTrapZone.types';
import RCTFocusTrapZone from './FocusTrapZoneNativeComponent';

export function filterOutComponentRef(propName: string): boolean {
return propName !== 'componentRef';
export function filterOutComponentRef<T>(props: T): T {
if (props && typeof props === 'object' && 'componentRef' in props) {
const { componentRef: _componentRef, ...rest } = props as Record<string, unknown>;
return rest as T;
}
return props;
}

export const FocusTrapZone = composable<IFocusTrapZoneType>({
Expand Down
Loading
Loading