Skip to content
Merged
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
36 changes: 11 additions & 25 deletions @theme/components/Menu/ProductsMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,8 @@ export function ProductsMenu({
items[i + 1].sublabel = descriptions[i];
}

const products = getProducts(items);
const openSourceTools = getOpenSourceTools(items);

const products = getSectionItems(items, 'Products');
const openSourceTools = getSectionItems(items, 'Open Source');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Severity: Medium

The getSectionItems refactoring is correct, but it isn't called for the new 'Agents' separator, leaving 'Reviewer' omitted from the mobile menu. Please fetch and render the 'Agents' section, and ensure its description is mapped correctly.

return (
<MenuWrapper className={className} data-component-name="Menu/ProductsMenu">
<div>
Expand Down Expand Up @@ -67,7 +66,7 @@ export function ProductsMenu({
</>
);
})}
{openSourceTools && (
{openSourceTools.length > 0 && (
<OpenSourceToolsWrapper>
<OpenSourceSeparator>
<img src={require('../Navbar/images/open-source-icon.svg')} />
Expand Down Expand Up @@ -106,32 +105,19 @@ export function ProductsMenu({
);
}

const getProducts = (arr) => {
const separatorsIndices = arr
.map((obj, index) => (obj.type === 'separator' ? index : null))
.filter((index) => index !== null);

if (separatorsIndices.length < 2) {
return [];
}
const start = separatorsIndices[0];
const end = separatorsIndices[separatorsIndices.length - 1];

return arr.slice(start + 1, end);
};

const getOpenSourceTools = (arr) => {
const separatorsIndices = arr
.map((obj, index) => (obj.type === 'separator' ? index : null))
.filter((index) => index !== null);
const getSectionItems = (arr: ItemState[], separatorLabel: string) => {
const start = arr.findIndex(
(item) => item.type === 'separator' && item.label === separatorLabel,
);

if (separatorsIndices.length < 2) {
if (start === -1) {
return [];
}

const end = separatorsIndices[separatorsIndices.length - 1];
const rest = arr.slice(start + 1);
const nextSeparatorIndex = rest.findIndex((item) => item.type === 'separator');

return arr.slice(end + 1, arr.length);
return nextSeparatorIndex === -1 ? rest : rest.slice(0, nextSeparatorIndex);
};

const OpenSourceItem = styled(MenuItem)<{isLast?: boolean}>`
Expand Down
93 changes: 78 additions & 15 deletions @theme/components/Navbar/NavbarItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,16 @@ export function NavbarItem({ navItem, className }: NavbarItemProps): JSX.Element
})
.includes(true);

const descriptions = [
'Collaborative editor suite',
'Combo of Redoc, Revel, and Reef',
'External developer showcase',
'API reference and mock server',
'Internal service catalog',
'API monitoring',
];
const groupItemsComponents = groupItems.reduce((acc, curr, index) => {
const descriptions: Record<string, string> = {
Realm: 'Combo of Redoc, Revel, and Reef',
Revel: 'External developer showcase',
Redoc: 'API reference and mock server',
Reef: 'Internal service catalog',
'Respect Monitoring': 'API monitoring',
Reviewer: 'Reads pull requests, leaves expert feedback'
};
const newItems = new Set(['Reviewer']);
const groupItemsComponents = groupItems.reduce((acc, curr) => {
if (curr.type.startsWith('separator')) {
acc.push({ [curr.label as string]: [] });
} else {
Expand Down Expand Up @@ -102,13 +103,18 @@ export function NavbarItem({ navItem, className }: NavbarItemProps): JSX.Element
</ReuniteBlock>,
);
} else {
acc[acc.length - 1][Object.keys(acc[acc.length - 1])[0]].push(
const currentSection = Object.keys(acc[acc.length - 1])[0];
const description =
currentSection === 'Open Source' ? undefined : descriptions[curr.label as string];
const showNewTag = newItems.has(curr.label as string);
acc[acc.length - 1][currentSection].push(
<StyledLink key={`${curr.label}`} to={curr.link}>
{curr.icon && <Icon src={curr.icon} />}
<TextBlock>
{curr.label}
{descriptions[index - 1] && <span>{descriptions[index - 1]}</span>}
{description && <span>{description}</span>}
</TextBlock>
{showNewTag && <NewTag>New</NewTag>}
</StyledLink>,
);
}
Expand All @@ -118,6 +124,7 @@ export function NavbarItem({ navItem, className }: NavbarItemProps): JSX.Element

const products: any = [];
const openSource: any = [];
const aiTools: any = [];
let reunite: any = {};

groupItemsComponents.map((item) => {
Expand All @@ -130,10 +137,14 @@ export function NavbarItem({ navItem, className }: NavbarItemProps): JSX.Element
products.push(value);
}
});
} else {
} else if (key === 'Open Source') {
(value as any).map((value) => {
openSource.push(value);
});
} else {
(value as any).map((value) => {
aiTools.push(value);
});
}
});
});
Expand Down Expand Up @@ -181,7 +192,7 @@ export function NavbarItem({ navItem, className }: NavbarItemProps): JSX.Element
return (
<DropdownListItem
key={index}
product={`${link.key.toLowerCase()}`}
product={`${link.key.toLowerCase().replace(/\s+/g, '-')}`}
isLast={index === products.length - 1}
>
{link}
Expand All @@ -206,6 +217,23 @@ export function NavbarItem({ navItem, className }: NavbarItemProps): JSX.Element
)}
</DropdownList>
</ProductsBlock>
{aiTools.length > 0 && (
<AiToolsSection>
<Label>
Agents:
</Label>
<AiToolsItems>
{aiTools.map((link, index) => (
<DropdownListItem
key={index}
product={`${link.key.toLowerCase().replace(/\s+/g, '-')}`}
>
{link}
</DropdownListItem>
))}
</AiToolsItems>
</AiToolsSection>
)}
</DropdownWrapper>
</DropdownCasket>
</NavbarMenuItemDropdown>
Expand Down Expand Up @@ -352,6 +380,41 @@ const TextBlock = styled.div`
}
`;

const NewTag = styled.div`
position: absolute;
top: 0;
right: 0;

display: flex;
align-items: center;
justify-content: center;
min-width: 20px;
padding: 0 4px;
border-radius: 4px;
background: var(--tag-basic-bg-color);
color: var(--tag-basic-content-color);
font-family: Inter;
font-size: 12px;
font-weight: 400;
line-height: 20px;
`;

const AiToolsSection = styled.div`
display: flex;
flex-direction: column;
gap: 4px;

margin-top: 8px;
padding-top: 8px;
border-top: 1px solid var(--dropdown-list-border-color);
`;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Severity: Medium

AiToolsSection is defined as a div but directly contains DropdownListItem components, which are li elements. To ensure valid HTML and maintain accessibility, AiToolsSection should be defined as a ul (e.g., styled.ul) with reset list-styles.


const AiToolsItems = styled.div`
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 4px;
`;

const Icon = styled.img`
height: 24px;
width: 24px;
Expand All @@ -370,7 +433,7 @@ export const DropdownList = styled.ul`
z-index: 1;
`;

export const DropdownListItem = styled.li<{ product?: string, isLast?: boolean }>`
export const DropdownListItem = styled.li<{ product?: string; isLast?: boolean }>`
display: block;
width: 100%;
border: none;
Expand All @@ -395,7 +458,7 @@ export const DropdownListItem = styled.li<{ product?: string, isLast?: boolean }
background: ${({ product, isLast }) =>
isLast
? 'var(--hover-last-navbar-color)'
: `var(--${product}-color-hover)`};
: `var(--${product}-color-hover, var(--hover-last-navbar-color))`};
}
`;

Expand Down
6 changes: 6 additions & 0 deletions @theme/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,10 @@
--reef-color-hover: #F9EAFF;
--revel-color-hover: #F1EDFF;
--realm-color-hover: linear-gradient(90deg, #E4F0FF 0%, #CDF8FD 100%);
--reviewer-color-hover: #F3F3F6;
--bg-open-source-tools: #FBFBFC;
--tag-basic-bg-color: #EDEDF2;
--tag-basic-content-color: #2A2B33;

--navbar-height: 64px;
--navbar-logo-width: 103px;
Expand Down Expand Up @@ -564,11 +567,14 @@
--reef-color-hover: #3B3C45;
--revel-color-hover: #3B3C45;
--realm-color-hover: #3B3C45;
--reviewer-color-hover: #3B3C45;
--bg-open-source-tools: #2A2B33;
--button-bg: #fff;
--color-ontonal: #2A2B33;
--color-arrow: #9B9CA8;
--hover-last-navbar-color: #3B3C45;
--tag-basic-bg-color: #3B3C45;
--tag-basic-content-color: #EDEDF2;
}

:root.dark nav img {
Expand Down
16 changes: 16 additions & 0 deletions images/icons/ai-reviewer.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading