Skip to content

Commit 0b6947e

Browse files
committed
Categorize sidebar
1 parent ab975f9 commit 0b6947e

File tree

2 files changed

+67
-42
lines changed

2 files changed

+67
-42
lines changed

src/lib/output/themes/default/partials/navigation.tsx

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
import { DeclarationReflection, ProjectReflection, Reflection, ReflectionKind } from "../../../../models";
1+
import {
2+
DeclarationReflection,
3+
ProjectReflection,
4+
Reflection,
5+
ReflectionCategory,
6+
ReflectionKind,
7+
} from "../../../../models";
28
import { JSX } from "../../../../utils";
39
import type { PageEvent } from "../../../events";
410
import { camelToTitleCase, classNames, getDisplayName, wbr } from "../../lib";
@@ -98,42 +104,60 @@ export function settings(context: DefaultThemeRenderContext) {
98104
);
99105
}
100106

107+
type NavigationElement = ReflectionCategory | DeclarationReflection;
108+
109+
function getNavigationElements(parent: NavigationElement | ProjectReflection): NavigationElement[] {
110+
if (parent instanceof ReflectionCategory) {
111+
return parent.children;
112+
}
113+
114+
if (!parent.kindOf(ReflectionKind.SomeModule | ReflectionKind.Project)) {
115+
return [];
116+
}
117+
118+
if (parent.categories) {
119+
return parent.categories;
120+
}
121+
122+
return parent.children || [];
123+
}
124+
101125
export function navigation(context: DefaultThemeRenderContext, props: PageEvent<Reflection>) {
102126
// Create the navigation for the current page
103127
// Recurse to children if the parent is some kind of module
104128

105129
return (
106130
<nav class="tsd-navigation">
107-
{link(props.project)}
108-
<ul class="tsd-small-nested-navigation">
109-
{props.project.children?.map((c) => (
131+
{createNavElement(props.project, false)}
132+
<ul class="tsd-nested-navigation">
133+
{getNavigationElements(props.project).map((c) => (
110134
<li>{links(c)}</li>
111135
))}
112136
</ul>
113137
</nav>
114138
);
115139

116-
function links(mod: DeclarationReflection) {
117-
const children = (mod.kindOf(ReflectionKind.SomeModule | ReflectionKind.Project) && mod.children) || [];
118-
140+
function links(mod: NavigationElement) {
119141
const nameClasses = classNames(
120-
{ deprecated: mod.isDeprecated() },
121-
mod.isProject() ? void 0 : context.getReflectionClasses(mod)
142+
{ deprecated: mod instanceof Reflection && mod.isDeprecated() },
143+
!(mod instanceof Reflection) || mod.isProject() ? void 0 : context.getReflectionClasses(mod)
122144
);
123145

146+
const children = getNavigationElements(mod);
147+
124148
if (!children.length) {
125-
return link(mod, nameClasses);
149+
return createNavElement(mod, true, nameClasses);
126150
}
127151

128152
return (
129153
<details
130154
class={classNames({ "tsd-index-accordion": true }, nameClasses)}
131-
open={inPath(mod)}
132-
data-key={mod.getFullName()}
155+
open={mod instanceof Reflection && inPath(mod)}
156+
data-key={mod instanceof Reflection ? mod.getFullName() : mod.title}
133157
>
134158
<summary class="tsd-accordion-summary">
135159
{context.icons.chevronDown()}
136-
{link(mod)}
160+
{createNavElement(mod, false)}
137161
</summary>
138162
<div class="tsd-accordion-details">
139163
<ul class="tsd-nested-navigation">
@@ -146,13 +170,17 @@ export function navigation(context: DefaultThemeRenderContext, props: PageEvent<
146170
);
147171
}
148172

149-
function link(child: DeclarationReflection | ProjectReflection, nameClasses?: string) {
150-
return (
151-
<a href={context.urlTo(child)} class={classNames({ current: child === props.model }, nameClasses)}>
152-
{context.icons[child.kind]()}
153-
<span>{wbr(getDisplayName(child))}</span>
154-
</a>
155-
);
173+
function createNavElement(child: NavigationElement | ProjectReflection, icon: boolean, nameClasses?: string) {
174+
if (child instanceof Reflection) {
175+
return (
176+
<a href={context.urlTo(child)} class={classNames({ current: child === props.model }, nameClasses)}>
177+
{icon && context.icons[child.kind]()}
178+
<span>{wbr(getDisplayName(child))}</span>
179+
</a>
180+
);
181+
}
182+
183+
return <span>{child.title}</span>;
156184
}
157185

158186
function inPath(mod: DeclarationReflection | ProjectReflection) {

static/style.css

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -696,7 +696,12 @@ input[type="checkbox"]:checked ~ svg .tsd-checkbox-checkmark {
696696
.tsd-navigation.settings {
697697
margin: 1rem 0;
698698
}
699+
.tsd-navigation > a,
700+
.tsd-navigation .tsd-accordion-summary {
701+
width: calc(100% - 0.5rem);
702+
}
699703
.tsd-navigation a,
704+
.tsd-navigation summary > span,
700705
.tsd-page-navigation a {
701706
display: inline-flex;
702707
align-items: center;
@@ -705,14 +710,6 @@ input[type="checkbox"]:checked ~ svg .tsd-checkbox-checkmark {
705710
text-decoration: none;
706711
box-sizing: border-box;
707712
}
708-
.tsd-navigation a {
709-
/* why 3rem? No idea, but it seems to work. */
710-
width: calc(100% - 3rem);
711-
}
712-
.tsd-page-navigation a {
713-
/* why is this different? */
714-
width: 100%;
715-
}
716713
.tsd-navigation a.current,
717714
.tsd-page-navigation a.current {
718715
background: var(--color-active-menu-item);
@@ -732,17 +729,13 @@ input[type="checkbox"]:checked ~ svg .tsd-checkbox-checkmark {
732729
padding: 0;
733730
max-width: 100%;
734731
}
735-
.tsd-nested-navigation > li > a {
736-
margin-left: 3rem;
732+
.tsd-nested-navigation > li > a,
733+
.tsd-nested-navigation > li > span {
734+
width: calc(100% - 1.75rem - 0.5rem);
735+
margin-left: 1.75rem;
737736
}
738737
.tsd-nested-navigation > li > details {
739-
margin-left: 1.5rem;
740-
}
741-
.tsd-small-nested-navigation > li > a {
742-
margin-left: 1.5rem;
743-
}
744-
.tsd-small-nested-navigation > li > details {
745-
margin-left: 0;
738+
margin-left: 1.75rem;
746739
}
747740
.tsd-page-navigation ul {
748741
padding-left: 1.75rem;
@@ -765,28 +758,32 @@ a.tsd-index-link {
765758
align-items: center;
766759
color: var(--color-text);
767760
}
761+
.tsd-accordion-summary {
762+
list-style-type: none;
763+
display: flex;
764+
align-items: center;
765+
}
768766
.tsd-accordion-summary,
769767
.tsd-accordion-summary a {
770768
user-select: none;
771769
-moz-user-select: none;
772770
-webkit-user-select: none;
773771
-ms-user-select: none;
774772

775-
display: flex;
776-
align-items: center;
777773
cursor: pointer;
778774
}
775+
.tsd-accordion-summary a {
776+
flex-grow: 1;
777+
}
779778
.tsd-accordion-summary > * {
780779
margin-top: 0;
781780
margin-bottom: 0;
782781
padding-top: 0;
783782
padding-bottom: 0;
784783
}
785-
.tsd-accordion-summary::-webkit-details-marker {
786-
display: none;
787-
}
788784
.tsd-index-accordion .tsd-accordion-summary svg {
789785
margin-right: 0.25rem;
786+
margin-left: 0.25rem;
790787
}
791788
.tsd-index-content > :not(:first-child) {
792789
margin-top: 0.75rem;

0 commit comments

Comments
 (0)