Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[react-nav-preview]feat: Adds SplitNav*Sub*Item #32964

Open
wants to merge 22 commits into
base: master
Choose a base branch
from
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 proprs for SubNavItems and Tooltips. Other pixel pushing on SplitNavItem",
"packageName": "@fluentui/react-nav-preview",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import * as React_2 from 'react';
import type { Slot } from '@fluentui/react-utilities';
import { SlotClassNames } from '@fluentui/react-utilities';
import { ToggleButtonProps } from '@fluentui/react-button';
import type { TooltipProps } from '@fluentui/react-tooltip';

// @public
export const AppItem: ForwardRefComponent<AppItemProps>;
Expand Down Expand Up @@ -398,15 +399,19 @@ export type SplitNavItemProps = ComponentProps<SplitNavItemSlots>;
// @public (undocumented)
export type SplitNavItemSlots = {
root: Slot<'div'>;
navItem?: Slot<NavItemProps>;
navItem?: NonNullable<Slot<NavItemProps & NavSubItemProps>>;
actionButton?: Slot<ButtonProps>;
toggleButton?: Slot<ToggleButtonProps>;
menuButton?: Slot<MenuButtonProps>;
actionButtonTooltip?: Slot<TooltipProps>;
toggleButtonTooltip?: Slot<TooltipProps>;
menuButtonTooltip?: Slot<TooltipProps>;
};

// @public
export type SplitNavItemState = ComponentState<SplitNavItemSlots> & {
size: NavSize;
isSubNav: boolean;
};

// @public
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"dependencies": {
"@fluentui/react-aria": "^9.13.6",
"@fluentui/react-button": "^9.3.92",
"@fluentui/react-tooltip": "^9.1.20",
"@fluentui/react-context-selector": "^9.1.67",
"@fluentui/react-divider": "^9.2.75",
"@fluentui/react-drawer": "^9.5.16",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import type { ComponentProps, ComponentState, Slot } from '@fluentui/react-utilities';
import { NavItemProps } from '../NavItem/NavItem.types';
import { ButtonProps, MenuButtonProps, ToggleButtonProps } from '@fluentui/react-button';
import type { TooltipProps } from '@fluentui/react-tooltip';
import { NavSize } from '../Nav/Nav.types';
import { NavSubItemProps } from '../NavSubItem/NavSubItem.types';

export type SplitNavItemSlots = {
/**
Expand All @@ -10,9 +12,10 @@ export type SplitNavItemSlots = {
root: Slot<'div'>;

/**
* Primary navigation item in SplitNavItem.
* The NavItem Slot.
* Will behave as a SubNavItem if it's in an a SubGroup.
*/
navItem?: Slot<NavItemProps>;
navItem?: NonNullable<Slot<NavItemProps & NavSubItemProps>>;

/**
* Basic button slot.
Expand All @@ -28,6 +31,21 @@ export type SplitNavItemSlots = {
* Menu button slot to stuff more things in when the other two aren't enough.
*/
menuButton?: Slot<MenuButtonProps>;

/**
* Tooltip for the action button.
*/
actionButtonTooltip?: Slot<TooltipProps>;

/**
* Tooltip for the toggle button.
*/
toggleButtonTooltip?: Slot<TooltipProps>;

/**
* Tooltip for the menu button.
*/
menuButtonTooltip?: Slot<TooltipProps>;
};

/**
Expand All @@ -45,4 +63,10 @@ export type SplitNavItemState = ComponentState<SplitNavItemSlots> & {
* @default 'medium'
*/
size: NavSize;

/**
* A boolean that represents if the main item in the SplitNavItem is a SubNav item.
* If false, it's a NavItem.
*/
isSubNav: boolean;
};
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,26 @@ export const renderSplitNavItem_unstable = (state: SplitNavItemState) => {
return (
<state.root>
{state.navItem && <state.navItem />}
{state.actionButton && <state.actionButton />}
{state.toggleButton && <state.toggleButton />}
{state.menuButton && <state.menuButton />}
{state.actionButton && state.actionButtonTooltip && (
<state.actionButtonTooltip>
<state.actionButton />
</state.actionButtonTooltip>
)}
{state.actionButton && !state.actionButtonTooltip && <state.actionButton />}

{state.toggleButton && state.toggleButtonTooltip && (
<state.toggleButtonTooltip>
<state.toggleButton />
</state.toggleButtonTooltip>
)}
{state.toggleButton && !state.toggleButtonTooltip && <state.toggleButton />}

{state.menuButton && state.menuButtonTooltip && (
<state.menuButtonTooltip>
<state.menuButton />
</state.menuButtonTooltip>
)}
{state.menuButton && !state.menuButtonTooltip && <state.menuButton />}
</state.root>
);
};
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import * as React from 'react';
import { getIntrinsicElementProps, slot } from '@fluentui/react-utilities';
import { Tooltip } from '@fluentui/react-tooltip';
import type { SplitNavItemProps, SplitNavItemState } from './SplitNavItem.types';
import { useNavContext_unstable } from '../NavContext';
import { Button, MenuButton, ToggleButton } from '@fluentui/react-button';
import { MoreHorizontalFilled, Pin20Regular } from '@fluentui/react-icons';
import { NavItem } from '../NavItem/index';
import { NavSubItem } from '../NavSubItem/NavSubItem';
import { useNavCategoryContext_unstable } from '../NavCategoryContext';

