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
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "feat: add headless Tags components",
"packageName": "@fluentui/react-headless-components-preview",
"email": "vgenaev@gmail.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
## API Report File for "@fluentui/react-headless-components-preview"

> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).

```ts

import type { ForwardRefComponent } from '@fluentui/react-utilities';
import type { InteractionTagPrimaryBaseState } from '@fluentui/react-tags';
import type { InteractionTagPrimaryContextValues as InteractionTagPrimaryContextValues_2 } from '@fluentui/react-tags';
import { InteractionTagPrimaryBaseProps as InteractionTagPrimaryProps } from '@fluentui/react-tags';
import { InteractionTagPrimarySlots } from '@fluentui/react-tags';
import * as React_2 from 'react';
import { renderInteractionTagPrimary_unstable as renderInteractionTagPrimary } from '@fluentui/react-tags';

// @public
export const InteractionTagPrimary: ForwardRefComponent<InteractionTagPrimaryProps>;

// @public (undocumented)
export type InteractionTagPrimaryContextValues = InteractionTagPrimaryContextValues_2;

export { InteractionTagPrimaryProps }

export { InteractionTagPrimarySlots }

// @public (undocumented)
export type InteractionTagPrimaryState = InteractionTagPrimaryBaseState & {
root: {
'data-disabled'?: string;
'data-selected'?: string;
'data-has-secondary-action'?: string;
};
};

export { renderInteractionTagPrimary }

// @public
export const useInteractionTagPrimary: (props: InteractionTagPrimaryProps, ref: React_2.Ref<HTMLButtonElement>) => InteractionTagPrimaryState;

// @public (undocumented)
export const useInteractionTagPrimaryContextValues: (_state: InteractionTagPrimaryState) => InteractionTagPrimaryContextValues;

// (No @packageDocumentation comment for this package)

```
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
## API Report File for "@fluentui/react-headless-components-preview"

> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).

```ts

import type { ForwardRefComponent } from '@fluentui/react-utilities';
import type { InteractionTagSecondaryBaseState } from '@fluentui/react-tags';
import { InteractionTagSecondaryBaseProps as InteractionTagSecondaryProps } from '@fluentui/react-tags';
import { InteractionTagSecondarySlots } from '@fluentui/react-tags';
import type * as React_2 from 'react';
import { renderInteractionTagSecondary_unstable as renderInteractionTagSecondary } from '@fluentui/react-tags';

// @public
export const InteractionTagSecondary: ForwardRefComponent<InteractionTagSecondaryProps>;

export { InteractionTagSecondaryProps }

export { InteractionTagSecondarySlots }

// @public (undocumented)
export type InteractionTagSecondaryState = InteractionTagSecondaryBaseState & {
root: {
'data-disabled'?: string;
'data-selected'?: string;
};
};

export { renderInteractionTagSecondary }

// @public
export const useInteractionTagSecondary: (props: InteractionTagSecondaryProps, ref: React_2.Ref<HTMLButtonElement>) => InteractionTagSecondaryState;

// (No @packageDocumentation comment for this package)

```
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
## API Report File for "@fluentui/react-headless-components-preview"

> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).

```ts

import type { ForwardRefComponent } from '@fluentui/react-utilities';
import type { InteractionTagBaseState } from '@fluentui/react-tags';
import type { InteractionTagContextValue } from '@fluentui/react-tags';
import { InteractionTagBaseProps as InteractionTagProps } from '@fluentui/react-tags';
import { InteractionTagSlots } from '@fluentui/react-tags';
import * as React_2 from 'react';
import { renderInteractionTag_unstable as renderInteractionTag } from '@fluentui/react-tags';

// @public
export const InteractionTag: ForwardRefComponent<InteractionTagProps>;

// @public (undocumented)
export type InteractionTagContextValues = {
interactionTag: InteractionTagContextValue;
};

export { InteractionTagProps }

export { InteractionTagSlots }

// @public (undocumented)
export type InteractionTagState = InteractionTagBaseState & {
root: {
'data-disabled'?: string;
'data-selected'?: string;
};
};

export { renderInteractionTag }

// @public
export const useInteractionTag: (props: InteractionTagProps, ref: React_2.Ref<HTMLDivElement>) => InteractionTagState;

// @public (undocumented)
export const useInteractionTagContextValues: (state: InteractionTagState) => InteractionTagContextValues;

// (No @packageDocumentation comment for this package)

```
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
## API Report File for "@fluentui/react-headless-components-preview"

> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).

```ts

import type { ForwardRefComponent } from '@fluentui/react-utilities';
import * as React_2 from 'react';
import { renderTagGroup_unstable as renderTagGroup } from '@fluentui/react-tags';
import type { TagGroupBaseState } from '@fluentui/react-tags';
import type { TagGroupContextValue } from '@fluentui/react-tags';
import { TagGroupBaseProps as TagGroupProps } from '@fluentui/react-tags';
import { TagGroupSlots } from '@fluentui/react-tags';

export { renderTagGroup }

// @public
export const TagGroup: ForwardRefComponent<TagGroupProps>;

// @public (undocumented)
export type TagGroupContextValues = {
tagGroup: TagGroupContextValue;
};

export { TagGroupProps }

export { TagGroupSlots }

// @public (undocumented)
export type TagGroupState = TagGroupBaseState & {
root: {
focusgroup?: string;
'data-disabled'?: string;
'data-dismissible'?: string;
};
};

// @public
export const useTagGroup: (props: TagGroupProps, ref: React_2.Ref<HTMLDivElement>) => TagGroupState;

// @public (undocumented)
export const useTagGroupContextValues: (state: TagGroupState) => TagGroupContextValues;

// (No @packageDocumentation comment for this package)

```
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
## API Report File for "@fluentui/react-headless-components-preview"

> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).

