diff --git a/.changeset/navlist-linked-subnav.md b/.changeset/navlist-linked-subnav.md new file mode 100644 index 00000000000..c2ae5e0c8bc --- /dev/null +++ b/.changeset/navlist-linked-subnav.md @@ -0,0 +1,5 @@ +--- +'@primer/react': minor +--- + +NavList: Support linked sub-nav parent items with a separate toggle diff --git a/packages/react/src/ActionList/ActionList.module.css b/packages/react/src/ActionList/ActionList.module.css index aa7d807f673..b3351b6972b 100644 --- a/packages/react/src/ActionList/ActionList.module.css +++ b/packages/react/src/ActionList/ActionList.module.css @@ -115,7 +115,7 @@ border-radius: var(--borderRadius-medium); /* apply flex if trailing action exists as an immediate child */ - &[data-has-trailing-action] { + &[data-has-trailing-action]:not([data-has-subitem='true']) { display: flex; flex-wrap: nowrap; } @@ -497,6 +497,24 @@ /* button or a tag */ +.ActionListItemRow { + display: flex; + border-radius: var(--borderRadius-medium); + + @media (hover: hover) { + &:hover { + background-color: var(--control-transparent-bgColor-hover); + outline: solid var(--borderWidth-thin) transparent; + outline-offset: calc(-1 * var(--borderWidth-thin)); + box-shadow: var(--boxShadow-thin) var(--control-transparent-borderColor-active); + } + } + + &:active { + background-color: var(--control-transparent-bgColor-active); + } +} + /* [ [spacer] [leadingAction] [leadingVisual] [content] ] */ .ActionListContent { --subitem-depth: 0px; diff --git a/packages/react/src/ActionList/Item.tsx b/packages/react/src/ActionList/Item.tsx index 1606952e3e1..2957b3ff6f1 100644 --- a/packages/react/src/ActionList/Item.tsx +++ b/packages/react/src/ActionList/Item.tsx @@ -334,67 +334,69 @@ const UnwrappedItem = ( data-trailing-action-loading={trailingActionRendered && slots.trailingAction?.props.loading ? true : undefined} className={clsx(classes.ActionListItem, className)} > - - - {/* Reset TooltipContext so that child components don't detect - the ConditionalTooltip and suppress their own internal tooltips. */} - - - - - {slots.leadingVisual} - - {/* TODO: next-major: change to data-component="ActionList.Item.DividerContainer" next major version */} - - - - {childrenWithoutSlots} - {/* Loading message needs to be in here so it is read with the label */} - {/* If the item is inactive, we do not simultaneously announce that it is loading */} - {loading === true && !inactive && Loading} - - {slots.description} - + + + + {/* Reset TooltipContext so that child components don't detect + the ConditionalTooltip and suppress their own internal tooltips. */} + + + - {trailingVisual} + {slots.leadingVisual} - - { - // If the item is inactive, but it's not in an overlay (e.g. ActionMenu, SelectPanel), - // render the inactive warning message directly in the item. - !showInactiveIndicator && inactiveText ? ( - - {inactiveText} + {/* TODO: next-major: change to data-component="ActionList.Item.DividerContainer" next major version */} + + + + {childrenWithoutSlots} + {/* Loading message needs to be in here so it is read with the label */} + {/* If the item is inactive, we do not simultaneously announce that it is loading */} + {loading === true && !inactive && Loading} - ) : null - } - - - - - {!inactive && !loading && !menuContext && Boolean(slots.trailingAction) && slots.trailingAction} + {slots.description} + + + {trailingVisual} + + + { + // If the item is inactive, but it's not in an overlay (e.g. ActionMenu, SelectPanel), + // render the inactive warning message directly in the item. + !showInactiveIndicator && inactiveText ? ( + + {inactiveText} + + ) : null + } + + + + + {!inactive && !loading && !menuContext && Boolean(slots.trailingAction) && slots.trailingAction} + {slots.subItem} diff --git a/packages/react/src/NavList/NavList.docs.json b/packages/react/src/NavList/NavList.docs.json index 72258bed5f1..3376dd09627 100644 --- a/packages/react/src/NavList/NavList.docs.json +++ b/packages/react/src/NavList/NavList.docs.json @@ -15,6 +15,7 @@ {"id": "components-navlist-features--with-group-expand"}, {"id": "components-navlist-features--with-group-heading-links"}, {"id": "components-navlist-features--with-inactive-items"}, + {"id": "components-navlist-features--with-linked-sub-nav-parent"}, {"id": "components-navlist-features--with-nested-sub-items"}, {"id": "components-navlist-features--with-next-js-link"}, {"id": "components-navlist-features--with-react-router-link"}, @@ -95,7 +96,7 @@ "name": "href", "type": "string", "defaultValue": "", - "description": "The URL that the item navigates to. `href` is passed to the underlying `` element. If `as` is specified, the component may need different props. If the item contains a sub-nav, the item is rendered as a `