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
7 changes: 4 additions & 3 deletions .agents/skills/dependabot-rollup/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
name: dependabot-rollup
description: >-
Review and optionally combine open Dependabot patch and minor pull requests into a validated draft rollup PR. Use this skill to test Dependabot bundling locally or in a cloud agent without adding a scheduled GitHub Actions workflow. Always presents a dry-run plan and requires explicit approval before changing branches or GitHub pull requests.
Review and optionally combine at most 11 open Dependabot patch and minor pull requests into a validated draft rollup PR. Use this skill to test Dependabot bundling locally or in a cloud agent without adding a scheduled GitHub Actions workflow. Always presents a dry-run plan and requires explicit approval before changing branches or GitHub pull requests.
disable-model-invocation: true
argument-hint: '[--repo owner/repo] [--base branch] [--max count] [--push-remote remote]'
allowed-tools: Bash Read Grep Glob
Expand All @@ -17,10 +17,10 @@ Build a reviewable rollup of compatible Dependabot updates without scheduled aut
| --------------- | ---------------------------------- | --------------------------------------------- |
| `--repo` | `microsoft/fluentui` | Repository containing the Dependabot PRs |
| `--base` | `master` | Base branch for discovery and the rollup |
| `--max` | `11` | Maximum eligible PRs in one proposed rollup |
| `--max` | `11` | Eligible PR limit, from 1 through 11 |
| `--push-remote` | Current branch's configured remote | Writable fork remote used only after approval |

Parse overrides from `$ARGUMENTS`. Reject an invalid repository name, a non-positive integer for `--max`, an unknown Git remote, or unknown arguments instead of guessing.
Parse overrides from `$ARGUMENTS`. Reject an invalid repository name, a `--max` value that is not an integer from 1 through 11, an unknown Git remote, or unknown arguments instead of guessing. The value 11 is an absolute ceiling, not only the default.

## Workflow

Expand Down Expand Up @@ -197,6 +197,7 @@ Report:
- Never run on a schedule or add a GitHub Actions workflow.
- Never request or print a GitHub token; use the user's existing `gh` authentication.
- Never include semver-major, non-semver, downgrade, or unparseable updates.
- Never propose, merge, or publish a rollup containing more than 11 updates.
- Never include more than one PR for the same dependency in a proposed rollup.
- Never mutate the user's current working tree.
- Never auto-resolve merge conflicts or bypass failed validation.
Expand Down
23 changes: 2 additions & 21 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,14 @@ updates:
- 'minor'
- 'patch'

# npm dependencies - weekly minor and patch updates grouped by dependency type
# npm dependencies - weekly minor and patch updates
- package-ecosystem: 'npm'
directory: '/'
schedule:
interval: 'weekly'
open-pull-requests-limit: 6
versioning-strategy: increase
ignore:
# Ignore major version bumps for all npm dependencies in weekly updates
# Ignore major version bumps for scheduled npm version updates
- dependency-name: '*'
update-types: ['version-update:semver-major']
groups:
npm-security-updates:
applies-to: security-updates
patterns:
- '*'
npm-dev-minor-patch:
dependency-type: 'development'
patterns:
- '*'
update-types:
- 'minor'
- 'patch'
npm-prod-minor-patch:
dependency-type: 'production'
patterns:
- '*'
update-types:
- 'minor'
- 'patch'
16 changes: 10 additions & 6 deletions .github/instructions/dependabot-security-fixes.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,28 @@ This instruction guide explains how Dependabot automation works for security fix

Dependabot is configured to automatically create pull requests for:

1. **Security updates** - Advisory-driven updates grouped into consolidated npm pull requests
2. **npm dependencies** - Weekly minor and patch updates grouped by dependency type
1. **Security updates** - Advisory-driven npm pull requests created independently for each update
2. **npm dependencies** - Weekly minor and patch version updates created as individual pull requests
3. **GitHub Actions** - Weekly updates for workflow dependencies

## Configuration

The Dependabot configuration is defined in `.github/dependabot.yml`:

- **Production dependencies**: Weekly minor and patch version updates
- **Development dependencies**: Weekly minor and patch version updates
- **npm dependencies**: Weekly minor and patch version updates as individual pull requests
- **GitHub Actions**: Weekly updates
- **Security updates**: Grouped separately and not limited by the version update schedule
- **Security updates**: Individual pull requests not limited by the version update schedule
- **Rollups**: Maintainers can use `/dependabot-rollup` to combine at most 11 eligible non-major updates

The repository's Advanced Security **Grouped security updates** setting must remain disabled. Dependabot does not support a maximum dependency count for automatic groups, so enabling that setting would bypass the 11-update rollup limit.

The npm `open-pull-requests-limit` controls the number of scheduled version-update pull requests. It does not limit the number of dependencies in a pull request or change Dependabot's separate security-update pull request limit.

