mirror of
https://github.com/Xevion/utsa-handbook.git
synced 2025-12-06 15:16:58 -06:00
Continue work on sidebar generation/styling
This commit is contained in:
@@ -1,3 +1,8 @@
|
|||||||
|
# 0.0.3
|
||||||
|
|
||||||
|
- Continued dark mode work
|
||||||
|
- Added sidebar with content collection query for dynamic navigation
|
||||||
|
|
||||||
# 0.0.2
|
# 0.0.2
|
||||||
|
|
||||||
- Added version/commit hash to the footer
|
- Added version/commit hash to the footer
|
||||||
|
|||||||
@@ -12,12 +12,14 @@ const isCurrentPage = (item): boolean => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getLinkClasses = (link) => {
|
const getLinkClasses = (link) => {
|
||||||
const baseClasses = "block py-2 px-6 my-1 transition-colors border-l dark:border-l-zinc-600 hover:border-zinc-400 hover:text-slate-900"
|
const baseClasses = "block py-2 px-6 my-1 transition-colors border-l hover:border-zinc-400 hover:text-slate-900"
|
||||||
const isCurrent = isCurrentPage(link);
|
const isCurrent = isCurrentPage(link);
|
||||||
|
|
||||||
return clsx(baseClasses, {
|
return clsx(baseClasses, {
|
||||||
"border-slate-500 text-slate-900": isCurrent,
|
// Classes for when the link is not the current page
|
||||||
"dark:text-slate-200 text-slate-500": !isCurrent,
|
"dark:border-l-zinc-600 text-zinc-500 dark:text-zinc-400": !isCurrent,
|
||||||
|
// Classes for when the link is the current page
|
||||||
|
"dark:border-l-zinc-500 text-zinc-900 dark:text-zinc-200": isCurrent,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { getCollection, getEntries } from 'astro:content';
|
import { getCollection, getEntries, type CollectionEntry } from 'astro:content';
|
||||||
|
|
||||||
|
|
||||||
export type Link = {
|
export type Link = {
|
||||||
@@ -7,37 +7,65 @@ export type Link = {
|
|||||||
header?: boolean;
|
header?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const headerOrder: Record<string, number> = {
|
||||||
|
root: 0,
|
||||||
|
learning: 1,
|
||||||
|
living: 2,
|
||||||
|
improving: 3,
|
||||||
|
default: 999
|
||||||
|
}
|
||||||
|
|
||||||
|
function toTitleCase(s: string): string {
|
||||||
|
return s.replace(
|
||||||
|
/\w\S*/g,
|
||||||
|
function(txt) {
|
||||||
|
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Queries the content collection to build the sidebar dynamically
|
* Queries the content collection to build the sidebar dynamically
|
||||||
* @returns {Link[]} - An array of links to be used in the sidebar
|
* @returns {Link[]} - An array of links to be used in the sidebar
|
||||||
*/
|
*/
|
||||||
const get = async (): Link[] => {
|
const get = async (): Promise<Link[]> => {
|
||||||
const entries = await getCollection('handbook');
|
const entries = await getCollection('handbook');
|
||||||
return entries.map((entry) => {
|
const entriesByHeader: Record<string, CollectionEntry<'handbook'>[]> = {};
|
||||||
return {
|
|
||||||
text: entry.data.title,
|
entries.forEach((entry) => {
|
||||||
link: `/handbook/${entry.slug}`,
|
// Acquire the header using the first part of the slug (otherwise, use 'root' as the header)
|
||||||
header: entry.slug.endsWith('index.md') || entry.data.header,
|
const header = entry.slug.indexOf('/') !== -1 ? entry.slug.split('/')[0] : 'root';
|
||||||
};
|
|
||||||
|
if (entriesByHeader[header])
|
||||||
|
entriesByHeader[header].push(entry);
|
||||||
|
else
|
||||||
|
entriesByHeader[header] = [entry];
|
||||||
});
|
});
|
||||||
|
|
||||||
// Fake data
|
// Begin building the links array (root level first, then the rest of the entries)
|
||||||
return [
|
const links: Link[] = entriesByHeader.root.map((entry) => ({
|
||||||
{ text: "Core", header: true },
|
text: entry.data.title,
|
||||||
{ text: "Introduction", link: "/core/introduction" },
|
link: `/handbook/${entry.slug}`,
|
||||||
{ text: "Colors", link: "/core/colors" },
|
}));
|
||||||
{ text: "Typography", link: "/core/typography" },
|
|
||||||
{ text: "Shadows", link: "/core/shadows" },
|
|
||||||
|
|
||||||
{ text: "Components", header: true },
|
delete entriesByHeader.root;
|
||||||
{ text: "Buttons", link: "/components/buttons" },
|
|
||||||
{ text: "Input", link: "/components/input" },
|
|
||||||
{ text: "Status pills", link: "/components/status-pill" },
|
|
||||||
{ text: "Table", link: "/components/table" },
|
|
||||||
|
|
||||||
{ text: "Patterns", header: true },
|
const sortedHeaders = Object.keys(entriesByHeader).sort((a, b) => {
|
||||||
{ text: "Introduction", link: "/patterns/introduction" },
|
return (headerOrder[a] || headerOrder.default) - (headerOrder[b] || headerOrder.default);
|
||||||
];
|
});
|
||||||
|
|
||||||
|
sortedHeaders.forEach((header) => {
|
||||||
|
links.push({ text: toTitleCase(header), header: true });
|
||||||
|
entriesByHeader[header].forEach((entry) => {
|
||||||
|
links.push({
|
||||||
|
text: entry.data.title,
|
||||||
|
link: `/handbook/${entry.slug}`,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
return links;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default get;
|
export default get;
|
||||||
|
|||||||
Reference in New Issue
Block a user