Skip to content

Commit

Permalink
feat(react-tag): Added selected state for Tag and InteractionTag
Browse files Browse the repository at this point in the history
  • Loading branch information
ValentinaKozlova committed Feb 11, 2025
1 parent 0274540 commit 58d7bd3
Show file tree
Hide file tree
Showing 16 changed files with 295 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ export type InteractionTagProps<Value = TagValue> = ComponentProps<Partial<Inter
*/
disabled?: boolean;

/**
* An InteractionTag can be selected.
*
* @default false
*/
selected?: boolean;

/**
* An InteractionTag can have rounded or circular shape.
*
Expand All @@ -52,7 +59,7 @@ export type InteractionTagProps<Value = TagValue> = ComponentProps<Partial<Inter
* State used in rendering InteractionTag
*/
export type InteractionTagState<Value = TagValue> = ComponentState<InteractionTagSlots> &
Required<Pick<InteractionTagProps, 'appearance' | 'disabled' | 'shape' | 'size' | 'value'>> & {
Required<Pick<InteractionTagProps, 'appearance' | 'disabled' | 'selected' | 'shape' | 'size' | 'value'>> & {
/**
* Event handler from TagGroup context that allows TagGroup to dismiss the tag
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export const useInteractionTag_unstable = (
const {
appearance = contextAppearance ?? 'filled',
disabled = false,
selected = false,
shape = 'rounded',
size = contextSize,
value = id,
Expand All @@ -40,6 +41,7 @@ export const useInteractionTag_unstable = (
disabled: contextDisabled ? true : disabled,
handleTagDismiss,
interactionTagPrimaryId,
selected,
shape,
size,
value,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ export type InteractionTagPrimaryProps = ComponentProps<Partial<InteractionTagPr
* @default false
*/
hasSecondaryAction?: boolean;

/**
* An InteractionTag can be selected.
*
* @default false
*/
selected?: boolean;
};

/**
Expand All @@ -47,6 +54,6 @@ export type InteractionTagPrimaryProps = ComponentProps<Partial<InteractionTagPr
export type InteractionTagPrimaryState = ComponentState<InteractionTagPrimarySlots> &
Required<
Pick<InteractionTagContextValue, 'appearance' | 'disabled' | 'shape' | 'size'> &
Pick<InteractionTagPrimaryProps, 'hasSecondaryAction'>
Pick<InteractionTagPrimaryProps, 'hasSecondaryAction' | 'selected'>
> &
UseTagAvatarContextValuesOptions;
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,16 @@ export const useInteractionTagPrimary_unstable = (
props: InteractionTagPrimaryProps,
ref: React.Ref<HTMLButtonElement>,
): InteractionTagPrimaryState => {
const { appearance, disabled, interactionTagPrimaryId, shape, size } = useInteractionTagContext_unstable();
const { hasSecondaryAction = false } = props;
const { appearance, disabled, interactionTagPrimaryId, shape, size } = useInteractionTagContext_unstable(); // TODO add selected from state
const { hasSecondaryAction = false, selected = false } = props;

return {
appearance,
avatarShape: avatarShapeMap[shape],
avatarSize: avatarSizeMap[size],
disabled,
hasSecondaryAction,
selected,
shape,
size,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,19 @@ const useRootStyles = makeStyles({
},
},
},

selected: {
background: tokens.colorBrandBackground,
color: tokens.colorNeutralForegroundOnBrand,
...shorthands.borderColor(tokens.colorBrandBackground),
':hover': {
backgroundColor: tokens.colorBrandBackgroundHover,
color: tokens.colorNeutralForegroundOnBrand,
},
':active': {
backgroundColor: tokens.colorBrandBackgroundPressed,
color: tokens.colorNeutralForegroundOnBrand,
},
},
medium: {
paddingRight: '7px',
},
Expand Down Expand Up @@ -279,7 +291,7 @@ export const useInteractionTagPrimaryStyles_unstable = (

const rootCircularContrastStyles = useRootCircularContrastStyles();

const { shape, size, appearance } = state;
const { shape, size, appearance, selected } = state;

state.root.className = mergeClasses(
interactionTagPrimaryClassNames.root,
Expand All @@ -289,6 +301,7 @@ export const useInteractionTagPrimaryStyles_unstable = (
shape === 'circular' && !state.hasSecondaryAction && rootCircularContrastStyles.withoutSecondaryAction,

state.disabled ? rootDisabledAppearances[appearance] : rootStyles[appearance],
selected && rootStyles.selected,
rootStyles[size],

!state.media && !state.icon && rootWithoutMediaStyles[size],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ export type InteractionTagSecondaryProps = ComponentProps<InteractionTagSecondar
* State used in rendering InteractionTagSecondary
*/
export type InteractionTagSecondaryState = ComponentState<InteractionTagSecondarySlots> &
Required<Pick<InteractionTagContextValue, 'appearance' | 'disabled' | 'shape' | 'size'>>;
Required<Pick<InteractionTagContextValue, 'appearance' | 'disabled' | 'selected' | 'shape' | 'size'>>;
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const useInteractionTagSecondary_unstable = (
props: InteractionTagSecondaryProps,
ref: React.Ref<HTMLButtonElement>,
): InteractionTagSecondaryState => {
const { appearance, disabled, handleTagDismiss, interactionTagPrimaryId, shape, size, value } =
const { appearance, disabled, handleTagDismiss, interactionTagPrimaryId, selected, shape, size, value } =
useInteractionTagContext_unstable();

const id = useId('fui-InteractionTagSecondary-', props.id);
Expand All @@ -40,6 +40,7 @@ export const useInteractionTagSecondary_unstable = (
return {
appearance,
disabled,
selected,
shape,
size,
components: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,19 @@ const useRootStyles = makeStyles({
},
},
},
selected: {
background: tokens.colorBrandBackground,
color: tokens.colorNeutralForegroundOnBrand,
...shorthands.borderColor(tokens.colorBrandBackground),
':hover': {
backgroundColor: tokens.colorBrandBackgroundHover,
color: tokens.colorNeutralForegroundOnBrand,
},
':active': {
backgroundColor: tokens.colorBrandBackgroundPressed,
color: tokens.colorNeutralForegroundOnBrand,
},
},

rounded: {
borderTopRightRadius: tokens.borderRadiusMedium,
Expand Down Expand Up @@ -162,14 +175,15 @@ export const useInteractionTagSecondaryStyles_unstable = (
const rootStyles = useRootStyles();
const rootDisabledStyles = useRootDisabledStyles();

const { shape, size, appearance } = state;
const { selected, shape, size, appearance } = state;

state.root.className = mergeClasses(
interactionTagSecondaryClassNames.root,
rootBaseClassName,
state.disabled ? rootDisabledStyles[appearance] : rootStyles[appearance],
rootStyles[shape],
rootStyles[size],
selected && rootStyles.selected,
state.root.className,
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ export type TagProps<Value = string> = ComponentProps<Partial<TagSlots>> & {
*/
dismissible?: boolean;

/**
* An InteractionTag can be selected.
*
* @default false
*/
selected?: boolean;

/**
* A Tag can have rounded or circular shape.
*
Expand All @@ -82,5 +89,5 @@ export type TagProps<Value = string> = ComponentProps<Partial<TagSlots>> & {
* State used in rendering Tag
*/
export type TagState = ComponentState<TagSlots> &
Required<Pick<TagProps, 'appearance' | 'disabled' | 'dismissible' | 'shape' | 'size'>> &
Required<Pick<TagProps, 'appearance' | 'disabled' | 'dismissible' | 'selected' | 'shape' | 'size'>> &
UseTagAvatarContextValuesOptions;
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export const useTag_unstable = (props: TagProps, ref: React.Ref<HTMLSpanElement
appearance = contextAppearance ?? 'filled',
disabled = false,
dismissible = contextDismissible ?? false,
selected = false,
shape = 'rounded',
size = contextSize,
value = id,
Expand Down Expand Up @@ -68,6 +69,7 @@ export const useTag_unstable = (props: TagProps, ref: React.Ref<HTMLSpanElement
avatarSize: tagAvatarSizeMap[size],
disabled: contextDisabled ? true : disabled,
dismissible,
selected,
shape,
size,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,11 @@ const useRootStyles = makeStyles({
backgroundColor: tokens.colorBrandBackground2,
color: tokens.colorBrandForeground2,
},

selected: {
backgroundColor: tokens.colorBrandBackground,
color: tokens.colorNeutralForegroundOnBrand,
...shorthands.borderColor(tokens.colorBrandBackground),
},
medium: {
height: '32px',
},
Expand Down Expand Up @@ -342,14 +346,15 @@ export const useTagStyles_unstable = (state: TagState): TagState => {
const primaryTextStyles = usePrimaryTextStyles();
const secondaryTextBaseClassName = useSecondaryTextBaseClassName();

const { shape, size, appearance } = state;
const { shape, size, appearance = 'filled', selected } = state;

state.root.className = mergeClasses(
tagClassNames.root,

shape === 'rounded' ? rootRoundedBaseClassName : rootCircularBaseClassName,

state.disabled ? rootDisabledStyles[appearance] : rootStyles[appearance],
selected && rootStyles.selected,
rootStyles[size],

!state.media && !state.icon && rootWithoutMediaStyles[size],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const interactionTagContextDefaultValue: InteractionTagContextValue = {
disabled: false,
handleTagDismiss: () => ({}),
interactionTagPrimaryId: '',
selected: false,
shape: 'rounded',
size: 'medium',
value: '',
Expand All @@ -18,7 +19,7 @@ const interactionTagContextDefaultValue: InteractionTagContextValue = {
* Context shared between InteractionTag and its children components
*/
export type InteractionTagContextValue<Value = string> = Required<
Pick<InteractionTagState, 'appearance' | 'disabled' | 'shape' | 'size'> & {
Pick<InteractionTagState, 'appearance' | 'disabled' | 'selected' | 'shape' | 'size'> & {
handleTagDismiss: TagDismissHandler<Value>;
interactionTagPrimaryId: string;
value?: Value;
Expand Down
Loading

0 comments on commit 58d7bd3

Please sign in to comment.