Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: themes #3

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions postcss.config.cjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
plugins: {
'tailwindcss/nesting': {},
'tailwindcss': {},
'autoprefixer': {},
},
};
2 changes: 1 addition & 1 deletion src/components/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
export const Button: React.FC<ButtonProps> = ({ loading, className, children, ...props }) => (
<button
className={classNames(
'px-4 py-2 rounded-md ring-0 ring-opacity-50 ring-inherit',
'px-4 py-2 rounded-md ring-0 ring-theme-primary',
'duration-300 focus:ring-4',
className,
)}
Expand Down
5 changes: 3 additions & 2 deletions src/components/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ import React, { HTMLProps } from 'react';
import classNames from 'classnames';

export const Card: React.FC<HTMLProps<HTMLDivElement>> = ({ className, children, ...props }) => (

<div
className={
classNames(
'bg-silver-800 rounded-xl drop-shadow px-5 py-4',
{ 'cursor-pointer hover:bg-silver-700 hover:drop-shadow-lg transition duration-200': props.onClick },
'rounded-xl bg-theme-padding text-theme-text drop-shadow px-5 py-4',
{ 'cursor-pointer hover:bg-theme-padding hover:-translate-y-1 hover:drop-shadow-lg transition duration-200': props.onClick },
className,
)
}
Expand Down
8 changes: 4 additions & 4 deletions src/components/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const Input: React.FC<InputProps> = ({ label, error, className, ...props
className={classNames(
'px-4 py-2 rounded-md bg-transparent outline-0 ring-0 border-2 block',
'duration-300 focus:ring-4 focus:ring-opacity-50',
{ 'border-silver-600': !error, 'border-red-500': error, 'ring-silver-600': !error, 'ring-red-500': error },
{ 'border-theme-workspace-padding': !error, 'border-red-500': error, 'ring-theme-workspace-padding': !error, 'ring-red-500': error },
className,
)}
{...props}
Expand Down Expand Up @@ -79,11 +79,11 @@ export const ToggleInput: React.FC<InputHTMLAttributes<HTMLInputElement>> = ({ c
className={classNames('opacity-0 w-full h-full cursor-pointer peer', className)}
{...props}
/>
<div className="absolute top-0 left-0 w-full h-full rounded-full bg-silver-700 pointer-events-none" />
<div className="absolute top-0 left-0 w-full h-full rounded-full bg-theme-workspace-padding pointer-events-none" />
<div
className={classNames(
'absolute top-1 left-1 w-3 h-3 rounded-full bg-silver-600 duration-100 pointer-events-none',
'peer-checked:bg-amethyst-400 peer-checked:left-6',
'absolute top-1 left-1 w-3 h-3 rounded-full bg-theme-padding duration-100 pointer-events-none',
'peer-checked:bg-theme-primary peer-checked:left-6',
)}
/>
</div>
Expand Down
8 changes: 4 additions & 4 deletions src/components/Instrument.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,10 @@ export const Instrument: React.FC<Element> = ({ uuid, name, element, x, y, width
height,
}}
>
<div className="absolute bottom-full w-full box-content border-2 border-b-0 border-silver-800 bg-silver-800 rounded-t-xl">
<div className="absolute bottom-full w-full box-content border-2 border-b-0 border-theme-padding bg-theme-padding rounded-t-xl">
<div className="absolute -top-0.5 w-full flex justify-center">
<span
className="w-1/4 h-2 bg-silver-700 rounded-b-full outline-0"
className="w-1/4 h-2 bg-theme-workspace-padding rounded-b-full outline-0"
ref={setNodeRef}
{...listeners}
{...attributes}
Expand All @@ -151,12 +151,12 @@ export const Instrument: React.FC<Element> = ({ uuid, name, element, x, y, width
<div className="px-4 py-1.5 flex gap-3 items-center">
<h4 className="font-medium">{name}</h4>
<button className="ml-auto" onClick={refresh}>
<HiRefresh className="cursor-pointer active:text-silver-500" size={22} />
<HiRefresh className="cursor-pointer active:text-theme-padding" size={22} />
</button>
<ToggleInput onClick={handleWatch} />
</div>
</div>
<div className="absolute w-full h-full box-content border-2 border-silver-700 bg-black">
<div className="absolute w-full h-full box-content border-2 border-theme-workspace-padding bg-black">
<InstrumentFrame ref={iframeRef} name={name} width={width} height={height} />
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/contextmenu/CanvasMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const CanvasMenu: React.FC<Omit<ContextMenuProps, 'children'>> = (props)

return (
<ContextMenu {...props}>
<div className="px-4 py-3 bg-silver-700/50 border-b-2 border-b-silver-700 font-medium">
<div className="px-4 py-3 bg-theme-padding border-b-2 border-b-theme-workspace-padding font-medium">
Instruments
</div>
{instruments.map((instrument) => (
Expand Down
2 changes: 1 addition & 1 deletion src/components/contextmenu/ElementMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const ElementMenu: React.FC<ElementMenuProps> = ({ element, ...props }) =

return (
<ContextMenu {...props}>
<div className="px-4 py-3 bg-silver-700/50 border-b-2 border-b-silver-700 font-medium">
<div className="px-4 py-3 bg-theme-background border-b-2 border-b-theme-workspace-padding font-medium">
{element.name}
</div>
<button
Expand Down
2 changes: 1 addition & 1 deletion src/components/contextmenu/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const ContextMenu: React.FC<ContextMenuProps> = ({ x, y, children }) => {
tabIndex={-1}
ref={menuRef}
style={{ left: x, top: y }}
className="absolute pointer-events-auto flex flex-col outline-0 bg-silver-800 rounded-lg overflow-hidden shadow-2xl text-sm"
className="absolute pointer-events-auto flex flex-col outline-0 bg-theme-background rounded-lg overflow-hidden shadow-2xl text-sm"
>
{children}
</div>
Expand Down
10 changes: 5 additions & 5 deletions src/components/menu/ElementsMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,21 @@ export const ElementsMenu: React.FC<ElementsMenuProps> = ({ ...props }) => {
<div className="flex justify-between items-center mb-4">
<h3>Instruments</h3>
<button onClick={refreshInstruments}>
<HiRefresh className="cursor-pointer active:text-silver-500" size={25} />
<HiRefresh className="cursor-pointer active:text-theme-workspace-padding" size={25} />
</button>
</div>
<div className="flex flex-col gap-3 mb-8">
{instruments.map((instrument) => (
<div className="flex items-center px-5 py-2 rounded-xl bg-silver-900/50">
<div className="flex items-center px-5 py-2 rounded-xl bg-theme-workspace-padding">
<span>{instrument.name}</span>
<span className="ml-auto text-silver-400">{instrument.dimensions.width}x{instrument.dimensions.height}</span>
<span className="ml-auto text-theme-text text-opacity-30">{instrument.dimensions.width}x{instrument.dimensions.height}</span>
</div>
))}
</div>
<h3 className="mb-4">Utilities</h3>
<div className="flex flex-col gap-3">
<div className="flex items-center px-5 py-2 rounded-xl bg-silver-900/50">Button</div>
<div className="flex items-center px-5 py-2 rounded-xl bg-silver-900/50">WebView</div>
<div className="flex items-center px-5 py-2 rounded-xl bg-theme-workspace-padding">Button</div>
<div className="flex items-center px-5 py-2 rounded-xl bg-theme-workspace-padding">WebView</div>
</div>
</div>
</Menu>
Expand Down
26 changes: 26 additions & 0 deletions src/components/menu/SettingsMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { MdSettings } from 'react-icons/md';
import { Menu } from './index';
import { ThemeButton, themeButtons } from './ThemeButton';

interface SettingsMenuCanvasProps {
show?: boolean;
onClick?: () => void;
onExit?: () => void;
}

export const SettingsMenuCanvas: React.FC<SettingsMenuCanvasProps> = ({ ...props }) => (
<Menu title="Settings" icon={<MdSettings size={25} />} {...props}>
<div className="px-6 py-5">
<div className="container grid items-center mb-4">
<h3>Theme</h3>
<ul>
{themeButtons.map((button) => (
<li key={button.themeName}>
<ThemeButton {...button} />
</li>
))}
</ul>
</div>
</div>
</Menu>
);
14 changes: 7 additions & 7 deletions src/components/menu/SimVarsMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,15 @@ const SimVarSlider: React.FC<SimVarSliderProps> = memo(({ varKey }) => {
/>
<h6 className="font-mono text-left">
{simVar.name}
{simVar.index > 0 && <span className="text-amethyst-400">:{simVar.index}</span>}
{simVar.index > 0 && <span className="text-theme-primary">:{simVar.index}</span>}
</h6>
</button>
<button className="mr-0.5" onClick={() => dispatch(togglePin({ key: formatKey(simVar) }))}>
<RiPushpin2Line
size={20}
className={classNames({
'text-amethyst-400': simVar.pinned,
'text-silver-700': !simVar.pinned,
'text-theme-primary': simVar.pinned,
'text-theme-padding': !simVar.pinned,
})}
/>
</button>
Expand Down Expand Up @@ -105,14 +105,14 @@ const CollapsibleSimVarSection: React.FC<CollapsibleSimVarSectionProps> = ({ tit
return (
<>
<button
className="w-full px-6 py-3 bg-silver-700/50 border-t-2 border-t-silver-700 flex items-center justify-between shadow-sm"
className="w-full px-6 py-3 bg-theme-workspace-padding flex items-center justify-between shadow-sm"
onClick={() => setCollapsed(!collapsed)}
>
<h5>{title}</h5>
<FiChevronLeft
size={30}
className={classNames(
'text-silver-500 duration-200',
'text-theme-workspace-padding duration-200',
{ 'rotate-0': collapsed, '-rotate-90': !collapsed },
)}
/>
Expand Down Expand Up @@ -149,11 +149,11 @@ export const SimVarsMenu: React.FC<SimVarsMenuProps> = ({ ...props }) => {
</div>
<SimVarSection filter={(v) => v.pinned ?? false} />
<CollapsibleSimVarSection
title={<><big className="text-amethyst-400">A</big> Vars</>}
title={<><big className="text-theme-primary">A</big> Vars</>}
filter={(v) => v.name.toLowerCase().includes(filter.toLowerCase()) && v.type === 'A'}
/>
<CollapsibleSimVarSection
title={<><big className="text-amethyst-400">L</big> Vars</>}
title={<><big className="text-theme-primary">L</big> Vars</>}
filter={(v) => v.name.toLowerCase().includes(filter.toLowerCase()) && v.type === 'L'}
/>
</Menu>
Expand Down
63 changes: 63 additions & 0 deletions src/components/menu/ThemeButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { useEffect, useState } from 'react';
import { MdCheckCircle } from 'react-icons/md';
import { useGlobalSelector, GlobalState, GlobalDispatch, useGlobalDispatch } from '../../redux/global';
import { themeConfigs, fallbackThemeConfig, themes } from '../../redux/global/ui/uitheme';
import { setTheme } from '../../redux/global/configSlice';
import { Button } from '../Button';

export interface ThemeButtonProps {
themeName: string;
title: string;
className?: string;
}

export const ThemeButton: React.FC<ThemeButtonProps> = ({ themeName, title, className }: ThemeButtonProps) => {
const globalDispatch = useGlobalDispatch<GlobalDispatch>();

const { theme } = useGlobalSelector((state: GlobalState) => state.config);

const themeConfig = theme !== undefined ? theme : fallbackThemeConfig;

const { colors: { primary, secondary, text, padding, workspacePadding, background } } = themeConfig;

const [selected, setSelected] = useState(themeConfig.name === themeName);

const changeTheme = (name: string) => {
const newThemeConfig = themeConfigs.get(name);

if (newThemeConfig === undefined) {
console.error(`Theme ${name} not found.`);
return;
}

globalDispatch(setTheme(newThemeConfig));
};

useEffect(() => {
setSelected(themeConfig.name === themeName);
}, [themeConfig, themeName]);

useEffect(() => {
document.documentElement.style.setProperty('--primary-color', primary);
document.documentElement.style.setProperty('--secondary-color', secondary);
document.documentElement.style.setProperty('--text-color', text);
document.documentElement.style.setProperty('--padding-color', padding);
document.documentElement.style.setProperty('--workspace-padding-color', workspacePadding);
document.documentElement.style.setProperty('--background-color', background);
}, [background, padding, primary, secondary, workspacePadding, text]);

return (
<Button className={`flex w-64 ${className}`} onClick={() => changeTheme(themeName)}>
{selected
? <MdCheckCircle className="mt-1 mx-4 transition-opacity duration-200 ease-in-out opacity-100" size={20} />
: <MdCheckCircle className="mt-1 mx-4 transition-opacity duration-200 ease-in-out opacity-0" size={20} />}
{title}
nakajimayoshi marked this conversation as resolved.
Show resolved Hide resolved
</Button>
);
};

export const themeButtons = themes.map((theme) => ({
themeName: theme.name,
title: theme.name.split('-').map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(' '),
className: 'hover:font-semibold',
}));
8 changes: 4 additions & 4 deletions src/components/menu/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const Menu: React.FC<MenuProps> = ({ title, icon, show, onClick, onExit,
<>
<button
className={classNames(
'w-14 h-14 flex items-center justify-center bg-silver-700 rounded-xl cursor-pointer ring-amethyst-400 ring-opacity-50 duration-200',
'w-14 h-14 flex items-center justify-center bg-theme-workspace-padding rounded-xl cursor-pointer ring-theme-primary duration-200',
{ 'ring-0': !show, 'ring-4': show },
)}
onClick={show ? onExit : onClick}
Expand All @@ -26,11 +26,11 @@ export const Menu: React.FC<MenuProps> = ({ title, icon, show, onClick, onExit,
{/* TODO: Don't unmount component, just hide */}
<AnimatePresence>
{show && (
<div className="absolute left-28 top-14 w-[26rem] bg-silver-800 shadow-2xl rounded-2xl z-30 overflow-hidden">
<div className="px-6 py-4 bg-silver-700 flex justify-between items-center">
<div className="absolute left-28 top-4 w-[26rem] bg-theme-padding shadow-2xl rounded-2xl z-30 overflow-hidden">
<div className="px-6 py-4 bg-theme-workspace-padding flex justify-between items-center">
<h4 className="font-medium">{title}</h4>
<button onClick={onExit}>
<FiX size={30} className="text-silver-400 cursor-pointer hover:text-silver-200" />
<FiX size={30} className="text-theme-workspace-padding cursor-pointer hover:text-theme-text" />
</button>
</div>
{children}
Expand Down
2 changes: 1 addition & 1 deletion src/components/modal/NewProjectModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export const NewProjectModal: React.FC<NewProjectModalProps> = ({ show, onExit }
}}
/>
{status && <p className="text-red-500">{status}</p>}
<Button className="bg-amethyst-500 hover:bg-amethyst-700 ring-amethyst-700 text-gray-100 font-bold" type="submit">Submit</Button>
<Button className="bg-theme-background hover:bg-theme-padding ring-theme-primary text-theme-text font-bold" type="submit">Submit</Button>
</Form>
)}
</Formik>
Expand Down
6 changes: 3 additions & 3 deletions src/components/modal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export const Modal: React.FC<ModalProps> = ({ title, show, onExit, children }) =
onClick={onExit}
>
<motion.div
className="relative max-w-1/2 mx-auto bg-silver-800 rounded-2xl shadow-2xl"
className="relative max-w-1/2 mx-auto bg-theme-background rounded-2xl shadow-2xl"
variants={modalAnimation}
transition={{
duration: 0.2,
Expand All @@ -70,11 +70,11 @@ export const Modal: React.FC<ModalProps> = ({ title, show, onExit, children }) =
exit="hidden"
onClick={(e) => e.stopPropagation()}
>
<div className="px-8 py-5 bg-silver-700 rounded-t-2xl flex justify-between items-center">
<div className="px-8 py-5 bg-theme-workspace-padding rounded-t-2xl flex justify-between items-center">
<h3 className="font-medium">{title}</h3>
<FiX
size={30}
className="text-silver-400 cursor-pointer hover:text-silver-200"
className="text-theme-padding cursor-pointer hover:text-theme-text"
onClick={onExit}
/>
</div>
Expand Down
Loading