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
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export type TagPickerControlSlots = {
};

// @public
export type TagPickerControlState = ComponentState<TagPickerControlSlots> & Pick<TagPickerContextValue, 'size' | 'appearance'>;
export type TagPickerControlState = ComponentState<TagPickerControlSlots> & Pick<TagPickerContextValue, 'size' | 'appearance' | 'disabled'>;

// @public
export const TagPickerGroup: ForwardRefComponent<TagPickerGroupProps>;
Expand Down Expand Up @@ -141,7 +141,7 @@ export type TagPickerInputSlots = {
} & Pick<ComboboxSlots, 'expandIcon'>;

// @public
export type TagPickerInputState = ComponentState<TagPickerInputSlots> & Pick<TagPickerContextValue, 'size'>;
export type TagPickerInputState = ComponentState<TagPickerInputSlots> & Pick<TagPickerContextValue, 'size' | 'disabled'>;

// @public
export const TagPickerList: ForwardRefComponent<TagPickerListProps>;
Expand All @@ -167,7 +167,7 @@ export const TagPickerOption: ForwardRefComponent<TagPickerOptionProps>;
export const tagPickerOptionClassNames: SlotClassNames<TagPickerOptionSlots>;

// @public
export type TagPickerOptionProps = ComponentProps<TagPickerOptionSlots> & Omit<OptionProps, 'checkIcon'> & {
export type TagPickerOptionProps = ComponentProps<TagPickerOptionSlots> & Omit<OptionProps, 'checkIcon' | 'disabled'> & {
children: React_2.ReactNode;
text?: string;
value: string;
Expand All @@ -183,15 +183,15 @@ export type TagPickerOptionSlots = Omit<OptionSlots, 'checkIcon'> & {
export type TagPickerOptionState = ComponentState<TagPickerOptionSlots> & Omit<OptionState, 'checkIcon'>;

// @public
export type TagPickerProps = ComponentProps<TagPickerSlots> & Pick<ComboboxProps, 'onOptionSelect' | 'positioning'> & Pick<Partial<TagPickerContextValue>, 'size' | 'selectedOptions' | 'appearance'> & {
export type TagPickerProps = ComponentProps<TagPickerSlots> & Pick<ComboboxProps, 'onOptionSelect' | 'positioning' | 'disabled'> & Pick<Partial<TagPickerContextValue>, 'size' | 'selectedOptions' | 'appearance'> & {
children: [JSX.Element, JSX.Element] | JSX.Element;
};

// @public (undocumented)
export type TagPickerSlots = {};

// @public
export type TagPickerState = ComponentState<TagPickerSlots> & Omit<ComboboxState, 'listbox' | 'root' | 'input' | 'expandIcon' | 'clearIcon' | 'components' | 'size'> & Pick<TagPickerContextValue, 'triggerRef' | 'popoverId' | 'popoverRef' | 'targetRef' | 'size'> & {
export type TagPickerState = ComponentState<TagPickerSlots> & Omit<ComboboxState, 'listbox' | 'root' | 'input' | 'expandIcon' | 'clearIcon' | 'components' | 'size'> & Pick<TagPickerContextValue, 'triggerRef' | 'popoverId' | 'popoverRef' | 'targetRef' | 'size' | 'disabled'> & {
positioning?: PositioningShorthand;
trigger: React_2.ReactNode;
popover?: React_2.ReactNode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export type TagPickerSize = 'medium' | 'large' | 'extra-large';
* Picker Props
*/
export type TagPickerProps = ComponentProps<TagPickerSlots> &
Pick<ComboboxProps, 'onOptionSelect' | 'positioning'> &
Pick<ComboboxProps, 'onOptionSelect' | 'positioning' | 'disabled'> &
Pick<Partial<TagPickerContextValue>, 'size' | 'selectedOptions' | 'appearance'> & {
/**
* Can contain two children including a trigger and a popover
Expand All @@ -27,7 +27,7 @@ export type TagPickerProps = ComponentProps<TagPickerSlots> &
*/
export type TagPickerState = ComponentState<TagPickerSlots> &
Omit<ComboboxState, 'listbox' | 'root' | 'input' | 'expandIcon' | 'clearIcon' | 'components' | 'size'> &
Pick<TagPickerContextValue, 'triggerRef' | 'popoverId' | 'popoverRef' | 'targetRef' | 'size'> & {
Pick<TagPickerContextValue, 'triggerRef' | 'popoverId' | 'popoverRef' | 'targetRef' | 'size' | 'disabled'> & {
/**
* Configures the positioned menu
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { useComboboxBaseState } from '../../utils/useComboboxBaseState';
export const useTagPicker_unstable = (props: TagPickerProps): TagPickerState => {
const popoverId = useId('picker-listbox');
const triggerInnerRef = React.useRef<HTMLInputElement>(null);
const { positioning, size = 'medium' } = props;
const { positioning, size = 'medium', disabled = false } = props;

// Set a default set of fallback positions to try if the dropdown does not fit on screen
const fallbackPositions: PositioningShorthandValue[] = ['above', 'after', 'after-top', 'before', 'before-top'];
Expand Down Expand Up @@ -47,9 +47,16 @@ export const useTagPicker_unstable = (props: TagPickerProps): TagPickerState =>
size: 'medium',
});
const onOptionClickBase = state.onOptionClick;
state.onOptionClick = useEventCallback(e => {
onOptionClickBase(e);
state.setOpen(e, false);
state.onOptionClick = useEventCallback(event => {
onOptionClickBase(event);
state.setOpen(event, false);
});
const setOpenBase = state.setOpen;
state.setOpen = useEventCallback((event, newValue) => {
if (disabled) {
return;
}
setOpenBase(event, newValue);
});

const children = React.Children.toArray(props.children) as React.ReactElement[];
Expand Down Expand Up @@ -81,6 +88,7 @@ export const useTagPicker_unstable = (props: TagPickerProps): TagPickerState =>
trigger,
popover: state.open || state.hasFocus ? popover : undefined,
popoverId,
disabled,
triggerRef: useMergedRefs(triggerInnerRef, activeParentRef),
popoverRef: useMergedRefs(listboxRef, containerRef),
targetRef,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export function useTagPickerContextValues(state: TagPickerState): TagPickerConte
getOptionById,
open,
popoverId,
disabled,
} = state;
return {
activeDescendant: React.useMemo(
Expand Down Expand Up @@ -60,6 +61,7 @@ export function useTagPickerContextValues(state: TagPickerState): TagPickerConte
getOptionById,
open,
popoverId,
disabled,
},
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ export type TagPickerControlProps = ComponentProps<TagPickerControlSlots>;
* State used in rendering PickerControl
*/
export type TagPickerControlState = ComponentState<TagPickerControlSlots> &
Pick<TagPickerContextValue, 'size' | 'appearance'>;
Pick<TagPickerContextValue, 'size' | 'appearance' | 'disabled'>;
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const useTagPickerControl_unstable = (
const triggerRef = useTagPickerContext_unstable(ctx => ctx.triggerRef);
const size = useTagPickerContext_unstable(ctx => ctx.size);
const appearance = useTagPickerContext_unstable(ctx => ctx.appearance);
const disabled = useTagPickerContext_unstable(ctx => ctx.disabled);
const handleMouseDown = useEventCallback((event: React.MouseEvent<HTMLDivElement>) => {
if (event.target !== triggerRef.current) {
event.preventDefault();
Expand All @@ -48,5 +49,6 @@ export const useTagPickerControl_unstable = (
),
size,
appearance,
disabled,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -150,14 +150,13 @@ const useStyles = makeStyles({
*/
export const useTagPickerControlStyles_unstable = (state: TagPickerControlState): TagPickerControlState => {
const styles = useStyles();
// TODO handle invalid styles
state.root.className = mergeClasses(
tagPickerControlClassNames.root,
styles.root,
styles[state.size],
styles[state.appearance],
// !state.disabled && state.appearance === 'outline' && styles.outlineInteractive,
// state.disabled && styles.disabled,
!state.disabled && state.appearance === 'outline' && styles.outlineInteractive,
state.disabled && styles.disabled,
state.root.className,
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ export type TagPickerInputProps = Omit<
/**
* State used in rendering TagPickerInput
*/
export type TagPickerInputState = ComponentState<TagPickerInputSlots> & Pick<TagPickerContextValue, 'size'>;
export type TagPickerInputState = ComponentState<TagPickerInputSlots> &
Pick<TagPickerContextValue, 'size' | 'disabled'>;
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,7 @@ import type { TagPickerInputProps, TagPickerInputState } from './TagPickerInput.
import { ChevronDownRegular as ChevronDownIcon } from '@fluentui/react-icons';
import { useActiveDescendantContext } from '@fluentui/react-aria';
import { useTagPickerContext_unstable } from '../../contexts/TagPickerContext';
import {
slot,
useMergedRefs,
getIntrinsicElementProps,
useEventCallback,
mergeCallbacks,
} from '@fluentui/react-utilities';
import { slot, useMergedRefs, getIntrinsicElementProps, useEventCallback } from '@fluentui/react-utilities';
import { useInputTriggerSlot } from '../../utils/useInputTriggerSlot';
import { Backspace, Enter } from '@fluentui/keyboard-keys';

Expand All @@ -29,6 +23,7 @@ export const useTagPickerInput_unstable = (
): TagPickerInputState => {
const { controller: activeDescendantController } = useActiveDescendantContext();
const size = useTagPickerContext_unstable(ctx => ctx.size);
const contextDisabled = useTagPickerContext_unstable(ctx => ctx.disabled);
const {
triggerRef,
clearSelection,
Expand All @@ -44,7 +39,7 @@ export const useTagPickerInput_unstable = (
value: contextValue,
} = usePickerContext();

const { value = contextValue, disabled } = props;
const { value = contextValue, disabled = contextDisabled } = props;

const root = useInputTriggerSlot(
{
Expand Down Expand Up @@ -108,22 +103,10 @@ export const useTagPickerInput_unstable = (
},
elementType: 'span',
}),
disabled,
size,
};

/* handle open/close + focus change when clicking expandIcon */
const { onMouseDown: onIconMouseDown } = state.expandIcon || {};

const onExpandIconMouseDown = useEventCallback(
mergeCallbacks(onIconMouseDown, (event: React.MouseEvent<HTMLSpanElement>) => {
event.preventDefault();
}),
);

if (state.expandIcon) {
state.expandIcon.onMouseDown = onExpandIconMouseDown;
}

return state;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export const useTagPickerInputStyles_unstable = (state: TagPickerInputState): Ta
tagPickerInputClassNames.root,
styles.root,
styles[state.size],
// state.disabled && styles.disabled,
state.disabled && styles.disabled,
state.root.className,
);

Expand All @@ -130,7 +130,7 @@ export const useTagPickerInputStyles_unstable = (state: TagPickerInputState): Ta
tagPickerInputClassNames.expandIcon,
iconStyles.icon,
iconStyles[state.size],
// state.disabled && iconStyles.disabled,
state.disabled && iconStyles.disabled,
// state.showClearIcon && iconStyles.visuallyHidden,
state.expandIcon.className,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export type TagPickerOptionSlots = Omit<OptionSlots, 'checkIcon'> & {
* TagPickerOption Props
*/
export type TagPickerOptionProps = ComponentProps<TagPickerOptionSlots> &
Omit<OptionProps, 'checkIcon'> & {
Omit<OptionProps, 'checkIcon' | 'disabled'> & {
children: React.ReactNode;
text?: string;
value: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export interface TagPickerContextValue
popoverId: string;
targetRef: React.RefObject<HTMLElement>;
size: TagPickerSize;
disabled: boolean;
}

/**
Expand All @@ -46,6 +47,7 @@ export const tagPickerContextDefaultValue: TagPickerContextValue = {
popoverId: '',
size: 'medium',
appearance: 'outline',
disabled: false,
};

const TagPickerContext = createContext<TagPickerContextValue | undefined>(undefined);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import * as React from 'react';
import {
TagPicker,
TagPickerList,
TagPickerInput,
TagPickerControl,
TagPickerProps,
TagPickerOption,
TagPickerGroup,
} from '@fluentui/react-tag-picker-preview';
import { Tag, Avatar } from '@fluentui/react-components';

const options = [
'John Doe',
'Jane Doe',
'Max Mustermann',
'Erika Mustermann',
'Pierre Dupont',
'Amelie Dupont',
'Mario Rossi',
'Maria Rossi',
];

export const Disabled = () => {
const [selectedOptions, setSelectedOptions] = React.useState<string[]>([
options[0],
options[1],
options[2],
options[3],
]);
const onOptionSelect: TagPickerProps['onOptionSelect'] = (e, data) => {
setSelectedOptions(data.selectedOptions);
};

return (
<div style={{ maxWidth: 400 }}>
<TagPicker disabled onOptionSelect={onOptionSelect} selectedOptions={selectedOptions}>
<TagPickerControl>
<TagPickerGroup>
{selectedOptions.map(option => (
<Tag key={option} shape="rounded" media={<Avatar name={option} color="colorful" />} value={option}>
{option}
</Tag>
))}
</TagPickerGroup>
<TagPickerInput />
</TagPickerControl>
<TagPickerList>
{options
.filter(option => !selectedOptions.includes(option))
.map(option => (
<TagPickerOption
secondaryContent="Microsoft FTE"
media={<Avatar name={option} color="colorful" />}
value={option}
key={option}
>
{option}
</TagPickerOption>
))}
</TagPickerList>
</TagPicker>
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export { Button } from './TagPickerButton.stories';
export { Filtering } from './TagPickerFiltering.stories';
export { Size } from './TagPickerSize.stories';
export { Appearance } from './TagPickerAppearance.stories';
export { Disabled } from './TagPickerDisabled.stories';

export default {
title: 'Preview Components/Tag Picker',
Expand Down