Skip to content

Commit 6de65b7

Browse files
committed
Added secondaryColor
1 parent 81f1b5d commit 6de65b7

File tree

5 files changed

+91
-8
lines changed

5 files changed

+91
-8
lines changed

.env.example

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ NEXT_PUBLIC_BASE_PATH='/dashboard'
1212
NEXT_PUBLIC_BASE_ASSET_PATH='/dashboard/'
1313
NEXT_PUBLIC_SESSION_BALANCE_TRANSFER_ADDRESS='<session_balance_transfer_address>'
1414
NEXT_PUBLIC_IPFS_CDN_URL='https://ipfs.internal.citizenwallet.xyz'
15-
NEXT_PUBLIC_COMMUNITY_THEME_PRIMARY_COLOR='#9563D3'
15+
NEXT_PUBLIC_COMMUNITY_THEME_PRIMARY_COLOR='#1CB260'
16+
NEXT_PUBLIC_COMMUNITY_THEME_SECONDARY_COLOR='#01392C'
1617

1718
# SERVER
1819
APP_BASE_URL='https://app.citizenwallet.xyz/#/'

src/containers/Config/index.tsx

+42-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"use client";
2-
2+
import { getTextColor } from "@/lib/colors";
33
import { isAddress } from "ethers";
44
import { useDebouncedCallback } from "use-debounce";
55
import {
@@ -71,6 +71,7 @@ export default function Container({ sponsor }: ContainerProps) {
7171
const logic = useConfigActions();
7272
const step = useConfigStore((state) => state.step);
7373
const primaryColor = useConfigStore((state) => state.primaryColor);
74+
const secondaryColor = useConfigStore((state) => state.secondaryColor);
7475
const invalidUrl = useConfigStore((state) => state.invalidUrl);
7576
const network = useConfigStore((state) => state.network);
7677
const scan = useConfigStore((state) => state.scan);
@@ -141,9 +142,14 @@ export default function Container({ sponsor }: ContainerProps) {
141142
}
142143
};
143144

144-
const handleColorChange: ColorChangeHandler = (color: ColorResult) => {
145+
const handlePrimaryColorChange: ColorChangeHandler = (color: ColorResult) => {
145146
logic.updatePrimaryColor(color.hex);
146147
};
148+
const handleSecondaryColorChange: ColorChangeHandler = (
149+
color: ColorResult
150+
) => {
151+
logic.updateSecondaryColor(color.hex);
152+
};
147153

148154
const handleLogoSelect = (e: React.ChangeEvent<HTMLInputElement>) => {
149155
if (file) {
@@ -176,14 +182,17 @@ export default function Container({ sponsor }: ContainerProps) {
176182
validAddress,
177183
metadata,
178184
file,
179-
primaryColor
185+
primaryColor,
186+
secondaryColor
180187
);
181188
};
182189

183190
const handleValidityChange = (value: boolean) => {
184191
setValid(value);
185192
};
186193

194+
const textColor = getTextColor(secondaryColor);
195+
187196
const handleDeploy = async (
188197
owner: string,
189198
factoryService: CommunityFactoryContractService,
@@ -275,7 +284,13 @@ export default function Container({ sponsor }: ContainerProps) {
275284
<AccordionContent>
276285
<Flex direction="column" justify="start" align="stretch" gap="2">
277286
<Flex justify="center">
278-
<Card style={{ maxWidth: 300 }}>
287+
<Card
288+
style={{
289+
maxWidth: 300,
290+
color: textColor,
291+
backgroundColor: secondaryColor,
292+
}}
293+
>
279294
<Flex gap="3" align="center" className="overflow-hidden">
280295
<Avatar
281296
size="3"
@@ -294,7 +309,7 @@ export default function Container({ sponsor }: ContainerProps) {
294309
>
295310
{name.trim() ? name : "Community Name"}
296311
</Text>
297-
<Text as="div" size="2" color="gray">
312+
<Text as="div" size="2" style={{ color: textColor }}>
298313
{description.trim()
299314
? description
300315
: "Token Description"}
@@ -404,7 +419,28 @@ export default function Container({ sponsor }: ContainerProps) {
404419
<SketchPicker
405420
disableAlpha
406421
color={primaryColor}
407-
onChange={handleColorChange}
422+
onChange={handlePrimaryColorChange}
423+
/>
424+
</Popover.Content>
425+
</Popover.Root>
426+
</Flex>
427+
<Label>Secondary Color</Label>
428+
<Flex justify="center" align="center">
429+
<Popover.Root>
430+
<Popover.Trigger>
431+
<Button
432+
variant="solid"
433+
style={{ backgroundColor: secondaryColor }}
434+
>
435+
<OpacityIcon height={14} width={14} />
436+
{secondaryColor}
437+
</Button>
438+
</Popover.Trigger>
439+
<Popover.Content side="bottom" size="1">
440+
<SketchPicker
441+
disableAlpha
442+
color={secondaryColor}
443+
onChange={handleSecondaryColorChange}
408444
/>
409445
</Popover.Content>
410446
</Popover.Root>

src/lib/colors.ts

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
function hexToRgb(hex: string): { r: number; g: number; b: number } {
2+
hex = hex.replace(/^#/, "");
3+
const bigint = parseInt(hex, 16);
4+
const r = (bigint >> 16) & 255;
5+
const g = (bigint >> 8) & 255;
6+
const b = bigint & 255;
7+
return { r, g, b };
8+
}
9+
10+
function getLuminance({
11+
r,
12+
g,
13+
b,
14+
}: {
15+
r: number;
16+
g: number;
17+
b: number;
18+
}): number {
19+
const [R, G, B] = [r, g, b].map((v) => {
20+
v /= 255;
21+
return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
22+
});
23+
return 0.2126 * R + 0.7152 * G + 0.0722 * B;
24+
}
25+
26+
// Returns the text color that should be used based on the luminosity of the background color
27+
export function getTextColor(hex: string): "black" | "white" {
28+
const rgb = hexToRgb(hex);
29+
const luminance = getLuminance(rgb);
30+
// Use a threshold of 0.5 for luminance
31+
return luminance > 0.5 ? "black" : "white";
32+
}

src/state/config/actions.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ class ConfigActions {
4040
updatePrimaryColor(color: string) {
4141
this.store.setState({ primaryColor: color });
4242
}
43+
updateSecondaryColor(color: string) {
44+
this.store.setState({ secondaryColor: color });
45+
}
4346

4447
async imageUpload(logo: string): Promise<boolean> {
4548
try {
@@ -93,7 +96,8 @@ class ConfigActions {
9396
decimals: bigint;
9497
},
9598
file: string,
96-
primaryColor?: string
99+
primaryColor?: string,
100+
secondaryColor?: string
97101
) {
98102
const isValid = isValidUrl(url);
99103
if (!isValid) {
@@ -110,6 +114,11 @@ class ConfigActions {
110114
process.env.NEXT_PUBLIC_COMMUNITY_THEME_PRIMARY_COLOR ||
111115
"#000000";
112116

117+
const secondary =
118+
secondaryColor ||
119+
process.env.NEXT_PUBLIC_COMMUNITY_THEME_SECONDARY_COLOR ||
120+
"#000000";
121+
113122
const community: ConfigCommunity = {
114123
name,
115124
description,
@@ -119,6 +128,7 @@ class ConfigActions {
119128
logo: file,
120129
theme: {
121130
primary,
131+
secondary,
122132
},
123133
};
124134

src/state/config/state.ts

+4
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ export enum DeployStep {
2929
export type ConfigStore = {
3030
step: ConfigStep;
3131
primaryColor: string;
32+
secondaryColor: string;
3233
setPrimaryColor: (color: string) => void;
34+
setSecondaryColor: (color: string) => void;
3335
config?: Config;
3436
network?: Network;
3537
scan?: ConfigScan;
@@ -67,6 +69,8 @@ const getInitialState = () => ({
6769
step: ConfigStep.Chain,
6870
primaryColor:
6971
process.env.NEXT_PUBLIC_COMMUNITY_THEME_PRIMARY_COLOR || "#000000",
72+
secondaryColor:
73+
process.env.NEXT_PUBLIC_COMMUNITY_THEME_SECONDARY_COLOR || "#000000",
7074
config: undefined,
7175
loading: true,
7276
error: false,

0 commit comments

Comments
 (0)