mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-03-18 05:41:44 +01:00
add theme option
This commit is contained in:
parent
184884d5d2
commit
bcc842770a
.changeset
package.jsonsrc
components/embed-event/event-types
providers
services/settings
theme
views/settings
5
.changeset/cuddly-ligers-type.md
Normal file
5
.changeset/cuddly-ligers-type.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"nostrudel": minor
|
||||
---
|
||||
|
||||
Add theme option and better dark theme
|
@ -13,8 +13,10 @@
|
||||
"analyze": "npx vite-bundle-visualizer -o ./stats.html"
|
||||
},
|
||||
"dependencies": {
|
||||
"@chakra-ui/anatomy": "^2.2.1",
|
||||
"@chakra-ui/icons": "^2.1.1",
|
||||
"@chakra-ui/react": "^2.8.1",
|
||||
"@chakra-ui/styled-system": "^2.9.1",
|
||||
"@emotion/react": "^11.11.1",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"@getalby/bitcoin-connect-react": "^1.1.0",
|
||||
@ -22,6 +24,7 @@
|
||||
"@webscopeio/react-textarea-autocomplete": "^4.9.2",
|
||||
"bech32": "^2.0.0",
|
||||
"cheerio": "^1.0.0-rc.12",
|
||||
"chroma-js": "^2.4.2",
|
||||
"dayjs": "^1.11.9",
|
||||
"debug": "^4.3.4",
|
||||
"emojilib": "2",
|
||||
@ -59,6 +62,7 @@
|
||||
"devDependencies": {
|
||||
"@changesets/cli": "^2.26.2",
|
||||
"@testing-library/cypress": "^9.0.0",
|
||||
"@types/chroma-js": "^2.4.1",
|
||||
"@types/debug": "^4.1.8",
|
||||
"@types/identicon.js": "^2.3.1",
|
||||
"@types/leaflet": "^1.9.3",
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { MouseEventHandler, useCallback } from "react";
|
||||
import { Card, CardProps, Flex, LinkBox, LinkOverlay, Spacer } from "@chakra-ui/react";
|
||||
import { Card, CardProps, Flex, LinkBox, LinkOverlay, Spacer, cssVar } from "@chakra-ui/react";
|
||||
import { Link as RouterLink } from "react-router-dom";
|
||||
|
||||
import { NostrEvent } from "../../../types/nostr-event";
|
||||
@ -19,7 +19,7 @@ import styled from "@emotion/styled";
|
||||
|
||||
const HoverLinkOverlay = styled(LinkOverlay)`
|
||||
&:hover:before {
|
||||
background-color: rgba(0, 0, 0, 0.15);
|
||||
background-color: var(--chakra-colors-card-hover-overlay);
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -14,10 +14,10 @@ import MuteModalProvider from "./mute-modal-provider";
|
||||
|
||||
// Top level providers, should be render as close to the root as possible
|
||||
export const GlobalProviders = ({ children }: { children: React.ReactNode }) => {
|
||||
const { primaryColor, maxPageWidth } = useAppSettings();
|
||||
const { theme: themeName, primaryColor, maxPageWidth } = useAppSettings();
|
||||
const theme = useMemo(
|
||||
() => createTheme(primaryColor, maxPageWidth !== "none" ? maxPageWidth : undefined),
|
||||
[primaryColor, maxPageWidth],
|
||||
() => createTheme(themeName, primaryColor, maxPageWidth !== "none" ? maxPageWidth : undefined),
|
||||
[themeName, primaryColor, maxPageWidth],
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -27,17 +27,26 @@ export type AppSettingsV1 = Omit<AppSettingsV0, "version"> & {
|
||||
mutedWords?: string;
|
||||
maxPageWidth: "none" | "md" | "lg" | "xl";
|
||||
};
|
||||
export type AppSettingsV2 = Omit<AppSettingsV1, "version"> & {
|
||||
version: 2;
|
||||
theme: string;
|
||||
};
|
||||
|
||||
export function isV0(settings: { version: number }): settings is AppSettingsV0 {
|
||||
return settings.version === undefined || settings.version === 0;
|
||||
}
|
||||
export function isV1(settings: { version: number }): settings is AppSettingsV1 {
|
||||
return settings.version === 1;
|
||||
}
|
||||
export function isV2(settings: { version: number }): settings is AppSettingsV2 {
|
||||
return settings.version === 2;
|
||||
}
|
||||
|
||||
export type AppSettings = AppSettingsV1;
|
||||
export type AppSettings = AppSettingsV2;
|
||||
|
||||
export const defaultSettings: AppSettings = {
|
||||
version: 1,
|
||||
version: 2,
|
||||
theme: "default",
|
||||
colorMode: "system",
|
||||
maxPageWidth: "none",
|
||||
blurImages: true,
|
||||
@ -59,8 +68,9 @@ export const defaultSettings: AppSettings = {
|
||||
};
|
||||
|
||||
export function upgradeSettings(settings: { version: number }): AppSettings | null {
|
||||
if (isV0(settings)) return { ...settings, version: 1, maxPageWidth: "none" };
|
||||
if (isV1(settings)) return settings;
|
||||
if (isV0(settings)) return { ...settings, version: 2, maxPageWidth: "none", theme: "default" };
|
||||
if (isV1(settings)) return { ...settings, version: 2, theme: "default" };
|
||||
if (isV2(settings)) return settings;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
6
src/theme/helpers.ts
Normal file
6
src/theme/helpers.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export function pallet(colors: string[]) {
|
||||
return [50, 100, 200, 300, 400, 500, 600, 700, 800, 900].reduce(
|
||||
(pallet, key, i) => ({ ...pallet, [key]: colors[i] }),
|
||||
{},
|
||||
);
|
||||
}
|
@ -1,27 +1,43 @@
|
||||
import { extendTheme, Theme, DeepPartial } from "@chakra-ui/react";
|
||||
import { containerTheme } from "./container";
|
||||
import chroma from "chroma-js";
|
||||
|
||||
import midnightTheme from "./midnight";
|
||||
|
||||
function pallet(colors: string[]) {
|
||||
return [50, 100, 200, 300, 400, 500, 600, 700, 800, 900].reduce(
|
||||
(pallet, key, i) => ({ ...pallet, [key]: colors[i] }),
|
||||
{},
|
||||
);
|
||||
}
|
||||
|
||||
function getTheme(name: string) {
|
||||
if (name === "midnight") return midnightTheme;
|
||||
return {};
|
||||
}
|
||||
|
||||
const breakpoints = ["sm", "md", "lg", "xl", "2xl"] as const;
|
||||
|
||||
export default function createTheme(primaryColor: string = "#8DB600", maxBreakpoint?: (typeof breakpoints)[number]) {
|
||||
const theme = extendTheme({
|
||||
export default function createTheme(
|
||||
themeName: string,
|
||||
primaryColor: string = "#8DB600",
|
||||
maxBreakpoint?: (typeof breakpoints)[number],
|
||||
) {
|
||||
const theme = extendTheme(getTheme(themeName), {
|
||||
colors: {
|
||||
primary: {
|
||||
50: primaryColor,
|
||||
100: primaryColor,
|
||||
200: primaryColor,
|
||||
300: primaryColor,
|
||||
400: primaryColor,
|
||||
500: primaryColor,
|
||||
600: primaryColor,
|
||||
700: primaryColor,
|
||||
800: primaryColor,
|
||||
900: primaryColor,
|
||||
},
|
||||
primary: pallet(chroma.scale([chroma(primaryColor).brighten(1), chroma(primaryColor).darken(1)]).colors(10)),
|
||||
},
|
||||
components: {
|
||||
Container: containerTheme,
|
||||
},
|
||||
semanticTokens: {
|
||||
colors: {
|
||||
"card-hover-overlay": {
|
||||
_light: "blackAlpha.100",
|
||||
_dark: "whiteAlpha.100",
|
||||
},
|
||||
},
|
||||
},
|
||||
} as DeepPartial<Theme>);
|
||||
|
||||
// if maxBreakpoint is set, set all breakpoints above it to a large number so they are never reached
|
||||
|
9
src/theme/midnight/components/button.ts
Normal file
9
src/theme/midnight/components/button.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { defineStyleConfig } from "@chakra-ui/styled-system";
|
||||
|
||||
export const buttonTheme = defineStyleConfig({
|
||||
variants: {
|
||||
link: {
|
||||
color: "colors.chakra-body-text",
|
||||
},
|
||||
},
|
||||
});
|
29
src/theme/midnight/components/card.ts
Normal file
29
src/theme/midnight/components/card.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import { cardAnatomy as parts } from "@chakra-ui/anatomy";
|
||||
import { createMultiStyleConfigHelpers, cssVar } from "@chakra-ui/styled-system";
|
||||
|
||||
const { definePartsStyle, defineMultiStyleConfig } = createMultiStyleConfigHelpers(parts.keys);
|
||||
|
||||
const $bg = cssVar("card-bg");
|
||||
const $padding = cssVar("card-padding");
|
||||
const $shadow = cssVar("card-shadow");
|
||||
const $radius = cssVar("card-radius");
|
||||
const $border = cssVar("card-border-width", "0");
|
||||
const $borderColor = cssVar("card-border-color");
|
||||
|
||||
export const cardTheme = defineMultiStyleConfig({
|
||||
baseStyle: {},
|
||||
variants: {
|
||||
elevated: definePartsStyle({
|
||||
container: {
|
||||
_dark: {
|
||||
[$bg.variable]: "colors.chakra-subtle-bg",
|
||||
},
|
||||
},
|
||||
}),
|
||||
filled: definePartsStyle({
|
||||
container: {
|
||||
[$bg.variable]: "colors.chakra-subtle-bg",
|
||||
},
|
||||
}),
|
||||
},
|
||||
});
|
16
src/theme/midnight/components/drawer.ts
Normal file
16
src/theme/midnight/components/drawer.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { drawerAnatomy as parts } from "@chakra-ui/anatomy";
|
||||
import { createMultiStyleConfigHelpers, cssVar, defineStyle } from "@chakra-ui/styled-system";
|
||||
|
||||
const { definePartsStyle, defineMultiStyleConfig } = createMultiStyleConfigHelpers(parts.keys);
|
||||
|
||||
const $bg = cssVar("drawer-bg");
|
||||
|
||||
export const drawerTheme = defineMultiStyleConfig({
|
||||
baseStyle: definePartsStyle({
|
||||
dialog: {
|
||||
_dark: {
|
||||
[$bg.variable]: "colors.gray.800",
|
||||
},
|
||||
},
|
||||
}),
|
||||
});
|
28
src/theme/midnight/index.ts
Normal file
28
src/theme/midnight/index.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import chroma from "chroma-js";
|
||||
import { DeepPartial, Theme, extendTheme } from "@chakra-ui/react";
|
||||
|
||||
import { cardTheme } from "./components/card";
|
||||
import { pallet } from "../helpers";
|
||||
import { buttonTheme } from "./components/button";
|
||||
import { drawerTheme } from "./components/drawer";
|
||||
|
||||
const midnightTheme = extendTheme({
|
||||
colors: {
|
||||
gray: pallet(chroma.scale(["#d5d5d5", "#0e0e0e"]).colors(10)),
|
||||
},
|
||||
components: {
|
||||
Card: cardTheme,
|
||||
Button: buttonTheme,
|
||||
Drawer: drawerTheme,
|
||||
},
|
||||
semanticTokens: {
|
||||
colors: {
|
||||
"chakra-body-text": { _light: "gray.800", _dark: "white" },
|
||||
"chakra-body-bg": { _light: "white", _dark: "gray.900" },
|
||||
"chakra-subtle-bg": { _light: "gray.100", _dark: "gray.800" },
|
||||
"chakra-subtle-text": { _light: "gray.600", _dark: "gray.400" },
|
||||
},
|
||||
},
|
||||
} as DeepPartial<Theme>);
|
||||
|
||||
export default midnightTheme;
|
@ -33,6 +33,15 @@ export default function DisplaySettings() {
|
||||
</h2>
|
||||
<AccordionPanel>
|
||||
<Flex direction="column" gap="4">
|
||||
<FormControl>
|
||||
<FormLabel htmlFor="theme" mb="0">
|
||||
Theme
|
||||
</FormLabel>
|
||||
<Select id="theme" {...register("theme")}>
|
||||
<option value="default">Default</option>
|
||||
<option value="midnight">Midnight</option>
|
||||
</Select>
|
||||
</FormControl>
|
||||
<FormControl>
|
||||
<FormLabel htmlFor="colorMode" mb="0">
|
||||
Color Mode
|
||||
|
14
yarn.lock
14
yarn.lock
@ -998,7 +998,7 @@
|
||||
"@chakra-ui/shared-utils" "2.0.5"
|
||||
"@chakra-ui/spinner" "2.1.0"
|
||||
|
||||
"@chakra-ui/anatomy@2.2.1":
|
||||
"@chakra-ui/anatomy@2.2.1", "@chakra-ui/anatomy@^2.2.1":
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@chakra-ui/anatomy/-/anatomy-2.2.1.tgz#f7ef088dcb8be4f1d075f37101830199fb93f763"
|
||||
integrity sha512-bbmyWTGwQo+aHYDMtLIj7k7hcWvwE7GFVDViLFArrrPhfUTDdQTNqhiDp1N7eh2HLyjNhc2MKXV8s2KTQqkmTg==
|
||||
@ -1640,7 +1640,7 @@
|
||||
"@chakra-ui/react-context" "2.1.0"
|
||||
"@chakra-ui/shared-utils" "2.0.5"
|
||||
|
||||
"@chakra-ui/styled-system@2.9.1":
|
||||
"@chakra-ui/styled-system@2.9.1", "@chakra-ui/styled-system@^2.9.1":
|
||||
version "2.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@chakra-ui/styled-system/-/styled-system-2.9.1.tgz#888a4901b2afa174461259a8875379adb0363934"
|
||||
integrity sha512-jhYKBLxwOPi9/bQt9kqV3ELa/4CjmNNruTyXlPp5M0v0+pDMUngPp48mVLoskm9RKZGE0h1qpvj/jZ3K7c7t8w==
|
||||
@ -2527,6 +2527,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-5.0.2.tgz#6f1225829d89794fd9f891989c9ce667422d7f64"
|
||||
integrity sha512-PHKZuMN+K5qgKIWhBodXzQslTo5P+K/6LqeKXS6O/4liIDdZqaX5RXrCK++LAw+y/nptN48YmUMFiQHRSWYwtQ==
|
||||
|
||||
"@types/chroma-js@^2.4.1":
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/chroma-js/-/chroma-js-2.4.1.tgz#f76bbd7c760c1db18734b9d8f473ced7275a374e"
|
||||
integrity sha512-YIm3RLfWdDU0/3rsNnu/Hh4uKCLQ9p/w1NvnFfBOBL/BGqOvuLNuhXwkJMUKMscmFJdan25lYqv2+qh1l7tZLg==
|
||||
|
||||
"@types/chrome@^0.0.74":
|
||||
version "0.0.74"
|
||||
resolved "https://registry.yarnpkg.com/@types/chrome/-/chrome-0.0.74.tgz#f69827c48fcf7fecc90c96089807661749a5a5e3"
|
||||
@ -3217,6 +3222,11 @@ cheerio@^1.0.0-rc.12:
|
||||
parse5 "^7.0.0"
|
||||
parse5-htmlparser2-tree-adapter "^7.0.0"
|
||||
|
||||
chroma-js@^2.4.2:
|
||||
version "2.4.2"
|
||||
resolved "https://registry.yarnpkg.com/chroma-js/-/chroma-js-2.4.2.tgz#dffc214ed0c11fa8eefca2c36651d8e57cbfb2b0"
|
||||
integrity sha512-U9eDw6+wt7V8z5NncY2jJfZa+hUH8XEj8FQHgFJTrUFnJfXYf4Ml4adI2vXZOjqRDpFWtYVWypDfZwnJ+HIR4A==
|
||||
|
||||
ci-info@^3.1.0, ci-info@^3.2.0:
|
||||
version "3.8.0"
|
||||
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.8.0.tgz#81408265a5380c929f0bc665d62256628ce9ef91"
|
||||
|
Loading…
x
Reference in New Issue
Block a user