mirror of
https://github.com/zoriya/v10.git
synced 2026-08-16 02:45:09 +00:00
feat(site): film grain (#150)
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
import clsx from 'clsx';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
import texture from './texture.svg?raw';
|
||||
|
||||
const textureUrl = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(texture)}`;
|
||||
|
||||
interface Props {
|
||||
currentPath: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export default function FilmGrain({ currentPath, className }: Props) {
|
||||
return (
|
||||
<div
|
||||
className={twMerge(
|
||||
clsx(
|
||||
'absolute w-full h-full top-0 left-0 pointer-events-none mix-blend-overlay z-10',
|
||||
currentPath.startsWith('/docs') ? 'opacity-70 dark:opacity-50' : 'opacity-70 dark:opacity-60',
|
||||
),
|
||||
className,
|
||||
)}
|
||||
style={{
|
||||
backgroundImage: `url("${textureUrl}")`,
|
||||
backgroundPosition: `0% 0%`,
|
||||
backgroundRepeat: `repeat`,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from './FilmGrain';
|
||||
@@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="600" height="600">
|
||||
<filter id="a" x="0%" y="0%" width="100%" height="100%">
|
||||
<feTurbulence baseFrequency=".5" stitchTiles="stitch" result="noise" />
|
||||
<feColorMatrix in="noise" type="saturate" values="0" result="grayscaleNoise" />
|
||||
</filter>
|
||||
<rect width="100%" height="100%" filter="url(#a)" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 359 B |
@@ -2,6 +2,7 @@ import { Dialog } from '@base-ui-components/react/dialog';
|
||||
import clsx from 'clsx';
|
||||
import { ArrowUpRight, Menu, X } from 'lucide-react';
|
||||
import { DISCORD_INVITE_URL, GITHUB_REPO_URL } from '@/consts';
|
||||
import FilmGrain from '../FilmGrain';
|
||||
|
||||
interface NavLink {
|
||||
href: string;
|
||||
@@ -32,6 +33,7 @@ export default function MobileNav({ navLinks, currentPath, dark = false, childre
|
||||
<Dialog.Portal>
|
||||
{/* Popup container */}
|
||||
<Dialog.Popup className={clsx('fixed inset-0 z-50 flex flex-col', dark ? 'bg-dark-100 text-light-100' : 'bg-light-80 dark:bg-dark-100 text-dark-100 dark:text-light-100')}>
|
||||
<FilmGrain currentPath={currentPath} />
|
||||
{/* Header with close button */}
|
||||
<div
|
||||
className={clsx(
|
||||
@@ -41,14 +43,16 @@ export default function MobileNav({ navLinks, currentPath, dark = false, childre
|
||||
style={{ height: 'var(--nav-h)' }}
|
||||
>
|
||||
<Dialog.Title className="sr-only">Navigation</Dialog.Title>
|
||||
<p className="text-h5 px-3">Video.js</p>
|
||||
<p className="text-h5 px-3">Video.js v10</p>
|
||||
<Dialog.Close className={clsx('flex items-center justify-center p-3 h-full aspect-square', dark ? 'bg-light-80 text-dark-100 intent:bg-light-40' : 'bg-dark-100 text-light-80 intent:bg-dark-80 dark:bg-light-80 dark:text-dark-100 dark:intent:bg-light-40')} aria-label="Close navigation menu">
|
||||
<X size={24} />
|
||||
</Dialog.Close>
|
||||
</div>
|
||||
|
||||
{/* Children */}
|
||||
{children ? <div className={clsx('border-b', dark ? 'border-dark-80' : 'border-light-40 dark:border-dark-80')}>{children}</div> : null}
|
||||
{/* Astro makes it hard to know if we have children, so, we use -mt-px to hide the border-b if we don't */}
|
||||
<div className={clsx('-mt-px border-b', dark ? 'border-dark-80' : 'border-light-40 dark:border-dark-80')}>
|
||||
{children}
|
||||
</div>
|
||||
|
||||
{/* Navigation links */}
|
||||
<nav className="flex flex-col py-3">
|
||||
|
||||
@@ -4,6 +4,7 @@ import MobileNav from './MobileNav';
|
||||
import { ArrowUpRight } from 'lucide-react';
|
||||
import Discord from '@/components/icons/Discord';
|
||||
import GitHub from '@/components/icons/GitHub';
|
||||
import FilmGrain from '../FilmGrain';
|
||||
|
||||
export interface Props {
|
||||
dark?: boolean;
|
||||
@@ -35,10 +36,12 @@ const { class: className, dark = false } = Astro.props;
|
||||
]}
|
||||
style="height: var(--nav-h);"
|
||||
>
|
||||
<!-- Logo -->
|
||||
{/* Grain */}
|
||||
<FilmGrain currentPath={Astro.url.pathname} />
|
||||
{/* Logo */}
|
||||
<a href="/" class="flex items-center px-3 text-h5">Video.js v10</a>
|
||||
|
||||
<!-- Desktop nav links -->
|
||||
{/* Desktop nav links */}
|
||||
<div class="hidden sm:flex -mb-px pr-3">
|
||||
{
|
||||
navLinks.map((link) => (
|
||||
@@ -76,7 +79,7 @@ const { class: className, dark = false } = Astro.props;
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Mobile nav -->
|
||||
{/* Mobile nav */}
|
||||
<MobileNav client:load navLinks={navLinks} currentPath={currentPath} dark={dark}>
|
||||
<slot name="mobile-nav" />
|
||||
</MobileNav>
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { SupportedFramework, SupportedStyle } from '@/types/docs';
|
||||
import { PreferenceUpdater } from '@/components/docs/PreferenceUpdater';
|
||||
import SidebarItem from '@/components/docs/SidebarItem.astro';
|
||||
import { filterSidebar } from '@/utils/docs/sidebar';
|
||||
import FilmGrain from '../FilmGrain';
|
||||
|
||||
type Props<F extends SupportedFramework = SupportedFramework> = {
|
||||
framework: F;
|
||||
@@ -15,8 +16,14 @@ const { framework, style, docTitles } = Astro.props;
|
||||
const filteredSidebar = filterSidebar(framework, style);
|
||||
---
|
||||
|
||||
<slot />
|
||||
<PreferenceUpdater client:idle currentFramework={framework} currentStyle={style} />
|
||||
<nav class="p-6 text-dark-80 dark:text-light-40">
|
||||
{filteredSidebar.map((item) => <SidebarItem item={item} framework={framework} style={style} docTitles={docTitles} />)}
|
||||
</nav>
|
||||
<div class="bg-light-80 dark:bg-dark-100">
|
||||
<slot />
|
||||
<PreferenceUpdater client:idle currentFramework={framework} currentStyle={style} />
|
||||
<nav class="p-6">
|
||||
{
|
||||
filteredSidebar.map((item) => (
|
||||
<SidebarItem item={item} framework={framework} style={style} docTitles={docTitles} />
|
||||
))
|
||||
}
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
@@ -7,6 +7,7 @@ import { SITE_TITLE } from '@/consts';
|
||||
|
||||
import '@/styles/globals.css';
|
||||
|
||||
import FilmGrain from '@/components/FilmGrain';
|
||||
import Posthog from '@/components/Posthog.astro';
|
||||
import ThemeInit from '@/components/ThemeInit.astro';
|
||||
|
||||
@@ -18,6 +19,7 @@ interface Props {
|
||||
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
|
||||
|
||||
const { title, description, image } = Astro.props;
|
||||
|
||||
const fullTitle = Array.isArray(title)
|
||||
? title.filter((t) => t !== SITE_TITLE).join(' | ') + ` | ${SITE_TITLE}`
|
||||
: title === SITE_TITLE
|
||||
@@ -78,15 +80,21 @@ const fullTitle = Array.isArray(title)
|
||||
<body
|
||||
class:list={[
|
||||
'relative',
|
||||
'bg-light-80 dark:bg-dark-100 text-dark-100 dark:text-light-100',
|
||||
'font-sans antialiased text-pretty text-base',
|
||||
'font-sans antialiased text-pretty text-base text-dark-100 dark:text-light-100',
|
||||
'min-w-80',
|
||||
'[--nav-h:calc(var(--spacing)*13)] sm:[--nav-h:calc(var(--spacing)*14)]',
|
||||
'selection:bg-yellow selection:text-dark-100',
|
||||
]}
|
||||
>
|
||||
{/* BaseUI requires body.relative and div.isolate */}
|
||||
<div class="isolate">
|
||||
<div
|
||||
class:list={[
|
||||
// BaseUI requires body.relative and div.isolate
|
||||
'isolate',
|
||||
// background colors are applied here for a more consistent FilmGrain blending
|
||||
'bg-light-80 dark:bg-dark-100',
|
||||
]}
|
||||
>
|
||||
<FilmGrain currentPath={Astro.url.pathname} />
|
||||
<slot />
|
||||
</div>
|
||||
</body>
|
||||
|
||||
@@ -11,6 +11,7 @@ import Base from './Base.astro';
|
||||
import { Selectors } from '@/components/docs/Selectors';
|
||||
import { getDocTitle } from '@/utils/docs/title';
|
||||
import FooterEasterEgg from '@/components/FooterEasterEgg.astro';
|
||||
import FilmGrain from '@/components/FilmGrain';
|
||||
|
||||
type Props<F extends SupportedFramework = SupportedFramework> = {
|
||||
doc: CollectionEntry<'docs'>;
|
||||
@@ -36,9 +37,10 @@ const docTitles = new Map(allDocs.map((d) => [d.id, getDocTitle(d, framework)]))
|
||||
<DocsSidebar slot="mobile-nav" framework={framework} style={style} docTitles={docTitles} />
|
||||
</NavBar>
|
||||
<aside
|
||||
class="hidden lg:block lg:border-r border-light-40 dark:border-dark-80 sticky overflow-y-scroll"
|
||||
class="hidden lg:block lg:border-r border-light-40 dark:border-dark-80 z-10 sticky overflow-y-scroll"
|
||||
style="top: var(--nav-h); max-height: calc(100vh - var(--nav-h));"
|
||||
>
|
||||
<FilmGrain currentPath={Astro.url.pathname} />
|
||||
<DocsSidebar framework={framework} style={style} docTitles={docTitles}>
|
||||
<Selectors client:load currentFramework={framework} currentStyle={style} currentSlug={slug} />
|
||||
</DocsSidebar>
|
||||
|
||||
Reference in New Issue
Block a user