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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ _Become a [Gold Sponsor](https://github.com/sponsors/jbetancur) and your logo go
Thank you to our recurring backers:

- Rich Tillman
- [Simon Schick](https://github.com/SimonSchick)

# Contributors

Expand Down
223 changes: 108 additions & 115 deletions apps/docs/package-lock.json

Large diffs are not rendered by default.

100 changes: 100 additions & 0 deletions apps/docs/src/components/TableOfContents.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
---
// Renders client-side: .astro pages don't expose headings to the build, so the
// list is built from the DOM on load. Existing hand-written ids are preserved.
---

<aside
id="docs-toc"
class="hidden xl:block w-52 shrink-0 sticky top-20 h-[calc(100vh-6rem)] overflow-y-auto"
hidden
>
<p class="text-xs font-semibold uppercase tracking-wider text-gray-400 mb-3">On this page</p>
<ul id="docs-toc-list" class="space-y-1 text-sm border-l border-gray-100"></ul>
</aside>

<script is:inline>
(function () {
var toc = document.getElementById('docs-toc');
var list = document.getElementById('docs-toc-list');
var article = document.querySelector('article');
if (!toc || !list || !article) return;

function slugify(text) {
return text
.trim()
.toLowerCase()
.replace(/[^\w\s-]/g, '')
.replace(/\s+/g, '-')
.replace(/-+/g, '-')
.replace(/^-|-$/g, '');
}

var headings = [].slice.call(article.querySelectorAll('h2, h3'));
if (headings.length < 2) return;

var used = Object.create(null);
var links = [];

headings.forEach(function (heading) {
var id = heading.id;
if (!id) {
var base = slugify(heading.textContent || '') || 'section';
id = base;
var n = 2;
while (used[id] || document.getElementById(id)) {
id = base + '-' + n++;
}
heading.id = id;
}
used[id] = true;

var a = document.createElement('a');
a.href = '#' + id;
a.textContent = heading.textContent || '';
a.className =
'block py-1 pr-2 -ml-px border-l border-transparent text-gray-500 hover:text-gray-900 transition-colors ' +
(heading.tagName === 'H3' ? 'pl-6 text-xs' : 'pl-3');

var li = document.createElement('li');
li.appendChild(a);
list.appendChild(li);
links.push({ id: id, el: a });
});

toc.hidden = false;

var active = null;
function setActive(id) {
if (id === active) return;
active = id;
links.forEach(function (link) {
var on = link.id === id;
link.el.classList.toggle('border-brand-500', on);
link.el.classList.toggle('text-brand-700', on);
link.el.classList.toggle('font-medium', on);
link.el.classList.toggle('border-transparent', !on);
link.el.classList.toggle('text-gray-500', !on);
});
}

// Track which headings are above the viewport top; the last one is current.
var visible = Object.create(null);
var observer = new IntersectionObserver(
function (entries) {
entries.forEach(function (entry) {
visible[entry.target.id] = entry.isIntersecting;
});
for (var i = links.length - 1; i >= 0; i--) {
if (visible[links[i].id]) {
setActive(links[i].id);
return;
}
}
},
{ rootMargin: '-70px 0px -75% 0px' },
);
headings.forEach(function (h) {
observer.observe(h);
});
})();
</script>
5 changes: 4 additions & 1 deletion apps/docs/src/data/backers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,7 @@ export interface Backer {
url?: string;
}

export const backers: Backer[] = [{ name: 'Rich Tillman', url: 'https://opencollective.com/rich-tillman' }];
export const backers: Backer[] = [
{ name: 'Rich Tillman', url: 'https://opencollective.com/rich-tillman' },
{ name: 'Simon Schick', url: 'https://github.com/SimonSchick' },
];
3 changes: 3 additions & 0 deletions apps/docs/src/layouts/DocsLayout.astro
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
import Layout from './Layout.astro';
import Demo from '../components/Demo.astro';
import TableOfContents from '../components/TableOfContents.astro';
import HeadlessDemo from '../components/demos/HeadlessDemo.tsx';

interface Props {
Expand Down Expand Up @@ -293,6 +294,8 @@ function HeadlessTable({ data }: { data: Employee[] }) {
</nav>
)}
</article>

<TableOfContents />
</div>
</Layout>

Expand Down
34 changes: 20 additions & 14 deletions apps/docs/src/pages/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -306,20 +306,26 @@ export default function App() {
</div>

{backers.length > 0 && (
<p class="text-sm text-gray-500 mb-8">
Thank you to our backers for their recurring support:{' '}
{backers.map(({ name, url }, i) => (
<>
{i > 0 && ', '}
{url ? (
<a href={url} target="_blank" rel="noopener noreferrer" class="text-brand-600 hover:text-brand-700 font-medium">{name}</a>
) : (
<span class="text-gray-700 font-medium">{name}</span>
)}
</>
))}
. <a href="/support#backers" class="text-brand-600 hover:text-brand-700 font-medium">See all →</a>
</p>
<div class="mb-8">
<h3 class="text-sm font-semibold text-gray-900 mb-1">Backers</h3>
<p class="text-sm text-gray-500 mb-4">Thank you to our backers for their recurring support.</p>
<ul class="flex flex-wrap items-center justify-center gap-x-6 gap-y-2 text-sm">
{backers.slice(0, 6).map(({ name, url }) => (
<li>
{url ? (
<a href={url} target="_blank" rel="noopener noreferrer" class="text-brand-600 hover:text-brand-700 font-medium">{name}</a>
) : (
<span class="text-gray-700 font-medium">{name}</span>
)}
</li>
))}
</ul>
{backers.length > 6 && (
<p class="text-sm mt-4">
<a href="/support#backers" class="text-brand-600 hover:text-brand-700 font-medium">See all →</a>
</p>
)}
</div>
)}

<div class="flex items-center justify-center gap-4">
Expand Down
6 changes: 3 additions & 3 deletions apps/docs/src/styles/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,10 @@ article td {
@apply px-3 py-2 border border-gray-200 text-gray-600;
}

/* Headings */
/* Headings — scroll-margin clears the sticky 56px header on anchor jumps */
article h1 { @apply text-2xl font-bold text-gray-900 mb-3; }
article h2 { @apply text-lg font-semibold text-gray-900 mt-8 mb-3 pt-4 border-t border-gray-100; }
article h3 { @apply text-base font-semibold text-gray-800 mt-5 mb-2; }
article h2 { @apply text-lg font-semibold text-gray-900 mt-8 mb-3 pt-4 border-t border-gray-100 scroll-mt-20; }
article h3 { @apply text-base font-semibold text-gray-800 mt-5 mb-2 scroll-mt-20; }
article p { @apply text-gray-600 leading-relaxed mb-3; }
article ul { @apply list-disc pl-5 space-y-1 text-gray-600 mb-4; }
article ol { @apply list-decimal pl-5 space-y-1 text-gray-600 mb-4; }
Expand Down