Skip to content

Commit

Permalink
wip fonts and animation experiment
Browse files Browse the repository at this point in the history
  • Loading branch information
mehdibha committed Feb 11, 2025
1 parent 7690969 commit 5c8cea5
Show file tree
Hide file tree
Showing 22 changed files with 2,058 additions and 69 deletions.
5 changes: 1 addition & 4 deletions www/content/docs/components/buttons/button.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@ links:
href: https://github.com/mehdibha/dotUI/tree/main/content/components/buttons/button.mdx?plain=1
---

<ComponentPreview
name="button/default"
preview={`<Button>button</Button>`}
/>
<ComponentPreview name="button/default" preview={`<Button>button</Button>`} />

## Installation

Expand Down
4 changes: 2 additions & 2 deletions www/src/app/(home)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,15 @@ export default function HomePage() {
size="lg"
className="h-10"
>
Get started
Create your library
</Button>
<Button
href="/themes"
variant="outline"
size="lg"
className="bg-bg-inverse/5 h-10"
>
Explore themes
Explore docs
</Button>
</div>
</section>
Expand Down
28 changes: 27 additions & 1 deletion www/src/app/internal/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,31 @@
// "use client";
import React from "react";

// import { FontSelector } from "@/modules/themes/components/font-selector";

export default function Demo() {
return <div>internal</div>;
// const [font, setFont] = React.useState<string | null>(null);

// const content = variableFonts
// .filter((elem) => elem.subsets.includes("latin"))
// .filter((elem) => elem.variants.includes("regular"))
// .filter((elem) => elem.category === "handwriting")
// .map((elem) => elem.family);

// const rawContent = JSON.stringify(content, null, 2);

// const allCategories = variableFonts.map((elem) => elem.category)
// const uniqueCategories = [...new Set(allCategories)]
// console.log(uniqueCategories)

// React.useEffect(() => {
// // copy to clipboard
// navigator.clipboard.writeText(rawContent);
// }, [rawContent]);

return (
<div className="container max-w-xs py-40">
{/* <FontSelector label="Body" font={font} onFontChange={setFont} /> */}
</div>
);
}
1 change: 1 addition & 0 deletions www/src/components/core/command.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "@/registry/core/command_basic";
20 changes: 10 additions & 10 deletions www/src/components/docs/component-preview.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import React from "react";
import { ScrollArea } from "@radix-ui/react-scroll-area";
import {
PaintBucket,
Settings2Icon,
// PaintBucket,
// Settings2Icon,
SlidersHorizontalIcon,
} from "lucide-react";
import { getFileSource } from "@/lib/get-file-source";
import { cn } from "@/lib/utils";
import { Button } from "@/components/core/button";
import { Tooltip } from "@/components/core/tooltip";
// import { Tooltip } from "@/components/core/tooltip";
import { CodeBlock } from "@/components/docs/code-block";
import { Index } from "@/__registry__/demos";
import {
ComponentWrapper,
Loader,
ResizableContainer,
} from "./component-preview-client";
import { StyleSwitcher } from "./style-switcher";
import { ThemeCustomizerDialog } from "./theme-customizer";
// import { StyleSwitcher } from "./style-switcher";
// import { ThemeCustomizerDialog } from "./theme-customizer";
import { ThemeOverride } from "./theme-override";

export interface ComponentPreviewProps {
Expand Down Expand Up @@ -138,8 +138,8 @@ export const ComponentPreview = async ({
);
};

const getComponentName = (name: string) => {
const groupName = name.split("/")[0];
if (groupName === "range-calendar") return "calendar";
return groupName;
};
// const getComponentName = (name: string) => {
// const groupName = name.split("/")[0];
// if (groupName === "range-calendar") return "calendar";
// return groupName;
// };
20 changes: 1 addition & 19 deletions www/src/components/docs/theme-override.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"use client";

import React, { ReactNode } from "react";
import { googleFonts } from "@/lib/fonts";
import { cn } from "@/lib/utils";
import { useThemes } from "@/hooks/use-themes";

Expand All @@ -16,24 +15,7 @@ export const ThemeOverride = React.forwardRef<
HTMLDivElement,
ThemeOverrideProps
>(({ children, ...props }, ref) => {
const { currentTheme, mode, fonts } = useThemes();
const headingFont = googleFonts.find((f) => f.id === fonts.heading);

// fonts
React.useEffect(() => {
if (headingFont) {
const head = document.head;
const existingLink = head.querySelector("#heading-font");
if (existingLink) {
existingLink.remove();
}
const link = document.createElement("link");
link.rel = "stylesheet";
link.href = headingFont.url;
link.id = "heading-font";
head.appendChild(link);
}
}, [headingFont]);
const { currentTheme, mode } = useThemes();

// colors
const currentMode = currentTheme.colors[mode];
Expand Down
2 changes: 1 addition & 1 deletion www/src/components/mobile-nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export const MobileNav = ({
<div className="font-josefin group-data-collapsed/sidebar:opacity-0 mt-[5px] font-bold leading-normal tracking-tighter transition-colors">
{siteConfig.global.name}
</div>
</Link>
</Link>
<Button size="sm" shape="square" onPress={close}>
<PanelLeftCloseIcon />
</Button>
Expand Down
6 changes: 1 addition & 5 deletions www/src/components/search-command.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,7 @@ export function SearchCommand({

return (
<SearchCommandDialog keyboardShortcut={keyboardShortcut} trigger={children}>
<Command
inputValue={search}
onInputChange={setSearch}
className="h-72"
>
<Command inputValue={search} onInputChange={setSearch} className="h-72">
<div className="p-1">
<SearchFieldRoot placeholder="Search" autoFocus className="w-full">
<InputRoot className="focus-within:ring-1">
Expand Down
11 changes: 11 additions & 0 deletions www/src/modules/themes/components/font-loader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export function FontLoader({ font }: { font: string | null | undefined }) {
if (!font) return null;
const googleFontUrl = generateGoogleFontUrl(font);
return <link href={googleFontUrl} rel="stylesheet" />;
}

function generateGoogleFontUrl(font: string) {
const familyName = font.replace(/\s+/g, "+");

return `https://fonts.googleapis.com/css?family=${familyName}`;
}
134 changes: 134 additions & 0 deletions www/src/modules/themes/components/font-selector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
"use client";

import React from "react";
import { ChevronDownIcon } from "lucide-react";
import { useInView } from "motion/react";
import {
UNSTABLE_Virtualizer as Virtualizer,
UNSTABLE_ListLayout as ListLayout,
useFilter,
} from "react-aria-components";
import { cn } from "@/lib/utils";
import { Button } from "@/components/core/button";
import { CommandRoot } from "@/components/core/command";
import { DialogRoot, Dialog } from "@/components/core/dialog";
import {
ListBox,
ListBoxItem,
ListBoxSection,
} from "@/components/core/list-box";
import { SearchField } from "@/components/core/search-field";
import { Select, SelectItem } from "@/components/core/select";
import { FontLoader } from "@/modules/themes/components/font-loader";
import {
sansSerifFonts,
monoFonts,
serifFonts,
displayFonts,
handwritingFonts,
} from "@/modules/themes/lib/google-fonts";

export const FontSelector = ({
label,
font,
onFontChange,
}: {
label: string;
font: string | null;
onFontChange: (font: string | null) => void;
}) => {
const { contains } = useFilter({ sensitivity: "base" });

const layout = React.useMemo(() => {
return new ListLayout({ rowHeight: 32, headingHeight: 20 });
}, []);

return (
<div className="flex flex-col gap-1">
<p className="text-fg-muted text-sm">{label}</p>
<DialogRoot>
<Button variant="outline">
<span className={cn("flex-1 text-left", !font && "text-fg-muted")}>
{font ?? "Select a font"}
</span>
<ChevronDownIcon />
</Button>
<Dialog
type="popover"
popoverProps={{ placement: "bottom" }}
className="p-0! space-y-2"
>
{({ close }) => (
<>
<div className="p-2 pb-0">
<Select selectedKey="featured">
<SelectItem id="featured">Featured fonts</SelectItem>
<SelectItem id="all">All google fonts</SelectItem>
</Select>
</div>
<CommandRoot filter={contains} className="h-72">
<div className="p-2">
<SearchField
placeholder="Search"
autoFocus
className="w-full"
/>
</div>
<Virtualizer layout={layout}>
<ListBox
selectionMode="single"
selectedKeys={font ? [font] : []}
onSelectionChange={(keys) => {
onFontChange(([...keys][0] as string | null) ?? null);
close();
}}
className="p-0! h-full w-full border-0"
>
{[
{ title: "Sans serif", items: sansSerifFonts },
{ title: "Serif", items: serifFonts },
{ title: "Mono", items: monoFonts },
{ title: "Display", items: displayFonts },
{ title: "Handwriting", items: handwritingFonts },
].map(({ title, items }) => (
<ListBoxSection key={title} title={title}>
{items.map((font) => (
<ListBoxItem
key={font}
id={font.trim().toLowerCase()}
textValue={font}
className="font-body"
style={
{
"--font-body": font,
} as React.CSSProperties
}
>
{font}
<FontLoaderInView font={font} />
</ListBoxItem>
))}
</ListBoxSection>
))}
</ListBox>
</Virtualizer>
</CommandRoot>
</>
)}
</Dialog>
</DialogRoot>
</div>
);
};

const FontLoaderInView = ({ font }: { font: string }) => {
const ref = React.useRef(null);
const inView = useInView(ref);

return (
<>
<span ref={ref} />
{inView && <FontLoader font={font} />}
</>
);
};
18 changes: 13 additions & 5 deletions www/src/modules/themes/components/theme-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { PrimitivesProvider } from "@/modules/themes/contexts/primitives-context
import { VariantsProvider } from "@/modules/themes/contexts/variants-context";
import { createThemeCssVars } from "@/modules/themes/lib/create-theme";
import { Theme } from "@/modules/themes/types";
import { FontLoader } from "./font-loader";

interface ThemeProviderProps
extends Omit<React.ComponentProps<"div">, "children"> {
Expand All @@ -24,6 +25,7 @@ export const ThemeProvider = ({
}: ThemeProviderProps) => {
const { resolvedTheme } = useTheme();
const currentMode = mode ?? (resolvedTheme === "light" ? "light" : "dark");

const cssVars = React.useMemo(() => {
if (!theme || !resolvedTheme) return {};
const themeCssVars = createThemeCssVars(
Expand All @@ -45,12 +47,18 @@ export const ThemeProvider = ({
return (
<VariantsProvider variants={theme?.variants}>
<PrimitivesProvider primitives={theme?.primitives}>
<FontLoader font={theme?.fonts?.heading} />
<FontLoader font={theme?.fonts?.body} />
<div
style={{
...cssVars,
...style,
}}
className={cn("bg-bg text-fg isolate", className)}
style={
{
...cssVars,
...style,
"--font-heading": theme?.fonts?.heading,
"--font-body": theme?.fonts?.body,
} as React.CSSProperties
}
className={cn("bg-bg text-fg font-body isolate", className)}
suppressHydrationWarning
{...props}
>
Expand Down
Loading

0 comments on commit 5c8cea5

Please sign in to comment.