@moneyforward/mfui-components 3.3.0 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,4 +12,4 @@ import { type DropdownMenuItemProps } from './DropdownMenuItem.types';
12
12
  *
13
13
  * Otherwise, it will be rendered as a div element.
14
14
  */
15
- export declare function DropdownMenuItem({ children, className, href, target, customLinkComponent, onClick, 'aria-labelledby': ariaLabelledby, ...rest }: DropdownMenuItemProps): import("react/jsx-runtime").JSX.Element;
15
+ export declare function DropdownMenuItem({ children, className, href, target, customLinkComponent, onClick, disabled, 'aria-labelledby': ariaLabelledby, ...rest }: DropdownMenuItemProps): import("react/jsx-runtime").JSX.Element;
@@ -20,7 +20,7 @@ import { useDropdownMenuContext } from '../DropdownMenuContext';
20
20
  *
21
21
  * Otherwise, it will be rendered as a div element.
22
22
  */
23
- export function DropdownMenuItem({ children, className, href, target, customLinkComponent, onClick, 'aria-labelledby': ariaLabelledby, ...rest }) {
23
+ export function DropdownMenuItem({ children, className, href, target, customLinkComponent, onClick, disabled, 'aria-labelledby': ariaLabelledby, ...rest }) {
24
24
  const classes = dropdownMenuItemSlotRecipe();
25
25
  const { closeMenuPopover } = useDropdownMenuContext();
26
26
  const id = useId();
@@ -48,11 +48,13 @@ export function DropdownMenuItem({ children, className, href, target, customLink
48
48
  }
49
49
  }, []);
50
50
  const handleClick = useCallback((event) => {
51
+ if (disabled)
52
+ return;
51
53
  if (onClick) {
52
54
  onClick(event);
53
55
  closeMenuPopover?.();
54
56
  }
55
- }, [onClick, closeMenuPopover]);
57
+ }, [disabled, onClick, closeMenuPopover]);
56
58
  const isButton = useMemo(() => onClick && !href, [onClick, href]);
