New Theme Builder UI

This commit is contained in:
Sean Edmunds
2025-06-27 16:07:29 -05:00
parent f7870d10b1
commit bfe80b5844
7 changed files with 479 additions and 313 deletions

54
package-lock.json generated
View File

@@ -13,16 +13,16 @@
"@mantine/form": "^8.1.2", "@mantine/form": "^8.1.2",
"@mantine/hooks": "^8.1.2", "@mantine/hooks": "^8.1.2",
"@mantine/notifications": "^8.1.2", "@mantine/notifications": "^8.1.2",
"@tanstack/react-query": "^5.81.2", "@tanstack/react-query": "^5.81.4",
"@tanstack/react-query-devtools": "^5.81.2", "@tanstack/react-query-devtools": "^5.81.4",
"@tanstack/react-query-persist-client": "^5.81.2", "@tanstack/react-query-persist-client": "^5.81.4",
"idb-keyval": "^6.2.2", "idb-keyval": "^6.2.2",
"jotai": "^2.12.5", "jotai": "^2.12.5",
"react": "^19.1.0", "react": "^19.1.0",
"react-dom": "^19.1.0", "react-dom": "^19.1.0",
"react-icons": "^5.5.0", "react-icons": "^5.5.0",
"react-router-dom": "^7.6.2", "react-router-dom": "^7.6.2",
"recharts": "^3.0.1" "recharts": "^3.0.2"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^24.0.4", "@types/node": "^24.0.4",
@@ -1630,9 +1630,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@tanstack/query-core": { "node_modules/@tanstack/query-core": {
"version": "5.81.2", "version": "5.81.4",
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.81.2.tgz", "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.81.4.tgz",
"integrity": "sha512-QLYkPdrudoMATDFa3MiLEwRhNnAlzHWDf0LKaXUqJd0/+QxN8uTPi7bahRlxoAyH0UbLMBdeDbYzWALj7THOtw==", "integrity": "sha512-z0yBgRFTPIEYcjFFiahOwtEU3kEKpF5Rwls7UjBCsRghmhwIXyxd5U2p0yEmUfcwm85W4XZkt4dc1OWc5my3Yw==",
"license": "MIT", "license": "MIT",
"funding": { "funding": {
"type": "github", "type": "github",
@@ -1650,12 +1650,12 @@
} }
}, },
"node_modules/@tanstack/query-persist-client-core": { "node_modules/@tanstack/query-persist-client-core": {
"version": "5.81.2", "version": "5.81.4",
"resolved": "https://registry.npmjs.org/@tanstack/query-persist-client-core/-/query-persist-client-core-5.81.2.tgz", "resolved": "https://registry.npmjs.org/@tanstack/query-persist-client-core/-/query-persist-client-core-5.81.4.tgz",
"integrity": "sha512-FSLHr3DL+eezaKNiAexM7+KdgpXvLmUuMQhtORPIC7QuhemM6kfzcrQC5AN34zhvVh2PZXRcib2JnHKeTMjyyg==", "integrity": "sha512-8SlCCzIPBYCOfWRPUGkzJAdPMu+7JT42J51n6rWvaLVj20mzrVX2EKTtm7QoP19LdX+prS8ndCMClrILQi7nUA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@tanstack/query-core": "5.81.2" "@tanstack/query-core": "5.81.4"
}, },
"funding": { "funding": {
"type": "github", "type": "github",
@@ -1663,12 +1663,12 @@
} }
}, },
"node_modules/@tanstack/react-query": { "node_modules/@tanstack/react-query": {
"version": "5.81.2", "version": "5.81.4",
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.81.2.tgz", "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.81.4.tgz",
"integrity": "sha512-pe8kFlTrL2zFLlcAj2kZk9UaYYHDk9/1hg9EBaoO3cxDhOZf1FRGJeziSXKrVZyxIfs7b3aoOj/bw7Lie0mDUg==", "integrity": "sha512-bBrf5kTNr9t5BnskvyHQGwe2LRZsgnmx1sClyRQbAHxhSJfnT6z9h27IfGpY6JtfEH5y5R9jJegTG/93zyox/A==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@tanstack/query-core": "5.81.2" "@tanstack/query-core": "5.81.4"
}, },
"funding": { "funding": {
"type": "github", "type": "github",
@@ -1679,9 +1679,9 @@
} }
}, },
"node_modules/@tanstack/react-query-devtools": { "node_modules/@tanstack/react-query-devtools": {
"version": "5.81.2", "version": "5.81.4",
"resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-5.81.2.tgz", "resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-5.81.4.tgz",
"integrity": "sha512-TX0OQ4cbgX6z2uN8c9x0QUNbyePGyUGdcgrGnV6TYEJc7KPT8PqeASuzoA5NGw1CiMGvyFAkIGA2KipvhM9d1g==", "integrity": "sha512-zFg7rzOmM9Q+Ym/TujWR4HD+jKwQd+N8WuWZRmHU8sjI2flyxWTWIEQvl9BFt+HiNA6leS3ODZ9SHYmEb3zduw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@tanstack/query-devtools": "5.81.2" "@tanstack/query-devtools": "5.81.2"
@@ -1691,24 +1691,24 @@
"url": "https://github.com/sponsors/tannerlinsley" "url": "https://github.com/sponsors/tannerlinsley"
}, },
"peerDependencies": { "peerDependencies": {
"@tanstack/react-query": "^5.81.2", "@tanstack/react-query": "^5.81.4",
"react": "^18 || ^19" "react": "^18 || ^19"
} }
}, },
"node_modules/@tanstack/react-query-persist-client": { "node_modules/@tanstack/react-query-persist-client": {
"version": "5.81.2", "version": "5.81.4",
"resolved": "https://registry.npmjs.org/@tanstack/react-query-persist-client/-/react-query-persist-client-5.81.2.tgz", "resolved": "https://registry.npmjs.org/@tanstack/react-query-persist-client/-/react-query-persist-client-5.81.4.tgz",
"integrity": "sha512-HUlnB7FGqN/he4AOvR0vNA06Wn4dg3rEK7EgzenWfc0gQ9Aa6thqTWgT3Q27CnKiTkzhRn2uZJKRseTP4g54LQ==", "integrity": "sha512-8SlkNDZmWUZLKYYm6DvYybJYrZngnERx/7W1KLUQ3IPaANM9tfmtQjBQBhr1dagyebNK1h/c69IY24dfUaNVIA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@tanstack/query-persist-client-core": "5.81.2" "@tanstack/query-persist-client-core": "5.81.4"
}, },
"funding": { "funding": {
"type": "github", "type": "github",
"url": "https://github.com/sponsors/tannerlinsley" "url": "https://github.com/sponsors/tannerlinsley"
}, },
"peerDependencies": { "peerDependencies": {
"@tanstack/react-query": "^5.81.2", "@tanstack/react-query": "^5.81.4",
"react": "^18 || ^19" "react": "^18 || ^19"
} }
}, },
@@ -3785,9 +3785,9 @@
} }
}, },
"node_modules/recharts": { "node_modules/recharts": {
"version": "3.0.1", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/recharts/-/recharts-3.0.1.tgz", "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.0.2.tgz",
"integrity": "sha512-T5PZzeqzkdQpwdd/wG/hzuhaKAFTNY/PsezVlhdg4GbME4mfcau3DEYP4VCejEsUVOpX6hQTN6FJE4z9zL0RWA==", "integrity": "sha512-eDc3ile9qJU9Dp/EekSthQPhAVPG48/uM47jk+PF7VBQngxeW3cwQpPHb/GHC1uqwyCRWXcIrDzuHRVrnRryoQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@reduxjs/toolkit": "1.x.x || 2.x.x", "@reduxjs/toolkit": "1.x.x || 2.x.x",

View File

@@ -15,16 +15,16 @@
"@mantine/form": "^8.1.2", "@mantine/form": "^8.1.2",
"@mantine/hooks": "^8.1.2", "@mantine/hooks": "^8.1.2",
"@mantine/notifications": "^8.1.2", "@mantine/notifications": "^8.1.2",
"@tanstack/react-query": "^5.81.2", "@tanstack/react-query": "^5.81.4",
"@tanstack/react-query-devtools": "^5.81.2", "@tanstack/react-query-devtools": "^5.81.4",
"@tanstack/react-query-persist-client": "^5.81.2", "@tanstack/react-query-persist-client": "^5.81.4",
"idb-keyval": "^6.2.2", "idb-keyval": "^6.2.2",
"jotai": "^2.12.5", "jotai": "^2.12.5",
"react": "^19.1.0", "react": "^19.1.0",
"react-dom": "^19.1.0", "react-dom": "^19.1.0",
"react-icons": "^5.5.0", "react-icons": "^5.5.0",
"react-router-dom": "^7.6.2", "react-router-dom": "^7.6.2",
"recharts": "^3.0.1" "recharts": "^3.0.2"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^24.0.4", "@types/node": "^24.0.4",

View File

@@ -22,7 +22,7 @@ function ExampleApp({ selectedTheme }: { selectedTheme: Theme }) {
paddingTop: '1rem', paddingTop: '1rem',
}} }}
> >
<FiCheck style={{ color: selectedTheme.primaryColor }} height={32} width={32} /> <FiCheck style={{ color: selectedTheme?.primaryColor }} height={32} width={32} />
</Stack> </Stack>
<Stack <Stack
style={{ style={{
@@ -39,7 +39,7 @@ function ExampleApp({ selectedTheme }: { selectedTheme: Theme }) {
fontWeight: 400, fontWeight: 400,
fontSize: '.625rem', fontSize: '.625rem',
fontStyle: 'normal', fontStyle: 'normal',
color: selectedTheme.primaryColor, color: selectedTheme?.primaryColor,
fontFamily: fontFamily:
'-apple-system, Jost, BlinkMacSystemFont, Helvetica Neue, Roboto, sans-serif !important', '-apple-system, Jost, BlinkMacSystemFont, Helvetica Neue, Roboto, sans-serif !important',
margin: 0, margin: 0,
@@ -52,7 +52,7 @@ function ExampleApp({ selectedTheme }: { selectedTheme: Theme }) {
fontWeight: 400, fontWeight: 400,
fontSize: '.625rem', fontSize: '.625rem',
fontStyle: 'italic', fontStyle: 'italic',
color: selectedTheme.accentColor, color: selectedTheme?.accentColor,
fontFamily: fontFamily:
'-apple-system, Jost, BlinkMacSystemFont, Helvetica Neue, Roboto, sans-serif !important', '-apple-system, Jost, BlinkMacSystemFont, Helvetica Neue, Roboto, sans-serif !important',
margin: 0, margin: 0,

View File

@@ -1,20 +1,23 @@
import { import {
ActionIcon,
Button, Button,
ColorPicker, ColorPicker,
ColorSwatch,
Group, Group,
Modal, Modal,
ScrollArea, ScrollArea,
Stack, Stack,
Text, Text,
TextInput, TextInput,
Tooltip,
UnstyledButton, UnstyledButton,
} from '@mantine/core'; } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
import { useCommonHooks } from 'hooks'; import { useCommonHooks } from 'hooks';
import { useEffect, useRef, useState } from 'react'; import { useEffect, useRef, useState } from 'react';
import { FiSave, FiX } from 'react-icons/fi'; import { FiImage, FiSave, FiX } from 'react-icons/fi';
import { modalClasses, scrollAreaClasses, textInputClasses } from 'styles'; import { modalClasses, scrollAreaClasses, textClasses, textInputClasses } from 'styles';
import type { Theme } from 'types'; import type { Theme } from 'types';
import ThemeModalColorSwatches from './ThemeModalColorSwatches';
import ThemeModalContent from './ThemeModalContent'; import ThemeModalContent from './ThemeModalContent';
function ThemeModal({ function ThemeModal({
@@ -22,10 +25,6 @@ function ThemeModal({
handleClose, handleClose,
selectedTheme, selectedTheme,
setSelectedTheme, setSelectedTheme,
colorId,
setColorId,
colorValue,
setColorValue,
openPicker, openPicker,
backgroundList, backgroundList,
pickerOpen, pickerOpen,
@@ -36,10 +35,6 @@ function ThemeModal({
handleClose: () => void; handleClose: () => void;
selectedTheme: Theme; selectedTheme: Theme;
setSelectedTheme: (selectedTheme: Theme) => void; setSelectedTheme: (selectedTheme: Theme) => void;
colorId: string;
setColorId: (colorId: string) => void;
colorValue: string;
setColorValue: (colorValue: string) => void;
openPicker: () => void; openPicker: () => void;
backgroundList: string[]; backgroundList: string[];
pickerOpen: boolean; pickerOpen: boolean;
@@ -50,10 +45,18 @@ function ThemeModal({
const viewportRef = useRef<HTMLDivElement>(null); const viewportRef = useRef<HTMLDivElement>(null);
const [query, setQuery] = useState(''); const [query, setQuery] = useState('');
const [hovered, setHovered] = useState(-1); const [hovered, setHovered] = useState(-1);
const [colorId, setColorId] = useState<string>('');
const [colorValue, setColorValue] = useState('#000000');
const [designerTheme, setDesignerTheme] = useState<Theme>({
...selectedTheme,
});
const filtered = backgroundList.filter((item: string) => const filtered = backgroundList.filter((item: string) =>
item.toLowerCase().includes(query.toLowerCase()), item.toLowerCase().includes(query.toLowerCase()),
); );
const [backgroundPicker, { open: openBackgroundPicker, close: closeBackgroundPicker }] =
useDisclosure(false);
const re = /(?:\.([^.]+))?$/; const re = /(?:\.([^.]+))?$/;
const items = filtered.map((item: string, index: number) => { const items = filtered.map((item: string, index: number) => {
return ( return (
@@ -75,8 +78,8 @@ function ThemeModal({
alignItems: 'center', alignItems: 'center',
}} }}
onClick={() => onClick={() =>
setSelectedTheme({ setDesignerTheme({
...selectedTheme, ...designerTheme,
backgroundImage: item, backgroundImage: item,
}) })
} }
@@ -116,18 +119,11 @@ function ThemeModal({
}); });
useEffect(() => { useEffect(() => {
if (selectedTheme) { setDesignerTheme(selectedTheme);
if (selectedTheme?.backgroundImage === 'none') {
setQuery('');
} else {
setQuery(selectedTheme?.backgroundImage || '');
}
}
}, [selectedTheme]); }, [selectedTheme]);
return ( return (
<Modal.Root <Modal.Root
size={'50%'} size={'75%'}
className={modalClasses.editThemeModal} className={modalClasses.editThemeModal}
classNames={modalClasses} classNames={modalClasses}
opened={opened} opened={opened}
@@ -152,7 +148,8 @@ function ThemeModal({
color: 'var(--mantine-color-primary-0)', color: 'var(--mantine-color-primary-0)',
}, },
input: { input: {
color: 'var(--mantine-color-primary-0)', color: selectedTheme.primaryColor,
backgroundColor: selectedTheme.backgroundColor,
border: 'none', border: 'none',
borderBottom: '1px solid var(--mantine-color-primary-0)', borderBottom: '1px solid var(--mantine-color-primary-0)',
}, },
@@ -161,32 +158,158 @@ function ThemeModal({
</Group> </Group>
<Modal.CloseButton /> <Modal.CloseButton />
</Modal.Header> </Modal.Header>
<Modal.Body p={'2rem'}> <Modal.Body>
<ThemeModalContent selectedTheme={selectedTheme} /> <Group p={'2rem'} w={'100%'} align='flex-start' justify='space-between'>
<Group <Stack display={'flex'} pos={'relative'} w={'70%'}>
w={'100%'} <ThemeModalContent selectedTheme={designerTheme} />
h={'100%'} <Tooltip
gap={isMobile ? 20 : 0} label={'Change Primary Color'}
style={{ flexDirection: isMobile ? 'column' : 'row' }} c={'var(--mantine-color-primary-0)'}
bg={'var(--mantine-color-background-0)'}
> >
<Stack w={isMobile ? '100%' : '50%'}> <ColorSwatch
{pickerOpen ? ( onClick={() => {
<Group justify='center'> closeBackgroundPicker();
setColorId('primaryColor');
openPicker();
setColorValue(selectedTheme.primaryColor);
}}
color={selectedTheme.primaryColor}
bd={`1px solid ${selectedTheme.primaryColor}`}
pos={'absolute'}
top={'6.25rem'}
left={'1.5rem'}
/>
</Tooltip>
<Tooltip
label={'Change Accent Color'}
c={'var(--mantine-color-primary-0)'}
bg={'var(--mantine-color-background-0)'}
>
<ColorSwatch
onClick={() => {
closeBackgroundPicker();
setColorId('accentColor');
openPicker();
setColorValue(selectedTheme.accentColor);
}}
color={selectedTheme.accentColor}
bd={`1px solid ${selectedTheme.primaryColor}`}
pos={'absolute'}
bottom={'6rem'}
left={'11rem'}
/>
</Tooltip>
<Tooltip
label={'Change Background Color'}
c={'var(--mantine-color-primary-0)'}
bg={'var(--mantine-color-background-0)'}
>
<ColorSwatch
onClick={() => {
closeBackgroundPicker();
setColorId('backgroundColor');
openPicker();
setColorValue(selectedTheme.backgroundColor);
}}
color={selectedTheme.backgroundColor}
bd={`1px solid ${selectedTheme.primaryColor}`}
pos={'absolute'}
bottom={'10rem'}
right={'3.5rem'}
/>
</Tooltip>
<Tooltip
label={'Change Border Color'}
c={'var(--mantine-color-primary-0)'}
bg={'var(--mantine-color-background-0)'}
>
<ColorSwatch
onClick={() => {
closeBackgroundPicker();
setColorId('borderColor');
openPicker();
setColorValue(selectedTheme.borderColor);
}}
color={selectedTheme.borderColor}
bd={`1px solid ${selectedTheme.primaryColor}`}
pos={'absolute'}
top={'4.5rem'}
right={'7rem'}
/>
</Tooltip>
<Tooltip
label={'Change Search Color'}
c={'var(--mantine-color-primary-0)'}
bg={'var(--mantine-color-background-0)'}
>
<ColorSwatch
onClick={() => {
closeBackgroundPicker();
setColorId('searchBackground');
openPicker();
setColorValue(selectedTheme.searchColor);
}}
color={selectedTheme.searchColor}
bd={`1px solid ${selectedTheme.primaryColor}`}
pos={'absolute'}
top={'3.25rem'}
left={'14.5rem'}
/>
</Tooltip>
<Tooltip
label={'Change Background'}
c={'var(--mantine-color-primary-0)'}
bg={'var(--mantine-color-background-0)'}
>
<ActionIcon
onClick={() => {
closePicker();
openBackgroundPicker();
}}
pos={'absolute'}
right={0}
>
<FiImage size={20} />
</ActionIcon>
</Tooltip>
</Stack>
<Stack
w={'28%'}
h={'436px'}
p={'1rem'}
style={{
borderRadius: '1rem',
backgroundColor:
'color-mix(in srgb, var(--mantine-color-primary-0) 20%, transparent)',
}}
>
{pickerOpen && (
<Stack h={'100%'} align='center' justify='space-between'>
<Text className={textClasses.sectionTitle} classNames={textClasses}>
Change {colorId}
</Text>
<ColorPicker <ColorPicker
value={colorValue} value={colorValue}
onChange={setColorValue} onChange={(e) => {
format={colorId === 'background' ? 'hex' : 'hexa'} setColorValue(e);
setDesignerTheme({
...designerTheme,
[colorId]: e,
});
}}
format={colorId === 'backgroundColor' ? 'hex' : 'hexa'}
w={'90%'} w={'90%'}
mb={colorId === 'background' ? '1.5rem' : undefined} mb={colorId === 'backgroundColor' ? '1.5rem' : undefined}
/> />
<Group justify='center'>
<TextInput <TextInput
className={textInputClasses.default} className={textInputClasses.default}
classNames={textInputClasses} classNames={textInputClasses}
w={'55%'} w={'90%'}
value={colorValue} value={colorValue}
onChange={(e) => setColorValue(e.target.value)} onChange={(e) => setColorValue(e.target.value)}
/> />
<Group mt={'auto'} justify='center'>
<Button <Button
color={'green'} color={'green'}
onClick={() => { onClick={() => {
@@ -203,7 +326,7 @@ function ThemeModal({
accentColor: colorValue, accentColor: colorValue,
}); });
break; break;
case 'background': case 'backgroundColor':
setSelectedTheme({ setSelectedTheme({
...selectedTheme, ...selectedTheme,
backgroundColor: colorValue, backgroundColor: colorValue,
@@ -230,33 +353,26 @@ function ThemeModal({
<Button <Button
color={'red'} color={'red'}
styles={{ label: { color: 'black' } }} styles={{ label: { color: 'black' } }}
onClick={closePicker} onClick={() => {
closePicker();
setDesignerTheme({
...designerTheme,
[colorId]: selectedTheme[colorId as keyof Theme],
});
}}
> >
<FiX /> <FiX />
</Button> </Button>
<Group w={'100%'} align='center' justify='center' />
</Group> </Group>
</Group>
) : (
<ThemeModalColorSwatches
selectedTheme={selectedTheme}
openPicker={openPicker}
setColorId={setColorId}
setColorValue={setColorValue}
/>
)}
</Stack> </Stack>
<Stack )}
h={'100%'} {backgroundPicker && (
w={isMobile ? '100%' : '50%'} <Stack h={'100%'} align='center' justify='center'>
align='center'
justify='center'
>
<Group gap={0}> <Group gap={0}>
<Text mr={'.5rem'}>Search:</Text>
<TextInput <TextInput
className={textInputClasses.default} className={textInputClasses.default}
classNames={textInputClasses} classNames={textInputClasses}
placeholder='Search'
value={query.replace(/\.[^/.]+$/, '')} value={query.replace(/\.[^/.]+$/, '')}
rightSection={ rightSection={
<FiX <FiX
@@ -304,7 +420,7 @@ function ThemeModal({
className={scrollAreaClasses.default} className={scrollAreaClasses.default}
classNames={scrollAreaClasses} classNames={scrollAreaClasses}
style={{ style={{
height: 150, height: 325,
width: '90%', width: '90%',
borderRadius: 8, borderRadius: 8,
}} }}
@@ -313,6 +429,36 @@ function ThemeModal({
{items} {items}
</Stack> </Stack>
</ScrollArea.Autosize> </ScrollArea.Autosize>
<Group justify='center'>
<Button
color={'green'}
onClick={() => {
setSelectedTheme({
...selectedTheme,
backgroundImage: designerTheme.backgroundImage,
});
closeBackgroundPicker();
}}
>
<FiSave />
</Button>
<Button
color={'red'}
styles={{ label: { color: 'black' } }}
onClick={() => {
closeBackgroundPicker();
setDesignerTheme({
...designerTheme,
backgroundImage: selectedTheme.backgroundImage,
});
}}
>
<FiX />
</Button>
</Group>
</Stack>
)}
{!pickerOpen && !backgroundPicker && <Stack />}
</Stack> </Stack>
</Group> </Group>
<Group> <Group>
@@ -322,7 +468,10 @@ function ThemeModal({
<Button <Button
color={'red'} color={'red'}
styles={{ label: { color: 'black' } }} styles={{ label: { color: 'black' } }}
onClick={handleClose} onClick={() => {
closeBackgroundPicker();
handleClose();
}}
> >
Cancel Cancel
</Button> </Button>

View File

@@ -1,5 +1,4 @@
import { ColorSwatch, Group, Stack, Text } from '@mantine/core'; import { ColorSwatch, Group, Stack, Text } from '@mantine/core';
import { useCommonHooks } from 'hooks';
import { colorSwatchClasses, textClasses } from 'styles'; import { colorSwatchClasses, textClasses } from 'styles';
import type { Theme } from 'types'; import type { Theme } from 'types';
@@ -14,9 +13,8 @@ function ThemeModalColorSwatches({
setColorId: (colorId: string) => void; setColorId: (colorId: string) => void;
setColorValue: (colorValue: string) => void; setColorValue: (colorValue: string) => void;
}) { }) {
const { isMobile } = useCommonHooks();
return ( return (
<Stack h={isMobile ? '100%' : 256} justify='center'> <Stack justify='center'>
<Group justify='space-between'> <Group justify='space-between'>
<Text className={textClasses.label} classNames={textClasses}> <Text className={textClasses.label} classNames={textClasses}>
Primary Color Primary Color

View File

@@ -1,4 +1,6 @@
import { Group, Stack, Text } from '@mantine/core'; import { Select, Stack, Text } from '@mantine/core';
import SearchSelectItem from 'pages/homepage/components/Search/SearchSelectItem';
import { selectClasses } from 'styles';
import type { Theme } from 'types'; import type { Theme } from 'types';
import ThemeExampleApp from './ThemeExampleApp'; import ThemeExampleApp from './ThemeExampleApp';
@@ -6,7 +8,6 @@ export default function ThemeModalContent({ selectedTheme }: { selectedTheme: Th
return ( return (
<Stack <Stack
style={{ style={{
width: '100%',
backgroundImage: backgroundImage:
selectedTheme?.backgroundImage.toLocaleLowerCase() !== 'none' selectedTheme?.backgroundImage.toLocaleLowerCase() !== 'none'
? `linear-gradient(${selectedTheme?.backgroundColor}33, ${selectedTheme?.backgroundColor}33), url(../../api/backgroundImages/${selectedTheme?.backgroundImage})` ? `linear-gradient(${selectedTheme?.backgroundColor}33, ${selectedTheme?.backgroundColor}33), url(../../api/backgroundImages/${selectedTheme?.backgroundImage})`
@@ -22,17 +23,37 @@ export default function ThemeModalContent({ selectedTheme }: { selectedTheme: Th
backgroundPosition: 'center', backgroundPosition: 'center',
borderRadius: '10px', borderRadius: '10px',
border: '2px solid var(--mantine-color-primary-0)', border: '2px solid var(--mantine-color-primary-0)',
padding: '1rem',
}} }}
align='center'
> >
<Group <Select
justify='center' disabled
style={{ w={'80%'}
color: selectedTheme.primaryColor, classNames={selectClasses}
paddingTop: '1rem', data={[
{
label: 'Google Search',
value: 'google',
},
]}
searchValue={'example search'}
data-active={true}
dropdownOpened={true}
autoFocus={false}
leftSection={'Google Search'}
rightSection={<div />}
renderOption={(item: any) => {
return (
<SearchSelectItem
item={item}
handleSearchHistoryItem={undefined}
searchEndpoint={undefined}
/>
);
}} }}
> />
{selectedTheme.name} <Stack gap={0} w={'100%'}>
</Group>
<Text <Text
pl={'1.5rem'} pl={'1.5rem'}
style={{ style={{
@@ -44,7 +65,7 @@ export default function ThemeModalContent({ selectedTheme }: { selectedTheme: Th
textTransform: 'uppercase', textTransform: 'uppercase',
marginTop: '1.25rem', marginTop: '1.25rem',
marginBottom: '1.25rem', marginBottom: '1.25rem',
color: selectedTheme.primaryColor, color: selectedTheme?.primaryColor,
}} }}
> >
Applications Applications
@@ -69,6 +90,8 @@ export default function ThemeModalContent({ selectedTheme }: { selectedTheme: Th
<ThemeExampleApp selectedTheme={selectedTheme} /> <ThemeExampleApp selectedTheme={selectedTheme} />
<ThemeExampleApp selectedTheme={selectedTheme} /> <ThemeExampleApp selectedTheme={selectedTheme} />
</Stack> </Stack>
</Stack>
<Stack gap={0} w={'100%'}>
<Text <Text
pl={'1.5rem'} pl={'1.5rem'}
style={{ style={{
@@ -80,13 +103,14 @@ export default function ThemeModalContent({ selectedTheme }: { selectedTheme: Th
textTransform: 'uppercase', textTransform: 'uppercase',
marginTop: '1.25rem', marginTop: '1.25rem',
marginBottom: '1.25rem', marginBottom: '1.25rem',
color: selectedTheme.primaryColor, color: selectedTheme?.primaryColor,
}} }}
> >
Bookmarks Bookmarks
</Text> </Text>
<Stack <Stack
style={{ style={{
width: '100%',
display: 'flex', display: 'flex',
flexDirection: 'row', flexDirection: 'row',
flexWrap: 'nowrap', flexWrap: 'nowrap',
@@ -112,7 +136,7 @@ export default function ThemeModalContent({ selectedTheme }: { selectedTheme: Th
fontWeight: 400, fontWeight: 400,
height: '10px', height: '10px',
width: 'auto', width: 'auto',
color: selectedTheme.accentColor, color: selectedTheme?.accentColor,
textTransform: 'uppercase', textTransform: 'uppercase',
marginTop: '1.25rem', marginTop: '1.25rem',
marginBottom: '1.25rem', marginBottom: '1.25rem',
@@ -125,7 +149,7 @@ export default function ThemeModalContent({ selectedTheme }: { selectedTheme: Th
display: 'block', display: 'block',
fontSize: '.875rem', fontSize: '.875rem',
lineHeight: 2, lineHeight: 2,
color: selectedTheme.primaryColor, color: selectedTheme?.primaryColor,
}} }}
component='a' component='a'
> >
@@ -136,7 +160,7 @@ export default function ThemeModalContent({ selectedTheme }: { selectedTheme: Th
display: 'block', display: 'block',
fontSize: '.875rem', fontSize: '.875rem',
lineHeight: 2, lineHeight: 2,
color: selectedTheme.primaryColor, color: selectedTheme?.primaryColor,
}} }}
component='a' component='a'
> >
@@ -159,7 +183,7 @@ export default function ThemeModalContent({ selectedTheme }: { selectedTheme: Th
fontWeight: 400, fontWeight: 400,
height: '10px', height: '10px',
width: 'auto', width: 'auto',
color: selectedTheme.accentColor, color: selectedTheme?.accentColor,
textTransform: 'uppercase', textTransform: 'uppercase',
marginTop: '1.25rem', marginTop: '1.25rem',
marginBottom: '1.25rem', marginBottom: '1.25rem',
@@ -172,7 +196,7 @@ export default function ThemeModalContent({ selectedTheme }: { selectedTheme: Th
display: 'block', display: 'block',
fontSize: '.875rem', fontSize: '.875rem',
lineHeight: 2, lineHeight: 2,
color: selectedTheme.primaryColor, color: selectedTheme?.primaryColor,
}} }}
component='a' component='a'
> >
@@ -183,7 +207,7 @@ export default function ThemeModalContent({ selectedTheme }: { selectedTheme: Th
display: 'block', display: 'block',
fontSize: '.875rem', fontSize: '.875rem',
lineHeight: 2, lineHeight: 2,
color: selectedTheme.primaryColor, color: selectedTheme?.primaryColor,
}} }}
component='a' component='a'
> >
@@ -192,5 +216,6 @@ export default function ThemeModalContent({ selectedTheme }: { selectedTheme: Th
</Stack> </Stack>
</Stack> </Stack>
</Stack> </Stack>
</Stack>
); );
} }

View File

@@ -34,8 +34,6 @@ function ThemesSettings() {
backgroundModalOpened, backgroundModalOpened,
{ open: openBackgroundModal, close: closeBackgroundModal }, { open: openBackgroundModal, close: closeBackgroundModal },
] = useDisclosure(false); ] = useDisclosure(false);
const [colorId, setColorId] = useState<string>('');
const [colorValue, setColorValue] = useState('#000000');
const [backgroundList, setBackgroundList] = useState<string[]>(['None']); const [backgroundList, setBackgroundList] = useState<string[]>(['None']);
const [inUseBackgrounds, setInUseBackgrounds] = useState<string[]>([]); const [inUseBackgrounds, setInUseBackgrounds] = useState<string[]>([]);
const [selectedTheme, setSelectedTheme] = useState<Theme>({ const [selectedTheme, setSelectedTheme] = useState<Theme>({
@@ -144,13 +142,9 @@ function ThemesSettings() {
handleClose={handleClose} handleClose={handleClose}
selectedTheme={selectedTheme} selectedTheme={selectedTheme}
setSelectedTheme={setSelectedTheme} setSelectedTheme={setSelectedTheme}
setColorId={setColorId}
colorId={colorId}
setColorValue={setColorValue}
openPicker={openPicker} openPicker={openPicker}
backgroundList={backgroundList} backgroundList={backgroundList}
pickerOpen={pickerOpen} pickerOpen={pickerOpen}
colorValue={colorValue}
closePicker={closePicker} closePicker={closePicker}
handleSaveTheme={handleSaveTheme} handleSaveTheme={handleSaveTheme}
/> />