Skip to content
Closed

Dev #39

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
8 changes: 8 additions & 0 deletions .githooks/pre-push
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/sh
# Runs lint before every push. CI re-checks this, so it can't be skipped
# for real; bypass locally in an emergency with `git push --no-verify`.
echo "› pre-push: running pnpm lint"
pnpm lint || {
echo "✗ lint failed — push aborted. Fix issues or bypass with --no-verify."
exit 1
}
3 changes: 3 additions & 0 deletions .github/workflows/build-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ jobs:
- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Lint
run: pnpm lint

- name: Typecheck
run: pnpm typecheck

Expand Down
1 change: 0 additions & 1 deletion app/icons/[library]/[name]/opengraph-image.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,6 @@ export default async function OGImage({
}}
>
{logoDataUrl ? (
// eslint-disable-next-line @next/next/no-img-element
<img
src={logoDataUrl}
width={44}
Expand Down
6 changes: 2 additions & 4 deletions app/icons/_components/docs/CodeBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,10 @@ const CodeBlock = async ({ code, lang = "tsx", title }: Props) => {
});

return (
<div className="group/code bg-surface relative my-6 overflow-hidden rounded-xl shadow-lg shadow-black/20 ring-1 ring-white/10">
<div className="group/code bg-surface relative my-6 overflow-hidden rounded-xl shadow-lg ring-1 shadow-black/20 ring-white/10">
{title ? (
<div className="flex items-center justify-between border-b border-white/[0.08] bg-white/[0.03] py-2 pr-2 pl-4">
<span className="text-textSecondary font-mono text-xs">
{title}
</span>
<span className="text-textSecondary font-mono text-xs">{title}</span>
<div className="flex items-center gap-1">
<span className="text-textMuted rounded bg-white/6 px-1.5 py-0.5 font-mono text-[0.65rem] tracking-wide uppercase">
{lang}
Expand Down
2 changes: 1 addition & 1 deletion app/icons/_components/docs/CommandTabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const CommandTabs: React.FC<{ title: string; items: CommandItem[] }> = ({
const current = items.find((i) => i.manager === active) ?? items[0];

return (
<div className="group/code bg-surface relative my-6 overflow-hidden rounded-xl shadow-lg shadow-black/20 ring-1 ring-white/10">
<div className="group/code bg-surface relative my-6 overflow-hidden rounded-xl shadow-lg ring-1 shadow-black/20 ring-white/10">
<div className="flex items-center justify-between border-b border-white/[0.08] bg-white/[0.03] px-2">
<div className="flex items-center">
<span className="text-textMuted mr-1 px-2 font-mono text-xs">
Expand Down
9 changes: 5 additions & 4 deletions app/icons/_components/iconlist/IconLibraryEmptyState.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from "react";
import Link from "next/link";

type Props = {};

Expand All @@ -21,19 +22,19 @@ const IconLibraryEmptyState: React.FC<Props> = () => {
</p>

<div className="mt-2 flex gap-3">
<a
<Link
href="/icons/lucide"
className="rounded-md bg-(--cta-bg) px-4 py-2 text-sm font-medium text-(--cta-text) transition hover:opacity-90"
>
Browse Lucide Icons
</a>
</Link>

<a
<Link
href="/icons/huge"
className="border-border bg-surface text-textPrimary hover:bg-surfaceElevated rounded-md border px-4 py-2 text-sm font-medium transition"
>
Browse Huge Icons
</a>
</Link>
</div>
</div>
</main>
Expand Down
34 changes: 7 additions & 27 deletions app/icons/_contexts/DistributionContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,8 @@
* - one provider, one writer, every tile shares the same value
*/

import {
createContext,
useCallback,
useContext,
useEffect,
useMemo,
useState,
} from "react";
import { useStoredPreference } from "@/hooks/useStoredPreference";
import { createContext, useContext, useMemo } from "react";

export type Distribution = "shadcn" | "npm";

Expand All @@ -45,25 +39,11 @@ const DistributionContext = createContext<DistributionContextValue | undefined>(
export const DistributionProvider: React.FC<{ children: React.ReactNode }> = ({
children,
}) => {
const [distribution, setState] = useState<Distribution>("shadcn");

useEffect(() => {
try {
const saved = localStorage.getItem(STORAGE_KEY);
if (isValid(saved)) setState(saved);
} catch {
// localStorage may be unavailable; ignore.
}
}, []);

const setDistribution = useCallback((d: Distribution) => {
setState(d);
try {
localStorage.setItem(STORAGE_KEY, d);
} catch {
// ignore
}
}, []);
const [distribution, setDistribution] = useStoredPreference<Distribution>(
STORAGE_KEY,
"shadcn",
isValid,
);

const value = useMemo(
() => ({ distribution, setDistribution }),
Expand Down
14 changes: 7 additions & 7 deletions app/icons/_contexts/IconSearchContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,17 +81,17 @@ export const IconSearchProvider: React.FC<{
// URL → state: handles back/forward and external links. Only writes
// when the URL drifts from the debounced value (i.e. someone else
// changed it), preventing a feedback loop with the effect above.
// Keyed on the serialized URL so typing (which only moves `query`)
// never re-triggers it; adjusted during render instead of in an effect.
const searchParamsKey = searchParams?.toString() ?? "";
useEffect(() => {
if (!searchParams) return;
const urlQuery = searchParams.get(QUERY_PARAM) ?? "";
const [prevKey, setPrevKey] = useState(searchParamsKey);
if (searchParamsKey !== prevKey) {
setPrevKey(searchParamsKey);
const urlQuery = searchParams?.get(QUERY_PARAM) ?? "";
if (urlQuery !== debouncedQuery && urlQuery !== query) {
setQuery(urlQuery);
}
// Depend on the serialized URL, not `query` - `query` would re-trigger
// on every keystroke and cause a flicker.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [searchParamsKey]);
}

const inputValue = useMemo(() => ({ query, setQuery }), [query]);
const resultValue = useMemo(() => ({ debouncedQuery }), [debouncedQuery]);
Expand Down
31 changes: 4 additions & 27 deletions app/icons/_contexts/PackageManagerContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,8 @@
* tiles consume the same context value.
*/

import {
createContext,
useCallback,
useContext,
useEffect,
useMemo,
useState,
} from "react";
import { useStoredPreference } from "@/hooks/useStoredPreference";
import { createContext, useContext, useMemo } from "react";

export type PackageManager = "npm" | "pnpm" | "bun";

Expand All @@ -47,25 +41,8 @@ const PackageManagerContext = createContext<
export const PackageManagerProvider: React.FC<{
children: React.ReactNode;
}> = ({ children }) => {
const [packageManager, setState] = useState<PackageManager>("npm");

useEffect(() => {
try {
const saved = localStorage.getItem(STORAGE_KEY);
if (isValid(saved)) setState(saved);
} catch {
// localStorage may be unavailable (SSR-mismatch, privacy mode); ignore.
}
}, []);

const setPackageManager = useCallback((pm: PackageManager) => {
setState(pm);
try {
localStorage.setItem(STORAGE_KEY, pm);
} catch {
// ignore write failures
}
}, []);
const [packageManager, setPackageManager] =
useStoredPreference<PackageManager>(STORAGE_KEY, "npm", isValid);

const value = useMemo(
() => ({ packageManager, setPackageManager }),
Expand Down
15 changes: 15 additions & 0 deletions app/icons/docs/_components/Badge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { ReactNode } from "react";

/**
* Small inline pill for MDX (e.g. "Recommended"). Rendered as a component so
* MDX never re-parses its text into a block <p>. The `[&_p]` guard flattens
* any <p> the production MDX build still injects, so it stays a tight inline
* pill in both the Turbopack dev server and the webpack production build.
*/
const Badge: React.FC<{ children: ReactNode }> = ({ children }) => (
<span className="mr-2 inline-block rounded-full border border-emerald-500/30 bg-emerald-500/10 px-2.5 py-0.5 align-middle text-xs font-semibold text-emerald-400 [&_p]:m-0! [&_p]:inline [&_p]:leading-none [&_p]:text-inherit">
{children}
</span>
);

export default Badge;
9 changes: 2 additions & 7 deletions app/icons/docs/_components/Callout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,9 @@ export function Callout({
const s = styles[type];
const Icon = s.icon;
return (
<div
className={cn(
"my-6 flex gap-3 rounded-lg border p-4 text-sm",
s.box,
)}
>
<div className={cn("my-6 flex gap-3 rounded-lg border p-4 text-sm", s.box)}>
<Icon className={cn("mt-0.5 size-4.5 shrink-0", s.icon_)} />
<div className="text-textSecondary leading-7 [&>:first-child]:mt-0 [&>:last-child]:mb-0 [&>p]:my-0">
<div className="text-textSecondary leading-7 [&_p]:my-0! [&>:first-child]:mt-0 [&>:last-child]:mb-0">
{children}
</div>
</div>
Expand Down
3 changes: 2 additions & 1 deletion app/icons/docs/_components/DocsHelp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ const DocsHelp = () => (
<div>
<p className="text-textPrimary text-sm font-semibold">Need a hand?</p>
<p className="text-textMuted mt-1 text-sm">
Open an issue on GitHub or reach out on Twitter, we're happy to help.
Open an issue on GitHub or reach out on Twitter, we&apos;re happy to
help.
</p>
</div>
<div className="flex shrink-0 gap-2">
Expand Down
7 changes: 2 additions & 5 deletions app/icons/docs/_components/DocsNavbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,13 @@ const DocsNavbar = async () => {
>
Icons
</Link>
<Link
href="/icons/docs"
className="text-textPrimary font-medium"
>
<Link href="/icons/docs" className="text-textPrimary font-medium">
Docs
</Link>
</nav>
</div>

<div className="flex items-center gap-2 sm:gap-3">
<div className="flex items-center gap-2 sm:gap-3">
<NavbarActions stars={stars} />
</div>
</div>
Expand Down
8 changes: 6 additions & 2 deletions app/icons/docs/_components/DocsPager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,16 @@ const PagerCard: React.FC<{
}> = ({ page, dir, fallback }) => (
<Link
href={page.href}
className={cn(cardClass, dir === "prev" ? "items-start" : "items-end text-right")}
className={cn(
cardClass,
dir === "prev" ? "items-start" : "items-end text-right",
)}
>
<span className="text-textMuted flex items-center gap-1 text-xs">
{dir === "prev" ? (
<>
<ChevronLeft className="size-3.5" /> {fallback ? "Explore" : "Previous"}
<ChevronLeft className="size-3.5" />{" "}
{fallback ? "Explore" : "Previous"}
</>
) : (
<>
Expand Down
4 changes: 1 addition & 3 deletions app/icons/docs/_components/ExampleDemos.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,7 @@ export function BannerDemo() {
size={18}
className="shrink-0 text-emerald-400"
/>
<p className="text-textPrimary text-sm">
Your changes have been saved.
</p>
<p className="text-textPrimary text-sm">Your changes have been saved.</p>
</div>
);
}
Expand Down
Loading
Loading