```ts

import type { ForwardRefComponent } from '@fluentui/react-utilities';
import * as React_2 from 'react';
import { renderTag_unstable as renderTag } from '@fluentui/react-tags';
import type { TagBaseState } from '@fluentui/react-tags';
import { TagContextValues } from '@fluentui/react-tags';
import { TagBaseProps as TagProps } from '@fluentui/react-tags';
import { TagSlots } from '@fluentui/react-tags';

export { renderTag }

// @public
export const Tag: ForwardRefComponent<TagProps>;

export { TagContextValues }

export { TagProps }

export { TagSlots }

// @public (undocumented)
export type TagState = TagBaseState & {
root: {
'data-disabled'?: string;
'data-dismissible'?: string;
'data-selected'?: string;
};
};

// @public
export const useTag: (props: TagProps, ref: React_2.Ref<HTMLSpanElement | HTMLButtonElement>) => TagState;

// @public (undocumented)
export const useTagContextValues: (_state: TagState) => TagContextValues;

// (No @packageDocumentation comment for this package)

```
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,24 @@
"import": "./lib/input.js",
"require": "./lib-commonjs/input.js"
},
"./interaction-tag": {
"types": "./dist/interaction-tag.d.ts",
"node": "./lib-commonjs/interaction-tag.js",
"import": "./lib/interaction-tag.js",
"require": "./lib-commonjs/interaction-tag.js"
},
"./interaction-tag-primary": {
"types": "./dist/interaction-tag-primary.d.ts",
"node": "./lib-commonjs/interaction-tag-primary.js",
"import": "./lib/interaction-tag-primary.js",
"require": "./lib-commonjs/interaction-tag-primary.js"
},
"./interaction-tag-secondary": {
"types": "./dist/interaction-tag-secondary.d.ts",
"node": "./lib-commonjs/interaction-tag-secondary.js",
"import": "./lib/interaction-tag-secondary.js",
"require": "./lib-commonjs/interaction-tag-secondary.js"
},
"./label": {
"types": "./dist/label.d.ts",
"node": "./lib-commonjs/label.js",
Expand Down Expand Up @@ -294,6 +312,18 @@
"import": "./lib/tab-list.js",
"require": "./lib-commonjs/tab-list.js"
},
"./tag": {
"types": "./dist/tag.d.ts",
"node": "./lib-commonjs/tag.js",
"import": "./lib/tag.js",
"require": "./lib-commonjs/tag.js"
},
"./tag-group": {
"types": "./dist/tag-group.d.ts",
"node": "./lib-commonjs/tag-group.js",
"import": "./lib/tag-group.js",
"require": "./lib-commonjs/tag-group.js"
},
"./textarea": {
"types": "./dist/textarea.d.ts",
"node": "./lib-commonjs/textarea.js",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import * as React from 'react';
import { render } from '@testing-library/react';
import { isConformant } from '../../testing/isConformant';
import { InteractionTag } from './InteractionTag';
import { InteractionTagPrimary } from '../InteractionTagPrimary';

const requiredProps = { children: <InteractionTagPrimary>tag</InteractionTagPrimary> };

describe('InteractionTag', () => {
isConformant({
Component: InteractionTag,
displayName: 'InteractionTag',
requiredProps,
});

it('provides a child InteractionTagPrimary with an aria-pressed when handleTagSelect is wired', () => {
const result = render(<InteractionTag {...requiredProps} />);
expect(result.getByRole('button')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'use client';

import * as React from 'react';
import type { ForwardRefComponent } from '@fluentui/react-utilities';

import type { InteractionTagProps } from './InteractionTag.types';
import { useInteractionTag, useInteractionTagContextValues } from './useInteractionTag';
import { renderInteractionTag } from './renderInteractionTag';

/**
* A visual representation of an attribute that can have primary and/or secondary actions.
* Composed with `InteractionTagPrimary` and optionally `InteractionTagSecondary` children.
*/
export const InteractionTag: ForwardRefComponent<InteractionTagProps> = React.forwardRef((props, ref) => {
const state = useInteractionTag(props, ref);
const contextValues = useInteractionTagContextValues(state);
return renderInteractionTag(state, contextValues);
});

InteractionTag.displayName = 'InteractionTag';
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { InteractionTagBaseState, InteractionTagContextValue } from '@fluentui/react-tags';

export type { InteractionTagSlots, InteractionTagBaseProps as InteractionTagProps } from '@fluentui/react-tags';

export type InteractionTagState = InteractionTagBaseState & {
root: {
/**
* Data attribute set when the interaction tag is disabled.
*/
'data-disabled'?: string;

/**
* Data attribute set when the interaction tag is selected.
*/
'data-selected'?: string;
};
};

export type InteractionTagContextValues = {
interactionTag: InteractionTagContextValue;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export { InteractionTag } from './InteractionTag';
export { renderInteractionTag } from './renderInteractionTag';
export { useInteractionTag, useInteractionTagContextValues } from './useInteractionTag';
export type {
InteractionTagSlots,
InteractionTagProps,
InteractionTagState,
InteractionTagContextValues,
} from './InteractionTag.types';
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { renderInteractionTag_unstable as renderInteractionTag } from '@fluentui/react-tags';
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
'use client';

import * as React from 'react';
import { useInteractionTagBase_unstable } from '@fluentui/react-tags';
import type { InteractionTagContextValue } from '@fluentui/react-tags';

import type { InteractionTagContextValues, InteractionTagProps, InteractionTagState } from './InteractionTag.types';
import { stringifyDataAttribute } from '../../utils';

/**
* Returns the state for an InteractionTag component, given its props and ref.
* The returned state can be modified with hooks before being passed to `renderInteractionTag`.
*/
export const useInteractionTag = (props: InteractionTagProps, ref: React.Ref<HTMLDivElement>): InteractionTagState => {
const state: InteractionTagState = useInteractionTagBase_unstable(props, ref);

/* eslint-disable react-hooks/immutability -- intentional: decorate base state with data-* attrs for styling */
state.root['data-disabled'] = stringifyDataAttribute(state.disabled);
state.root['data-selected'] = stringifyDataAttribute(state.selected);
/* eslint-enable react-hooks/immutability */

return state;
};

export const useInteractionTagContextValues = (state: InteractionTagState): InteractionTagContextValues => {
const { disabled, handleTagDismiss, handleTagSelect, interactionTagPrimaryId, selected, selectedValues, value } =
state;

const interactionTag: InteractionTagContextValue = React.useMemo(
() => ({
appearance: 'filled',
shape: 'rounded',
size: 'medium',
disabled,
handleTagDismiss,
handleTagSelect,
interactionTagPrimaryId,
selected,
selectedValues,
value,
}),
[disabled, handleTagDismiss, handleTagSelect, interactionTagPrimaryId, selected, selectedValues, value],
);

return { interactionTag };
};
Loading
Loading