Files
supabase/apps/design-system/registry/default/example/toc-single-demo.tsx
T
Ivan Vasilov 56de26fe22 chore: Migrate the monorepo to use Tailwind v4 (#45318)
This PR migrates the whole monorepo to use Tailwind v4:
- Removed `@tailwindcss/container-queries` plugin since it's included by
default in v4,
- Bump all instances of Tailwind to v4. Made minimal changes to the
shared config to remove non-supported features (`alpha` mentions),
- Migrate all apps to be compatible with v4 configs,
- Fix the `typography.css` import in 3 apps,
- Add missing rules which were included by default in v3,
- Run `pnpm dlx @tailwindcss/upgrade` on all apps, which renames a lot
of classes
- Rename all misnamed classes according to
https://tailwindcss.com/docs/upgrade-guide#renamed-utilities in all
apps.

---------

Co-authored-by: Jordi Enric <jordi.err@gmail.com>
2026-04-30 10:53:24 +00:00

227 lines
7.2 KiB
TypeScript

'use client'
import { createContext, PropsWithChildren, useContext, useEffect, useState } from 'react'
import { AnchorProvider, Toc, TOCItems, TOCScrollArea, type AnchorProviderProps } from 'ui-patterns'
export default function MultiSelectDemo() {
return (
<TocAnchorsProvider>
<div
id="example-toc-single-demo"
className="p-4 md:p-8 grid md:grid-cols-4 gap-4 max-h-[600px] overflow-y-auto"
>
<div className="md:col-span-3">
<div className="prose max-w-none">
<h1>Getting Started with Cloud Computing</h1>
<h2 id="single-introduction">
Introduction
<a
href="#single-introduction"
aria-hidden="true"
className="ml-2 opacity-0 group-hover:opacity-100 transition"
>
<span aria-hidden="true">#</span>
</a>
</h2>
<p>
Cloud computing has revolutionized how we build and deploy applications. This guide
will walk you through the fundamental concepts and best practices.
</p>
<h2 id="single-key-concepts">
Key Concepts
<a
href="#single-key-concepts"
aria-hidden="true"
className="ml-2 opacity-0 group-hover:opacity-100 transition"
>
<span aria-hidden="true">#</span>
</a>
</h2>
<p>
Before diving deep into cloud services, it&apos;s important to understand the basic
building blocks that make cloud computing possible.
</p>
<h3 id="single-iaas">
Infrastructure as a Service (IaaS)
<a
href="#single-iaas"
aria-hidden="true"
className="ml-2 opacity-0 group-hover:opacity-100 transition"
>
<span aria-hidden="true">#</span>
</a>
</h3>
<p>
IaaS provides virtualized computing resources over the internet. This includes virtual
machines, storage, and networking.
</p>
<h3 id="single-paas">
Platform as a Service (PaaS)
<a
href="#single-paas"
aria-hidden="true"
className="ml-2 opacity-0 group-hover:opacity-100 transition"
>
<span aria-hidden="true">#</span>
</a>
</h3>
<p>
PaaS delivers a platform allowing customers to develop, run, and manage applications
without dealing with infrastructure.
</p>
<h2 id="single-best-practices">
Best Practices
<a
href="#single-best-practices"
aria-hidden="true"
className="ml-2 opacity-0 group-hover:opacity-100 transition"
>
<span aria-hidden="true">#</span>
</a>
</h2>
<p>
Following cloud computing best practices ensures optimal performance, security, and
cost-effectiveness.
</p>
<h3 id="single-security">
Security Considerations
<a
href="#single-security"
aria-hidden="true"
className="ml-2 opacity-0 group-hover:opacity-100 transition"
>
<span aria-hidden="true">#</span>
</a>
</h3>
<p>
Security should be your top priority when working with cloud services. Implement
proper authentication, encryption, and access controls.
</p>
<h3 id="single-cost-optimization">
Cost Optimization
<a
href="#single-cost-optimization"
aria-hidden="true"
className="ml-2 opacity-0 group-hover:opacity-100 transition"
>
<span aria-hidden="true">#</span>
</a>
</h3>
<p>
Learn how to optimize your cloud spending through resource planning, monitoring, and
implementing cost-saving strategies.
</p>
<h2 id="single-conclusion">
Conclusion
<a
href="#single-conclusion"
aria-hidden="true"
className="ml-2 opacity-0 group-hover:opacity-100 transition"
>
<span aria-hidden="true">#</span>
</a>
</h2>
<p>
Cloud computing continues to evolve, offering new possibilities for businesses and
developers alike. Stay updated with the latest trends and best practices.
</p>
</div>
</div>
<TocComponent />
</div>
</TocAnchorsProvider>
)
}
const TocComponent = () => {
const { toc } = useTocAnchors()
return (
<Toc className="sticky top-0 border-l">
<h3 className="inline-flex items-center gap-1.5 font-mono text-xs uppercase text-foreground pl-[calc(1.5rem+6px)]">
On this page
</h3>
<TOCScrollArea className="ml-[-2px]">
<TOCItems items={toc} />
</TOCScrollArea>
</Toc>
)
}
interface TOCHeader {
id?: string
text: string
link: string
level: number
}
const TocAnchorsContext = createContext<AnchorProviderProps | undefined>(undefined)
const useTocAnchors = () => {
const context = useContext(TocAnchorsContext)
if (!context) {
throw new Error('useTocAnchors must be used within an TocAnchorsContext')
}
return context
}
const TocAnchorsProvider = ({ children }: PropsWithChildren) => {
const [tocList, setTocList] = useState<TOCHeader[]>([])
const toc = tocList.map((item) => ({
title: item.text,
url: item.link,
depth: item.level,
}))
useEffect(() => {
/**
* Because we're directly querying the DOM, needs the setTimeout so the DOM
* update will happen first.
*/
const timeoutHandle = setTimeout(() => {
const headings = Array.from(
document.querySelector('#example-toc-single-demo')?.querySelectorAll('h2, h3') ?? []
)
const newHeadings = headings
.filter((heading) => heading.id)
.map((heading) => {
const text = heading?.textContent?.replace('#', '')
const link = heading.querySelector('a')?.getAttribute('href')
if (!link) return null
const level = heading.tagName === 'H2' ? 2 : 3
return { text, link, level } as Partial<TOCHeader>
})
.filter((x): x is TOCHeader => !!x && !!x.text && !!x.link && !!x.level)
setTocList(newHeadings)
}, 100)
return () => clearTimeout(timeoutHandle)
/**
* window.location.href needed to recalculate toc when page changes,
* `useSubscribeTocRerender` above will trigger the rerender
*/
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [typeof window !== 'undefined' && window.location.href])
return (
<TocAnchorsContext.Provider value={{ toc }}>
<AnchorProvider toc={toc} single={true}>
{children}
</AnchorProvider>
</TocAnchorsContext.Provider>
)
}