From dcc4b98619b241d7cbec49f3040129bc5bb1841c Mon Sep 17 00:00:00 2001 From: Srividya Ramaswamy Date: Tue, 27 Oct 2026 12:54:51 -0700 Subject: [PATCH 1/6] fix(agentic): expose native Button Toggle semantics Declare resolved Toggle actions for caller-owned selection, retain native action forwarding, and add checked-state ownership and stable-layout regressions without physical input. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4b66f3ef-85ac-4405-bd35-dcc167a077b1 --- .changeset/sharp-teeth-happen.md | 5 + .../components/src/components/button/SPEC.md | 6 +- .../src/components/button/button.stories.tsx | 192 +++++++++++++++++- .../src/components/button/button.test.tsx | 70 ++++++- .../components/button/spec/accessibility.md | 8 + .../src/components/button/spec/source.json | 2 +- .../src/components/button/spec/usage.md | 23 +++ .../src/components/button/useButton.ts | 14 +- 8 files changed, 312 insertions(+), 8 deletions(-) create mode 100644 .changeset/sharp-teeth-happen.md diff --git a/.changeset/sharp-teeth-happen.md b/.changeset/sharp-teeth-happen.md new file mode 100644 index 0000000000..8ea5a12830 --- /dev/null +++ b/.changeset/sharp-teeth-happen.md @@ -0,0 +1,5 @@ +--- +"@fluentui-react-native/components": patch +--- + +Declare Button's native Toggle action when selected is supplied, preserving caller actions and externally owned checked state. diff --git a/packages/agentic/components/src/components/button/SPEC.md b/packages/agentic/components/src/components/button/SPEC.md index efac5fe7e3..bb7ae840f7 100644 --- a/packages/agentic/components/src/components/button/SPEC.md +++ b/packages/agentic/components/src/components/button/SPEC.md @@ -65,8 +65,8 @@ layout and requires an action-oriented `accessibilityLabel`. - **BTN-004:** Expose button semantics, merge caller accessibility state, warn for an unnamed icon-only button, and hide decorative icons. - **BTN-005:** Treat `selected` as externally owned state, expose checked - accessibility state when that prop is present, and reserve semibold label - width to prevent toggle reflow. + accessibility state and the resolved native Toggle action when that prop is + present, and reserve semibold label width to prevent toggle reflow. - **BTN-006:** Follow the [shared focus visual policy](../../../references/higher-order-components.md#focus-visual-policy) on the root: default to native rings on Windows/macOS and root-modality-aware custom rings on Win32, retaining the same dual-ring geometry. @@ -112,5 +112,5 @@ Button adds no component-owned motion. | BTN-002 | `renderButton.tsx`, `button.test.tsx`, `button.stories.tsx` | | BTN-003 | `button.styles.ts`, `useButtonStyles.ts`, `button.test.tsx` | | BTN-004 | `useButton.ts`, `useButtonStyles.ts`, `button.test.tsx` | -| BTN-005 | `useButton.ts`, `renderButton.tsx`, `button.test.tsx` | +| BTN-005 | `useButton.ts`, `renderButton.tsx`, `button.test.tsx`, `button.stories.tsx` | | BTN-006 | `useButton.ts`, `useButtonStyles.ts`, `renderButton.tsx`, `button.test.tsx` | diff --git a/packages/agentic/components/src/components/button/button.stories.tsx b/packages/agentic/components/src/components/button/button.stories.tsx index eeae742bf3..774e491db8 100644 --- a/packages/agentic/components/src/components/button/button.stories.tsx +++ b/packages/agentic/components/src/components/button/button.stories.tsx @@ -1,10 +1,12 @@ /** @jsxImportSource @fluentui-react-native/framework-base */ import { useState } from 'react'; import type { ReactNode } from 'react'; -import { StyleSheet, Text, View } from 'react-native'; +import { Platform, StyleSheet, Text, View } from 'react-native'; +import type { AccessibilityActionEvent } from 'react-native'; import type { Meta, StoryObj } from '@storybook/react-native'; import { ThemedRoot, useRootInputModality } from '@fluentui-react-native/design'; +import { resolveAccessibilityAction } from '@fluentui-react-native/framework-base'; import type { FocusKeyboardEvent, FocusRequest } from '@fluentui-react-native/framework-base'; import type { WdioStory } from '@fluentui-react-native/storybook-desktop/testing'; @@ -587,6 +589,194 @@ export const Disabled: Story = { }, }; +export const NativeToggleSemantics: Story = { + render: () => { + const Scene = () => { + const [action, setAction] = useState({ count: 0, name: 'none' }); + const [presses, setPresses] = useState(0); + return ( + +