/**
* Create the state required to render SplitNavItem.
Expand All @@ -19,16 +22,28 @@ export const useSplitNavItem_unstable = (
props: SplitNavItemProps,
ref: React.Ref<HTMLDivElement>,
): SplitNavItemState => {
const { navItem, actionButton, toggleButton, menuButton, children } = props;
const {
navItem,
actionButton,
toggleButton,
menuButton,
actionButtonTooltip,
toggleButtonTooltip,
menuButtonTooltip,
children,
} = props;

const { size = 'medium' } = useNavContext_unstable();

const navItemShorthand = slot.optional(navItem, {
const { value: potentialParenValue } = useNavCategoryContext_unstable();

const isSubNav = potentialParenValue.length > 0 ? true : false;

const navItemShorthand = slot.always(navItem, {
defaultProps: {
children,
},
renderByDefault: true,
elementType: NavItem,
elementType: isSubNav ? NavSubItem : NavItem,
});

const actionButtonShorthand = slot.optional(actionButton, {
Expand Down Expand Up @@ -58,13 +73,31 @@ export const useSplitNavItem_unstable = (
elementType: MenuButton,
});

const actionButtonTooltipShorthand = slot.optional(actionButtonTooltip, {
defaultProps: { relationship: 'label' },
elementType: Tooltip,
});

const toggleButtonTooltipShorthand = slot.optional(toggleButtonTooltip, {
defaultProps: { relationship: 'label' },
elementType: Tooltip,
});

const menuButtonTooltipShorthand = slot.optional(menuButtonTooltip, {
defaultProps: { relationship: 'label' },
elementType: Tooltip,
});

return {
components: {
root: 'div',
navItem: NavItem,
navItem: isSubNav ? NavSubItem : NavItem,
actionButton: Button,
toggleButton: ToggleButton,
menuButton: MenuButton,
actionButtonTooltip: Tooltip,
toggleButtonTooltip: Tooltip,
menuButtonTooltip: Tooltip,
},
root: slot.always(
getIntrinsicElementProps('div', {
Expand All @@ -80,6 +113,10 @@ export const useSplitNavItem_unstable = (
actionButton: actionButtonShorthand,
toggleButton: toggleButtonShorthand,
menuButton: menuButtonShorthand,
actionButtonTooltip: actionButtonTooltipShorthand,
toggleButtonTooltip: toggleButtonTooltipShorthand,
menuButtonTooltip: menuButtonTooltipShorthand,
size,
isSubNav,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ export const splitNavItemClassNames: SlotClassNames<SplitNavItemSlots> = {
actionButton: 'fui-SplitNavItem__actionButton',
toggleButton: 'fui-SplitNavItem__toggleButton',
menuButton: 'fui-SplitNavItem__menuButton',
/**
* Tooltips don't have a class name prop, so this is just to satisfy the linter.
*/
actionButtonTooltip: 'fui-SplitNavItem__actionButtonTooltip',
toggleButtonTooltip: 'fui-SplitNavItem__toggleButtonTooltip',
menuButtonTooltip: 'fui-SplitNavItem__menuButtonTooltip',
};
// Don't use makeResetStyles here because the sub components call it once and
// This links says that makeResetStyles should only be called once per element
Expand All @@ -20,58 +26,41 @@ export const splitNavItemClassNames: SlotClassNames<SplitNavItemSlots> = {
*/
const useSplitNaveItemStyles = makeStyles({
baseRoot: {
display: 'flex',
gap: 'unset',
alignItems: 'start',
alignItems: 'stretch',
padding: 'unset',
textAlign: 'unset',
backgroundColor: navItemTokens.backgroundColor,
...navItemTokens.transitionTokens,

transitionDuration: navItemTokens.animationTokens.animationDuration,
transitionTimingFunction: navItemTokens.animationTokens.animationTimingFunction,
transitionProperty: 'background',

':hover .fui-NavItem': {
':hover': {
backgroundColor: navItemTokens.backgroundColorHover,
transitionDuration: navItemTokens.animationTokens.animationDuration,
transitionTimingFunction: navItemTokens.animationTokens.animationTimingFunction,
transitionProperty: 'background',
},

':active .fui-NavItem': {
':active': {
backgroundColor: navItemTokens.backgroundColorPressed,
transitionDuration: navItemTokens.animationTokens.animationDuration,
transitionTimingFunction: navItemTokens.animationTokens.animationTimingFunction,
transitionProperty: 'background',
},
},
basenavItem: {
baseNavItem: {
// styles that we want to disagree with the default on
display: 'flex',
textTransform: 'none',
alignSelf: 'stretch',
textAlign: 'left',
position: 'relative',
justifyContent: 'start',
gap: tokens.spacingVerticalL,
backgroundColor: 'transparent',
},
baseSecondary: {
maxWidth: '24px',
minWidth: '24px',
paddingInline: '4px',
marginBlockStart: '4px',

transitionDuration: navItemTokens.animationTokens.animationDuration,
transitionTimingFunction: navItemTokens.animationTokens.animationTimingFunction,
transitionProperty: 'background',

':hover': {
backgroundColor: navItemTokens.backgroundColorHover,
},
':active': {
backgroundColor: navItemTokens.backgroundColorPressed,
},
minWidth: '28px',
paddingInlineEnd: '12px',
paddingInlineStart: '5px',
mltejera marked this conversation as resolved.
Show resolved Hide resolved
paddingBlockStart: '5px',
alignItems: 'start',
},
baseMedium: {
paddingBlockStart: '6px',
paddingBlockStart: '9px',
},
});

Expand All @@ -94,7 +83,7 @@ export const useSplitNavItemStyles_unstable = (state: SplitNavItemState): SplitN
if (state.navItem) {
state.navItem.className = mergeClasses(
splitNavItemClassNames.navItem,
splitNavItemStyles.basenavItem,
splitNavItemStyles.baseNavItem,
state.navItem.className,
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ export const navItemTokens = {
animationFillMode: 'both',
animationTimingFunction: tokens.curveAccelerateMid,
},
transitionTokens: {
transitionDuration: tokens.durationFast,
transitionTimingFunction: tokens.curveAccelerateMid,
transitionProperty: 'background',
},
};

/**
Expand Down
Loading
Loading