enzostvs HF staff commited on
Commit
900e2e7
1 Parent(s): a2f4024

add dark theme

Browse files
app/layout.tsx CHANGED
@@ -1,5 +1,6 @@
1
  import type { Metadata } from "next";
2
  import { Inter } from "next/font/google";
 
3
  import "@/assets/globals.css";
4
 
5
  const inter = Inter({ subsets: ["latin"] });
@@ -15,7 +16,9 @@ export default function RootLayout({
15
  }>) {
16
  return (
17
  <html lang="en">
18
- <body className={inter.className}>{children}</body>
 
 
19
  </html>
20
  );
21
  }
 
1
  import type { Metadata } from "next";
2
  import { Inter } from "next/font/google";
3
+ import { ThemeProvider } from "next-themes";
4
  import "@/assets/globals.css";
5
 
6
  const inter = Inter({ subsets: ["latin"] });
 
16
  }>) {
17
  return (
18
  <html lang="en">
19
+ <body className={inter.className}>
20
+ <ThemeProvider attribute="class">{children}</ThemeProvider>
21
+ </body>
22
  </html>
23
  );
24
  }
app/page.tsx CHANGED
@@ -1,7 +1,6 @@
1
  import { fetchAllPages } from "@/utils";
2
  import { SpaceProps } from "@/utils/type";
3
  import { Spaces } from "@/components/spaces";
4
- import { Suspense } from "react";
5
 
6
  export const revalidate = 120;
7
 
 
1
  import { fetchAllPages } from "@/utils";
2
  import { SpaceProps } from "@/utils/type";
3
  import { Spaces } from "@/components/spaces";
 
4
 
5
  export const revalidate = 120;
6
 
assets/globals.css CHANGED
@@ -3,7 +3,7 @@
3
  @tailwind utilities;
4
 
5
  body {
6
- @apply bg-gray-100 overflow-hidden;
7
  }
8
 
9
  @layer utilities {
 
3
  @tailwind utilities;
4
 
5
  body {
6
+ @apply bg-gray-100 overflow-hidden dark:bg-slate-950;
7
  }
8
 
9
  @layer utilities {
components/sort.tsx CHANGED
@@ -8,12 +8,13 @@ interface Props {
8
  }
9
  export const Sort = ({ value, onChange }: Props) => {
10
  return (
11
- <div className="flex items-center justify-center border-[3px] rounded-full border-gray-50 drop-shadow-sm bg-gray-100 ring-[1px] ring-gray-200 gap-1">
12
  <button
13
  className={classNames(
14
- "rounded-full pl-3 pr-4 py-2.5 transition-all duration-200 font-semibold text-xs hover:bg-gray-200/70 flex items-center justify-center gap-2",
15
  {
16
- "bg-black hover:!bg-black text-white": value === "likes",
 
17
  }
18
  )}
19
  onClick={() => onChange("likes")}
@@ -23,9 +24,10 @@ export const Sort = ({ value, onChange }: Props) => {
23
  </button>
24
  <button
25
  className={classNames(
26
- "rounded-full pl-3 pr-4 py-2.5 transition-all duration-200 font-semibold text-xs hover:bg-gray-200/70 flex items-center justify-center gap-2",
27
  {
28
- "bg-black hover:!bg-black text-white": value === "createdAt",
 
29
  }
30
  )}
31
  onClick={() => onChange("createdAt")}
 
8
  }
9
  export const Sort = ({ value, onChange }: Props) => {
10
  return (
11
+ <div className="flex items-center justify-center border-[3px] rounded-full border-gray-50 drop-shadow-sm bg-gray-100 dark:bg-slate-900 dark:border-slate-800 ring-[1px] ring-gray-200 dark:ring-slate-700 gap-1">
12
  <button
13
  className={classNames(
14
+ "rounded-full pl-3 pr-4 py-2.5 transition-all duration-200 font-semibold text-xs hover:bg-gray-200/70 dark:hover:bg-gray-700/70 flex items-center justify-center gap-2",
15
  {
16
+ "bg-black hover:!bg-black dark:bg-slate-950 dark:hover:!bg-slate-950 text-white":
17
+ value === "likes",
18
  }
19
  )}
20
  onClick={() => onChange("likes")}
 
24
  </button>
25
  <button
26
  className={classNames(
27
+ "rounded-full pl-3 pr-4 py-2.5 transition-all duration-200 font-semibold text-xs hover:bg-gray-200/70 dark:hover:bg-gray-700/70 flex items-center justify-center gap-2",
28
  {
29
+ "bg-black hover:!bg-black dark:bg-slate-950 dark:hover:!bg-slate-950 text-white":
30
+ value === "createdAt",
31
  }
32
  )}
33
  onClick={() => onChange("createdAt")}
components/spaces/details.tsx CHANGED
@@ -29,8 +29,8 @@ export const Details: React.FC<{ space: SpaceProps }> = ({ space }) => {
29
  }, [space]);
30
 
31
  return (
32
- <div className="border border-gray-200 shadow-md bg-white p-4 rounded-lg absolute -bottom-2 translate-y-full left-0 z-[99999]">
33
- <p className="text-sm text-gray-600 flex items-center justify-start gap-1 font-medium">
34
  This Space is currently using{" "}
35
  <span className="border border-emerald-200 bg-emerald-50 font-medium text-emerald-500 flex items-center justify-center gap-1 max-w-max rounded-md px-1 py-0.5 text-xs">
36
  {gpuNumber} <GpuIcon />
 
29
  }, [space]);
30
 
31
  return (
32
+ <div className="border border-gray-200 shadow-md bg-white dark:bg-slate-900 dark:border-slate-800 p-4 rounded-lg absolute -bottom-2 translate-y-full left-0 z-[99999]">
33
+ <p className="text-sm text-gray-600 dark:text-slate-500 flex items-center justify-start gap-1 font-medium">
34
  This Space is currently using{" "}
35
  <span className="border border-emerald-200 bg-emerald-50 font-medium text-emerald-500 flex items-center justify-center gap-1 max-w-max rounded-md px-1 py-0.5 text-xs">
36
  {gpuNumber} <GpuIcon />
components/spaces/index.tsx CHANGED
@@ -1,7 +1,9 @@
1
  "use client";
2
- import { useState } from "react";
3
- import { useUpdateEffect } from "react-use";
4
  import { useRouter } from "next/navigation";
 
 
5
 
6
  import { SpaceProps } from "@/utils/type";
7
  import { SpaceIcon } from "@/components/space_icon";
@@ -10,10 +12,12 @@ import { Space } from "@/components/spaces/space";
10
  import { Sort } from "@/components/sort";
11
 
12
  export const Spaces: React.FC<{ spaces: SpaceProps[] }> = ({ spaces }) => {
 
 
 
13
  const [selectedGpu, setSelectedGpu] = useState<string | undefined>(undefined);
14
  const router = useRouter();
15
  const [sort, setSort] = useState<"likes" | "createdAt">("likes");
16
- const [elementsInView, setElementsInView] = useState<string[]>([]);
17
 
18
  useUpdateEffect(() => {
19
  router.push("/?sort=" + sort);
@@ -32,14 +36,28 @@ export const Spaces: React.FC<{ spaces: SpaceProps[] }> = ({ spaces }) => {
32
  <div className="w-full container px-6 py-10 lg:py-20 mx-auto space-y-10 lg:space-y-14">
33
  <header className="max-w-5xl mx-auto w-full max-lg:flex-col items-start flex lg:items-end lg:justify-between gap-4">
34
  <div>
35
- <div className="mb-6 font-regular text-xs text-center max-w-max rounded-full border-gray-200 bg-gray-50 border text-gray-700 px-3 py-2 transition-all duration-300">
36
- <SpaceIcon className="inline-block w-4 h-4 mr-2 drop-shadow-lg" />
37
- Browse {spaces.length} spaces
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  </div>
39
- <h1 className="font-extrabold text-3xl text-black">
40
  Zero GPU Spaces
41
  </h1>
42
- <p className="text-neutral-500 font-regular text-base">
43
  Discover spaces with zero GPU usage on 🤗 Hugging Face Spaces.
44
  </p>
45
  </div>
 
1
  "use client";
2
+ import { useEffect, useState } from "react";
3
+ import { useLocalStorage, useUpdateEffect } from "react-use";
4
  import { useRouter } from "next/navigation";
5
+ import { useTheme } from "next-themes";
6
+ import { MdDarkMode, MdLightMode } from "react-icons/md";
7
 
8
  import { SpaceProps } from "@/utils/type";
9
  import { SpaceIcon } from "@/components/space_icon";
 
12
  import { Sort } from "@/components/sort";
13
 
14
  export const Spaces: React.FC<{ spaces: SpaceProps[] }> = ({ spaces }) => {
15
+ const { systemTheme, theme, setTheme } = useTheme();
16
+ const currentTheme = theme === "system" ? systemTheme : theme;
17
+
18
  const [selectedGpu, setSelectedGpu] = useState<string | undefined>(undefined);
19
  const router = useRouter();
20
  const [sort, setSort] = useState<"likes" | "createdAt">("likes");
 
21
 
22
  useUpdateEffect(() => {
23
  router.push("/?sort=" + sort);
 
36
  <div className="w-full container px-6 py-10 lg:py-20 mx-auto space-y-10 lg:space-y-14">
37
  <header className="max-w-5xl mx-auto w-full max-lg:flex-col items-start flex lg:items-end lg:justify-between gap-4">
38
  <div>
39
+ <div className="mb-6 flex items-center justify-start gap-2.5">
40
+ <button
41
+ className="flex items-center justify-center w-9 h-9 rounded-full border border-gray-200 bg-gray-50 dark:bg-slate-900 dark:border-slate-800 transition-all duration-200 hover:brightness-125"
42
+ onClick={() =>
43
+ theme == "dark" ? setTheme("light") : setTheme("dark")
44
+ }
45
+ >
46
+ {theme === "light" ? (
47
+ <MdDarkMode className="w-6 h-6 text-purple-600" />
48
+ ) : (
49
+ <MdLightMode className="w-6 h-6 text-amber-500" />
50
+ )}
51
+ </button>
52
+ <div className="font-regular text-xs text-center max-w-max rounded-full border-gray-200 bg-gray-50 border text-gray-700 dark:text-slate-400 dark:bg-slate-900 dark:border-slate-800 px-3 py-2 transition-all duration-300">
53
+ <SpaceIcon className="inline-block w-4 h-4 mr-2 drop-shadow-lg" />
54
+ Browse {spaces.length} spaces
55
+ </div>
56
  </div>
57
+ <h1 className="font-extrabold text-3xl text-black dark:text-slate-100">
58
  Zero GPU Spaces
59
  </h1>
60
+ <p className="text-neutral-500 font-regular text-base dark:text-slate-300">
61
  Discover spaces with zero GPU usage on 🤗 Hugging Face Spaces.
62
  </p>
63
  </div>
components/spaces/space.tsx CHANGED
@@ -1,8 +1,6 @@
1
  import Link from "next/link";
2
  import Image from "next/image";
3
  import { TiHeartFullOutline } from "react-icons/ti";
4
- import { FiChevronRight } from "react-icons/fi";
5
- import classNames from "classnames";
6
 
7
  import { SpaceProps } from "@/utils/type";
8
  import { GpuIcon } from "../gpu_icon";
@@ -18,16 +16,18 @@ export const Space: React.FC<Props> = ({ space, selected, onSelect }) => {
18
  <Link
19
  href={`https://huggingface.co/spaces/${space.id}`}
20
  target="_blank"
21
- className="space relative hover:z-40 bg-gray-50 border border-gray-200 px-6 py-4 rounded-xl transition-all duration-300 hover:-translate-y-1.5 hover:border-amber-400 hover:shadow-xl hover:shadow-black/5 group"
22
  data-space-id={space.id}
23
  onMouseEnter={() => onSelect?.(space.id)}
24
  onMouseLeave={() => onSelect?.(space.id)}
25
  >
26
  <header className="flex items-center justify-between gap-5">
27
  <div>
28
- <h2 className="font-semibold text-black">{space?.title}</h2>
 
 
29
  {space.shortDescription && (
30
- <p className="text-gray-500 text-xs mt-0.5 line-clamp-1">
31
  {space.shortDescription}
32
  </p>
33
  )}
@@ -48,7 +48,7 @@ export const Space: React.FC<Props> = ({ space, selected, onSelect }) => {
48
  className="rounded-full w-4 h-4"
49
  />
50
  <div>
51
- <p className="text-gray-500 text-xs font-regular">
52
  {space.authorData.name}
53
  </p>
54
  </div>
@@ -56,7 +56,7 @@ export const Space: React.FC<Props> = ({ space, selected, onSelect }) => {
56
  </div>
57
  <div className="space-y-3 flex flex-col items-end">
58
  <div
59
- className="rounded-full truncate min-w-[2.5rem] min-h-[2.5rem] max-w-[2.5rem] max-h-[2.5rem] overflow-hidden flex items-center justify-center bg-gradient-to-br from-blue-500 to-red-500 border-[2px] border-white ring-1 ring-gray-200"
60
  style={{
61
  // @ts-ignore
62
  "--tw-gradient-from": `${space.colorFrom} var(--tw-gradient-to-position)`,
 
1
  import Link from "next/link";
2
  import Image from "next/image";
3
  import { TiHeartFullOutline } from "react-icons/ti";
 
 
4
 
5
  import { SpaceProps } from "@/utils/type";
6
  import { GpuIcon } from "../gpu_icon";
 
16
  <Link
17
  href={`https://huggingface.co/spaces/${space.id}`}
18
  target="_blank"
19
+ className="space relative hover:z-40 bg-gray-50 border border-gray-200 dark:bg-slate-900 dark:border-slate-800 px-6 py-4 rounded-xl transition-all duration-300 hover:-translate-y-1.5 hover:border-amber-400 hover:shadow-xl hover:shadow-black/5 group"
20
  data-space-id={space.id}
21
  onMouseEnter={() => onSelect?.(space.id)}
22
  onMouseLeave={() => onSelect?.(space.id)}
23
  >
24
  <header className="flex items-center justify-between gap-5">
25
  <div>
26
+ <h2 className="font-semibold text-black dark:text-slate-100">
27
+ {space?.title}
28
+ </h2>
29
  {space.shortDescription && (
30
+ <p className="text-gray-500 dark:text-slate-400 text-xs mt-0.5 line-clamp-1">
31
  {space.shortDescription}
32
  </p>
33
  )}
 
48
  className="rounded-full w-4 h-4"
49
  />
50
  <div>
51
+ <p className="text-gray-500 dark:text-slate-400 text-xs font-regular">
52
  {space.authorData.name}
53
  </p>
54
  </div>
 
56
  </div>
57
  <div className="space-y-3 flex flex-col items-end">
58
  <div
59
+ className="rounded-full truncate min-w-[2.5rem] min-h-[2.5rem] max-w-[2.5rem] max-h-[2.5rem] overflow-hidden flex items-center justify-center bg-gradient-to-br from-blue-500 to-red-500 border-[2px] border-white ring-1 ring-gray-200 dark:border-slate-900 dark:ring-slate-700"
60
  style={{
61
  // @ts-ignore
62
  "--tw-gradient-from": `${space.colorFrom} var(--tw-gradient-to-position)`,
package-lock.json CHANGED
@@ -10,6 +10,7 @@
10
  "dependencies": {
11
  "classnames": "^2.5.1",
12
  "next": "14.2.3",
 
13
  "react": "^18",
14
  "react-dom": "^18",
15
  "react-icons": "^5.1.0",
@@ -3264,6 +3265,15 @@
3264
  }
3265
  }
3266
  },
 
 
 
 
 
 
 
 
 
3267
  "node_modules/next/node_modules/postcss": {
3268
  "version": "8.4.31",
3269
  "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
 
10
  "dependencies": {
11
  "classnames": "^2.5.1",
12
  "next": "14.2.3",
13
+ "next-themes": "^0.3.0",
14
  "react": "^18",
15
  "react-dom": "^18",
16
  "react-icons": "^5.1.0",
 
3265
  }
3266
  }
3267
  },
3268
+ "node_modules/next-themes": {
3269
+ "version": "0.3.0",
3270
+ "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.3.0.tgz",
3271
+ "integrity": "sha512-/QHIrsYpd6Kfk7xakK4svpDI5mmXP0gfvCoJdGpZQ2TOrQZmsW0QxjaiLn8wbIKjtm4BTSqLoix4lxYYOnLJ/w==",
3272
+ "peerDependencies": {
3273
+ "react": "^16.8 || ^17 || ^18",
3274
+ "react-dom": "^16.8 || ^17 || ^18"
3275
+ }
3276
+ },
3277
  "node_modules/next/node_modules/postcss": {
3278
  "version": "8.4.31",
3279
  "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
package.json CHANGED
@@ -11,6 +11,7 @@
11
  "dependencies": {
12
  "classnames": "^2.5.1",
13
  "next": "14.2.3",
 
14
  "react": "^18",
15
  "react-dom": "^18",
16
  "react-icons": "^5.1.0",
 
11
  "dependencies": {
12
  "classnames": "^2.5.1",
13
  "next": "14.2.3",
14
+ "next-themes": "^0.3.0",
15
  "react": "^18",
16
  "react-dom": "^18",
17
  "react-icons": "^5.1.0",
tailwind.config.ts CHANGED
@@ -1,6 +1,7 @@
1
  import type { Config } from "tailwindcss";
2
 
3
  const config: Config = {
 
4
  content: [
5
  "./pages/**/*.{js,ts,jsx,tsx,mdx}",
6
  "./components/**/*.{js,ts,jsx,tsx,mdx}",
 
1
  import type { Config } from "tailwindcss";
2
 
3
  const config: Config = {
4
+ darkMode: "class",
5
  content: [
6
  "./pages/**/*.{js,ts,jsx,tsx,mdx}",
7
  "./components/**/*.{js,ts,jsx,tsx,mdx}",