## Security Vulnerability Resolution

### Automatic Security Updates

GitHub triggers automatic security updates independently of the configured version update schedule. The Dependabot configuration groups eligible npm security updates into consolidated pull requests, including fixes that require major version bumps.
GitHub triggers automatic security updates independently of the configured version update schedule. Each npm security update remains a separate pull request. Major security remediations are never included in `/dependabot-rollup`, so compatibility work stays isolated for focused review.

### Manual Resolution via Yarn Resolutions

Expand Down
22 changes: 11 additions & 11 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,17 +91,17 @@ state.root.className = mergeClasses(

## Skills (Slash Commands)

| Skill | Command | Purpose |
| ------------------- | -------------------- | ---------------------------------------------------------- |
| `v9-component` | `/v9-component Name` | Scaffold a new v9 component with all required files |
| `change` | `/change` | Create beachball change file from current diff |
| `lint-check` | `/lint-check [pkg]` | Run lint, parse errors, and auto-fix common issues |
| `token-lookup` | `/token-lookup val` | Find the design token for a hardcoded CSS value |
| `package-info` | `/package-info pkg` | Quick lookup: path, deps, owner, tests, structure |
| `visual-test` | `/visual-test Name` | Visually verify a component via Storybook + playwright-cli |
| `review-pr` | `/review-pr #123` | Review a PR with confidence scoring and category checks |
| `triage-issues` | `/triage-issues` | Walk the Needs-Triage queue and recommend labels/assignee |
| `dependabot-rollup` | `/dependabot-rollup` | Dry-run and optionally roll up Dependabot patch/minor PRs |
| Skill | Command | Purpose |
| ------------------- | -------------------- | -------------------------------------------------------------------- |
| `v9-component` | `/v9-component Name` | Scaffold a new v9 component with all required files |
| `change` | `/change` | Create beachball change file from current diff |
| `lint-check` | `/lint-check [pkg]` | Run lint, parse errors, and auto-fix common issues |
| `token-lookup` | `/token-lookup val` | Find the design token for a hardcoded CSS value |
| `package-info` | `/package-info pkg` | Quick lookup: path, deps, owner, tests, structure |
| `visual-test` | `/visual-test Name` | Visually verify a component via Storybook + playwright-cli |
| `review-pr` | `/review-pr #123` | Review a PR with confidence scoring and category checks |
| `triage-issues` | `/triage-issues` | Walk the Needs-Triage queue and recommend labels/assignee |
| `dependabot-rollup` | `/dependabot-rollup` | Dry-run and optionally roll up at most 11 Dependabot patch/minor PRs |

## Package Layout

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import * as React from 'react';
import type { PositioningImperativeRef, PositioningProps } from '@fluentui/react-components';

import {
useId,
Text,
Expand All @@ -8,9 +10,11 @@ import {
Button,
PopoverTrigger,
PopoverSurface,
PositioningImperativeRef,
} from '@fluentui/react-components';

// Derive the event type from PositioningProps instead of importing directly
type OnPositioningEndEvent = Parameters<Exclude<PositioningProps['onPositioningEnd'], undefined>>[0];

const useStyles = makeStyles({
root: {
display: 'flex',
Expand Down Expand Up @@ -49,7 +53,7 @@ const useStyles = makeStyles({
export const ListenToUpdates = () => {
const styles = useStyles();
const labelId = useId();
const [statusLog, setStatusLog] = React.useState<number[]>([]);
const [statusLog, setStatusLog] = React.useState<Array<{ timestamp: number; message: string }>>([]);
const positioningRef = React.useRef<PositioningImperativeRef>(null);
const [open, setOpen] = React.useState(false);

Expand All @@ -64,8 +68,17 @@ export const ListenToUpdates = () => {
positioningRef.current?.updatePosition();
}, []);

const onPositioningEnd = React.useCallback(() => {
setStatusLog(s => [Date.now(), ...s]);
const onPositioningEnd = React.useCallback((e: OnPositioningEndEvent) => {
const { placement, escaped, referenceHidden } = e.detail;
const visibility = escaped || referenceHidden ? 'hidden' : 'visible';

setStatusLog(s => [
{
timestamp: Date.now(),
message: `placement=${placement}, escaped=${escaped}, referenceHidden=${referenceHidden}, visibility=${visibility}`,
},
...s,
]);
}, []);

return (
Expand All @@ -91,11 +104,11 @@ export const ListenToUpdates = () => {
Status log
</div>
<div role="log" aria-labelledby={labelId} className={styles.log}>
{statusLog.map((time, i) => {
const date = new Date(time);
{statusLog.map((entry, i) => {
const date = new Date(entry.timestamp);
return (
<div key={i}>
{date.toLocaleTimeString()} <Text weight="bold">Position updated [{i}]</Text>
{date.toLocaleTimeString()} <Text weight="bold">{entry.message}</Text>
</div>
);
})}
Expand All @@ -117,6 +130,9 @@ ListenToUpdates.parameters = {
'This constraint makes it difficult to know exactly when an element has been positioned. In order to listen',
'to position updates you can use the `onPositioningEnd` callback.',
'',
'The callback now includes `placement`, `escaped`, and `referenceHidden` in `event.detail` so consumers can',
'respond to visibility conditions without relying on CSS attribute selectors.',
'',
'> ⚠️ _Very few use cases would actually require listening to position updates. Please remember that_',
'_there is a difference between this and the **open/close state** which is normally handled in React_',
].join('\n'),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "none",
"comment": "chore: re-export headless render helpers",
"packageName": "@fluentui/react-headless-components-preview",
"email": "vgenaev@gmail.com",
"dependentChangeType": "none"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "feat(react-positioning): add escaped/referenceHidden visibility flags to onPositioningEnd event detail",
"packageName": "@fluentui/react-positioning",
"email": "paulmardling@microsoft.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
```ts

import type { AvatarBaseProps } from '@fluentui/react-avatar';
import { AvatarBaseState } from '@fluentui/react-avatar';
import type { AvatarBaseState } from '@fluentui/react-avatar';
import type { AvatarSlots as AvatarSlots_2 } from '@fluentui/react-avatar';
import type { ForwardRefComponent } from '@fluentui/react-utilities';
import { JSXElement } from '@fluentui/react-utilities';
import type * as React_2 from 'react';
import { renderAvatar_unstable as renderAvatar } from '@fluentui/react-avatar';

// @public
export const Avatar: ForwardRefComponent<AvatarProps>;
Expand All @@ -23,8 +23,7 @@ export type AvatarSlots = AvatarSlots_2;
// @public
export type AvatarState = AvatarBaseState;

// @public
export const renderAvatar: (state: AvatarBaseState) => JSXElement;
export { renderAvatar }

// @public
export const useAvatar: (props: AvatarProps, ref: React_2.Ref<HTMLElement>) => AvatarState;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
```ts

import type { BadgeBaseProps } from '@fluentui/react-badge';
import { BadgeBaseState } from '@fluentui/react-badge';
import type { BadgeBaseState } from '@fluentui/react-badge';
import type { BadgeSlots as BadgeSlots_2 } from '@fluentui/react-badge';
import type { ForwardRefComponent } from '@fluentui/react-utilities';
import { JSXElement } from '@fluentui/react-utilities';
import type * as React_2 from 'react';
import { renderBadge_unstable as renderBadge } from '@fluentui/react-badge';

// @public
export const Badge: ForwardRefComponent<BadgeProps>;
Expand All @@ -27,8 +27,7 @@ export type BadgeState = BadgeBaseState & {
};
};

// @public
export const renderBadge: (state: BadgeBaseState) => JSXElement;
export { renderBadge }

// @public
export const useBadge: (props: BadgeProps, ref: React_2.Ref<HTMLDivElement>) => BadgeState;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
```ts

import type { BreadcrumbBaseProps } from '@fluentui/react-breadcrumb';
import { BreadcrumbBaseState } from '@fluentui/react-breadcrumb';
import type { BreadcrumbBaseState } from '@fluentui/react-breadcrumb';
import type { BreadcrumbButtonBaseProps } from '@fluentui/react-breadcrumb';
import type { BreadcrumbButtonBaseState } from '@fluentui/react-breadcrumb';
import type { BreadcrumbButtonSlots as BreadcrumbButtonSlots_2 } from '@fluentui/react-breadcrumb';
Expand All @@ -20,6 +20,7 @@ import type { BreadcrumbSlots as BreadcrumbSlots_2 } from '@fluentui/react-bread
import type { ForwardRefComponent } from '@fluentui/react-utilities';
import { JSXElement } from '@fluentui/react-utilities';
import type * as React_2 from 'react';
import { renderBreadcrumb_unstable as renderBreadcrumb } from '@fluentui/react-breadcrumb';

// @public
export const Breadcrumb: ForwardRefComponent<BreadcrumbProps>;
Expand Down Expand Up @@ -76,8 +77,7 @@ export type BreadcrumbSlots = BreadcrumbSlots_2;
// @public
export type BreadcrumbState = BreadcrumbBaseState;

// @public
export const renderBreadcrumb: (state: BreadcrumbBaseState, contextValues: BreadcrumbContextValues_2) => JSXElement;
export { renderBreadcrumb }

// @public
export const renderBreadcrumbButton: (state: BreadcrumbButtonState) => JSXElement;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
```ts

import type { CardBaseProps } from '@fluentui/react-card';
import { CardBaseState } from '@fluentui/react-card';
import type { CardBaseState } from '@fluentui/react-card';
import { CardContextValue as CardContextValue_2 } from '@fluentui/react-card';
import type { CardFooterBaseProps } from '@fluentui/react-card';
import { CardFooterBaseState } from '@fluentui/react-card';
Expand All @@ -21,6 +21,7 @@ import type { CardSlots as CardSlots_2 } from '@fluentui/react-card';
import type { ForwardRefComponent } from '@fluentui/react-utilities';
import { JSXElement } from '@fluentui/react-utilities';
import type * as React_2 from 'react';
import { renderCard_unstable as renderCard } from '@fluentui/react-card';

// @public
export const Card: ForwardRefComponent<CardProps>;
Expand Down Expand Up @@ -80,8 +81,7 @@ export type CardState = CardBaseState & {
};
};

// @public
export const renderCard: (state: CardBaseState, cardContextValue: CardContextValue_2) => JSXElement;
export { renderCard }

// @public
export const renderCardFooter: (state: CardFooterBaseState) => JSXElement;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
```ts

import type { CheckboxBaseProps } from '@fluentui/react-checkbox';
import { CheckboxBaseState } from '@fluentui/react-checkbox';
import type { CheckboxBaseState } from '@fluentui/react-checkbox';
import type { CheckboxSlots as CheckboxSlots_2 } from '@fluentui/react-checkbox';
import type { ForwardRefComponent } from '@fluentui/react-utilities';
import { JSXElement } from '@fluentui/react-utilities';
import type * as React_2 from 'react';
import { renderCheckbox_unstable as renderCheckbox } from '@fluentui/react-checkbox';

// @public
export const Checkbox: ForwardRefComponent<CheckboxProps>;
Expand All @@ -28,8 +28,7 @@ export type CheckboxState = CheckboxBaseState & {
};
};

// @public
export const renderCheckbox: (state: CheckboxBaseState) => JSXElement;
export { renderCheckbox }

// @public
export const useCheckbox: (props: CheckboxProps, ref: React_2.Ref<HTMLInputElement>) => CheckboxState;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,21 @@ import type { BaseComboboxState } from '@fluentui/react-combobox';
import { ComboboxContextValues } from '@fluentui/react-combobox';
import { ComboboxSlots } from '@fluentui/react-combobox';
import type { ForwardRefComponent } from '@fluentui/react-utilities';
import { JSXElement } from '@fluentui/react-utilities';
import { ListboxContextValues as ListboxContextValues_2 } from '@fluentui/react-combobox';
import type { JSXElement } from '@fluentui/react-utilities';
import type { ListboxContextValues as ListboxContextValues_2 } from '@fluentui/react-combobox';
import type { ListboxProps as ListboxProps_2 } from '@fluentui/react-combobox';
import type { ListboxSlots as ListboxSlots_2 } from '@fluentui/react-combobox';
import { ListboxState as ListboxState_2 } from '@fluentui/react-combobox';
import type { ListboxState as ListboxState_2 } from '@fluentui/react-combobox';
import type { OptionGroupProps as OptionGroupProps_2 } from '@fluentui/react-combobox';
import type { OptionGroupSlots as OptionGroupSlots_2 } from '@fluentui/react-combobox';
import { OptionGroupState as OptionGroupState_2 } from '@fluentui/react-combobox';
import type { OptionGroupState as OptionGroupState_2 } from '@fluentui/react-combobox';
import type { OptionProps as OptionProps_2 } from '@fluentui/react-combobox';
import type { OptionSlots as OptionSlots_2 } from '@fluentui/react-combobox';
import { OptionState as OptionState_2 } from '@fluentui/react-combobox';
import type { OptionState as OptionState_2 } from '@fluentui/react-combobox';
import type * as React_2 from 'react';
import { renderListbox_unstable as renderListbox } from '@fluentui/react-combobox';
import { renderOption_unstable as renderOption } from '@fluentui/react-combobox';
import { renderOptionGroup_unstable as renderOptionGroup } from '@fluentui/react-combobox';

// @public (undocumented)
export const Combobox: ForwardRefComponent<ComboboxProps>;
Expand Down Expand Up @@ -87,14 +90,11 @@ export type OptionState = OptionState_2 & {
// @public (undocumented)
export const renderCombobox: (state: ComboboxState, contextValues: ComboboxContextValues) => JSXElement;

// @public
export const renderListbox: (state: ListboxState_2, contextValues: ListboxContextValues_2) => JSXElement;
export { renderListbox }

// @public
export const renderOption: (state: OptionState_2) => JSXElement;
export { renderOption }

// @public
export const renderOptionGroup: (state: OptionGroupState_2) => JSXElement;
export { renderOptionGroup }

// @public (undocumented)
export const useCombobox: (props: ComboboxProps, ref: React_2.Ref<HTMLInputElement>) => ComboboxState;
Expand Down
Loading
Loading