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
52 changes: 46 additions & 6 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -130,23 +130,29 @@ body {
margin: 1.5rem 0;
font-size: 0.875rem;
line-height: 1.5;
border-radius: var(--radius);
overflow: hidden;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.prose-doc table thead {
border-bottom: 1px solid var(--border);
border-bottom: 2px solid var(--border);
}

.prose-doc table th {
font-weight: 600;
text-align: left;
padding: 0.75rem 1rem;
padding: 0.875rem 1rem;
border-bottom: 1px solid var(--border);
background-color: var(--muted);
position: sticky;
top: 0;
z-index: 10;
}

.prose-doc table tbody tr {
border-bottom: 1px solid var(--border);
transition: background-color 0.2s ease;
transition: all 0.2s ease;
}

.prose-doc table tbody tr:last-child {
Expand All @@ -155,21 +161,55 @@ body {

.prose-doc table tbody tr:hover {
background-color: var(--muted);
transform: translateX(2px);
}

.prose-doc table td {
padding: 0.75rem 1rem;
padding: 0.875rem 1rem;
vertical-align: top;
border-right: 1px solid var(--border);
}

.prose-doc table td:last-child {
border-right: none;
}

.prose-doc table td:first-child {
font-weight: 500;
color: var(--primary);
background-color: var(--muted);
}

.prose-doc table code {
background-color: var(--accent);
padding: 0.125rem 0.25rem;
border-radius: var(--radius-sm);
font-size: 0.875em;
font-weight: 500;
}

.prose-doc table blockquote {
margin: 1rem 0;
padding: 0.5rem 1rem;
border-left: 4px solid var(--primary);
background-color: var(--muted);
border-radius: 0 var(--radius) var(--radius) 0;
}

/* Responsive table improvements */
@media (max-width: 768px) {
.prose-doc table {
font-size: 0.75rem;
}

.prose-doc table th,
.prose-doc table td {
padding: 0.5rem 0.75rem;
}
}

/* Sidebar scrollbar */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: var(--muted-foreground); }

::-webkit-scrollbar-thumb:hover { background: var(--muted-foreground); }
34 changes: 9 additions & 25 deletions src/components/layout/DocsLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import React, { useState, useEffect } from "react";
import React from "react";
import { DocsSidebar } from "./DocsSidebar";
import { Breadcrumbs } from "./Breadcrumbs";
import { DocNavigation } from "./DocNavigation";
Expand All @@ -16,43 +16,27 @@ interface DocsLayoutProps {
}

export function DocsLayout({ children }: DocsLayoutProps) {
const [isSearchOpen, setIsSearchOpen] = useState(false);
const tocItems = useTableOfContents();

useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => {
if ((event.metaKey || event.ctrlKey) && event.key === "k") {
event.preventDefault();
setIsSearchOpen(true);
}
if (event.key === "Escape") {
setIsSearchOpen(false);
}
};

document.addEventListener("keydown", handleKeyDown);
return () => document.removeEventListener("keydown", handleKeyDown);
}, []);

return (
<>
<div className="container mx-auto px-4">
{/* Deprecation notice */}
<DeprecationNotice className="mb-6" />

{/* Version selector and page header */}
<div className="flex items-center justify-between py-4 border-b mb-6" style={{ borderColor: "var(--border)" }}>
<div className="flex items-center justify-end py-4 border-b mb-6" style={{ borderColor: "var(--border)" }}>
<VersionSelector />
</div>

<div className="flex-1 items-start md:grid md:grid-cols-[240px_minmax(0,1fr)] md:gap-8 lg:grid-cols-[260px_minmax(0,1fr)_220px] lg:gap-10">
{/* Sidebar */}
<aside aria-label="Documentation navigation">
<div className="flex flex-col md:flex-row gap-8 lg:gap-10">
{/* Sidebar - Fixed positioning */}
<div className="hidden md:block md:w-64 lg:w-65 shrink-0">
<DocsSidebar />
</aside>
</div>

{/* Main content */}
<main id="main-content" className="relative py-8 min-w-0" role="main" aria-label="Main content">
{/* Main content - Takes remaining space */}
<main id="main-content" className="flex-1 relative py-8 min-w-0" role="main" aria-label="Main content">
<Breadcrumbs />
<article className="prose-doc max-w-none">{children}</article>

Expand All @@ -67,7 +51,7 @@ export function DocsLayout({ children }: DocsLayoutProps) {
</main>

{/* Right TOC column */}
<aside className="hidden lg:block" aria-label="Table of contents">
<aside className="hidden lg:block w-56 shrink-0" aria-label="Table of contents">
<div className="sticky top-20 py-8">
<TableOfContents items={tocItems} />
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/layout/DocsSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export function DocsSidebar() {
const docsConfig = getDocsConfig(currentVersion?.value);

return (
<aside className="fixed top-14 z-30 -ml-2 hidden h-[calc(100vh-3.5rem)] w-full shrink-0 md:sticky md:block">
<aside className="fixed top-14 left-0 z-30 hidden h-[calc(100vh-3.5rem)] w-64 shrink-0 md:sticky md:block md:left-auto">
<div className="h-full overflow-y-auto py-6 pr-6 lg:py-8">
<div className="flex flex-col gap-6">
{docsConfig.sidebarNav.map((item, index) => (
Expand Down
20 changes: 10 additions & 10 deletions src/components/layout/VersionSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export function VersionSelector() {
<button
onClick={() => setIsOpen(!isOpen)}
className={cn(
"flex items-center gap-2 px-3 py-1.5 text-sm rounded-md",
"flex items-center justify-end gap-1 px-8 py-1.5 text-sm rounded-md",
"border transition-colors",
"hover:bg-accent/10 hover:border-primary/50",
"focus:outline-none focus:ring-2 focus:ring-primary/20"
Expand All @@ -31,7 +31,7 @@ export function VersionSelector() {
>
<span className="font-medium">{currentVersion.label}</span>
{currentVersion.deprecated && (
<AlertTriangle className="h-3 w-3 text-amber-500" />
<AlertTriangle className="h-3 w-3 text-amber-400" />
)}
<ChevronDown
className={cn(
Expand All @@ -45,14 +45,14 @@ export function VersionSelector() {
<>
{/* Backdrop */}
<div
className="fixed inset-0 z-10"
className="fixed inset-0 z-40"
onClick={() => setIsOpen(false)}
/>

{/* Dropdown */}
<div className={cn(
"absolute top-full left-0 mt-1 min-w-[250px]",
"bg-background/95 backdrop-blur-sm border rounded-md shadow-lg z-20",
"absolute top-full left-0 mt-1 min-w-[220px]",
"bg-background/95 backdrop-blur-md border rounded-md shadow-lg z-20",
"py-1"
)} style={{ borderColor: "var(--border)" }}>
{versions.map((version) => (
Expand All @@ -65,8 +65,8 @@ export function VersionSelector() {
router.push(currentPath);
}}
className={cn(
"w-full px-3 py-2 text-left text-sm cursor-pointer",
"hover:bg-accent/10 transition-colors flex items-center justify-between",
"w-full px-3 py-2 text-left text-sm cursor-pointer flex items-center justify-between",
"hover:bg-accent/10 transition-colors",
version.current && "text-primary font-medium",
version.deprecated && "text-muted-foreground"
)}
Expand All @@ -77,14 +77,14 @@ export function VersionSelector() {
<AlertTriangle className="h-3 w-3 text-amber-500" />
)}
</div>
<div className="flex items-center gap-2">
<div className="flex items-center gap-2 text-xs ">
{version.current && (
<span className="text-xs text-muted-foreground">
<span className="text-muted-foreground">
(current)
</span>
)}
{version.stable && !version.current && (
<span className="text-xs text-green-600">
<span className="text-green-600">
(stable)
</span>
)}
Expand Down
96 changes: 96 additions & 0 deletions src/components/ui/MDXTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import React from "react";
import { cn } from "@/lib/utils";

interface MDXTableProps {
children: React.ReactNode;
className?: string;
}

interface MDXTableHeaderProps {
children: React.ReactNode;
className?: string;
}

interface MDXTableBodyProps {
children: React.ReactNode;
className?: string;
}

interface MDXTableRowProps {
children: React.ReactNode;
className?: string;
isFirst?: boolean;
}

interface MDXTableCellProps {
children: React.ReactNode;
className?: string;
isHeader?: boolean;
isFirst?: boolean;
}

export function MDXTable({ children, className }: MDXTableProps) {
return (
<div className="my-4 w-full overflow-x-auto rounded-lg border border-border">
<table className={cn("w-full text-sm border-collapse", className)}>
{children}
</table>
</div>
);
}

export function MDXTableHeader({ children, className }: MDXTableHeaderProps) {
return (
<thead className={cn("border-b border-border bg-muted", className)}>
{children}
</thead>
);
}

export function MDXTableBody({ children, className }: MDXTableBodyProps) {
return (
<tbody className={cn("[&_tr:last-child]:border-0 [&_tr:hover]:bg-muted/50 [&_tr]:transition-colors [&_tr]:border-b", className)}>
{children}
</tbody>
);
}

export function MDXTableRow({ children, className, isFirst }: MDXTableRowProps) {
return (
<tr className={cn(
"border-b border-border transition-colors hover:bg-muted/50",
isFirst && "font-medium text-primary bg-muted/50",
className
)}>
{children}
</tr>
);
}

export function MDXTableCell({ children, className, isHeader, isFirst }: MDXTableCellProps) {
const Component = isHeader ? "th" : "td";

return (
<Component
className={cn(
"px-4 py-3 align-middle",
isFirst && "font-medium text-primary bg-muted/50",
"[&:has([role=checkbox])]:pr-0",
className
)}
>
{children}
</Component>
);
}

export function MDXTableHead({ children, className }: MDXTableCellProps) {
return (
<th className={cn(
"px-4 py-3 text-left font-semibold bg-muted",
className
)}>
{children}
</th>
);
}
4 changes: 2 additions & 2 deletions src/components/ui/TableOfContents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ export function TableOfContents({ items }: TableOfContentsProps) {
>
On This Page
</p>
{items.map((item) => (
{items.map((item, index) => (
<a
key={item.id}
key={`${item.id}-${index}`}
href={`#${item.id}`}
className={cn(
"block py-1 text-sm transition-colors",
Expand Down
27 changes: 22 additions & 5 deletions src/content/getting-started/introduction.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,28 @@ At its core, Xether AI gives you:

## Who Is It For?

| Role | How Xether AI Helps |
| ------------------- | ---------------------------------------------------------------------------- |
| Data Engineers | Build and schedule pipelines without writing boilerplate infrastructure code |
| ML Engineers | Get clean, versioned datasets with full lineage for reproducible training |
| Data Scientists | Explore dataset versions and generate synthetic data for experimentation |
<MDXTable>
<MDXTableHeader>
<MDXTableRow>
<MDXTableHead>Role</MDXTableHead>
<MDXTableHead>How Xether AI Helps</MDXTableHead>
</MDXTableRow>
</MDXTableHeader>
<MDXTableBody>
<MDXTableRow>
<MDXTableCell isFirst>Data Engineers</MDXTableCell>
<MDXTableCell>Build and schedule pipelines without writing boilerplate infrastructure code</MDXTableCell>
</MDXTableRow>
<MDXTableRow>
<MDXTableCell isFirst>ML Engineers</MDXTableCell>
<MDXTableCell>Get clean, versioned datasets with full lineage for reproducible training</MDXTableCell>
</MDXTableRow>
<MDXTableRow>
<MDXTableCell isFirst>Data Scientists</MDXTableCell>
<MDXTableCell>Explore dataset versions and generate synthetic data for experimentation</MDXTableCell>
</MDXTableRow>
</MDXTableBody>
</MDXTable>

## Core Concepts

Expand Down
6 changes: 3 additions & 3 deletions src/hooks/useTableOfContents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ export function useTableOfContents() {
"#main-content h2, #main-content h3"
);

const tocItems: TocItem[] = Array.from(headings).map((heading) => {
const tocItems: TocItem[] = Array.from(headings).map((heading, index) => {
// Ensure heading has an ID
if (!heading.id) {
const id = heading.textContent
const baseId = heading.textContent
?.toLowerCase()
.replace(/[^a-z0-9]+/g, "-")
.replace(/(^-|-$)/g, "") || "";
heading.id = id;
heading.id = `${baseId}-${index}`;
}

return {
Expand Down
Loading