Skip to content

Commit feb36cd

Browse files
committed
wip search docs filter
1 parent 8f5670e commit feb36cd

File tree

7 files changed

+120
-27
lines changed

7 files changed

+120
-27
lines changed

www/scripts/build-internal-registry.ts

+2-4
Original file line numberDiff line numberDiff line change
@@ -176,9 +176,7 @@ async function buildDemos() {
176176
// // export const Components = {`;
177177
// }
178178

179-
const createPalette = () => {
180-
181-
}
179+
const createPalette = () => {};
182180

183181
const buildThemes = async () => {
184182
const targetPath = path.join(process.cwd(), "src/styles/themes.css");
@@ -208,7 +206,7 @@ const buildThemes = async () => {
208206
},
209207
},
210208
"light"
211-
)
209+
);
212210
themesCSS
213211
.push
214212
// template(THEME_STYLES_WITH_VARIABLES)({

www/src/app/(app)/themes/page.tsx

+6-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export const metadata: Metadata = {
2727
export default function Page() {
2828
return (
2929
<div className="pb-20">
30-
<section className="pt-16 pb-10">
30+
<section className="pb-10 pt-16">
3131
<h1 className="font-heading xs:text-2xl text-pretty text-xl font-semibold tracking-tighter sm:text-3xl md:text-4xl">
3232
Everything starts with identity.
3333
</h1>
@@ -39,7 +39,11 @@ export default function Page() {
3939
<Button variant="primary">Explore themes</Button>
4040
</ExploreThemesDialog>
4141
<CreateThemeDialog>
42-
<Button variant="outline" className="bg-bg-inverse/5" prefix={<PlusIcon />}>
42+
<Button
43+
variant="outline"
44+
className="bg-bg-inverse/5"
45+
prefix={<PlusIcon />}
46+
>
4347
Create theme
4448
</Button>
4549
</CreateThemeDialog>

www/src/app/layout.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ export default async function RootLayout({
5050
children: React.ReactNode;
5151
}) {
5252
const cookieStore = await cookies();
53-
const theme = cookieStore.get("site-theme")?.value ?? ""
54-
console.log(theme)
53+
const theme = cookieStore.get("site-theme")?.value ?? "";
54+
console.log(theme);
5555
return (
5656
<html lang="en" suppressHydrationWarning>
5757
<body
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export * from "@/registry/core/color-swatch-picker_basic"
1+
export * from "@/registry/core/color-swatch-picker_basic";

www/src/components/search-command-client.tsx

+104-16
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
ChevronsUpDownIcon,
66
CornerDownLeftIcon,
77
FileTextIcon,
8+
HashIcon,
89
SearchIcon,
910
} from "lucide-react";
1011
import { useFilter } from "react-aria-components";
@@ -41,12 +42,15 @@ export function SearchCommandClient({
4142
children,
4243
items,
4344
}: SearchCommandClientProps) {
44-
const { contains } = useFilter({ sensitivity: "base" });
4545
const [inputValue, setInputValue] = React.useState("");
46+
const filteredItems = React.useMemo(
47+
() => filterResults(inputValue, items),
48+
[inputValue, items]
49+
);
50+
4651
return (
4752
<SearchCommandDialog keyboardShortcut={keyboardShortcut} trigger={children}>
4853
<Command
49-
filter={contains}
5054
inputValue={inputValue}
5155
onInputChange={setInputValue}
5256
className="h-72"
@@ -59,20 +63,30 @@ export function SearchCommandClient({
5963
</InputRoot>
6064
</SearchFieldRoot>
6165
</div>
62-
<MenuContent items={items} className="h-full overflow-y-scroll py-1">
63-
{items.map((category, categoryIndex) => (
64-
<MenuSection key={categoryIndex} title={category.title}>
65-
{category.items.map((page) => (
66-
<React.Fragment key={page.id}>
67-
<MenuItem
68-
href={page.url}
69-
textValue={page.title}
70-
prefix={<FileTextIcon />}
71-
className="py-2"
72-
>
73-
{page.title}
74-
</MenuItem>
75-
</React.Fragment>
66+
<MenuContent className="h-full overflow-y-scroll py-1">
67+
{filteredItems.map((category) => (
68+
<MenuSection key={category.id} title={category.title}>
69+
{category.items.map((item) => (
70+
<MenuItem
71+
key={`${item.href}-${item.type}`}
72+
href={item.href}
73+
textValue={item.title}
74+
prefix={item.type === "page" ? <FileTextIcon /> : undefined}
75+
className={
76+
item.type === "page"
77+
? "[&_svg]:text-fg-muted gap-3 py-2"
78+
: "py-0 pl-2.5"
79+
}
80+
>
81+
{item.type === "page" ? (
82+
item.title
83+
) : (
84+
<div className="[&_svg]:text-fg-muted ml-2 flex items-center gap-3 border-l pl-4 [&_svg]:size-4">
85+
<HashIcon />
86+
<p className="flex-1 truncate py-2">{item.title}</p>
87+
</div>
88+
)}
89+
</MenuItem>
7690
))}
7791
</MenuSection>
7892
))}
@@ -91,6 +105,80 @@ export function SearchCommandClient({
91105
</SearchCommandDialog>
92106
);
93107
}
108+
109+
type FilteredItems = {
110+
title: string;
111+
href: string;
112+
type: "page" | "heading";
113+
}[];
114+
115+
type FilteredResult = {
116+
id: string;
117+
title: string;
118+
items: FilteredItems;
119+
}[];
120+
121+
const filterResults = (
122+
query: string,
123+
items: SearchCommandClientProps["items"]
124+
): FilteredResult => {
125+
// When no query, return all pages without headings
126+
if (!query) {
127+
return items.map((category) => ({
128+
id: category.title,
129+
title: category.title,
130+
items: category.items.map((page) => ({
131+
title: page.title,
132+
href: page.url,
133+
type: "page",
134+
})),
135+
}));
136+
}
137+
138+
const normalizedQuery = query.toLowerCase().trim();
139+
const results: FilteredResult = [];
140+
141+
items.forEach((category) => {
142+
const matchedItems: FilteredItems = [];
143+
144+
category.items.forEach((page) => {
145+
const isPageMatch = page.title.toLowerCase().includes(normalizedQuery);
146+
const matchedHeadings = page.headings.filter((heading) =>
147+
heading.content.toLowerCase().includes(normalizedQuery)
148+
);
149+
150+
// Add page if title matches or if there are matched headings
151+
if (isPageMatch || matchedHeadings.length > 0) {
152+
matchedItems.push({
153+
title: page.title,
154+
href: page.url,
155+
type: "page",
156+
});
157+
}
158+
159+
// Add matched headings after their parent page
160+
matchedHeadings.forEach((heading) => {
161+
matchedItems.push({
162+
title: heading.content,
163+
href: `${page.url}#${heading.id}`,
164+
type: "heading",
165+
});
166+
});
167+
});
168+
169+
// Only add categories that have matches
170+
if (matchedItems.length > 0) {
171+
results.push({
172+
id: category.title,
173+
title: category.title,
174+
items: matchedItems,
175+
});
176+
}
177+
});
178+
179+
return results;
180+
};
181+
94182
const SearchCommandDialog = ({
95183
keyboardShortcut = false,
96184
trigger,

www/src/components/theme-colors-selector.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ export const ThemeColorsSelector = ({
2626
return (
2727
<DialogRoot>
2828
{children}
29-
<Dialog type="popover" popoverProps={{ placement: "bottom right", shouldFlip: false }}>
29+
<Dialog
30+
type="popover"
31+
popoverProps={{ placement: "bottom right", shouldFlip: false }}
32+
>
3033
<p className="text-fg-muted text-sm">Neutral</p>
3134
<ColorSwatchPicker
3235
value={accentColor.value}

www/src/modules/themes/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
export * from "./lib/create-dynamic-component";
2-
export * from "./site-themes"
2+
export * from "./site-themes";

0 commit comments

Comments
 (0)