add options for layout, theme and color settings

pull/183/head v0.3.45
Ben Phelps 2 years ago
parent 05427253b9
commit 93d5dd88ba

@ -61,6 +61,7 @@ export default function ColorToggle() {
{colors.map((color) => ( {colors.map((color) => (
<button type="button" onClick={() => setColor(color)} key={color}> <button type="button" onClick={() => setColor(color)} key={color}>
<div <div
title={color}
className={classNames( className={classNames(
active === color ? "border-2" : "border-0", active === color ? "border-2" : "border-0",
`rounded-md w-5 h-5 border-black/50 dark:border-white/50 theme-${color} bg-theme-400` `rounded-md w-5 h-5 border-black/50 dark:border-white/50 theme-${color} bg-theme-400`

@ -1,15 +1,18 @@
import classNames from "classnames";
import List from "components/services/list"; import List from "components/services/list";
export default function ServicesGroup({ services }) { export default function ServicesGroup({ services, layout }) {
return ( return (
<div <div
key={services.name} key={services.name}
className="basis-full md:basis-1/2 lg:basis-1/3 xl:basis-1/4 flex-1 p-1" className={classNames(
layout?.style === "row" ? "basis-full" : "basis-full md:basis-1/2 lg:basis-1/3 xl:basis-1/4",
"flex-1 p-1"
)}
> >
<h2 className="text-theme-800 dark:text-theme-300 text-xl font-medium"> <h2 className="text-theme-800 dark:text-theme-300 text-xl font-medium">{services.name}</h2>
{services.name} <List services={services.services} layout={layout} />
</h2>
<List services={services.services} />
</div> </div>
); );
} }

@ -1,8 +1,27 @@
import classNames from "classnames";
import Item from "components/services/item"; import Item from "components/services/item";
export default function List({ services }) { const columnMap = [
"grid-cols-1 md:grid-cols-1 lg:grid-cols-1",
"grid-cols-1 md:grid-cols-1 lg:grid-cols-1",
"grid-cols-1 md:grid-cols-2 lg:grid-cols-2",
"grid-cols-1 md:grid-cols-2 lg:grid-cols-3",
"grid-cols-1 md:grid-cols-2 lg:grid-cols-4",
"grid-cols-1 md:grid-cols-2 lg:grid-cols-5",
"grid-cols-1 md:grid-cols-2 lg:grid-cols-6",
"grid-cols-1 md:grid-cols-2 lg:grid-cols-7",
"grid-cols-1 md:grid-cols-2 lg:grid-cols-8",
];
export default function List({ services, layout }) {
return ( return (
<ul className="mt-3 flex flex-col"> <ul
className={classNames(
layout?.style === "row" ? `grid ${columnMap[layout?.columns]} gap-x-2` : "flex flex-col",
"mt-3"
)}
>
{services.map((service) => ( {services.map((service) => (
<Item key={service.name} service={service} /> <Item key={service.name} service={service} />
))} ))}

@ -6,6 +6,8 @@ import "styles/weather-icons.css";
import "styles/theme.css"; import "styles/theme.css";
import "utils/i18n"; import "utils/i18n";
import { ColorProvider } from "utils/color-context";
import { ThemeProvider } from "utils/theme-context";
function MyApp({ Component, pageProps }) { function MyApp({ Component, pageProps }) {
return ( return (
@ -14,7 +16,11 @@ function MyApp({ Component, pageProps }) {
fetcher: (resource, init) => fetch(resource, init).then((res) => res.json()), fetcher: (resource, init) => fetch(resource, init).then((res) => res.json()),
}} }}
> >
<Component {...pageProps} /> <ColorProvider>
<ThemeProvider>
<Component {...pageProps} />
</ThemeProvider>
</ColorProvider>
</SWRConfig> </SWRConfig>
); );
} }

@ -3,15 +3,15 @@ import useSWR from "swr";
import Head from "next/head"; import Head from "next/head";
import dynamic from "next/dynamic"; import dynamic from "next/dynamic";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useEffect } from "react"; import { useEffect, useContext } from "react";
import ServicesGroup from "components/services/group"; import ServicesGroup from "components/services/group";
import BookmarksGroup from "components/bookmarks/group"; import BookmarksGroup from "components/bookmarks/group";
import Widget from "components/widget"; import Widget from "components/widget";
import Revalidate from "components/revalidate"; import Revalidate from "components/revalidate";
import { getSettings } from "utils/config"; import { getSettings } from "utils/config";
import { ColorProvider } from "utils/color-context"; import { ColorContext } from "utils/color-context";
import { ThemeProvider } from "utils/theme-context"; import { ThemeContext } from "utils/theme-context";
const ThemeToggle = dynamic(() => import("components/theme-toggle"), { const ThemeToggle = dynamic(() => import("components/theme-toggle"), {
ssr: false, ssr: false,
@ -35,6 +35,8 @@ export async function getStaticProps() {
export default function Home({ settings }) { export default function Home({ settings }) {
const { i18n } = useTranslation(); const { i18n } = useTranslation();
const { theme, setTheme } = useContext(ThemeContext);
const { color, setColor } = useContext(ColorContext);
const { data: services } = useSWR("/api/services"); const { data: services } = useSWR("/api/services");
const { data: bookmarks } = useSWR("/api/bookmarks"); const { data: bookmarks } = useSWR("/api/bookmarks");
@ -50,61 +52,67 @@ export default function Home({ settings }) {
if (settings.language) { if (settings.language) {
i18n.changeLanguage(settings.language); i18n.changeLanguage(settings.language);
} }
}, [i18n, settings.language]);
if (settings.theme && theme !== settings.theme) {
setTheme(settings.theme);
}
if (settings.color && color !== settings.color) {
setColor(settings.color);
}
}, [i18n, settings, color, setColor, theme, setTheme]);
return ( return (
<ColorProvider> <>
<ThemeProvider> <Head>
<Head> <title>{settings.title || "Homepage"}</title>
<title>{settings.title || "Homepage"}</title> {settings.base && <base href={settings.base} />}
{settings.base && <base href={settings.base} />} {settings.favicon && <link rel="icon" href={settings.favicon} />}
{settings.favicon && <link rel="icon" href={settings.favicon} />} </Head>
</Head> <div className="fixed w-full h-full m-0 p-0" style={wrappedStyle} />
<div className="fixed w-full h-full m-0 p-0" style={wrappedStyle} /> <div className="relative w-full container m-auto flex flex-col h-screen justify-between">
<div className="relative w-full container m-auto flex flex-col h-screen justify-between"> <div className="flex flex-row flex-wrap m-8 pb-4 mt-10 border-b-2 border-theme-800 dark:border-theme-200 justify-between">
<div className="flex flex-row flex-wrap m-8 pb-4 mt-10 border-b-2 border-theme-800 dark:border-theme-200 justify-between"> {widgets && (
{widgets && ( <>
<> {widgets
.filter((widget) => !rightAlignedWidgets.includes(widget.type))
.map((widget, i) => (
<Widget key={i} widget={widget} />
))}
<div className="ml-4 flex flex-wrap basis-full grow sm:basis-auto justify-between md:justify-end mt-2 md:mt-0">
{widgets {widgets
.filter((widget) => !rightAlignedWidgets.includes(widget.type)) .filter((widget) => rightAlignedWidgets.includes(widget.type))
.map((widget, i) => ( .map((widget, i) => (
<Widget key={i} widget={widget} /> <Widget key={i} widget={widget} />
))} ))}
</div>
<div className="ml-4 flex flex-wrap basis-full grow sm:basis-auto justify-between md:justify-end mt-2 md:mt-0"> </>
{widgets
.filter((widget) => rightAlignedWidgets.includes(widget.type))
.map((widget, i) => (
<Widget key={i} widget={widget} />
))}
</div>
</>
)}
</div>
{services && (
<div className="flex flex-wrap p-8 items-start">
{services.map((group) => (
<ServicesGroup key={group.name} services={group} />
))}
</div>
)} )}
</div>
{bookmarks && ( {services && (
<div className="grow flex flex-wrap pt-0 p-8"> <div className="flex flex-wrap p-8 items-start">
{bookmarks.map((group) => ( {services.map((group) => (
<BookmarksGroup key={group.name} group={group} /> <ServicesGroup key={group.name} services={group} layout={settings.layout?.[group.name]} />
))} ))}
</div> </div>
)} )}
<div className="rounded-full flex p-8 w-full justify-between"> {bookmarks && (
<ColorToggle /> <div className="grow flex flex-wrap pt-0 p-8">
<Revalidate /> {bookmarks.map((group) => (
<ThemeToggle /> <BookmarksGroup key={group.name} group={group} />
))}
</div> </div>
)}
<div className="rounded-full flex p-8 w-full justify-end">
{!settings?.color && <ColorToggle />}
<Revalidate />
{!settings?.theme && <ThemeToggle />}
</div> </div>
</ThemeProvider> </div>
</ColorProvider> </>
); );
} }

Loading…
Cancel
Save