57
59
  const Tag = useMemo(() => {
58
60
  if (href) {
@@ -66,6 +68,16 @@ export function DropdownMenuItem({ children, className, href, target, customLink
66
68
  // If the href is provided, it should be an anchor element and focusable.
67
69
  // If the href is undefined and onClick is provided, it should be a button element and focusable.
68
70
  // If both are undefined, it should be a div element and not focusable.
69
- const isFocusable = !!href || !!onClick;
70
- return (_jsx(FocusIndicator, { position: "inside", children: _jsx(Tag, { ...rest, ref: itemRef, ...(ariaLabelledby && { id }), "data-mfui-menu-item": true, role: "menuitem", className: cx(classes.root, 'mfui-DropdownMenuItem__root', className), tabIndex: -1, href: href, target: target, "data-mfui-focusable": isFocusable, type: onClick ? 'button' : undefined, "aria-labelledby": ariaLabelledby ? `${ariaLabelledby} ${id}` : undefined, onKeyDown: handleKeyDown, onClick: isButton ? handleClick : undefined, children: typeof children === 'string' ? _jsx(Typography, { variant: "body", children: children }) : children }) }));
71
+ // If disabled is true, the menu item is not focusable.
72
+ const isFocusable = (!!href || !!onClick) && !disabled;
73
+ // Anchor navigation is suppressed when disabled to prevent unintended navigation.
74
+ const resolvedHref = isButton || disabled ? undefined : href;
75
+ // For button elements, use the native disabled attribute for full browser semantics.
76
+ // For anchor and div elements, use aria-disabled and data-disabled since they have no native disabled support.
77
+ const disabledProps = isButton
78
+ ? { disabled }
79
+ : disabled
80
+ ? { 'aria-disabled': true, 'data-disabled': '' }
81
+ : {};
82
+ return (_jsx(FocusIndicator, { position: "inside", children: _jsx(Tag, { ...rest, ref: itemRef, ...(ariaLabelledby && { id }), "data-mfui-menu-item": true, role: "menuitem", className: cx(classes.root, 'mfui-DropdownMenuItem__root', className), tabIndex: -1, href: resolvedHref, target: target, "data-mfui-focusable": isFocusable, type: onClick ? 'button' : undefined, "aria-labelledby": ariaLabelledby ? `${ariaLabelledby} ${id}` : undefined, ...disabledProps, onKeyDown: handleKeyDown, onClick: isButton ? handleClick : undefined, children: typeof children === 'string' ? _jsx(Typography, { variant: "body", children: children }) : children }) }));
71
83
  }
@@ -16,6 +16,10 @@ type AnchorProps = {
16
16
  * This property is ignored if the href property is provided.
17
17
  */
18
18
  onClick?: undefined;
19
+ /**
20
+ * When true, the menu item is disabled and not interactive.
21
+ */
22
+ disabled?: boolean;
19
23
  };
20
24
  type DivProps = {
21
25
  /**
@@ -34,6 +38,10 @@ type DivProps = {
34
38
  * If not provided and the href prop is not provided, the menu item will be rendered as a div element.
35
39
  */
36
40
  onClick?: undefined;
41
+ /**
42
+ * When true, the menu item is disabled and not interactive.
43
+ */
44
+ disabled?: boolean;
37
45
  };
38
46
  type ButtonProps = {
39
47
  /**
@@ -52,6 +60,10 @@ type ButtonProps = {
52
60
  * The handler to call when the menu item is clicked or the Enter key is pressed.
53
61
  */
54
62
  onClick?: ComponentPropsWithoutRef<'button'>['onClick'];
63
+ /**
64
+ * When true, the menu item is disabled and not interactive.
65
+ */
66
+ disabled?: boolean;
55
67
  };
56
68
  /**
57
69
  * The props for the MenuItem component.
@@ -37,7 +37,7 @@ export function BaseMainNavigation({ className, featureShortcut, navigationItems
37
37
  else {
38
38
  setOpenPopoverIndex(null);
39
39
  }
40
- } })) : (_jsxs("details", { open: hasCurrentNavigationInChildren(navigation.children), className: cx(classes.parentDetails, 'mfui-BaseMainNavigation__parentDetails'), children: [_jsx(FocusIndicator, { position: "inside", children: _jsxs("summary", { className: cx(classes.parentSummary, 'mfui-BaseMainNavigation__parentSummary'), children: [_jsx("div", { className: cx(classes.parentSummaryIcon, 'mfui-BaseMainNavigation__parentSummaryIcon'), children: navigation.icon }), _jsx(Typography, { variant: "controlLabel", children: navigation.label }), _jsx(DisclosureBasicCollapsed, { className: "mfui-BaseMainNavigation__icon_collapsed", "aria-hidden": "true", "data-mfui-content": "main-navigation-icon-collapsed" }), _jsx(DisclosureBasicExpanded, { className: "mfui-BaseMainNavigation__icon_expanded", "aria-hidden": "true", "data-mfui-content": "main-navigation-icon-expanded" })] }) }), _jsx("ul", { className: cx(classes.childrenList, 'mfui-BaseMainNavigation__childrenList'), children: navigation.children.map((child, childIndex) => (_jsx("li", { className: cx(classes.childrenListItem, 'mfui-BaseMainNavigation__childrenListItem'), children: _jsx(FocusIndicator, { position: "inside", children: _jsx(NavigationLink, { tag: InternalLinkTag, isExternal: child.isExternal, href: child.href, className: cx(classes.childrenListItemAnchor, 'mfui-BaseMainNavigation__childrenListItemAnchor'), "aria-current": child.isCurrent ? 'page' : undefined, children: _jsx(Typography, { variant: "controlLabel", children: child.label }) }) }) }, childIndex))) })] }))) : (_jsx(Tooltip, { className: cx(classes.listItemTooltip, 'mfui-BaseMainNavigation__listItemTooltip'), content: navigation.label, disabled: !isCollapsed, placement: "right", children: _jsx(FocusIndicator, { position: "inside", children: _jsx(NavigationLink, { tag: InternalLinkTag, isExternal: navigation.isExternal, href: navigation.href, className: cx(classes.listItemAnchor, 'mfui-BaseMainNavigation__listItemAnchor'), "aria-label": isCollapsed ? navigation.label : undefined, "aria-current": navigation.isCurrent ? 'page' : undefined, children: _jsxs("div", { className: cx(classes.labelGroup, 'mfui-BaseMainNavigation__labelGroup'), children: [_jsxs("div", { className: cx(classes.iconAndLabel, 'mfui-BaseMainNavigation__iconAndLabel'), children: [_jsx("div", { className: cx(classes.listItemAnchorIcon, 'mfui-BaseMainNavigation__listItemAnchorIcon'), children: navigation.icon }), isCollapsed ? null : _jsx(Typography, { variant: "controlLabel", children: navigation.label })] }), navigation.locked ? (_jsx(Lock, { className: cx(classes.lockIcon, 'mfui-BaseMainNavigation__lockIcon'), "aria-label": navigation.lockIconProps?.['aria-label'] ?? 'ロックされています' })) : null, !isCollapsed && navigation.statusSlot && navigation.locked !== true
40
+ } })) : (_jsxs("details", { open: navigation.isOpenByDefault || hasCurrentNavigationInChildren(navigation.children), className: cx(classes.parentDetails, 'mfui-BaseMainNavigation__parentDetails'), children: [_jsx(FocusIndicator, { position: "inside", children: _jsxs("summary", { className: cx(classes.parentSummary, 'mfui-BaseMainNavigation__parentSummary'), children: [_jsx("div", { className: cx(classes.parentSummaryIcon, 'mfui-BaseMainNavigation__parentSummaryIcon'), children: navigation.icon }), _jsx(Typography, { variant: "controlLabel", children: navigation.label }), _jsx(DisclosureBasicCollapsed, { className: "mfui-BaseMainNavigation__icon_collapsed", "aria-hidden": "true", "data-mfui-content": "main-navigation-icon-collapsed" }), _jsx(DisclosureBasicExpanded, { className: "mfui-BaseMainNavigation__icon_expanded", "aria-hidden": "true", "data-mfui-content": "main-navigation-icon-expanded" })] }) }), _jsx("ul", { className: cx(classes.childrenList, 'mfui-BaseMainNavigation__childrenList'), children: navigation.children.map((child, childIndex) => (_jsx("li", { className: cx(classes.childrenListItem, 'mfui-BaseMainNavigation__childrenListItem'), children: _jsx(FocusIndicator, { position: "inside", children: _jsx(NavigationLink, { tag: InternalLinkTag, isExternal: child.isExternal, href: child.href, className: cx(classes.childrenListItemAnchor, 'mfui-BaseMainNavigation__childrenListItemAnchor'), "aria-current": child.isCurrent ? 'page' : undefined, children: _jsx(Typography, { variant: "controlLabel", children: child.label }) }) }) }, childIndex))) })] }))) : (_jsx(Tooltip, { className: cx(classes.listItemTooltip, 'mfui-BaseMainNavigation__listItemTooltip'), content: navigation.label, disabled: !isCollapsed, placement: "right", children: _jsx(FocusIndicator, { position: "inside", children: _jsx(NavigationLink, { tag: InternalLinkTag, isExternal: navigation.isExternal, href: navigation.href, className: cx(classes.listItemAnchor, 'mfui-BaseMainNavigation__listItemAnchor'), "aria-label": isCollapsed ? navigation.label : undefined, "aria-current": navigation.isCurrent ? 'page' : undefined, children: _jsxs("div", { className: cx(classes.labelGroup, 'mfui-BaseMainNavigation__labelGroup'), children: [_jsxs("div", { className: cx(classes.iconAndLabel, 'mfui-BaseMainNavigation__iconAndLabel'), children: [_jsx("div", { className: cx(classes.listItemAnchorIcon, 'mfui-BaseMainNavigation__listItemAnchorIcon'), children: navigation.icon }), isCollapsed ? null : _jsx(Typography, { variant: "controlLabel", children: navigation.label })] }), navigation.locked ? (_jsx(Lock, { className: cx(classes.lockIcon, 'mfui-BaseMainNavigation__lockIcon'), "aria-label": navigation.lockIconProps?.['aria-label'] ?? 'ロックされています' })) : null, !isCollapsed && navigation.statusSlot && navigation.locked !== true
41
41
  ? navigation.statusSlot
42
42
  : null] }) }) }) })) }, index))) }) }), enableCollapsible ? (_jsx("div", { className: cx(classes.footer, 'mfui-BaseMainNavigation__footer'), children: _jsx(Tooltip, { content: toggleButtonLabel, placement: "right", children: _jsx(ToggleButton, { className: cx(classes.toggleButton, 'mfui-BaseMainNavigation__toggleButton'), iconClassName: cx(classes.toggleButtonIcon, 'mfui-BaseMainNavigation__toggleButtonIcon'), isCollapsed: isCollapsed, "aria-label": toggleButtonLabel, targetId: navId, handleClickToggleButton: handleClickToggleButton }) }) })) : null] }));
43
43
  }
@@ -81,6 +81,14 @@ type ParentNavigationItem = {
81
81
  * This property is not allowed for the parent navigation items.
82
82
  */
83
83
  isCurrent?: undefined;
84
+ /**
85
+ * Whether the nested navigation is open by default.
86
+ * When set to true, the parent navigation item is expanded on initial render,
87
+ * regardless of whether any child has `isCurrent: true`.
88
+ *
89
+ * @default false
90
+ */
91
+ isOpenByDefault?: boolean;
84
92
  /**
85
93
  * Nested navigation items.
86
94
  *
@@ -47,5 +47,5 @@ export const NarrowViewportMainNavigation = forwardRef(({ className, featureShor
47
47
  }
48
48
  return (_jsx(Portal, { children: _jsxs("div", { ref: dialogRef, role: "dialog", className: cx(classes.root, 'mfui-NarrowViewportMainNavigation__root', className), tabIndex: -1, onKeyDown: handleOnKeyDown, children: [_jsx("div", { "data-mfui-content": "backdrop", className: cx(classes.backdrop, 'mfui-NarrowViewportMainNavigation__backdrop'), onClick: handleCloseMainNavigation }), _jsxs("div", { "data-mfui-content": "inside", className: cx(classes.container, 'mfui-NarrowViewportMainNavigation__container'), onClick: (event) => {
49
49
  event.stopPropagation();
50
- }, children: [featureShortcut ? (_jsx("div", { className: cx(classes.featureShortcut, 'mfui-NarrowViewportMainNavigation__featureShortcut'), children: _jsx(FocusIndicator, { children: _jsx(NavigationLink, { tag: InternalLinkTag, isExternal: featureShortcut.isExternal, href: featureShortcut.href, className: cx(classes.featureShortcutAnchor, 'mfui-NarrowViewportMainNavigation__featureShortcutAnchor'), onClick: handleCloseMainNavigation, children: _jsx(Typography, { variant: "controlLabel", children: featureShortcut.label }) }) }) })) : null, _jsx("nav", { className: cx(classes.nav, 'mfui-NarrowViewportMainNavigation__nav'), children: _jsx("ul", { className: cx(classes.list, 'mfui-NarrowViewportMainNavigation__list'), children: navigationItems.map((navigation, index) => (_jsx("li", { className: cx(classes.listItem, 'mfui-NarrowViewportMainNavigation__listItem'), children: navigation.children ? (_jsxs("details", { open: hasCurrentNavigationInChildren(navigation.children), className: cx(classes.parentDetails, 'mfui-NarrowViewportMainNavigation__parentDetails'), children: [_jsx(FocusIndicator, { position: "inside", children: _jsxs("summary", { className: cx(classes.parentSummary, 'mfui-NarrowViewportMainNavigation__parentSummary'), children: [_jsx("div", { className: cx(classes.parentSummaryIcon, 'mfui-NarrowViewportMainNavigation__parentSummaryIcon'), children: navigation.icon }), _jsx(Typography, { variant: "controlLabel", children: navigation.label }), _jsx(DisclosureBasicCollapsed, { className: "mfui-NarrowViewportMainNavigation__icon_collapsed", "aria-hidden": "true", "data-mfui-content": "main-navigation-icon-collapsed" }), _jsx(DisclosureBasicExpanded, { className: "mfui-NarrowViewportMainNavigation__icon_expanded", "aria-hidden": "true", "data-mfui-content": "main-navigation-icon-expanded" })] }) }), _jsx("ul", { className: cx(classes.childrenList, 'mfui-NarrowViewportMainNavigation__childrenList'), children: navigation.children.map((child, childIndex) => (_jsx("li", { className: cx(classes.childrenListItem, 'mfui-NarrowViewportMainNavigation__childrenListItem'), children: _jsx(FocusIndicator, { position: "inside", children: _jsx(NavigationLink, { tag: InternalLinkTag, isExternal: child.isExternal, href: child.href, className: cx(classes.childrenListItemAnchor, 'mfui-NarrowViewportMainNavigation__childrenListItemAnchor'), "aria-current": child.isCurrent ? 'page' : undefined, onClick: handleCloseMainNavigation, children: _jsx(Typography, { variant: "controlLabel", children: child.label }) }) }) }, childIndex))) })] })) : (_jsx(FocusIndicator, { position: "inside", children: _jsx(NavigationLink, { tag: InternalLinkTag, isExternal: navigation.isExternal, href: navigation.href, className: cx(classes.listItemAnchor, 'mfui-NarrowViewportMainNavigation__listItemAnchor'), "aria-current": navigation.isCurrent ? 'page' : undefined, children: _jsxs("div", { className: cx(classes.labelGroup, 'mfui-NarrowViewportMainNavigation__labelGroup'), children: [_jsxs("div", { className: cx(classes.iconAndLabel, 'mfui-NarrowViewportMainNavigation__iconAndLabel'), children: [_jsx("div", { className: cx(classes.listItemAnchorIcon, 'mfui-NarrowViewportMainNavigation__listItemAnchorIcon'), children: navigation.icon }), _jsx(Typography, { variant: "controlLabel", children: navigation.label })] }), navigation.locked ? (_jsx(Lock, { className: cx(classes.lockIcon, 'mfui-NarrowViewportMainNavigation__lockIcon'), "aria-label": navigation.lockIconProps?.['aria-label'] ?? 'ロックされています' })) : null] }) }) })) }, index))) }) })] })] }) }));
50
+ }, children: [featureShortcut ? (_jsx("div", { className: cx(classes.featureShortcut, 'mfui-NarrowViewportMainNavigation__featureShortcut'), children: _jsx(FocusIndicator, { children: _jsx(NavigationLink, { tag: InternalLinkTag, isExternal: featureShortcut.isExternal, href: featureShortcut.href, className: cx(classes.featureShortcutAnchor, 'mfui-NarrowViewportMainNavigation__featureShortcutAnchor'), onClick: handleCloseMainNavigation, children: _jsx(Typography, { variant: "controlLabel", children: featureShortcut.label }) }) }) })) : null, _jsx("nav", { className: cx(classes.nav, 'mfui-NarrowViewportMainNavigation__nav'), children: _jsx("ul", { className: cx(classes.list, 'mfui-NarrowViewportMainNavigation__list'), children: navigationItems.map((navigation, index) => (_jsx("li", { className: cx(classes.listItem, 'mfui-NarrowViewportMainNavigation__listItem'), children: navigation.children ? (_jsxs("details", { open: navigation.isOpenByDefault || hasCurrentNavigationInChildren(navigation.children), className: cx(classes.parentDetails, 'mfui-NarrowViewportMainNavigation__parentDetails'), children: [_jsx(FocusIndicator, { position: "inside", children: _jsxs("summary", { className: cx(classes.parentSummary, 'mfui-NarrowViewportMainNavigation__parentSummary'), children: [_jsx("div", { className: cx(classes.parentSummaryIcon, 'mfui-NarrowViewportMainNavigation__parentSummaryIcon'), children: navigation.icon }), _jsx(Typography, { variant: "controlLabel", children: navigation.label }), _jsx(DisclosureBasicCollapsed, { className: "mfui-NarrowViewportMainNavigation__icon_collapsed", "aria-hidden": "true", "data-mfui-content": "main-navigation-icon-collapsed" }), _jsx(DisclosureBasicExpanded, { className: "mfui-NarrowViewportMainNavigation__icon_expanded", "aria-hidden": "true", "data-mfui-content": "main-navigation-icon-expanded" })] }) }), _jsx("ul", { className: cx(classes.childrenList, 'mfui-NarrowViewportMainNavigation__childrenList'), children: navigation.children.map((child, childIndex) => (_jsx("li", { className: cx(classes.childrenListItem, 'mfui-NarrowViewportMainNavigation__childrenListItem'), children: _jsx(FocusIndicator, { position: "inside", children: _jsx(NavigationLink, { tag: InternalLinkTag, isExternal: child.isExternal, href: child.href, className: cx(classes.childrenListItemAnchor, 'mfui-NarrowViewportMainNavigation__childrenListItemAnchor'), "aria-current": child.isCurrent ? 'page' : undefined, onClick: handleCloseMainNavigation, children: _jsx(Typography, { variant: "controlLabel", children: child.label }) }) }) }, childIndex))) })] })) : (_jsx(FocusIndicator, { position: "inside", children: _jsx(NavigationLink, { tag: InternalLinkTag, isExternal: navigation.isExternal, href: navigation.href, className: cx(classes.listItemAnchor, 'mfui-NarrowViewportMainNavigation__listItemAnchor'), "aria-current": navigation.isCurrent ? 'page' : undefined, children: _jsxs("div", { className: cx(classes.labelGroup, 'mfui-NarrowViewportMainNavigation__labelGroup'), children: [_jsxs("div", { className: cx(classes.iconAndLabel, 'mfui-NarrowViewportMainNavigation__iconAndLabel'), children: [_jsx("div", { className: cx(classes.listItemAnchorIcon, 'mfui-NarrowViewportMainNavigation__listItemAnchorIcon'), children: navigation.icon }), _jsx(Typography, { variant: "controlLabel", children: navigation.label })] }), navigation.locked ? (_jsx(Lock, { className: cx(classes.lockIcon, 'mfui-NarrowViewportMainNavigation__lockIcon'), "aria-label": navigation.lockIconProps?.['aria-label'] ?? 'ロックされています' })) : null] }) }) })) }, index))) }) })] })] }) }));
51
51
  });
package/dist/styles.css CHANGED
@@ -720,17 +720,17 @@
720
720
  min-height: var(--mfui-sizes-mfui\.size\.dimension\.control-component\.height\.comfort);
721
721
  }
722
722
 
723
+ .mfui-DYOKU:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) {
724
+ color: var(--mfui-colors-mfui\.color\.disabled\.content);
725
+ background-color: var(--mfui-colors-mfui\.color\.base\.background\.none);
726
+ }
727
+
723
728
  .mfui-DYOKU[data-mfui-focusable=true]:is(:focus-visible, [data-focus-visible]) {
724
729
  color: var(--mfui-colors-mfui\.color\.base\.content\.hovered);
725
730
  background-color: var(--mfui-colors-mfui\.color\.base\.background\.hovered);
726
731
  z-index: 1;
727
732
  }
728
733
 
729
- .mfui-DYOKU[data-mfui-focusable=true]:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) {
730
- color: var(--mfui-colors-mfui\.color\.disabled\.content);
731
- background-color: var(--mfui-colors-mfui\.color\.base\.background\.pressed);
732
- }
733
-
734
734
  .mfui-DYOKU[data-mfui-focusable=true]:is(:hover, [data-hover]):not(:disabled, [disabled], [data-disabled]) {
735
735
  color: var(--mfui-colors-mfui\.color\.base\.content\.hovered);
736
736
  background-color: var(--mfui-colors-mfui\.color\.base\.background\.hovered);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moneyforward/mfui-components",
3
- "version": "3.3.0",
3
+ "version": "3.4.0",
4
4
  "description": "React UI Component Library for all Money Forward products",
5
5
  "repository": {
6
6
  "type": "git",