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
6 changes: 3 additions & 3 deletions e2e/fixtures/auto-nav-sidebar/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,12 @@ test.describe('Auto nav and sidebar test', async () => {
[
'Basic config',
'Theme config',
'Front matter config',
'Build config',
'Front matter config',
'Extname config',
'Nested',
'Runtime API',
'Components',
'Runtime API',
'Commands',
'Single',
'Section a',
Expand Down Expand Up @@ -186,7 +186,7 @@ test.describe('Auto nav and sidebar test', async () => {
.map(text => text.trim())
.filter(Boolean);
expect(itemTitleTexts.join(',')).toEqual(
['Runtime API', 'Components'].join(','),
['Components', 'Runtime API'].join(','),
);

const links = page.locator(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## Feature a

Description of feature A.

## Feature b

Description of feature B.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## Section a

Content for section 1.

## Section b

Content for section 2.
43 changes: 37 additions & 6 deletions e2e/fixtures/nested-overview/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,20 @@ test.describe('Nested overview page', async () => {
);
await expect(overviewHeadings).toHaveText(['Level 2']);

const overviewGroups = page.locator(
// Items can be in either standard layout or grid layout
const standardItems = page.locator(
'.rp-overview .rp-overview-group__item__title > a',
);
await expect(overviewGroups).toHaveText(['Level 2', 'two', 'Level 3']);
const gridItems = page.locator(
'.rp-overview .rp-overview-group__grid-item__link',
);

// Get text from both selectors and combine
const standardText = await standardItems.allTextContents();
const gridText = await gridItems.allTextContents();
const allText = [...standardText, ...gridText];

expect(allText).toEqual(['two', 'Level 2', 'Level 3']);
});

test('Should load nested overview page correctly - level 2', async ({
Expand All @@ -50,10 +60,21 @@ test.describe('Nested overview page', async () => {
);
await expect(overviewHeadings).toHaveText(['two', 'Level 3']);

const overviewGroups = page.locator(
// Items can be in either standard layout or grid layout
const standardItems = page.locator(
'.rp-overview .rp-overview-group__item__title > a',
);
await expect(overviewGroups).toHaveText(['two', 'Level 3', 'three']);
const gridItems = page.locator(
'.rp-overview .rp-overview-group__grid-item__link',
);

// Get text from both selectors and combine
const standardText = await standardItems.allTextContents();
const gridText = await gridItems.allTextContents();
const allText = [...standardText, ...gridText];

// Items with headers (standard layout) come first, then items without headers (grid layout)
expect(allText).toEqual(['two', 'three', 'Level 3']);
});

test('Should load nested overview page correctly - level 3', async ({
Expand All @@ -70,9 +91,19 @@ test.describe('Nested overview page', async () => {
);
await expect(overviewHeadings).toHaveText(['three']);

const overviewGroups = page.locator(
// Items can be in either standard layout or grid layout
const standardItems = page.locator(
'.rp-overview .rp-overview-group__item__title > a',
);
await expect(overviewGroups).toHaveText(['three']);
const gridItems = page.locator(
'.rp-overview .rp-overview-group__grid-item__link',
);

// Get text from both selectors and combine
const standardText = await standardItems.allTextContents();
const gridText = await gridItems.allTextContents();
const allText = [...standardText, ...gridText];

expect(allText).toEqual(['three']);
});
});
78 changes: 66 additions & 12 deletions packages/core/src/theme/components/OverviewGroup/index.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
:root {
--rp-c-overview-group-bg: var(--rp-c-bg-soft);
--rp-c-overview-group-bg-hover: color-mix(
in srgb,
var(--rp-c-brand-lighter) 30%,
transparent
);
--rp-c-overview-group-border: 1px solid var(--rp-c-divider-light);
}

.rp-overview-group {
width: 100%;
display: flex;
Expand All @@ -9,7 +19,7 @@
width: 100%;
flex-direction: row;

border: 1px solid var(--rp-c-divider-light);
border: var(--rp-c-overview-group-border);
border-radius: var(--rp-radius);
overflow: hidden;
transition:
Expand All @@ -20,11 +30,7 @@
border-color: var(--rp-c-brand-light);
box-shadow: 0 4px 6px 0 rgba(0, 0, 0, 0.04);
.rp-overview-group__item__title {
background-color: color-mix(
in srgb,
var(--rp-c-brand-lighter) 30%,
transparent
) !important;
background-color: var(--rp-c-overview-group-bg-hover);
.rp-overview-group__item__title__icon {
color: var(--rp-c-brand-dark);
}
Expand All @@ -40,22 +46,25 @@
}

&__title {
width: 20%;
flex: 0 0 20%;
word-break: break-all;
width: 25%;
flex: 0 0 25%;

padding: 16px 20px;

word-break: break-all;
font-size: 18px;
font-weight: 600;
background-color: var(--rp-c-bg-soft);
color: var(--rp-c-text-1);

background-color: var(--rp-c-overview-group-bg);

overflow: hidden;
position: relative;

transition: background-color 0.2s ease;

a {
&__link,
&__text {
color: inherit;
text-decoration: none;

Expand Down Expand Up @@ -121,10 +130,55 @@
}
}
}

// Grid layout for items without content (no headers/items)
&__grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
width: 100%;

@media (max-width: 1280px) {
grid-template-columns: repeat(3, 1fr);
}

@media (max-width: 768px) {
grid-template-columns: repeat(2, 1fr);
}

@media (max-width: 480px) {
grid-template-columns: 1fr;
}
}

&__grid-item {
border: 1px solid var(--rp-c-divider-light);
border-radius: var(--rp-radius);
transition:
border-color 0.2s ease,
box-shadow 0.2s ease,
background-color 0.2s ease;

&.rp-overview-group__item__title {
width: 100%;
flex: none;
}

&:hover {
border-color: var(--rp-c-brand-light);
box-shadow: 0 4px 6px 0 rgba(0, 0, 0, 0.04);
background-color: var(--rp-c-overview-group-bg-hover);

.rp-overview-group__item__title__icon {
color: var(--rp-c-brand-dark);
}
}
}
}

html.rp-dark {
.rp-overview-group__item:hover {
.rp-overview-group__item:hover,
.rp-overview-group__grid-item:hover {
.rp-overview-group__item__title__icon {
color: white;
}
Expand Down
51 changes: 49 additions & 2 deletions packages/core/src/theme/components/OverviewGroup/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Link, renderInlineMarkdown } from '@theme';
import './index.scss';
import type { Header } from '@rspress/core';
import { FallbackHeading, SvgWrapper } from '@theme';
import { useMemo } from 'react';
import IconPlugin from './icons/plugin.svg';

export interface GroupItem {
Expand All @@ -19,20 +20,41 @@ export interface Group {
}

export const OverviewGroup = ({ group }: { group: Group }) => {
const { itemsWithContent, itemsWithoutContent } = useMemo(() => {
// Separate items into those with content and those without
const itemsWithContent = group.items.filter(
item =>
(item.headers && item.headers.length > 0) ||
(item.items && item.items.length > 0),
);
const itemsWithoutContent = group.items.filter(
item =>
!(item.headers && item.headers.length > 0) &&
!(item.items && item.items.length > 0),
);

return { itemsWithContent, itemsWithoutContent };
}, [group]);

return (
<>
<FallbackHeading level={2} title={group.name} />
<div className="rp-overview-group rp-not-doc">
{group.items.map(item => (
{/* Render items with content in the standard split layout */}
{itemsWithContent.map(item => (
<div className="rp-overview-group__item" key={item.link}>
<div className="rp-overview-group__item__title">
{item.link ? (
<Link
href={item.link}
className="rp-overview-group__item__title__link"
{...renderInlineMarkdown(item.text)}
></Link>
) : (
<span {...renderInlineMarkdown(item.text)} />
<span
className="rp-overview-group__item__title__text"
{...renderInlineMarkdown(item.text)}
/>
)}
<SvgWrapper
icon={IconPlugin}
Expand Down Expand Up @@ -69,6 +91,31 @@ export const OverviewGroup = ({ group }: { group: Group }) => {
</ul>
</div>
))}

{/* Render items without content in a grid layout */}
{itemsWithoutContent.length > 0 && (
<div className="rp-overview-group__grid">
{itemsWithoutContent.map(item => (
<div
className="rp-overview-group__grid-item rp-overview-group__item__title"
key={item.link}
>
{item.link ? (
<Link
href={item.link}
className="rp-overview-group__item__title__link"
{...renderInlineMarkdown(item.text)}
></Link>
) : (
<span
className="rp-overview-group__item__title__text"
{...renderInlineMarkdown(item.text)}
/>
)}
</div>
))}
</div>
)}
</div>
</>
);
Expand Down
4 changes: 4 additions & 0 deletions website/docs/en/ui/runtime-components/head.mdx
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
---
overviewHeaders: []
---

# Head

The Head component lets you inject custom head content (built on [unhead](https://www.npmjs.com/package/unhead)).
Expand Down
4 changes: 4 additions & 0 deletions website/docs/en/ui/runtime-components/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
title: Runtime Components
overview: true
---
4 changes: 4 additions & 0 deletions website/docs/en/ui/runtime-components/no-ssr.mdx
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
---
overviewHeaders: []
---

# NoSSR

`NoSSR` skips server-side rendering for its children.
Expand Down
4 changes: 4 additions & 0 deletions website/docs/zh/ui/runtime-components/head.mdx
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
---
overviewHeaders: []
---

# Head

Head 组件用于向文档页面插入自定义 head 内容(基于 [unhead](https://www.npmjs.com/package/unhead))。
Expand Down
4 changes: 4 additions & 0 deletions website/docs/zh/ui/runtime-components/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
title: 运行时组件
overview: true
---
4 changes: 4 additions & 0 deletions website/docs/zh/ui/runtime-components/no-ssr.mdx
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
---
overviewHeaders: []
---

# NoSSR

`NoSSR` 用于禁用特定子树在服务端渲染,强制只在客户端渲染。
Expand Down
Loading