diff --git a/src/components/collapsible_nav_beta/collapsible_nav_beta.stories.tsx b/src/components/collapsible_nav_beta/collapsible_nav_beta.stories.tsx
index b7cc203b663..ad68078dad6 100644
--- a/src/components/collapsible_nav_beta/collapsible_nav_beta.stories.tsx
+++ b/src/components/collapsible_nav_beta/collapsible_nav_beta.stories.tsx
@@ -13,6 +13,7 @@ import { EuiHeader, EuiHeaderSection, EuiHeaderSectionItem } from '../header';
import { EuiPageTemplate } from '../page_template';
import { EuiFlyout, EuiFlyoutBody, EuiFlyoutFooter } from '../flyout';
import { EuiButton } from '../button';
+import { EuiTitle } from '../title';
import { EuiCollapsibleNavItem } from './collapsible_nav_item';
import {
@@ -58,6 +59,22 @@ const OpenCollapsibleNav: FunctionComponent<
);
};
+const KibanaNavTitle: FunctionComponent<{
+ title: string;
+}> = ({ title }) => (
+ ({
+ marginTop: euiTheme.size.base,
+ paddingBlock: euiTheme.size.xs,
+ paddingInline: euiTheme.size.s,
+ })}
+ >
+ {title}
+
+);
+
export const KibanaExample: Story = {
render: ({ ...args }) => (
@@ -78,15 +95,15 @@ export const KibanaExample: Story = {
href="#"
items={[
{ title: 'Get started', href: '#' },
- { title: 'Explore', isGroupTitle: true },
+ { renderItem: () => },
{ title: 'Discover', href: '#' },
{ title: 'Dashboards', href: '#' },
{ title: 'Visualize library', href: '#' },
- { title: 'Content', isGroupTitle: true },
+ { renderItem: () => },
{ title: 'Indices', href: '#' },
{ title: 'Transforms', href: '#' },
{ title: 'Indexing API', href: '#' },
- { title: 'Security', isGroupTitle: true },
+ { renderItem: () => },
{ title: 'API keys', href: '#' },
]}
/>
@@ -115,7 +132,7 @@ export const KibanaExample: Story = {
{ title: 'Alerts', href: '#' },
{ title: 'Cases', href: '#' },
{ title: 'SLOs', href: '#' },
- { title: 'Signals', isGroupTitle: true },
+ { renderItem: () => },
{ title: 'Logs', href: '#' },
{
title: 'Tracing',
@@ -126,7 +143,7 @@ export const KibanaExample: Story = {
{ title: 'Dependencies', href: '#' },
],
},
- { title: 'Toolbox', isGroupTitle: true },
+ { renderItem: () => },
{ title: 'Visualize library', href: '#' },
{ title: 'Dashboards', href: '#' },
{
@@ -217,18 +234,20 @@ export const KibanaExample: Story = {
{ title: 'Overview', href: '#' },
{ title: 'Notifications', href: '#' },
{ title: 'Memory usage', href: '#' },
- { title: 'Anomaly detection', isGroupTitle: true },
+ { renderItem: () => },
{ title: 'Jobs', href: '#' },
{ title: 'Anomaly explorer', href: '#' },
{ title: 'Single metric viewer', href: '#' },
{ title: 'Settings', href: '#' },
- { title: 'Data frame analytics', isGroupTitle: true },
+ {
+ renderItem: () => ,
+ },
{ title: 'Jobs', href: '#' },
{ title: 'Results explorer', href: '#' },
{ title: 'Analytics map', href: '#' },
- { title: 'Model management', isGroupTitle: true },
+ { renderItem: () => },
{ title: 'Trained models', href: '#' },
- { title: 'Data visualizer', isGroupTitle: true },
+ { renderItem: () => },
{ title: 'File', href: '#' },
{ title: 'Data view', href: '#' },
]}
diff --git a/src/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_accordion.tsx b/src/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_accordion.tsx
index 7bc84a55bc1..dc98ffbe649 100644
--- a/src/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_accordion.tsx
+++ b/src/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_accordion.tsx
@@ -20,9 +20,9 @@ import { EuiAccordion } from '../../accordion';
import {
EuiCollapsibleNavSubItem,
+ EuiCollapsibleNavSubItemProps,
_SharedEuiCollapsibleNavItemProps,
_EuiCollapsibleNavItemDisplayProps,
- EuiCollapsibleNavItemProps,
} from './collapsible_nav_item';
import { EuiCollapsibleNavLink } from './collapsible_nav_link';
import { euiCollapsibleNavAccordionStyles } from './collapsible_nav_accordion.styles';
@@ -33,10 +33,7 @@ type EuiCollapsibleNavAccordionProps = Omit<
> &
_EuiCollapsibleNavItemDisplayProps & {
buttonContent: ReactNode;
- // On the main `EuiCollapsibleNavItem` component, this uses `EuiCollapsibleNavSubItemProps`
- // to allow for section headings, but by the time `items` reaches this component, we
- // know for sure it's an actual accordion item and not a section heading
- items: EuiCollapsibleNavItemProps[];
+ items: EuiCollapsibleNavSubItemProps[];
};
/**
@@ -91,13 +88,10 @@ export const EuiCollapsibleNavAccordion: FunctionComponent<
/**
* Child items
*/
- // If any of the sub items have an icon, default to an
- // icon of `empty` so that all text lines up vertically
const itemsHaveIcons = useMemo(
() => items.some((item) => !!item.icon),
[items]
);
- const icon = itemsHaveIcons ? 'empty' : undefined;
const childrenCssStyles = [
styles.children.euiCollapsibleNavAccordion__children,
@@ -109,12 +103,19 @@ export const EuiCollapsibleNavAccordion: FunctionComponent<
css={childrenCssStyles}
className="euiCollapsibleNavAccordion__children"
>
- {items.map((item, index) => (
- // This is an intentional circular dependency between the accordion & parent item display.
- // EuiSideNavItem is purposely recursive to support any amount of nested sub items,
- // and split up into separate files/components for better dev readability
-
- ))}
+ {items.map((item, index) => {
+ // If any of the sub items have an icon, default to an
+ // icon of `empty` so that all text lines up vertically
+ if (!item.renderItem && itemsHaveIcons && !item.icon) {
+ item.icon = 'empty';
+ }
+ return (
+ // This is an intentional circular dependency between the accordion & parent item display.
+ // EuiSideNavItem is purposely recursive to support any amount of nested sub items,
+ // and split up into separate files/components for better dev readability
+
+ );
+ })}
);
diff --git a/src/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_item.stories.tsx b/src/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_item.stories.tsx
index 5a5de350df3..aefb238c58d 100644
--- a/src/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_item.stories.tsx
+++ b/src/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_item.stories.tsx
@@ -9,6 +9,7 @@
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
+import { EuiSpacer } from '../../spacer';
import { EuiCollapsibleNavBeta } from '../collapsible_nav_beta';
import {
@@ -100,10 +101,7 @@ export const EdgeCaseTesting: Story = {
{ ...args, title: 'Link', href: '#', isSelected: true },
{ ...args, title: 'Button', onClick: () => {} },
{ ...args, title: 'Span', href: '#' },
- {
- title: 'Section 2',
- isGroupTitle: true,
- },
+ { renderItem: () => },
{
...args,
title: 'Test 2',
@@ -125,11 +123,7 @@ export const EdgeCaseTesting: Story = {
{ title: 'grandchild 2', href: '#' },
],
},
- {
- title: 'Section 3',
- titleElement: 'h3',
- isGroupTitle: true,
- },
+ { renderItem: () => },
{
...args,
title: 'Nested accordion with grandchildren',
diff --git a/src/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_item.styles.ts b/src/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_item.styles.ts
index 1250997a4f4..bef726168fc 100644
--- a/src/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_item.styles.ts
+++ b/src/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_item.styles.ts
@@ -9,11 +9,7 @@
import { css } from '@emotion/react';
import { UseEuiTheme } from '../../../services';
-import {
- logicalCSS,
- logicalShorthandCSS,
- euiFontSize,
-} from '../../../global_styling';
+import { euiFontSize } from '../../../global_styling';
import { euiButtonColor } from '../../../themes/amsterdam/global_styling/mixins/button';
/**
@@ -47,17 +43,3 @@ export const euiCollapsibleNavItemTitleStyles = {
flex-grow: 1;
`,
};
-
-export const euiCollapsibleNavSubItemGroupTitleStyles = ({
- euiTheme,
-}: UseEuiTheme) => {
- return {
- euiCollapsibleNavItem__groupTitle: css`
- ${logicalCSS('margin-top', euiTheme.size.base)}
- ${logicalShorthandCSS(
- 'padding',
- `${euiTheme.size.xs} ${euiTheme.size.s}`
- )}
- `,
- };
-};
diff --git a/src/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_item.test.tsx b/src/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_item.test.tsx
index 708f301ee5c..5727b739f27 100644
--- a/src/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_item.test.tsx
+++ b/src/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_item.test.tsx
@@ -145,51 +145,18 @@ describe('EuiCollapsibleNavItem', () => {
).toHaveLength(5);
});
- it('renders group titles', () => {
- const { container } = render(
-
- );
-
- expect(container.querySelector('.euiCollapsibleNavItem__groupTitle'))
- .toMatchInlineSnapshot(`
-
- Section
-
- `);
- });
-
- it('allows customizing the group title element', () => {
- const { container } = render(
+ it('allows rendering totally custom sub items', () => {
+ const { getByTestSubject } = render(
},
{ title: 'Link 1', titleElement: 'h3' },
]}
/>
);
- expect(container.querySelector('.euiCollapsibleNavItem__groupTitle'))
- .toMatchInlineSnapshot(`
-
- Group title
-
- `);
+ expect(getByTestSubject('custom')).toBeInTheDocument();
});
});
});
diff --git a/src/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_item.tsx b/src/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_item.tsx
index f3b4bd57728..709637b2d87 100644
--- a/src/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_item.tsx
+++ b/src/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_item.tsx
@@ -6,25 +6,25 @@
* Side Public License, v 1.
*/
-import React, { FunctionComponent, HTMLAttributes, useContext } from 'react';
+import React, {
+ FunctionComponent,
+ HTMLAttributes,
+ ReactNode,
+ useContext,
+} from 'react';
import classNames from 'classnames';
-import { useEuiTheme } from '../../../services';
import { CommonProps, ExclusiveUnion } from '../../common';
import { EuiIcon, IconType, EuiIconProps } from '../../icon';
import { EuiLinkProps } from '../../link';
import { EuiAccordionProps } from '../../accordion';
-import { EuiTitle } from '../../title';
import { EuiCollapsibleNavContext } from '../context';
import { EuiCollapsedNavItem } from './collapsed';
import { EuiCollapsibleNavAccordion } from './collapsible_nav_accordion';
import { EuiCollapsibleNavLink } from './collapsible_nav_link';
-import {
- euiCollapsibleNavItemTitleStyles,
- euiCollapsibleNavSubItemGroupTitleStyles,
-} from './collapsible_nav_item.styles';
+import { euiCollapsibleNavItemTitleStyles } from './collapsible_nav_item.styles';
export type _SharedEuiCollapsibleNavItemProps = HTMLAttributes &
CommonProps & {
@@ -37,8 +37,8 @@ export type _SharedEuiCollapsibleNavItemProps = HTMLAttributes &
/**
* When passed, an `EuiAccordion` with nested child item links will be rendered.
*
- * Accepts any #EuiCollapsibleNavItem prop, and also accepts an
- * #EuiCollapsibleNavSubItemGroupTitle
+ * Accepts any #EuiCollapsibleNavItemProps. Or, to render completely custom
+ * subitem content, pass an object with a `renderItem` callback.
*/
items?: EuiCollapsibleNavSubItemProps[];
/**
@@ -79,20 +79,13 @@ export type EuiCollapsibleNavItemProps = {
iconProps?: Partial;
} & _SharedEuiCollapsibleNavItemProps;
-export type EuiCollapsibleNavSubItemGroupTitle = Pick<
- EuiCollapsibleNavItemProps,
- 'title' | 'titleElement'
-> & {
- /**
- * Pass this flag to seperate links by group title headings.
- * Strongly consider using the `titleElement` prop for accessibility.
- */
- isGroupTitle?: boolean;
+export type EuiCollapsibleNavCustomSubItem = {
+ renderItem: () => ReactNode;
};
export type EuiCollapsibleNavSubItemProps = ExclusiveUnion<
EuiCollapsibleNavItemProps,
- EuiCollapsibleNavSubItemGroupTitle
+ EuiCollapsibleNavCustomSubItem
>;
export type _EuiCollapsibleNavItemDisplayProps = {
@@ -182,31 +175,24 @@ const EuiCollapsibleNavItemTitle: FunctionComponent<
};
/**
- * Sub-items can either be a group title, to visually separate sections
- * of nav links, or they can simply be more links or accordions
+ * Sub-items can either be a totally custom rendered item,
+ * or they can simply be more links or accordions
*/
export const EuiCollapsibleNavSubItem: FunctionComponent<
EuiCollapsibleNavSubItemProps
-> = ({ isGroupTitle, className, ...props }) => {
- const euiTheme = useEuiTheme();
- const styles = euiCollapsibleNavSubItemGroupTitleStyles(euiTheme);
+> = ({ renderItem, className, ...props }) => {
const classes = classNames('euiCollapsibleNavSubItem', className);
- if (isGroupTitle) {
- const TitleElement = props.titleElement || 'div';
- return (
-
- {props.title}
-
- );
+ if (renderItem) {
+ return <>{renderItem()}>;
}
return (
-
+
);
};
diff --git a/src/components/collapsible_nav_beta/collapsible_nav_item/index.ts b/src/components/collapsible_nav_beta/collapsible_nav_item/index.ts
index 60bb1ef33be..3cfd0ef8d2a 100644
--- a/src/components/collapsible_nav_beta/collapsible_nav_item/index.ts
+++ b/src/components/collapsible_nav_beta/collapsible_nav_item/index.ts
@@ -9,7 +9,6 @@
export type {
EuiCollapsibleNavItemProps,
EuiCollapsibleNavSubItemProps,
- EuiCollapsibleNavSubItemGroupTitle,
} from './collapsible_nav_item';
export { EuiCollapsibleNavItem } from './collapsible_nav_item';
diff --git a/src/components/collapsible_nav_beta/index.ts b/src/components/collapsible_nav_beta/index.ts
index 4e5135afa7a..c393404f2fb 100644
--- a/src/components/collapsible_nav_beta/index.ts
+++ b/src/components/collapsible_nav_beta/index.ts
@@ -17,6 +17,5 @@ export { EuiCollapsibleNavBeta } from './collapsible_nav_beta';
export type {
EuiCollapsibleNavItemProps,
EuiCollapsibleNavSubItemProps,
- EuiCollapsibleNavSubItemGroupTitle,
} from './collapsible_nav_item';
export { EuiCollapsibleNavItem } from './collapsible_nav_item';