mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): remove themes, add hand-crafted dark and light modes
Themes are very fun but due to the differences in perceived saturation and lightness across the the color spectrum, it's impossible to have have multiple themes that look great without hand- crafting *every* shade for *every* theme. We've ended up with 4 OK themes (well, 3, because the light theme was pretty bad). I've removed the themes and added color mode support. There is now a single dark and light mode, each with their own color palette and the classic grey / purple / yellow invoke colors that @blessedcoolant first designed. I've re-styled almost everything except the model manager and lightbox, which I keep forgetting to work on. One new concept is the Chakra `layerStyle`. This lets us define "layers" - think body, first layer, second layer, etc - that can be applied on various components. By defining layers, we can be more consistent about the z-axis and its relationship to color and lightness.
This commit is contained in:
parent
28d78a8fb4
commit
032c7e68d0
@ -3,17 +3,10 @@ import {
|
||||
createLocalStorageManager,
|
||||
extendTheme,
|
||||
} from '@chakra-ui/react';
|
||||
import { RootState } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { ReactNode, useEffect } from 'react';
|
||||
import { ReactNode, useEffect, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { theme as invokeAITheme } from 'theme/theme';
|
||||
|
||||
import { greenTeaThemeColors } from 'theme/colors/greenTea';
|
||||
import { invokeAIThemeColors } from 'theme/colors/invokeAI';
|
||||
import { lightThemeColors } from 'theme/colors/lightTheme';
|
||||
import { oceanBlueColors } from 'theme/colors/oceanBlue';
|
||||
|
||||
import '@fontsource-variable/inter';
|
||||
import { MantineProvider } from '@mantine/core';
|
||||
import { mantineTheme } from 'mantine-theme/theme';
|
||||
@ -24,29 +17,19 @@ type ThemeLocaleProviderProps = {
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
const THEMES = {
|
||||
dark: invokeAIThemeColors,
|
||||
light: lightThemeColors,
|
||||
green: greenTeaThemeColors,
|
||||
ocean: oceanBlueColors,
|
||||
};
|
||||
|
||||
const manager = createLocalStorageManager('@@invokeai-color-mode');
|
||||
|
||||
function ThemeLocaleProvider({ children }: ThemeLocaleProviderProps) {
|
||||
const { i18n } = useTranslation();
|
||||
|
||||
const currentTheme = useAppSelector(
|
||||
(state: RootState) => state.ui.currentTheme
|
||||
);
|
||||
|
||||
const direction = i18n.dir();
|
||||
|
||||
const theme = extendTheme({
|
||||
...invokeAITheme,
|
||||
colors: THEMES[currentTheme as keyof typeof THEMES],
|
||||
direction,
|
||||
});
|
||||
const theme = useMemo(() => {
|
||||
return extendTheme({
|
||||
...invokeAITheme,
|
||||
direction,
|
||||
});
|
||||
}, [direction]);
|
||||
|
||||
useEffect(() => {
|
||||
document.body.dir = direction;
|
||||
|
@ -1,6 +1,14 @@
|
||||
import { ChevronUpIcon } from '@chakra-ui/icons';
|
||||
import { Box, Collapse, Flex, Spacer, Switch } from '@chakra-ui/react';
|
||||
import {
|
||||
Box,
|
||||
Collapse,
|
||||
Flex,
|
||||
Spacer,
|
||||
Switch,
|
||||
useColorMode,
|
||||
} from '@chakra-ui/react';
|
||||
import { PropsWithChildren, memo } from 'react';
|
||||
import { mode } from 'theme/util/mode';
|
||||
|
||||
export type IAIToggleCollapseProps = PropsWithChildren & {
|
||||
label: string;
|
||||
@ -11,6 +19,7 @@ export type IAIToggleCollapseProps = PropsWithChildren & {
|
||||
|
||||
const IAICollapse = (props: IAIToggleCollapseProps) => {
|
||||
const { label, isOpen, onToggle, children, withSwitch = false } = props;
|
||||
const { colorMode } = useColorMode();
|
||||
return (
|
||||
<Box>
|
||||
<Flex
|
||||
@ -21,10 +30,14 @@ const IAICollapse = (props: IAIToggleCollapseProps) => {
|
||||
px: 4,
|
||||
borderTopRadius: 'base',
|
||||
borderBottomRadius: isOpen ? 0 : 'base',
|
||||
bg: isOpen ? 'base.750' : 'base.800',
|
||||
color: 'base.100',
|
||||
bg: isOpen
|
||||
? mode('base.200', 'base.750')(colorMode)
|
||||
: mode('base.150', 'base.800')(colorMode),
|
||||
color: mode('base.900', 'base.100')(colorMode),
|
||||
_hover: {
|
||||
bg: isOpen ? 'base.700' : 'base.750',
|
||||
bg: isOpen
|
||||
? mode('base.250', 'base.700')(colorMode)
|
||||
: mode('base.200', 'base.750')(colorMode),
|
||||
},
|
||||
fontSize: 'sm',
|
||||
fontWeight: 600,
|
||||
@ -50,7 +63,13 @@ const IAICollapse = (props: IAIToggleCollapseProps) => {
|
||||
)}
|
||||
</Flex>
|
||||
<Collapse in={isOpen} animateOpacity style={{ overflow: 'unset' }}>
|
||||
<Box sx={{ p: 4, borderBottomRadius: 'base', bg: 'base.800' }}>
|
||||
<Box
|
||||
sx={{
|
||||
p: 4,
|
||||
borderBottomRadius: 'base',
|
||||
bg: mode('base.100', 'base.800')(colorMode),
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
</Collapse>
|
||||
|
@ -5,6 +5,7 @@ import {
|
||||
Icon,
|
||||
IconButtonProps,
|
||||
Image,
|
||||
useColorMode,
|
||||
} from '@chakra-ui/react';
|
||||
import { useDraggable, useDroppable } from '@dnd-kit/core';
|
||||
import { useCombinedRefs } from '@dnd-kit/utilities';
|
||||
@ -20,6 +21,7 @@ import { v4 as uuidv4 } from 'uuid';
|
||||
import IAIDropOverlay from './IAIDropOverlay';
|
||||
import { PostUploadAction } from 'services/api/thunks/image';
|
||||
import { useImageUploadButton } from 'common/hooks/useImageUploadButton';
|
||||
import { mode } from 'theme/util/mode';
|
||||
|
||||
type IAIDndImageProps = {
|
||||
image: ImageDTO | null | undefined;
|
||||
@ -62,6 +64,7 @@ const IAIDndImage = (props: IAIDndImageProps) => {
|
||||
} = props;
|
||||
|
||||
const dndId = useRef(uuidv4());
|
||||
const { colorMode } = useColorMode();
|
||||
|
||||
const {
|
||||
isOver,
|
||||
@ -99,10 +102,10 @@ const IAIDndImage = (props: IAIDndImageProps) => {
|
||||
? {}
|
||||
: {
|
||||
cursor: 'pointer',
|
||||
bg: 'base.800',
|
||||
bg: mode('base.200', 'base.800')(colorMode),
|
||||
_hover: {
|
||||
bg: 'base.750',
|
||||
color: 'base.300',
|
||||
bg: mode('base.300', 'base.650')(colorMode),
|
||||
color: mode('base.500', 'base.300')(colorMode),
|
||||
},
|
||||
};
|
||||
|
||||
@ -181,7 +184,7 @@ const IAIDndImage = (props: IAIDndImageProps) => {
|
||||
borderRadius: 'base',
|
||||
transitionProperty: 'common',
|
||||
transitionDuration: '0.1s',
|
||||
color: 'base.500',
|
||||
color: mode('base.500', 'base.500')(colorMode),
|
||||
...uploadButtonStyles,
|
||||
}}
|
||||
{...getUploadButtonProps()}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { Flex, Text } from '@chakra-ui/react';
|
||||
import { Flex, Text, useColorMode } from '@chakra-ui/react';
|
||||
import { motion } from 'framer-motion';
|
||||
import { memo, useRef } from 'react';
|
||||
import { mode } from 'theme/util/mode';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
type Props = {
|
||||
@ -11,6 +12,7 @@ type Props = {
|
||||
export const IAIDropOverlay = (props: Props) => {
|
||||
const { isOver, label = 'Drop' } = props;
|
||||
const motionId = useRef(uuidv4());
|
||||
const { colorMode } = useColorMode();
|
||||
return (
|
||||
<motion.div
|
||||
key={motionId.current}
|
||||
@ -42,7 +44,7 @@ export const IAIDropOverlay = (props: Props) => {
|
||||
insetInlineStart: 0,
|
||||
w: 'full',
|
||||
h: 'full',
|
||||
bg: 'base.900',
|
||||
bg: mode('base.700', 'base.900')(colorMode),
|
||||
opacity: 0.7,
|
||||
borderRadius: 'base',
|
||||
alignItems: 'center',
|
||||
@ -61,7 +63,9 @@ export const IAIDropOverlay = (props: Props) => {
|
||||
h: 'full',
|
||||
opacity: 1,
|
||||
borderWidth: 2,
|
||||
borderColor: isOver ? 'base.200' : 'base.500',
|
||||
borderColor: isOver
|
||||
? mode('base.50', 'base.200')(colorMode)
|
||||
: mode('base.100', 'base.500')(colorMode),
|
||||
borderRadius: 'base',
|
||||
borderStyle: 'dashed',
|
||||
transitionProperty: 'common',
|
||||
@ -75,7 +79,9 @@ export const IAIDropOverlay = (props: Props) => {
|
||||
fontSize: '2xl',
|
||||
fontWeight: 600,
|
||||
transform: isOver ? 'scale(1.1)' : 'scale(1)',
|
||||
color: isOver ? 'base.100' : 'base.500',
|
||||
color: isOver
|
||||
? mode('base.100', 'base.100')(colorMode)
|
||||
: mode('base.200', 'base.500')(colorMode),
|
||||
transitionProperty: 'common',
|
||||
transitionDuration: '0.1s',
|
||||
}}
|
||||
|
@ -6,9 +6,10 @@ import {
|
||||
IconProps,
|
||||
Spinner,
|
||||
SpinnerProps,
|
||||
useColorMode,
|
||||
} from '@chakra-ui/react';
|
||||
import { ReactElement } from 'react';
|
||||
import { FaImage } from 'react-icons/fa';
|
||||
import { mode } from 'theme/util/mode';
|
||||
|
||||
type Props = FlexProps & {
|
||||
spinnerProps?: SpinnerProps;
|
||||
@ -17,10 +18,11 @@ type Props = FlexProps & {
|
||||
export const IAIImageLoadingFallback = (props: Props) => {
|
||||
const { spinnerProps, ...rest } = props;
|
||||
const { sx, ...restFlexProps } = rest;
|
||||
const { colorMode } = useColorMode();
|
||||
return (
|
||||
<Flex
|
||||
sx={{
|
||||
bg: 'base.900',
|
||||
bg: mode('base.200', 'base.900')(colorMode),
|
||||
opacity: 0.7,
|
||||
w: 'full',
|
||||
h: 'full',
|
||||
@ -45,10 +47,12 @@ type IAINoImageFallbackProps = {
|
||||
export const IAINoImageFallback = (props: IAINoImageFallbackProps) => {
|
||||
const { sx: flexSx, ...restFlexProps } = props.flexProps ?? { sx: {} };
|
||||
const { sx: iconSx, ...restIconProps } = props.iconProps ?? { sx: {} };
|
||||
const { colorMode } = useColorMode();
|
||||
|
||||
return (
|
||||
<Flex
|
||||
sx={{
|
||||
bg: 'base.900',
|
||||
bg: mode('base.200', 'base.900')(colorMode),
|
||||
opacity: 0.7,
|
||||
w: 'full',
|
||||
h: 'full',
|
||||
@ -61,7 +65,7 @@ export const IAINoImageFallback = (props: IAINoImageFallbackProps) => {
|
||||
>
|
||||
<Icon
|
||||
as={props.as ?? FaImage}
|
||||
sx={{ color: 'base.700', ...iconSx }}
|
||||
sx={{ color: mode('base.700', 'base.500')(colorMode), ...iconSx }}
|
||||
{...restIconProps}
|
||||
/>
|
||||
</Flex>
|
||||
|
@ -1,6 +1,8 @@
|
||||
import { Tooltip } from '@chakra-ui/react';
|
||||
import { Tooltip, useColorMode, useToken } from '@chakra-ui/react';
|
||||
import { MultiSelect, MultiSelectProps } from '@mantine/core';
|
||||
import { useChakraThemeTokens } from 'common/hooks/useChakraThemeTokens';
|
||||
import { memo } from 'react';
|
||||
import { mode } from 'theme/util/mode';
|
||||
|
||||
type IAIMultiSelectProps = MultiSelectProps & {
|
||||
tooltip?: string;
|
||||
@ -8,71 +10,101 @@ type IAIMultiSelectProps = MultiSelectProps & {
|
||||
|
||||
const IAIMantineMultiSelect = (props: IAIMultiSelectProps) => {
|
||||
const { searchable = true, tooltip, ...rest } = props;
|
||||
const {
|
||||
base50,
|
||||
base100,
|
||||
base200,
|
||||
base250,
|
||||
base300,
|
||||
base400,
|
||||
base500,
|
||||
base600,
|
||||
base700,
|
||||
base800,
|
||||
base900,
|
||||
accent200,
|
||||
accent300,
|
||||
accent400,
|
||||
accent500,
|
||||
accent600,
|
||||
accent700,
|
||||
} = useChakraThemeTokens();
|
||||
const [boxShadow] = useToken('shadows', ['dark-lg']);
|
||||
const { colorMode } = useColorMode();
|
||||
|
||||
return (
|
||||
<Tooltip label={tooltip} placement="top" hasArrow>
|
||||
<MultiSelect
|
||||
searchable={searchable}
|
||||
styles={() => ({
|
||||
label: {
|
||||
color: 'var(--invokeai-colors-base-300)',
|
||||
color: mode(base700, base300)(colorMode),
|
||||
fontWeight: 'normal',
|
||||
},
|
||||
searchInput: {
|
||||
'::placeholder': {
|
||||
color: 'var(--invokeai-colors-base-700)',
|
||||
':placeholder': {
|
||||
color: mode(base300, base700)(colorMode),
|
||||
},
|
||||
},
|
||||
input: {
|
||||
backgroundColor: 'var(--invokeai-colors-base-900)',
|
||||
backgroundColor: mode(base50, base900)(colorMode),
|
||||
borderWidth: '2px',
|
||||
borderColor: 'var(--invokeai-colors-base-800)',
|
||||
color: 'var(--invokeai-colors-base-100)',
|
||||
borderColor: mode(base200, base800)(colorMode),
|
||||
color: mode(base900, base100)(colorMode),
|
||||
paddingRight: 24,
|
||||
fontWeight: 600,
|
||||
'&:hover': { borderColor: 'var(--invokeai-colors-base-700)' },
|
||||
'&:hover': { borderColor: mode(base300, base600)(colorMode) },
|
||||
'&:focus': {
|
||||
borderColor: 'var(--invokeai-colors-accent-600)',
|
||||
borderColor: mode(accent300, accent600)(colorMode),
|
||||
},
|
||||
'&:is(:focus, :hover)': {
|
||||
borderColor: mode(base400, base500)(colorMode),
|
||||
},
|
||||
'&:focus-within': {
|
||||
borderColor: 'var(--invokeai-colors-accent-600)',
|
||||
borderColor: mode(accent200, accent600)(colorMode),
|
||||
},
|
||||
'&:disabled': {
|
||||
backgroundColor: mode(base300, base700)(colorMode),
|
||||
color: mode(base600, base400)(colorMode),
|
||||
},
|
||||
},
|
||||
value: {
|
||||
backgroundColor: 'var(--invokeai-colors-base-800)',
|
||||
color: 'var(--invokeai-colors-base-100)',
|
||||
backgroundColor: mode(base200, base800)(colorMode),
|
||||
color: mode(base900, base100)(colorMode),
|
||||
button: {
|
||||
color: 'var(--invokeai-colors-base-100)',
|
||||
color: mode(base900, base100)(colorMode),
|
||||
},
|
||||
'&:hover': {
|
||||
backgroundColor: 'var(--invokeai-colors-base-700)',
|
||||
backgroundColor: mode(base300, base700)(colorMode),
|
||||
cursor: 'pointer',
|
||||
},
|
||||
},
|
||||
dropdown: {
|
||||
backgroundColor: 'var(--invokeai-colors-base-800)',
|
||||
borderColor: 'var(--invokeai-colors-base-700)',
|
||||
backgroundColor: mode(base200, base800)(colorMode),
|
||||
borderColor: mode(base200, base800)(colorMode),
|
||||
boxShadow,
|
||||
},
|
||||
item: {
|
||||
backgroundColor: 'var(--invokeai-colors-base-800)',
|
||||
color: 'var(--invokeai-colors-base-200)',
|
||||
backgroundColor: mode(base200, base800)(colorMode),
|
||||
color: mode(base800, base200)(colorMode),
|
||||
padding: 6,
|
||||
'&[data-hovered]': {
|
||||
color: 'var(--invokeai-colors-base-100)',
|
||||
backgroundColor: 'var(--invokeai-colors-base-750)',
|
||||
color: mode(base900, base100)(colorMode),
|
||||
backgroundColor: mode(base300, base700)(colorMode),
|
||||
},
|
||||
'&[data-active]': {
|
||||
backgroundColor: 'var(--invokeai-colors-base-750)',
|
||||
backgroundColor: mode(base300, base700)(colorMode),
|
||||
'&:hover': {
|
||||
color: 'var(--invokeai-colors-base-100)',
|
||||
backgroundColor: 'var(--invokeai-colors-base-750)',
|
||||
color: mode(base900, base100)(colorMode),
|
||||
backgroundColor: mode(base300, base700)(colorMode),
|
||||
},
|
||||
},
|
||||
'&[data-selected]': {
|
||||
color: 'var(--invokeai-colors-base-50)',
|
||||
backgroundColor: 'var(--invokeai-colors-accent-650)',
|
||||
color: mode(base900, base50)(colorMode),
|
||||
backgroundColor: mode(accent300, accent600)(colorMode),
|
||||
fontWeight: 600,
|
||||
'&:hover': {
|
||||
backgroundColor: 'var(--invokeai-colors-accent-600)',
|
||||
backgroundColor: mode(accent400, accent500)(colorMode),
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -80,7 +112,7 @@ const IAIMantineMultiSelect = (props: IAIMultiSelectProps) => {
|
||||
width: 24,
|
||||
padding: 20,
|
||||
button: {
|
||||
color: 'var(--invokeai-colors-base-100)',
|
||||
color: mode(base900, base100)(colorMode),
|
||||
},
|
||||
},
|
||||
})}
|
||||
|
@ -1,6 +1,8 @@
|
||||
import { Tooltip } from '@chakra-ui/react';
|
||||
import { Tooltip, useColorMode, useToken } from '@chakra-ui/react';
|
||||
import { Select, SelectProps } from '@mantine/core';
|
||||
import { useChakraThemeTokens } from 'common/hooks/useChakraThemeTokens';
|
||||
import { memo } from 'react';
|
||||
import { mode } from 'theme/util/mode';
|
||||
|
||||
export type IAISelectDataType = {
|
||||
value: string;
|
||||
@ -14,61 +16,105 @@ type IAISelectProps = SelectProps & {
|
||||
|
||||
const IAIMantineSelect = (props: IAISelectProps) => {
|
||||
const { searchable = true, tooltip, ...rest } = props;
|
||||
const {
|
||||
base50,
|
||||
base100,
|
||||
base200,
|
||||
base300,
|
||||
base400,
|
||||
base500,
|
||||
base600,
|
||||
base700,
|
||||
base800,
|
||||
base900,
|
||||
accent200,
|
||||
accent300,
|
||||
accent400,
|
||||
accent500,
|
||||
accent600,
|
||||
accent700,
|
||||
} = useChakraThemeTokens();
|
||||
|
||||
const { colorMode } = useColorMode();
|
||||
|
||||
const [boxShadow] = useToken('shadows', ['dark-lg']);
|
||||
|
||||
return (
|
||||
<Tooltip label={tooltip} placement="top" hasArrow>
|
||||
<Select
|
||||
searchable={searchable}
|
||||
styles={() => ({
|
||||
label: {
|
||||
color: 'var(--invokeai-colors-base-300)',
|
||||
color: mode(base700, base300)(colorMode),
|
||||
fontWeight: 'normal',
|
||||
},
|
||||
input: {
|
||||
backgroundColor: 'var(--invokeai-colors-base-900)',
|
||||
backgroundColor: mode(base50, base900)(colorMode),
|
||||
borderWidth: '2px',
|
||||
borderColor: 'var(--invokeai-colors-base-800)',
|
||||
color: 'var(--invokeai-colors-base-100)',
|
||||
borderColor: mode(base200, base800)(colorMode),
|
||||
color: mode(base900, base100)(colorMode),
|
||||
paddingRight: 24,
|
||||
fontWeight: 600,
|
||||
'&:hover': { borderColor: 'var(--invokeai-colors-base-700)' },
|
||||
'&:hover': { borderColor: mode(base300, base600)(colorMode) },
|
||||
'&:focus': {
|
||||
borderColor: 'var(--invokeai-colors-accent-600)',
|
||||
borderColor: mode(accent300, accent600)(colorMode),
|
||||
},
|
||||
'&:is(:focus, :hover)': {
|
||||
borderColor: mode(base400, base500)(colorMode),
|
||||
},
|
||||
'&:focus-within': {
|
||||
borderColor: mode(accent200, accent600)(colorMode),
|
||||
},
|
||||
'&:disabled': {
|
||||
backgroundColor: 'var(--invokeai-colors-base-700)',
|
||||
color: 'var(--invokeai-colors-base-400)',
|
||||
backgroundColor: mode(base300, base700)(colorMode),
|
||||
color: mode(base600, base400)(colorMode),
|
||||
},
|
||||
},
|
||||
value: {
|
||||
backgroundColor: mode(base100, base900)(colorMode),
|
||||
color: mode(base900, base100)(colorMode),
|
||||
button: {
|
||||
color: mode(base900, base100)(colorMode),
|
||||
},
|
||||
'&:hover': {
|
||||
backgroundColor: mode(base300, base700)(colorMode),
|
||||
cursor: 'pointer',
|
||||
},
|
||||
},
|
||||
dropdown: {
|
||||
backgroundColor: 'var(--invokeai-colors-base-800)',
|
||||
borderColor: 'var(--invokeai-colors-base-700)',
|
||||
backgroundColor: mode(base200, base800)(colorMode),
|
||||
borderColor: mode(base200, base800)(colorMode),
|
||||
boxShadow,
|
||||
},
|
||||
item: {
|
||||
backgroundColor: 'var(--invokeai-colors-base-800)',
|
||||
color: 'var(--invokeai-colors-base-200)',
|
||||
backgroundColor: mode(base200, base800)(colorMode),
|
||||
color: mode(base800, base200)(colorMode),
|
||||
padding: 6,
|
||||
'&[data-hovered]': {
|
||||
color: 'var(--invokeai-colors-base-100)',
|
||||
backgroundColor: 'var(--invokeai-colors-base-750)',
|
||||
color: mode(base900, base100)(colorMode),
|
||||
backgroundColor: mode(base300, base700)(colorMode),
|
||||
},
|
||||
'&[data-active]': {
|
||||
backgroundColor: 'var(--invokeai-colors-base-750)',
|
||||
backgroundColor: mode(base300, base700)(colorMode),
|
||||
'&:hover': {
|
||||
color: 'var(--invokeai-colors-base-100)',
|
||||
backgroundColor: 'var(--invokeai-colors-base-750)',
|
||||
color: mode(base900, base100)(colorMode),
|
||||
backgroundColor: mode(base300, base700)(colorMode),
|
||||
},
|
||||
},
|
||||
'&[data-selected]': {
|
||||
color: 'var(--invokeai-colors-base-50)',
|
||||
backgroundColor: 'var(--invokeai-colors-accent-650)',
|
||||
color: mode(base900, base50)(colorMode),
|
||||
backgroundColor: mode(accent300, accent600)(colorMode),
|
||||
fontWeight: 600,
|
||||
'&:hover': {
|
||||
backgroundColor: 'var(--invokeai-colors-accent-600)',
|
||||
backgroundColor: mode(accent400, accent500)(colorMode),
|
||||
},
|
||||
},
|
||||
},
|
||||
rightSection: {
|
||||
width: 32,
|
||||
button: {
|
||||
color: mode(base900, base100)(colorMode),
|
||||
},
|
||||
},
|
||||
})}
|
||||
{...rest}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { Checkbox, CheckboxProps, Text } from '@chakra-ui/react';
|
||||
import { Checkbox, CheckboxProps, Text, useColorMode } from '@chakra-ui/react';
|
||||
import { memo, ReactElement } from 'react';
|
||||
import { mode } from 'theme/util/mode';
|
||||
|
||||
type IAISimpleCheckboxProps = CheckboxProps & {
|
||||
label: string | ReactElement;
|
||||
@ -7,9 +8,15 @@ type IAISimpleCheckboxProps = CheckboxProps & {
|
||||
|
||||
const IAISimpleCheckbox = (props: IAISimpleCheckboxProps) => {
|
||||
const { label, ...rest } = props;
|
||||
const { colorMode } = useColorMode();
|
||||
return (
|
||||
<Checkbox colorScheme="accent" {...rest}>
|
||||
<Text color="base.200" fontSize="md">
|
||||
<Text
|
||||
sx={{
|
||||
fontSize: 'sm',
|
||||
color: mode('base.800', 'base.200')(colorMode),
|
||||
}}
|
||||
>
|
||||
{label}
|
||||
</Text>
|
||||
</Checkbox>
|
||||
|
124
invokeai/frontend/web/src/common/hooks/useChakraThemeTokens.ts
Normal file
124
invokeai/frontend/web/src/common/hooks/useChakraThemeTokens.ts
Normal file
@ -0,0 +1,124 @@
|
||||
import { useToken } from '@chakra-ui/react';
|
||||
|
||||
export const useChakraThemeTokens = () => {
|
||||
const [
|
||||
base50,
|
||||
base100,
|
||||
base150,
|
||||
base200,
|
||||
base250,
|
||||
base300,
|
||||
base350,
|
||||
base400,
|
||||
base450,
|
||||
base500,
|
||||
base550,
|
||||
base600,
|
||||
base650,
|
||||
base700,
|
||||
base750,
|
||||
base800,
|
||||
base850,
|
||||
base900,
|
||||
base950,
|
||||
accent50,
|
||||
accent100,
|
||||
accent150,
|
||||
accent200,
|
||||
accent250,
|
||||
accent300,
|
||||
accent350,
|
||||
accent400,
|
||||
accent450,
|
||||
accent500,
|
||||
accent550,
|
||||
accent600,
|
||||
accent650,
|
||||
accent700,
|
||||
accent750,
|
||||
accent800,
|
||||
accent850,
|
||||
accent900,
|
||||
accent950,
|
||||
] = useToken('colors', [
|
||||
'base.50',
|
||||
'base.100',
|
||||
'base.150',
|
||||
'base.200',
|
||||
'base.250',
|
||||
'base.300',
|
||||
'base.350',
|
||||
'base.400',
|
||||
'base.450',
|
||||
'base.500',
|
||||
'base.550',
|
||||
'base.600',
|
||||
'base.650',
|
||||
'base.700',
|
||||
'base.750',
|
||||
'base.800',
|
||||
'base.850',
|
||||
'base.900',
|
||||
'base.950',
|
||||
'accent.50',
|
||||
'accent.100',
|
||||
'accent.150',
|
||||
'accent.200',
|
||||
'accent.250',
|
||||
'accent.300',
|
||||
'accent.350',
|
||||
'accent.400',
|
||||
'accent.450',
|
||||
'accent.500',
|
||||
'accent.550',
|
||||
'accent.600',
|
||||
'accent.650',
|
||||
'accent.700',
|
||||
'accent.750',
|
||||
'accent.800',
|
||||
'accent.850',
|
||||
'accent.900',
|
||||
'accent.950',
|
||||
]);
|
||||
|
||||
return {
|
||||
base50,
|
||||
base100,
|
||||
base150,
|
||||
base200,
|
||||
base250,
|
||||
base300,
|
||||
base350,
|
||||
base400,
|
||||
base450,
|
||||
base500,
|
||||
base550,
|
||||
base600,
|
||||
base650,
|
||||
base700,
|
||||
base750,
|
||||
base800,
|
||||
base850,
|
||||
base900,
|
||||
base950,
|
||||
accent50,
|
||||
accent100,
|
||||
accent150,
|
||||
accent200,
|
||||
accent250,
|
||||
accent300,
|
||||
accent350,
|
||||
accent400,
|
||||
accent450,
|
||||
accent500,
|
||||
accent550,
|
||||
accent600,
|
||||
accent650,
|
||||
accent700,
|
||||
accent750,
|
||||
accent800,
|
||||
accent850,
|
||||
accent900,
|
||||
accent950,
|
||||
};
|
||||
};
|
@ -1,6 +1,6 @@
|
||||
// Grid drawing adapted from https://longviewcoder.com/2021/12/08/konva-a-better-grid/
|
||||
|
||||
import { useToken } from '@chakra-ui/react';
|
||||
import { useColorMode, useColorModeValue, useToken } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { RootState } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
@ -29,9 +29,12 @@ const IAICanvasGrid = () => {
|
||||
);
|
||||
const { stageScale, stageCoordinates, stageDimensions } =
|
||||
useAppSelector(selector);
|
||||
const { colorMode } = useColorMode();
|
||||
const [gridLines, setGridLines] = useState<ReactNode[]>([]);
|
||||
|
||||
const [gridLineColor] = useToken('colors', ['gridLineColor']);
|
||||
const [darkGridLineColor, lightGridLineColor] = useToken('colors', [
|
||||
'base.800',
|
||||
'base.200',
|
||||
]);
|
||||
|
||||
const unscale = useCallback(
|
||||
(value: number) => {
|
||||
@ -89,7 +92,7 @@ const IAICanvasGrid = () => {
|
||||
x={fullRect.x1 + i * 64}
|
||||
y={fullRect.y1}
|
||||
points={[0, 0, 0, ySize]}
|
||||
stroke={gridLineColor}
|
||||
stroke={colorMode === 'dark' ? darkGridLineColor : lightGridLineColor}
|
||||
strokeWidth={1}
|
||||
/>
|
||||
));
|
||||
@ -99,7 +102,7 @@ const IAICanvasGrid = () => {
|
||||
x={fullRect.x1}
|
||||
y={fullRect.y1 + i * 64}
|
||||
points={[0, 0, xSize, 0]}
|
||||
stroke={gridLineColor}
|
||||
stroke={colorMode === 'dark' ? darkGridLineColor : lightGridLineColor}
|
||||
strokeWidth={1}
|
||||
/>
|
||||
));
|
||||
@ -111,7 +114,9 @@ const IAICanvasGrid = () => {
|
||||
stageDimensions,
|
||||
currentTheme,
|
||||
unscale,
|
||||
gridLineColor,
|
||||
colorMode,
|
||||
darkGridLineColor,
|
||||
lightGridLineColor,
|
||||
]);
|
||||
|
||||
return <Group>{gridLines}</Group>;
|
||||
|
@ -104,7 +104,10 @@ const IAICanvasStatusText = () => {
|
||||
margin: 1,
|
||||
borderRadius: 'base',
|
||||
pointerEvents: 'none',
|
||||
bg: 'base.800',
|
||||
bg: 'base.200',
|
||||
_dark: {
|
||||
bg: 'base.800',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Box, ChakraProps, Flex } from '@chakra-ui/react';
|
||||
import { Box, ChakraProps, Flex, useColorMode } from '@chakra-ui/react';
|
||||
import { useAppDispatch } from 'app/store/storeHooks';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { FaCopy, FaTrash } from 'react-icons/fa';
|
||||
@ -22,6 +22,7 @@ import ParamControlNetShouldAutoConfig from './ParamControlNetShouldAutoConfig';
|
||||
import ParamControlNetBeginEnd from './parameters/ParamControlNetBeginEnd';
|
||||
import ParamControlNetControlMode from './parameters/ParamControlNetControlMode';
|
||||
import ParamControlNetProcessorSelect from './parameters/ParamControlNetProcessorSelect';
|
||||
import { mode } from 'theme/util/mode';
|
||||
|
||||
const expandedControlImageSx: ChakraProps['sx'] = { maxH: 96 };
|
||||
|
||||
@ -46,7 +47,7 @@ const ControlNet = (props: ControlNetProps) => {
|
||||
} = props.controlNet;
|
||||
const dispatch = useAppDispatch();
|
||||
const [isExpanded, toggleIsExpanded] = useToggle(false);
|
||||
|
||||
const { colorMode } = useColorMode();
|
||||
const handleDelete = useCallback(() => {
|
||||
dispatch(controlNetRemoved({ controlNetId }));
|
||||
}, [controlNetId, dispatch]);
|
||||
@ -67,7 +68,7 @@ const ControlNet = (props: ControlNetProps) => {
|
||||
flexDir: 'column',
|
||||
gap: 2,
|
||||
p: 3,
|
||||
bg: 'base.850',
|
||||
bg: mode('base.200', 'base.850')(colorMode),
|
||||
borderRadius: 'base',
|
||||
position: 'relative',
|
||||
}}
|
||||
@ -115,7 +116,7 @@ const ControlNet = (props: ControlNetProps) => {
|
||||
<ChevronUpIcon
|
||||
sx={{
|
||||
boxSize: 4,
|
||||
color: 'base.300',
|
||||
color: mode('base.700', 'base.300')(colorMode),
|
||||
transform: isExpanded ? 'rotate(0deg)' : 'rotate(180deg)',
|
||||
transitionProperty: 'common',
|
||||
transitionDuration: 'normal',
|
||||
@ -130,7 +131,7 @@ const ControlNet = (props: ControlNetProps) => {
|
||||
w: 1.5,
|
||||
h: 1.5,
|
||||
borderRadius: 'full',
|
||||
bg: 'error.200',
|
||||
bg: mode('error.700', 'error.200')(colorMode),
|
||||
top: 4,
|
||||
insetInlineEnd: 4,
|
||||
}}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Flex, Text } from '@chakra-ui/react';
|
||||
import { Flex, Text, useColorMode } from '@chakra-ui/react';
|
||||
import { FaImages } from 'react-icons/fa';
|
||||
import { boardIdSelected } from '../../store/boardSlice';
|
||||
import { useDispatch } from 'react-redux';
|
||||
@ -10,9 +10,11 @@ import { ImageDTO } from 'services/api/types';
|
||||
import { useRemoveImageFromBoardMutation } from 'services/api/endpoints/boardImages';
|
||||
import { useDroppable } from '@dnd-kit/core';
|
||||
import IAIDropOverlay from 'common/components/IAIDropOverlay';
|
||||
import { mode } from 'theme/util/mode';
|
||||
|
||||
const AllImagesBoard = ({ isSelected }: { isSelected: boolean }) => {
|
||||
const dispatch = useDispatch();
|
||||
const { colorMode } = useColorMode();
|
||||
|
||||
const handleAllImagesBoardClick = () => {
|
||||
dispatch(boardIdSelected());
|
||||
@ -79,7 +81,9 @@ const AllImagesBoard = ({ isSelected }: { isSelected: boolean }) => {
|
||||
</Flex>
|
||||
<Text
|
||||
sx={{
|
||||
color: isSelected ? 'base.50' : 'base.200',
|
||||
color: isSelected
|
||||
? mode('base.900', 'base.50')(colorMode)
|
||||
: mode('base.700', 'base.200')(colorMode),
|
||||
fontWeight: isSelected ? 600 : undefined,
|
||||
fontSize: 'xs',
|
||||
}}
|
||||
|
@ -62,13 +62,13 @@ const BoardsList = (props: Props) => {
|
||||
return (
|
||||
<Collapse in={isOpen} animateOpacity>
|
||||
<Flex
|
||||
layerStyle={'first'}
|
||||
sx={{
|
||||
flexDir: 'column',
|
||||
gap: 2,
|
||||
bg: 'base.800',
|
||||
borderRadius: 'base',
|
||||
p: 2,
|
||||
mt: 2,
|
||||
borderRadius: 'base',
|
||||
}}
|
||||
>
|
||||
<Flex sx={{ gap: 2, alignItems: 'center' }}>
|
||||
|
@ -8,6 +8,7 @@ import {
|
||||
Image,
|
||||
MenuItem,
|
||||
MenuList,
|
||||
useColorMode,
|
||||
} from '@chakra-ui/react';
|
||||
|
||||
import { useAppDispatch } from 'app/store/storeHooks';
|
||||
@ -30,6 +31,7 @@ import { AnimatePresence } from 'framer-motion';
|
||||
import IAIDropOverlay from 'common/components/IAIDropOverlay';
|
||||
import { SelectedItemOverlay } from '../SelectedItemOverlay';
|
||||
import { DeleteBoardImagesContext } from '../../../../app/contexts/DeleteBoardImagesContext';
|
||||
import { mode } from 'theme/util/mode';
|
||||
|
||||
interface HoverableBoardProps {
|
||||
board: BoardDTO;
|
||||
@ -43,6 +45,8 @@ const HoverableBoard = memo(({ board, isSelected }: HoverableBoardProps) => {
|
||||
board.cover_image_name ?? skipToken
|
||||
);
|
||||
|
||||
const { colorMode } = useColorMode();
|
||||
|
||||
const { board_name, board_id } = board;
|
||||
|
||||
const { onClickDeleteBoardImages } = useContext(DeleteBoardImagesContext);
|
||||
@ -110,7 +114,7 @@ const HoverableBoard = memo(({ board, isSelected }: HoverableBoardProps) => {
|
||||
</MenuItem>
|
||||
)}
|
||||
<MenuItem
|
||||
sx={{ color: 'error.300' }}
|
||||
sx={{ color: mode('error.700', 'error.300')(colorMode) }}
|
||||
icon={<FaTrash />}
|
||||
onClickCapture={handleDeleteBoard}
|
||||
>
|
||||
@ -180,7 +184,9 @@ const HoverableBoard = memo(({ board, isSelected }: HoverableBoardProps) => {
|
||||
>
|
||||
<EditablePreview
|
||||
sx={{
|
||||
color: isSelected ? 'base.50' : 'base.200',
|
||||
color: isSelected
|
||||
? mode('base.900', 'base.50')(colorMode)
|
||||
: mode('base.700', 'base.200')(colorMode),
|
||||
fontWeight: isSelected ? 600 : undefined,
|
||||
fontSize: 'xs',
|
||||
textAlign: 'center',
|
||||
@ -190,9 +196,9 @@ const HoverableBoard = memo(({ board, isSelected }: HoverableBoardProps) => {
|
||||
/>
|
||||
<EditableInput
|
||||
sx={{
|
||||
color: 'base.50',
|
||||
color: mode('base.900', 'base.50')(colorMode),
|
||||
fontSize: 'xs',
|
||||
borderColor: 'base.500',
|
||||
borderColor: mode('base.500', 'base.500')(colorMode),
|
||||
p: 0,
|
||||
outline: 0,
|
||||
}}
|
||||
|
@ -32,7 +32,6 @@ const CurrentImageDisplay = () => {
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
rowGap: 4,
|
||||
borderRadius: 'base',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
Text,
|
||||
VStack,
|
||||
forwardRef,
|
||||
useColorMode,
|
||||
useDisclosure,
|
||||
} from '@chakra-ui/react';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
@ -61,6 +62,7 @@ import BoardsList from './Boards/BoardsList';
|
||||
import { boardsSelector } from '../store/boardSlice';
|
||||
import { ChevronUpIcon } from '@chakra-ui/icons';
|
||||
import { useListAllBoardsQuery } from 'services/api/endpoints/boards';
|
||||
import { mode } from 'theme/util/mode';
|
||||
|
||||
const itemSelector = createSelector(
|
||||
[(state: RootState) => state],
|
||||
@ -135,6 +137,8 @@ const ImageGalleryContent = () => {
|
||||
},
|
||||
});
|
||||
|
||||
const { colorMode } = useColorMode();
|
||||
|
||||
const {
|
||||
shouldPinGallery,
|
||||
galleryImageMinimumWidth,
|
||||
@ -267,13 +271,17 @@ const ImageGalleryContent = () => {
|
||||
alignItems: 'center',
|
||||
px: 2,
|
||||
_hover: {
|
||||
bg: 'base.800',
|
||||
bg: mode('base.100', 'base.800')(colorMode),
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
noOfLines={1}
|
||||
sx={{ w: 'full', color: 'base.200', fontWeight: 600 }}
|
||||
sx={{
|
||||
w: 'full',
|
||||
color: mode('base.800', 'base.200')(colorMode),
|
||||
fontWeight: 600,
|
||||
}}
|
||||
>
|
||||
{selectedBoard ? selectedBoard.board_name : 'All Images'}
|
||||
</Text>
|
||||
|
@ -1,26 +1,40 @@
|
||||
import { useColorMode, useToken } from '@chakra-ui/react';
|
||||
import { motion } from 'framer-motion';
|
||||
import { mode } from 'theme/util/mode';
|
||||
|
||||
export const SelectedItemOverlay = () => (
|
||||
<motion.div
|
||||
initial={{
|
||||
opacity: 0,
|
||||
}}
|
||||
animate={{
|
||||
opacity: 1,
|
||||
transition: { duration: 0.1 },
|
||||
}}
|
||||
exit={{
|
||||
opacity: 0,
|
||||
transition: { duration: 0.1 },
|
||||
}}
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
insetInlineStart: 0,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
boxShadow: 'inset 0px 0px 0px 2px var(--invokeai-colors-accent-300)',
|
||||
borderRadius: 'var(--invokeai-radii-base)',
|
||||
}}
|
||||
/>
|
||||
);
|
||||
export const SelectedItemOverlay = () => {
|
||||
const [accent400, accent500] = useToken('colors', [
|
||||
'accent.400',
|
||||
'accent.500',
|
||||
]);
|
||||
|
||||
const { colorMode } = useColorMode();
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
initial={{
|
||||
opacity: 0,
|
||||
}}
|
||||
animate={{
|
||||
opacity: 1,
|
||||
transition: { duration: 0.1 },
|
||||
}}
|
||||
exit={{
|
||||
opacity: 0,
|
||||
transition: { duration: 0.1 },
|
||||
}}
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
insetInlineStart: 0,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
boxShadow: `inset 0px 0px 0px 2px ${mode(
|
||||
accent400,
|
||||
accent500
|
||||
)(colorMode)}`,
|
||||
borderRadius: 'var(--invokeai-radii-base)',
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
@ -12,15 +12,25 @@ const IAINodeHeader = (props: IAINodeHeaderProps) => {
|
||||
const { nodeId, template } = props;
|
||||
return (
|
||||
<Flex
|
||||
borderTopRadius="md"
|
||||
justifyContent="space-between"
|
||||
background="base.700"
|
||||
px={2}
|
||||
py={1}
|
||||
alignItems="center"
|
||||
sx={{
|
||||
borderTopRadius: 'md',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
px: 2,
|
||||
py: 1,
|
||||
bg: 'base.300',
|
||||
_dark: { bg: 'base.700' },
|
||||
}}
|
||||
>
|
||||
<Tooltip label={nodeId}>
|
||||
<Heading size="xs" fontWeight={600} color="base.100">
|
||||
<Heading
|
||||
size="xs"
|
||||
sx={{
|
||||
fontWeight: 600,
|
||||
color: 'base.900',
|
||||
_dark: { color: 'base.100' },
|
||||
}}
|
||||
>
|
||||
{template.title}
|
||||
</Heading>
|
||||
</Tooltip>
|
||||
@ -30,7 +40,16 @@ const IAINodeHeader = (props: IAINodeHeaderProps) => {
|
||||
hasArrow
|
||||
shouldWrapChildren
|
||||
>
|
||||
<Icon color="base.300" as={FaInfoCircle} h="min-content" />
|
||||
<Icon
|
||||
sx={{
|
||||
h: 'min-content',
|
||||
color: 'base.700',
|
||||
_dark: {
|
||||
color: 'base.300',
|
||||
},
|
||||
}}
|
||||
as={FaInfoCircle}
|
||||
/>
|
||||
</Tooltip>
|
||||
</Flex>
|
||||
);
|
||||
|
@ -72,7 +72,14 @@ export const InvocationComponent = memo((props: NodeProps<InvocationValue>) => {
|
||||
return (
|
||||
<InvocationComponentWrapper selected={selected}>
|
||||
<Flex sx={{ alignItems: 'center', justifyContent: 'center' }}>
|
||||
<Icon color="base.400" boxSize={32} as={FaExclamationCircle}></Icon>
|
||||
<Icon
|
||||
as={FaExclamationCircle}
|
||||
sx={{
|
||||
boxSize: 32,
|
||||
color: 'base.600',
|
||||
_dark: { color: 'base.400' },
|
||||
}}
|
||||
></Icon>
|
||||
<IAINodeResizer />
|
||||
</Flex>
|
||||
</InvocationComponentWrapper>
|
||||
@ -86,8 +93,9 @@ export const InvocationComponent = memo((props: NodeProps<InvocationValue>) => {
|
||||
sx={{
|
||||
flexDirection: 'column',
|
||||
borderBottomRadius: 'md',
|
||||
bg: 'base.800',
|
||||
py: 2,
|
||||
bg: 'base.200',
|
||||
_dark: { bg: 'base.800' },
|
||||
}}
|
||||
>
|
||||
<IAINodeOutputs nodeId={nodeId} outputs={outputs} template={template} />
|
||||
|
@ -8,12 +8,12 @@ import { memo } from 'react';
|
||||
const NodeEditor = () => {
|
||||
return (
|
||||
<Box
|
||||
layerStyle={'first'}
|
||||
sx={{
|
||||
position: 'relative',
|
||||
width: 'full',
|
||||
height: 'full',
|
||||
borderRadius: 'md',
|
||||
bg: 'base.850',
|
||||
borderRadius: 'base',
|
||||
}}
|
||||
>
|
||||
<ReactFlowProvider>
|
||||
|
@ -11,17 +11,20 @@ const NodeGraphOverlay = () => {
|
||||
return (
|
||||
<Box
|
||||
as="pre"
|
||||
fontFamily="monospace"
|
||||
position="absolute"
|
||||
top={2}
|
||||
right={2}
|
||||
opacity={0.7}
|
||||
background="base.800"
|
||||
p={2}
|
||||
maxHeight={500}
|
||||
maxWidth={500}
|
||||
overflowY="scroll"
|
||||
borderRadius="md"
|
||||
sx={{
|
||||
fontFamily: 'monospace',
|
||||
position: 'absolute',
|
||||
top: 2,
|
||||
right: 2,
|
||||
opacity: 0.7,
|
||||
p: 2,
|
||||
maxHeight: 500,
|
||||
maxWidth: 500,
|
||||
overflowY: 'scroll',
|
||||
borderRadius: 'base',
|
||||
bg: 'base.200',
|
||||
_dark: { bg: 'base.800' },
|
||||
}}
|
||||
>
|
||||
{JSON.stringify(graph, null, 2)}
|
||||
</Box>
|
||||
|
@ -1,15 +1,25 @@
|
||||
import { RootState } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { CSSProperties, memo } from 'react';
|
||||
import { useColorModeValue } from '@chakra-ui/react';
|
||||
import { memo } from 'react';
|
||||
import { MiniMap } from 'reactflow';
|
||||
|
||||
const MinimapStyle: CSSProperties = {
|
||||
background: 'var(--invokeai-colors-base-500)',
|
||||
};
|
||||
|
||||
const MinimapPanel = () => {
|
||||
const currentTheme = useAppSelector(
|
||||
(state: RootState) => state.ui.currentTheme
|
||||
const miniMapStyle = useColorModeValue(
|
||||
{
|
||||
background: 'var(--invokeai-colors-base-200)',
|
||||
},
|
||||
{
|
||||
background: 'var(--invokeai-colors-base-500)',
|
||||
}
|
||||
);
|
||||
|
||||
const nodeColor = useColorModeValue(
|
||||
'var(--invokeai-colors-accent-300)',
|
||||
'var(--invokeai-colors-accent-700)'
|
||||
);
|
||||
|
||||
const maskColor = useColorModeValue(
|
||||
'var(--invokeai-colors-blackAlpha-300)',
|
||||
'var(--invokeai-colors-blackAlpha-600)'
|
||||
);
|
||||
|
||||
return (
|
||||
@ -18,15 +28,9 @@ const MinimapPanel = () => {
|
||||
pannable
|
||||
zoomable
|
||||
nodeBorderRadius={30}
|
||||
style={MinimapStyle}
|
||||
nodeColor={
|
||||
currentTheme === 'light'
|
||||
? 'var(--invokeai-colors-accent-700)'
|
||||
: currentTheme === 'green'
|
||||
? 'var(--invokeai-colors-accent-600)'
|
||||
: 'var(--invokeai-colors-accent-700)'
|
||||
}
|
||||
maskColor="var(--invokeai-colors-base-700)"
|
||||
style={miniMapStyle}
|
||||
nodeColor={nodeColor}
|
||||
maskColor={maskColor}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
@ -4,17 +4,17 @@ import InitialImagePreview from './InitialImagePreview';
|
||||
const InitialImageDisplay = () => {
|
||||
return (
|
||||
<Flex
|
||||
layerStyle={'first'}
|
||||
sx={{
|
||||
position: 'relative',
|
||||
flexDirection: 'column',
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
rowGap: 4,
|
||||
borderRadius: 'base',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
bg: 'base.850',
|
||||
p: 4,
|
||||
borderRadius: 'base',
|
||||
}}
|
||||
>
|
||||
<Flex
|
||||
|
@ -20,6 +20,8 @@ import {
|
||||
MenuList,
|
||||
MenuOptionGroup,
|
||||
MenuItemOption,
|
||||
ButtonGroupProps,
|
||||
ButtonProps,
|
||||
} from '@chakra-ui/react';
|
||||
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
@ -55,7 +57,7 @@ interface CancelButtonProps {
|
||||
}
|
||||
|
||||
const CancelButton = (
|
||||
props: CancelButtonProps & Omit<IAIIconButtonProps, 'aria-label'>
|
||||
props: CancelButtonProps & Omit<ButtonProps, 'aria-label'>
|
||||
) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { btnGroupWidth = 'auto', ...rest } = props;
|
||||
@ -139,12 +141,14 @@ const CancelButton = (
|
||||
<MenuButton
|
||||
as={IAIIconButton}
|
||||
tooltip={t('parameters.cancel.setType')}
|
||||
tooltipPlacement="top"
|
||||
aria-label={t('parameters.cancel.setType')}
|
||||
icon={<ChevronDownIcon w="1em" h="1em" />}
|
||||
paddingX={0}
|
||||
paddingY={0}
|
||||
colorScheme="error"
|
||||
minWidth={5}
|
||||
{...rest}
|
||||
/>
|
||||
<MenuList minWidth="240px">
|
||||
<MenuOptionGroup
|
||||
|
@ -71,7 +71,7 @@ export default function InvokeButton(props: InvokeButton) {
|
||||
flexGrow={1}
|
||||
w="100%"
|
||||
tooltip={t('parameters.invoke')}
|
||||
tooltipProps={{ placement: 'bottom' }}
|
||||
tooltipProps={{ placement: 'top' }}
|
||||
colorScheme="accent"
|
||||
id="invoke-button"
|
||||
{...rest}
|
||||
|
@ -0,0 +1,25 @@
|
||||
import { useColorMode } from '@chakra-ui/react';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import { FaMoon, FaSun } from 'react-icons/fa';
|
||||
|
||||
const ColorModeButton = () => {
|
||||
const { colorMode, toggleColorMode } = useColorMode();
|
||||
|
||||
return (
|
||||
<IAIIconButton
|
||||
aria-label="Toggle Color Mode"
|
||||
size="sm"
|
||||
icon={
|
||||
colorMode === 'dark' ? (
|
||||
<FaSun fontSize={19} />
|
||||
) : (
|
||||
<FaMoon fontSize={18} />
|
||||
)
|
||||
}
|
||||
onClick={toggleColorMode}
|
||||
variant="link"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default ColorModeButton;
|
@ -1,5 +1,4 @@
|
||||
import {
|
||||
ChakraProps,
|
||||
Flex,
|
||||
Heading,
|
||||
Modal,
|
||||
@ -10,6 +9,7 @@ import {
|
||||
ModalHeader,
|
||||
ModalOverlay,
|
||||
Text,
|
||||
useColorMode,
|
||||
useDisclosure,
|
||||
} from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
@ -39,6 +39,7 @@ import { UIState } from 'features/ui/store/uiTypes';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import {
|
||||
ChangeEvent,
|
||||
PropsWithChildren,
|
||||
ReactElement,
|
||||
cloneElement,
|
||||
useCallback,
|
||||
@ -47,6 +48,7 @@ import {
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { LogLevelName } from 'roarr';
|
||||
import SettingsSchedulers from './SettingsSchedulers';
|
||||
import { mode } from 'theme/util/mode';
|
||||
|
||||
const selector = createSelector(
|
||||
[systemSelector, uiSelector],
|
||||
@ -83,14 +85,6 @@ const selector = createSelector(
|
||||
}
|
||||
);
|
||||
|
||||
const modalSectionStyles: ChakraProps['sx'] = {
|
||||
flexDirection: 'column',
|
||||
gap: 2,
|
||||
p: 4,
|
||||
bg: 'base.900',
|
||||
borderRadius: 'base',
|
||||
};
|
||||
|
||||
type ConfigOptions = {
|
||||
shouldShowDeveloperSettings: boolean;
|
||||
shouldShowResetWebUiText: boolean;
|
||||
@ -183,12 +177,12 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => {
|
||||
isCentered
|
||||
>
|
||||
<ModalOverlay />
|
||||
<ModalContent paddingInlineEnd={4}>
|
||||
<ModalContent>
|
||||
<ModalHeader>{t('common.settingsLabel')}</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody>
|
||||
<Flex sx={{ gap: 4, flexDirection: 'column' }}>
|
||||
<Flex sx={modalSectionStyles}>
|
||||
<StyledFlex>
|
||||
<Heading size="sm">{t('settings.general')}</Heading>
|
||||
<IAISwitch
|
||||
label={t('settings.confirmOnDelete')}
|
||||
@ -197,14 +191,14 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => {
|
||||
dispatch(setShouldConfirmOnDelete(e.target.checked))
|
||||
}
|
||||
/>
|
||||
</Flex>
|
||||
</StyledFlex>
|
||||
|
||||
<Flex sx={modalSectionStyles}>
|
||||
<StyledFlex>
|
||||
<Heading size="sm">{t('settings.generation')}</Heading>
|
||||
<SettingsSchedulers />
|
||||
</Flex>
|
||||
</StyledFlex>
|
||||
|
||||
<Flex sx={modalSectionStyles}>
|
||||
<StyledFlex>
|
||||
<Heading size="sm">{t('settings.ui')}</Heading>
|
||||
<IAISwitch
|
||||
label={t('settings.displayHelpIcons')}
|
||||
@ -245,10 +239,10 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => {
|
||||
)
|
||||
}
|
||||
/>
|
||||
</Flex>
|
||||
</StyledFlex>
|
||||
|
||||
{shouldShowDeveloperSettings && (
|
||||
<Flex sx={modalSectionStyles}>
|
||||
<StyledFlex>
|
||||
<Heading size="sm">{t('settings.developer')}</Heading>
|
||||
<IAISwitch
|
||||
label={t('settings.shouldLogToConsole')}
|
||||
@ -269,10 +263,10 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => {
|
||||
dispatch(setEnableImageDebugging(e.target.checked))
|
||||
}
|
||||
/>
|
||||
</Flex>
|
||||
</StyledFlex>
|
||||
)}
|
||||
|
||||
<Flex sx={modalSectionStyles}>
|
||||
<StyledFlex>
|
||||
<Heading size="sm">{t('settings.resetWebUI')}</Heading>
|
||||
<IAIButton colorScheme="error" onClick={handleClickResetWebUI}>
|
||||
{t('settings.resetWebUI')}
|
||||
@ -283,7 +277,7 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => {
|
||||
<Text>{t('settings.resetWebUIDesc2')}</Text>
|
||||
</>
|
||||
)}
|
||||
</Flex>
|
||||
</StyledFlex>
|
||||
</Flex>
|
||||
</ModalBody>
|
||||
|
||||
@ -319,3 +313,19 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => {
|
||||
};
|
||||
|
||||
export default SettingsModal;
|
||||
|
||||
const StyledFlex = (props: PropsWithChildren) => {
|
||||
return (
|
||||
<Flex
|
||||
layerStyle="second"
|
||||
sx={{
|
||||
flexDirection: 'column',
|
||||
gap: 2,
|
||||
p: 4,
|
||||
borderRadius: 'base',
|
||||
}}
|
||||
>
|
||||
{props.children}
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
@ -12,8 +12,8 @@ import InvokeAILogoComponent from './InvokeAILogoComponent';
|
||||
import LanguagePicker from './LanguagePicker';
|
||||
import ModelManagerModal from './ModelManager/ModelManagerModal';
|
||||
import SettingsModal from './SettingsModal/SettingsModal';
|
||||
import ThemeChanger from './ThemeChanger';
|
||||
import { useFeatureStatus } from '../hooks/useFeatureStatus';
|
||||
import ColorModeButton from './ColorModeButton';
|
||||
|
||||
const SiteHeader = () => {
|
||||
const { t } = useTranslation();
|
||||
@ -63,8 +63,6 @@ const SiteHeader = () => {
|
||||
/>
|
||||
</HotkeysModal>
|
||||
|
||||
<ThemeChanger />
|
||||
|
||||
{isLocalizationEnabled && <LanguagePicker />}
|
||||
|
||||
{isBugLinkEnabled && (
|
||||
@ -121,6 +119,8 @@ const SiteHeader = () => {
|
||||
</Link>
|
||||
)}
|
||||
|
||||
<ColorModeButton />
|
||||
|
||||
<SettingsModal>
|
||||
<IAIIconButton
|
||||
aria-label={t('common.settingsLabel')}
|
||||
|
@ -35,6 +35,18 @@ const statusIndicatorSelector = createSelector(
|
||||
defaultSelectorOptions
|
||||
);
|
||||
|
||||
const DARK_COLOR_MAP = {
|
||||
ok: 'green.400',
|
||||
working: 'yellow.400',
|
||||
error: 'red.400',
|
||||
};
|
||||
|
||||
const LIGHT_COLOR_MAP = {
|
||||
ok: 'green.600',
|
||||
working: 'yellow.500',
|
||||
error: 'red.500',
|
||||
};
|
||||
|
||||
const StatusIndicator = () => {
|
||||
const {
|
||||
isConnected,
|
||||
@ -46,7 +58,7 @@ const StatusIndicator = () => {
|
||||
const { t } = useTranslation();
|
||||
const ref = useRef(null);
|
||||
|
||||
const statusColorScheme = useMemo(() => {
|
||||
const statusString = useMemo(() => {
|
||||
if (isProcessing) {
|
||||
return 'working';
|
||||
}
|
||||
@ -90,9 +102,10 @@ const StatusIndicator = () => {
|
||||
sx={{
|
||||
fontSize: 'sm',
|
||||
fontWeight: '600',
|
||||
color: `${statusColorScheme}.400`,
|
||||
pb: '1px',
|
||||
userSelect: 'none',
|
||||
color: LIGHT_COLOR_MAP[statusString],
|
||||
_dark: { color: DARK_COLOR_MAP[statusString] },
|
||||
}}
|
||||
>
|
||||
{t(statusTranslationKey as ResourceKey)}
|
||||
@ -101,7 +114,14 @@ const StatusIndicator = () => {
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
<Icon as={FaCircle} boxSize="0.5rem" color={`${statusColorScheme}.400`} />
|
||||
<Icon
|
||||
as={FaCircle}
|
||||
sx={{
|
||||
boxSize: '0.5rem',
|
||||
color: LIGHT_COLOR_MAP[statusString],
|
||||
_dark: { color: DARK_COLOR_MAP[statusString] },
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
@ -1,60 +0,0 @@
|
||||
import {
|
||||
IconButton,
|
||||
Menu,
|
||||
MenuButton,
|
||||
MenuItemOption,
|
||||
MenuList,
|
||||
MenuOptionGroup,
|
||||
Tooltip,
|
||||
} from '@chakra-ui/react';
|
||||
import { RootState } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { setCurrentTheme } from 'features/ui/store/uiSlice';
|
||||
import i18n from 'i18n';
|
||||
import { map } from 'lodash-es';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaPalette } from 'react-icons/fa';
|
||||
|
||||
export const THEMES = {
|
||||
dark: i18n.t('common.darkTheme'),
|
||||
light: i18n.t('common.lightTheme'),
|
||||
green: i18n.t('common.greenTheme'),
|
||||
ocean: i18n.t('common.oceanTheme'),
|
||||
};
|
||||
|
||||
export default function ThemeChanger() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
const currentTheme = useAppSelector(
|
||||
(state: RootState) => state.ui.currentTheme
|
||||
);
|
||||
|
||||
return (
|
||||
<Menu closeOnSelect={false}>
|
||||
<Tooltip label={t('common.themeLabel')} hasArrow>
|
||||
<MenuButton
|
||||
as={IconButton}
|
||||
icon={<FaPalette />}
|
||||
variant="link"
|
||||
aria-label={t('common.themeLabel')}
|
||||
fontSize={20}
|
||||
minWidth={8}
|
||||
/>
|
||||
</Tooltip>
|
||||
<MenuList>
|
||||
<MenuOptionGroup value={currentTheme}>
|
||||
{map(THEMES, (themeName, themeKey: keyof typeof THEMES) => (
|
||||
<MenuItemOption
|
||||
key={themeKey}
|
||||
value={themeKey}
|
||||
onClick={() => dispatch(setCurrentTheme(themeKey))}
|
||||
>
|
||||
{themeName}
|
||||
</MenuItemOption>
|
||||
))}
|
||||
</MenuOptionGroup>
|
||||
</MenuList>
|
||||
</Menu>
|
||||
);
|
||||
}
|
@ -51,6 +51,7 @@ const FloatingGalleryButton = () => {
|
||||
w: 8,
|
||||
borderStartEndRadius: 0,
|
||||
borderEndEndRadius: 0,
|
||||
shadow: '2xl',
|
||||
}}
|
||||
>
|
||||
<MdPhotoLibrary />
|
||||
|
@ -19,6 +19,7 @@ import { FaSlidersH } from 'react-icons/fa';
|
||||
const floatingButtonStyles: ChakraProps['sx'] = {
|
||||
borderStartStartRadius: 0,
|
||||
borderEndStartRadius: 0,
|
||||
shadow: '2xl',
|
||||
};
|
||||
|
||||
export const floatingParametersPanelButtonSelector = createSelector(
|
||||
|
@ -6,6 +6,7 @@ import {
|
||||
useOutsideClick,
|
||||
useTheme,
|
||||
SlideDirection,
|
||||
useColorMode,
|
||||
} from '@chakra-ui/react';
|
||||
import {
|
||||
Resizable,
|
||||
@ -21,6 +22,7 @@ import {
|
||||
getSlideDirection,
|
||||
getStyles,
|
||||
} from './util';
|
||||
import { mode } from 'theme/util/mode';
|
||||
|
||||
type ResizableDrawerProps = ResizableProps & {
|
||||
children: ReactNode;
|
||||
@ -64,7 +66,7 @@ const ResizableDrawer = ({
|
||||
sx = {},
|
||||
}: ResizableDrawerProps) => {
|
||||
const langDirection = useTheme().direction as LangDirection;
|
||||
|
||||
const { colorMode } = useColorMode();
|
||||
const outsideClickRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const defaultWidth = useMemo(
|
||||
@ -160,11 +162,11 @@ const ResizableDrawer = ({
|
||||
handleStyles={handleStyles}
|
||||
{...minMaxDimensions}
|
||||
sx={{
|
||||
borderColor: 'base.800',
|
||||
borderColor: mode('base.200', 'base.800')(colorMode),
|
||||
p: 4,
|
||||
bg: 'base.900',
|
||||
bg: mode('base.100', 'base.900')(colorMode),
|
||||
height: 'full',
|
||||
boxShadow: '0 0 4rem 0 rgba(0, 0, 0, 0.8)',
|
||||
shadow: isOpen ? 'dark-lg' : undefined,
|
||||
...containerStyles,
|
||||
...sx,
|
||||
}}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { Box, Flex, FlexProps } from '@chakra-ui/react';
|
||||
import { Box, Flex, FlexProps, useColorMode } from '@chakra-ui/react';
|
||||
import { memo } from 'react';
|
||||
import { PanelResizeHandle } from 'react-resizable-panels';
|
||||
import { mode } from 'theme/util/mode';
|
||||
|
||||
type ResizeHandleProps = FlexProps & {
|
||||
direction?: 'horizontal' | 'vertical';
|
||||
@ -8,6 +9,7 @@ type ResizeHandleProps = FlexProps & {
|
||||
|
||||
const ResizeHandle = (props: ResizeHandleProps) => {
|
||||
const { direction = 'horizontal', ...rest } = props;
|
||||
const { colorMode } = useColorMode();
|
||||
|
||||
if (direction === 'horizontal') {
|
||||
return (
|
||||
@ -21,7 +23,13 @@ const ResizeHandle = (props: ResizeHandleProps) => {
|
||||
}}
|
||||
{...rest}
|
||||
>
|
||||
<Box sx={{ w: 0.5, h: 'calc(100% - 4px)', bg: 'base.850' }} />
|
||||
<Box
|
||||
sx={{
|
||||
w: 0.5,
|
||||
h: 'calc(100% - 4px)',
|
||||
bg: mode('base.100', 'base.850')(colorMode),
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
</PanelResizeHandle>
|
||||
);
|
||||
@ -38,7 +46,13 @@ const ResizeHandle = (props: ResizeHandleProps) => {
|
||||
}}
|
||||
{...rest}
|
||||
>
|
||||
<Box sx={{ w: 'calc(100% - 4px)', h: 0.5, bg: 'base.850' }} />
|
||||
<Box
|
||||
sx={{
|
||||
w: 'calc(100% - 4px)',
|
||||
h: 0.5,
|
||||
bg: mode('base.100', 'base.850')(colorMode),
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
</PanelResizeHandle>
|
||||
);
|
||||
|
@ -4,13 +4,13 @@ import CurrentImageDisplay from 'features/gallery/components/CurrentImageDisplay
|
||||
const TextToImageTabMain = () => {
|
||||
return (
|
||||
<Box
|
||||
layerStyle={'first'}
|
||||
sx={{
|
||||
position: 'relative',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
borderRadius: 'base',
|
||||
bg: 'base.850',
|
||||
p: 4,
|
||||
borderRadius: 'base',
|
||||
}}
|
||||
>
|
||||
<Flex
|
||||
|
@ -67,14 +67,14 @@ const UnifiedCanvasContent = () => {
|
||||
if (shouldUseCanvasBetaLayout) {
|
||||
return (
|
||||
<Box
|
||||
layerStyle="first"
|
||||
ref={setDroppableRef}
|
||||
tabIndex={0}
|
||||
sx={{
|
||||
w: 'full',
|
||||
h: 'full',
|
||||
borderRadius: 'base',
|
||||
bg: 'base.850',
|
||||
p: 4,
|
||||
borderRadius: 'base',
|
||||
}}
|
||||
>
|
||||
<Flex
|
||||
@ -110,11 +110,11 @@ const UnifiedCanvasContent = () => {
|
||||
ref={setDroppableRef}
|
||||
tabIndex={-1}
|
||||
sx={{
|
||||
layerStyle: 'first',
|
||||
w: 'full',
|
||||
h: 'full',
|
||||
borderRadius: 'base',
|
||||
bg: 'base.850',
|
||||
p: 4,
|
||||
borderRadius: 'base',
|
||||
}}
|
||||
>
|
||||
<Flex
|
||||
|
@ -8,7 +8,6 @@ import { SchedulerParam } from 'features/parameters/store/parameterZodSchemas';
|
||||
|
||||
export const initialUIState: UIState = {
|
||||
activeTab: 0,
|
||||
currentTheme: 'dark',
|
||||
shouldPinParametersPanel: true,
|
||||
shouldShowParametersPanel: true,
|
||||
shouldShowImageDetails: false,
|
||||
@ -30,9 +29,6 @@ export const uiSlice = createSlice({
|
||||
setActiveTab: (state, action: PayloadAction<number | InvokeTabName>) => {
|
||||
setActiveTabReducer(state, action.payload);
|
||||
},
|
||||
setCurrentTheme: (state, action: PayloadAction<string>) => {
|
||||
state.currentTheme = action.payload;
|
||||
},
|
||||
setShouldPinParametersPanel: (state, action: PayloadAction<boolean>) => {
|
||||
state.shouldPinParametersPanel = action.payload;
|
||||
state.shouldShowParametersPanel = true;
|
||||
@ -110,7 +106,6 @@ export const uiSlice = createSlice({
|
||||
|
||||
export const {
|
||||
setActiveTab,
|
||||
setCurrentTheme,
|
||||
setShouldPinParametersPanel,
|
||||
setShouldShowParametersPanel,
|
||||
setShouldShowImageDetails,
|
||||
|
@ -16,7 +16,6 @@ export type Rect = Coordinates & Dimensions;
|
||||
|
||||
export interface UIState {
|
||||
activeTab: number;
|
||||
currentTheme: string;
|
||||
shouldPinParametersPanel: boolean;
|
||||
shouldShowParametersPanel: boolean;
|
||||
shouldShowImageDetails: boolean;
|
||||
|
@ -2,7 +2,7 @@ import { MantineThemeOverride } from '@mantine/core';
|
||||
|
||||
export const mantineTheme: MantineThemeOverride = {
|
||||
colorScheme: 'dark',
|
||||
fontFamily: `'InterVariable', sans-serif`,
|
||||
fontFamily: `'Inter Variable', sans-serif`,
|
||||
components: {
|
||||
ScrollArea: {
|
||||
defaultProps: {
|
||||
|
@ -1,18 +0,0 @@
|
||||
import { InvokeAIThemeColors } from 'theme/themeTypes';
|
||||
import { generateColorPalette } from '../util/generateColorPalette';
|
||||
|
||||
export const greenTeaThemeColors: InvokeAIThemeColors = {
|
||||
base: generateColorPalette(223, 10),
|
||||
baseAlpha: generateColorPalette(223, 10, false, true),
|
||||
accent: generateColorPalette(160, 60),
|
||||
accentAlpha: generateColorPalette(160, 60, false, true),
|
||||
working: generateColorPalette(47, 68),
|
||||
workingAlpha: generateColorPalette(47, 68, false, true),
|
||||
warning: generateColorPalette(28, 75),
|
||||
warningAlpha: generateColorPalette(28, 75, false, true),
|
||||
ok: generateColorPalette(122, 49),
|
||||
okAlpha: generateColorPalette(122, 49, false, true),
|
||||
error: generateColorPalette(0, 50),
|
||||
errorAlpha: generateColorPalette(0, 50, false, true),
|
||||
gridLineColor: 'rgba(255, 255, 255, 0.15)',
|
||||
};
|
@ -1,18 +0,0 @@
|
||||
import { InvokeAIThemeColors } from 'theme/themeTypes';
|
||||
import { generateColorPalette } from 'theme/util/generateColorPalette';
|
||||
|
||||
export const invokeAIThemeColors: InvokeAIThemeColors = {
|
||||
base: generateColorPalette(220, 15),
|
||||
baseAlpha: generateColorPalette(220, 15, false, true),
|
||||
accent: generateColorPalette(250, 50),
|
||||
accentAlpha: generateColorPalette(250, 50, false, true),
|
||||
working: generateColorPalette(47, 67),
|
||||
workingAlpha: generateColorPalette(47, 67, false, true),
|
||||
warning: generateColorPalette(28, 75),
|
||||
warningAlpha: generateColorPalette(28, 75, false, true),
|
||||
ok: generateColorPalette(113, 70),
|
||||
okAlpha: generateColorPalette(113, 70, false, true),
|
||||
error: generateColorPalette(0, 76),
|
||||
errorAlpha: generateColorPalette(0, 76, false, true),
|
||||
gridLineColor: 'rgba(150, 150, 180, 0.15)',
|
||||
};
|
@ -1,18 +0,0 @@
|
||||
import { InvokeAIThemeColors } from 'theme/themeTypes';
|
||||
import { generateColorPalette } from '../util/generateColorPalette';
|
||||
|
||||
export const lightThemeColors: InvokeAIThemeColors = {
|
||||
base: generateColorPalette(223, 10, true),
|
||||
baseAlpha: generateColorPalette(223, 10, true, true),
|
||||
accent: generateColorPalette(40, 80, true),
|
||||
accentAlpha: generateColorPalette(40, 80, true, true),
|
||||
working: generateColorPalette(47, 68, true),
|
||||
workingAlpha: generateColorPalette(47, 68, true, true),
|
||||
warning: generateColorPalette(28, 75, true),
|
||||
warningAlpha: generateColorPalette(28, 75, true, true),
|
||||
ok: generateColorPalette(122, 49, true),
|
||||
okAlpha: generateColorPalette(122, 49, true, true),
|
||||
error: generateColorPalette(0, 50, true),
|
||||
errorAlpha: generateColorPalette(0, 50, true, true),
|
||||
gridLineColor: 'rgba(0, 0, 0, 0.15)',
|
||||
};
|
@ -1,18 +0,0 @@
|
||||
import { InvokeAIThemeColors } from 'theme/themeTypes';
|
||||
import { generateColorPalette } from '../util/generateColorPalette';
|
||||
|
||||
export const oceanBlueColors: InvokeAIThemeColors = {
|
||||
base: generateColorPalette(220, 30),
|
||||
baseAlpha: generateColorPalette(220, 30, false, true),
|
||||
accent: generateColorPalette(210, 80),
|
||||
accentAlpha: generateColorPalette(210, 80, false, true),
|
||||
working: generateColorPalette(47, 68),
|
||||
workingAlpha: generateColorPalette(47, 68, false, true),
|
||||
warning: generateColorPalette(28, 75),
|
||||
warningAlpha: generateColorPalette(28, 75, false, true),
|
||||
ok: generateColorPalette(122, 49),
|
||||
okAlpha: generateColorPalette(122, 49, false, true),
|
||||
error: generateColorPalette(0, 100),
|
||||
errorAlpha: generateColorPalette(0, 100, false, true),
|
||||
gridLineColor: 'rgba(136, 148, 184, 0.15)',
|
||||
};
|
@ -3,6 +3,7 @@ import {
|
||||
createMultiStyleConfigHelpers,
|
||||
defineStyle,
|
||||
} from '@chakra-ui/styled-system';
|
||||
import { mode } from '@chakra-ui/theme-tools';
|
||||
|
||||
const { definePartsStyle, defineMultiStyleConfig } =
|
||||
createMultiStyleConfigHelpers(parts.keys);
|
||||
@ -18,16 +19,16 @@ const invokeAIButton = defineStyle((props) => {
|
||||
fontSize: 'sm',
|
||||
border: 'none',
|
||||
borderRadius: 'base',
|
||||
bg: `${c}.800`,
|
||||
color: 'base.100',
|
||||
bg: mode(`${c}.200`, `${c}.700`)(props),
|
||||
color: mode(`${c}.900`, `${c}.100`)(props),
|
||||
_hover: {
|
||||
bg: `${c}.700`,
|
||||
bg: mode(`${c}.250`, `${c}.650`)(props),
|
||||
},
|
||||
_expanded: {
|
||||
bg: `${c}.750`,
|
||||
bg: mode(`${c}.250`, `${c}.650`)(props),
|
||||
borderBottomRadius: 'none',
|
||||
_hover: {
|
||||
bg: `${c}.700`,
|
||||
bg: mode(`${c}.300`, `${c}.600`)(props),
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -36,7 +37,7 @@ const invokeAIButton = defineStyle((props) => {
|
||||
const invokeAIPanel = defineStyle((props) => {
|
||||
const { colorScheme: c } = props;
|
||||
return {
|
||||
bg: `${c}.800`,
|
||||
bg: mode(`${c}.100`, `${c}.800`)(props),
|
||||
borderRadius: 'base',
|
||||
borderTopRadius: 'none',
|
||||
};
|
||||
|
@ -1,44 +1,55 @@
|
||||
import { defineStyle, defineStyleConfig } from '@chakra-ui/react';
|
||||
import { mode } from '@chakra-ui/theme-tools';
|
||||
|
||||
const invokeAI = defineStyle((props) => {
|
||||
const { colorScheme: c } = props;
|
||||
// must specify `_disabled` colors if we override `_hover`, else hover on disabled has no styles
|
||||
const _disabled = {
|
||||
bg: `${c}.600`,
|
||||
color: `${c}.100`,
|
||||
bg: mode(`${c}.350`, `${c}.700`)(props),
|
||||
color: mode(`${c}.750`, `${c}.150`)(props),
|
||||
svg: {
|
||||
fill: `${c}.100`,
|
||||
fill: mode(`${c}.750`, `${c}.150`)(props),
|
||||
},
|
||||
opacity: 1,
|
||||
filter: 'saturate(65%)',
|
||||
};
|
||||
|
||||
return {
|
||||
bg: `${c}.700`,
|
||||
color: `${c}.100`,
|
||||
bg: mode(`${c}.200`, `${c}.600`)(props),
|
||||
color: mode(`${c}.850`, `${c}.100`)(props),
|
||||
borderRadius: 'base',
|
||||
textShadow: mode(
|
||||
`0 0 0.3rem var(--invokeai-colors-${c}-50)`,
|
||||
`0 0 0.3rem var(--invokeai-colors-${c}-900)`
|
||||
)(props),
|
||||
svg: {
|
||||
fill: `${c}.100`,
|
||||
fill: mode(`${c}.850`, `${c}.100`)(props),
|
||||
filter: mode(
|
||||
`drop-shadow(0px 0px 0.3rem var(--invokeai-colors-${c}-100))`,
|
||||
`drop-shadow(0px 0px 0.3rem var(--invokeai-colors-${c}-800))`
|
||||
)(props),
|
||||
},
|
||||
_disabled,
|
||||
_hover: {
|
||||
bg: `${c}.650`,
|
||||
color: `${c}.50`,
|
||||
bg: mode(`${c}.300`, `${c}.500`)(props),
|
||||
color: mode(`${c}.900`, `${c}.50`)(props),
|
||||
svg: {
|
||||
fill: `${c}.50`,
|
||||
fill: mode(`${c}.900`, `${c}.50`)(props),
|
||||
},
|
||||
_disabled,
|
||||
},
|
||||
_checked: {
|
||||
bg: 'accent.700',
|
||||
color: 'accent.100',
|
||||
bg: mode('accent.200', 'accent.600')(props),
|
||||
color: mode('accent.800', 'accent.100')(props),
|
||||
svg: {
|
||||
fill: 'accent.100',
|
||||
fill: mode('accent.800', 'accent.100')(props),
|
||||
},
|
||||
_disabled,
|
||||
_hover: {
|
||||
bg: 'accent.600',
|
||||
color: 'accent.50',
|
||||
bg: mode('accent.300', 'accent.500')(props),
|
||||
color: mode('accent.900', 'accent.50')(props),
|
||||
svg: {
|
||||
fill: 'accent.50',
|
||||
fill: mode('accent.900', 'accent.50')(props),
|
||||
},
|
||||
_disabled,
|
||||
},
|
||||
|
@ -3,6 +3,7 @@ import {
|
||||
createMultiStyleConfigHelpers,
|
||||
defineStyle,
|
||||
} from '@chakra-ui/styled-system';
|
||||
import { mode } from '@chakra-ui/theme-tools';
|
||||
|
||||
const { definePartsStyle, defineMultiStyleConfig } =
|
||||
createMultiStyleConfigHelpers(parts.keys);
|
||||
@ -11,14 +12,18 @@ const invokeAIControl = defineStyle((props) => {
|
||||
const { colorScheme: c } = props;
|
||||
|
||||
return {
|
||||
bg: mode('base.200', 'base.700')(props),
|
||||
borderColor: mode('base.200', 'base.700')(props),
|
||||
color: mode('base.900', 'base.100')(props),
|
||||
|
||||
_checked: {
|
||||
bg: `${c}.200`,
|
||||
borderColor: `${c}.200`,
|
||||
color: 'base.900',
|
||||
bg: mode(`${c}.300`, `${c}.600`)(props),
|
||||
borderColor: mode(`${c}.300`, `${c}.600`)(props),
|
||||
color: mode(`${c}.900`, `${c}.100`)(props),
|
||||
|
||||
_hover: {
|
||||
bg: `${c}.300`,
|
||||
borderColor: `${c}.300`,
|
||||
bg: mode(`${c}.400`, `${c}.500`)(props),
|
||||
borderColor: mode(`${c}.400`, `${c}.500`)(props),
|
||||
},
|
||||
|
||||
_disabled: {
|
||||
@ -29,9 +34,9 @@ const invokeAIControl = defineStyle((props) => {
|
||||
},
|
||||
|
||||
_indeterminate: {
|
||||
bg: `${c}.200`,
|
||||
borderColor: `${c}.200`,
|
||||
color: 'base.900',
|
||||
bg: mode(`${c}.300`, `${c}.600`)(props),
|
||||
borderColor: mode(`${c}.300`, `${c}.600`)(props),
|
||||
color: mode(`${c}.900`, `${c}.100`)(props),
|
||||
},
|
||||
|
||||
_disabled: {
|
||||
@ -44,7 +49,7 @@ const invokeAIControl = defineStyle((props) => {
|
||||
},
|
||||
|
||||
_invalid: {
|
||||
borderColor: 'red.300',
|
||||
borderColor: mode('error.600', 'error.300')(props),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { defineStyle, defineStyleConfig } from '@chakra-ui/styled-system';
|
||||
import { mode } from '@chakra-ui/theme-tools';
|
||||
|
||||
const invokeAI = defineStyle((_props) => {
|
||||
const invokeAI = defineStyle((props) => {
|
||||
return {
|
||||
fontSize: 'sm',
|
||||
marginEnd: 0,
|
||||
@ -12,7 +13,7 @@ const invokeAI = defineStyle((_props) => {
|
||||
_disabled: {
|
||||
opacity: 0.4,
|
||||
},
|
||||
color: 'base.300',
|
||||
color: mode('base.700', 'base.300')(props),
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -1,38 +1,40 @@
|
||||
import { menuAnatomy } from '@chakra-ui/anatomy';
|
||||
import { createMultiStyleConfigHelpers } from '@chakra-ui/react';
|
||||
import { mode } from '@chakra-ui/theme-tools';
|
||||
|
||||
const { definePartsStyle, defineMultiStyleConfig } =
|
||||
createMultiStyleConfigHelpers(menuAnatomy.keys);
|
||||
|
||||
// define the base component styles
|
||||
const invokeAI = definePartsStyle({
|
||||
const invokeAI = definePartsStyle((props) => ({
|
||||
// define the part you're going to style
|
||||
button: {
|
||||
// this will style the MenuButton component
|
||||
fontWeight: '600',
|
||||
bg: 'base.500',
|
||||
color: 'base.200',
|
||||
fontWeight: 500,
|
||||
bg: mode('base.300', 'base.500')(props),
|
||||
color: mode('base.900', 'base.100')(props),
|
||||
_hover: {
|
||||
bg: 'base.600',
|
||||
color: 'white',
|
||||
bg: mode('base.400', 'base.600')(props),
|
||||
color: mode('base.900', 'base.50')(props),
|
||||
fontWeight: 600,
|
||||
},
|
||||
},
|
||||
list: {
|
||||
zIndex: 9999,
|
||||
bg: 'base.800',
|
||||
bg: mode('base.200', 'base.800')(props),
|
||||
},
|
||||
item: {
|
||||
// this will style the MenuItem and MenuItemOption components
|
||||
fontSize: 'sm',
|
||||
bg: 'base.800',
|
||||
bg: mode('base.200', 'base.800')(props),
|
||||
_hover: {
|
||||
bg: 'base.750',
|
||||
bg: mode('base.300', 'base.700')(props),
|
||||
},
|
||||
_focus: {
|
||||
bg: 'base.700',
|
||||
bg: mode('base.400', 'base.600')(props),
|
||||
},
|
||||
},
|
||||
});
|
||||
}));
|
||||
|
||||
export const menuTheme = defineMultiStyleConfig({
|
||||
variants: {
|
||||
|
@ -3,28 +3,31 @@ import {
|
||||
createMultiStyleConfigHelpers,
|
||||
defineStyle,
|
||||
} from '@chakra-ui/styled-system';
|
||||
import { mode } from '@chakra-ui/theme-tools';
|
||||
|
||||
const { defineMultiStyleConfig, definePartsStyle } =
|
||||
createMultiStyleConfigHelpers(parts.keys);
|
||||
|
||||
const invokeAIOverlay = defineStyle({
|
||||
bg: 'blackAlpha.600',
|
||||
});
|
||||
const invokeAIOverlay = defineStyle((props) => ({
|
||||
bg: mode('blackAlpha.700', 'blackAlpha.700')(props),
|
||||
}));
|
||||
|
||||
const invokeAIDialogContainer = defineStyle({});
|
||||
|
||||
const invokeAIDialog = defineStyle((_props) => {
|
||||
const invokeAIDialog = defineStyle((props) => {
|
||||
return {
|
||||
bg: 'base.850',
|
||||
layerStyle: 'first',
|
||||
maxH: '80vh',
|
||||
};
|
||||
});
|
||||
|
||||
const invokeAIHeader = defineStyle((_props) => {
|
||||
const invokeAIHeader = defineStyle((props) => {
|
||||
return {
|
||||
fontWeight: '600',
|
||||
fontSize: 'lg',
|
||||
color: 'base.200',
|
||||
layerStyle: 'first',
|
||||
borderTopRadius: 'base',
|
||||
borderInlineEndRadius: 'base',
|
||||
};
|
||||
});
|
||||
|
||||
@ -37,7 +40,7 @@ const invokeAIBody = defineStyle({
|
||||
const invokeAIFooter = defineStyle({});
|
||||
|
||||
export const invokeAI = definePartsStyle((props) => ({
|
||||
overlay: invokeAIOverlay,
|
||||
overlay: invokeAIOverlay(props),
|
||||
dialogContainer: invokeAIDialogContainer,
|
||||
dialog: invokeAIDialog(props),
|
||||
header: invokeAIHeader(props),
|
||||
|
@ -5,6 +5,7 @@ import {
|
||||
} from '@chakra-ui/styled-system';
|
||||
|
||||
import { getInputOutlineStyles } from '../util/getInputOutlineStyles';
|
||||
import { mode } from '@chakra-ui/theme-tools';
|
||||
|
||||
const { defineMultiStyleConfig, definePartsStyle } =
|
||||
createMultiStyleConfigHelpers(parts.keys);
|
||||
@ -33,7 +34,7 @@ const invokeAIStepperGroup = defineStyle((_props) => {
|
||||
};
|
||||
});
|
||||
|
||||
const invokeAIStepper = defineStyle((_props) => {
|
||||
const invokeAIStepper = defineStyle((props) => {
|
||||
return {
|
||||
border: 'none',
|
||||
// expand arrow hitbox
|
||||
@ -43,11 +44,11 @@ const invokeAIStepper = defineStyle((_props) => {
|
||||
my: 0,
|
||||
|
||||
svg: {
|
||||
color: 'base.300',
|
||||
color: mode('base.700', 'base.300')(props),
|
||||
width: 2.5,
|
||||
height: 2.5,
|
||||
_hover: {
|
||||
color: 'base.50',
|
||||
color: mode('base.900', 'base.100')(props),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -3,7 +3,7 @@ import {
|
||||
createMultiStyleConfigHelpers,
|
||||
defineStyle,
|
||||
} from '@chakra-ui/styled-system';
|
||||
import { cssVar } from '@chakra-ui/theme-tools';
|
||||
import { cssVar, mode } from '@chakra-ui/theme-tools';
|
||||
|
||||
const { defineMultiStyleConfig, definePartsStyle } =
|
||||
createMultiStyleConfigHelpers(parts.keys);
|
||||
@ -12,15 +12,20 @@ const $popperBg = cssVar('popper-bg');
|
||||
const $arrowBg = cssVar('popper-arrow-bg');
|
||||
const $arrowShadowColor = cssVar('popper-arrow-shadow-color');
|
||||
|
||||
const invokeAIContent = defineStyle((_props) => {
|
||||
const invokeAIContent = defineStyle((props) => {
|
||||
return {
|
||||
[$arrowBg.variable]: `colors.base.800`,
|
||||
[$popperBg.variable]: `colors.base.800`,
|
||||
[$arrowShadowColor.variable]: `colors.base.600`,
|
||||
[$arrowBg.variable]: mode('colors.base.100', 'colors.base.800')(props),
|
||||
[$popperBg.variable]: mode('colors.base.100', 'colors.base.800')(props),
|
||||
[$arrowShadowColor.variable]: mode(
|
||||
'colors.base.400',
|
||||
'colors.base.600'
|
||||
)(props),
|
||||
minW: 'unset',
|
||||
width: 'unset',
|
||||
p: 4,
|
||||
bg: 'base.800',
|
||||
bg: mode('base.100', 'base.800')(props),
|
||||
border: 'none',
|
||||
shadow: 'dark-lg',
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -1,13 +1,14 @@
|
||||
import { selectAnatomy as parts } from '@chakra-ui/anatomy';
|
||||
import { createMultiStyleConfigHelpers, defineStyle } from '@chakra-ui/react';
|
||||
import { getInputOutlineStyles } from '../util/getInputOutlineStyles';
|
||||
import { mode } from '@chakra-ui/theme-tools';
|
||||
|
||||
const { definePartsStyle, defineMultiStyleConfig } =
|
||||
createMultiStyleConfigHelpers(parts.keys);
|
||||
|
||||
const invokeAIIcon = defineStyle((_props) => {
|
||||
const invokeAIIcon = defineStyle((props) => {
|
||||
return {
|
||||
color: 'base.300',
|
||||
color: mode('base.200', 'base.300')(props),
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -1,12 +1,13 @@
|
||||
import { sliderAnatomy as parts } from '@chakra-ui/anatomy';
|
||||
import { createMultiStyleConfigHelpers, defineStyle } from '@chakra-ui/react';
|
||||
import { mode } from '@chakra-ui/theme-tools';
|
||||
|
||||
const { definePartsStyle, defineMultiStyleConfig } =
|
||||
createMultiStyleConfigHelpers(parts.keys);
|
||||
|
||||
const invokeAITrack = defineStyle((_props) => {
|
||||
const invokeAITrack = defineStyle((props) => {
|
||||
return {
|
||||
bg: 'base.400',
|
||||
bg: mode('base.400', 'base.600')(props),
|
||||
h: 1.5,
|
||||
};
|
||||
});
|
||||
@ -14,23 +15,24 @@ const invokeAITrack = defineStyle((_props) => {
|
||||
const invokeAIFilledTrack = defineStyle((props) => {
|
||||
const { colorScheme: c } = props;
|
||||
return {
|
||||
bg: `${c}.600`,
|
||||
bg: mode(`${c}.400`, `${c}.600`)(props),
|
||||
h: 1.5,
|
||||
};
|
||||
});
|
||||
|
||||
const invokeAIThumb = defineStyle((_props) => {
|
||||
const invokeAIThumb = defineStyle((props) => {
|
||||
return {
|
||||
w: 2,
|
||||
h: 4,
|
||||
bg: mode('base.50', 'base.100')(props),
|
||||
};
|
||||
});
|
||||
|
||||
const invokeAIMark = defineStyle((_props) => {
|
||||
const invokeAIMark = defineStyle((props) => {
|
||||
return {
|
||||
fontSize: 'xs',
|
||||
fontWeight: '500',
|
||||
color: 'base.400',
|
||||
color: mode('base.700', 'base.400')(props),
|
||||
mt: 2,
|
||||
insetInlineStart: 'unset',
|
||||
};
|
||||
|
@ -3,6 +3,7 @@ import {
|
||||
createMultiStyleConfigHelpers,
|
||||
defineStyle,
|
||||
} from '@chakra-ui/styled-system';
|
||||
import { mode } from '@chakra-ui/theme-tools';
|
||||
|
||||
const { defineMultiStyleConfig, definePartsStyle } =
|
||||
createMultiStyleConfigHelpers(parts.keys);
|
||||
@ -11,13 +12,13 @@ const invokeAITrack = defineStyle((props) => {
|
||||
const { colorScheme: c } = props;
|
||||
|
||||
return {
|
||||
bg: 'base.600',
|
||||
bg: mode('base.300', 'base.600')(props),
|
||||
|
||||
_focusVisible: {
|
||||
boxShadow: 'none',
|
||||
},
|
||||
_checked: {
|
||||
bg: `${c}.600`,
|
||||
bg: mode(`${c}.400`, `${c}.500`)(props),
|
||||
},
|
||||
};
|
||||
});
|
||||
@ -26,7 +27,7 @@ const invokeAIThumb = defineStyle((props) => {
|
||||
const { colorScheme: c } = props;
|
||||
|
||||
return {
|
||||
bg: `${c}.50`,
|
||||
bg: mode(`${c}.50`, `${c}.50`)(props),
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -3,6 +3,7 @@ import {
|
||||
createMultiStyleConfigHelpers,
|
||||
defineStyle,
|
||||
} from '@chakra-ui/styled-system';
|
||||
import { mode } from '@chakra-ui/theme-tools';
|
||||
|
||||
const { defineMultiStyleConfig, definePartsStyle } =
|
||||
createMultiStyleConfigHelpers(parts.keys);
|
||||
@ -16,30 +17,51 @@ const invokeAIRoot = defineStyle((_props) => {
|
||||
|
||||
const invokeAITab = defineStyle((_props) => ({}));
|
||||
|
||||
const invokeAITablist = defineStyle((_props) => ({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: 1,
|
||||
color: 'base.700',
|
||||
button: {
|
||||
fontSize: 'sm',
|
||||
padding: 2,
|
||||
borderRadius: 'base',
|
||||
_selected: {
|
||||
borderBottomColor: 'base.800',
|
||||
bg: 'accent.700',
|
||||
color: 'accent.100',
|
||||
const invokeAITablist = defineStyle((props) => {
|
||||
const { colorScheme: c } = props;
|
||||
|
||||
return {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: 1,
|
||||
color: mode('base.700', 'base.400')(props),
|
||||
button: {
|
||||
fontSize: 'sm',
|
||||
padding: 2,
|
||||
borderRadius: 'base',
|
||||
textShadow: mode(
|
||||
`0 0 0.3rem var(--invokeai-colors-accent-100)`,
|
||||
`0 0 0.3rem var(--invokeai-colors-accent-900)`
|
||||
)(props),
|
||||
svg: {
|
||||
fill: mode('base.700', 'base.300')(props),
|
||||
},
|
||||
_selected: {
|
||||
borderBottomColor: 'base.800',
|
||||
bg: mode('accent.200', 'accent.600')(props),
|
||||
color: mode('accent.800', 'accent.100')(props),
|
||||
_hover: {
|
||||
bg: mode('accent.300', 'accent.500')(props),
|
||||
color: mode('accent.900', 'accent.50')(props),
|
||||
},
|
||||
svg: {
|
||||
fill: mode('base.900', 'base.50')(props),
|
||||
filter: mode(
|
||||
`drop-shadow(0px 0px 0.3rem var(--invokeai-colors-accent-100))`,
|
||||
`drop-shadow(0px 0px 0.3rem var(--invokeai-colors-accent-900))`
|
||||
)(props),
|
||||
},
|
||||
},
|
||||
_hover: {
|
||||
bg: 'accent.600',
|
||||
color: 'accent.50',
|
||||
bg: mode('base.100', 'base.800')(props),
|
||||
color: mode('base.900', 'base.50')(props),
|
||||
svg: {
|
||||
fill: mode(`base.800`, `base.100`)(props),
|
||||
},
|
||||
},
|
||||
},
|
||||
_hover: {
|
||||
bg: 'base.600',
|
||||
color: 'base.50',
|
||||
},
|
||||
},
|
||||
}));
|
||||
};
|
||||
});
|
||||
|
||||
const invokeAITabpanel = defineStyle((_props) => ({
|
||||
padding: 0,
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { defineStyle, defineStyleConfig } from '@chakra-ui/react';
|
||||
import { mode } from '@chakra-ui/theme-tools';
|
||||
|
||||
const subtext = defineStyle((_props) => ({
|
||||
color: 'base.400',
|
||||
const subtext = defineStyle((props) => ({
|
||||
color: mode('colors.base.500', 'colors.base.400')(props),
|
||||
}));
|
||||
|
||||
export const textTheme = defineStyleConfig({
|
||||
|
17
invokeai/frontend/web/src/theme/components/tooltip.ts
Normal file
17
invokeai/frontend/web/src/theme/components/tooltip.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { defineStyle, defineStyleConfig } from '@chakra-ui/react';
|
||||
import { mode } from '@chakra-ui/theme-tools';
|
||||
import { cssVar } from '@chakra-ui/theme-tools';
|
||||
|
||||
const $arrowBg = cssVar('popper-arrow-bg');
|
||||
|
||||
// define the base component styles
|
||||
const baseStyle = defineStyle((props) => ({
|
||||
borderRadius: 'base',
|
||||
shadow: 'dark-lg',
|
||||
bg: mode('base.700', 'base.200')(props),
|
||||
[$arrowBg.variable]: mode('colors.base.700', 'colors.base.200')(props),
|
||||
pb: 1.5,
|
||||
}));
|
||||
|
||||
// export the component theme
|
||||
export const tooltipTheme = defineStyleConfig({ baseStyle });
|
@ -1,7 +1,5 @@
|
||||
import { ThemeOverride } from '@chakra-ui/react';
|
||||
import type { StyleFunctionProps } from '@chakra-ui/styled-system';
|
||||
|
||||
import { invokeAIThemeColors } from 'theme/colors/invokeAI';
|
||||
import { accordionTheme } from './components/accordion';
|
||||
import { buttonTheme } from './components/button';
|
||||
import { checkboxTheme } from './components/checkbox';
|
||||
@ -19,6 +17,15 @@ import { switchTheme } from './components/switch';
|
||||
import { tabsTheme } from './components/tabs';
|
||||
import { textTheme } from './components/text';
|
||||
import { textareaTheme } from './components/textarea';
|
||||
import { tooltipTheme } from './components/tooltip';
|
||||
import { generateColorPalette } from './util/generateColorPalette';
|
||||
|
||||
const BASE = { H: 240, S: 8 };
|
||||
const ACCENT = { H: 260, S: 52 };
|
||||
const WORKING = { H: 47, S: 50 };
|
||||
const WARNING = { H: 28, S: 50 };
|
||||
const OK = { H: 113, S: 50 };
|
||||
const ERROR = { H: 0, S: 50 };
|
||||
|
||||
export const theme: ThemeOverride = {
|
||||
config: {
|
||||
@ -26,30 +33,32 @@ export const theme: ThemeOverride = {
|
||||
initialColorMode: 'dark',
|
||||
useSystemColorMode: false,
|
||||
},
|
||||
layerStyles: {
|
||||
body: {
|
||||
bg: 'base.50',
|
||||
color: 'base.900',
|
||||
'.chakra-ui-dark &': { bg: 'base.900', color: 'base.50' },
|
||||
},
|
||||
first: {
|
||||
bg: 'base.100',
|
||||
color: 'base.900',
|
||||
'.chakra-ui-dark &': { bg: 'base.850', color: 'base.100' },
|
||||
},
|
||||
second: {
|
||||
bg: 'base.200',
|
||||
color: 'base.900',
|
||||
'.chakra-ui-dark &': { bg: 'base.800', color: 'base.100' },
|
||||
},
|
||||
},
|
||||
styles: {
|
||||
global: (_props: StyleFunctionProps) => ({
|
||||
body: {
|
||||
bg: 'base.900',
|
||||
color: 'base.50',
|
||||
overflow: {
|
||||
base: 'scroll',
|
||||
xl: 'hidden',
|
||||
},
|
||||
},
|
||||
global: (props) => ({
|
||||
layerStyle: 'body',
|
||||
'*': { ...no_scrollbar },
|
||||
}),
|
||||
},
|
||||
direction: 'ltr',
|
||||
fonts: {
|
||||
body: `'InterVariable', sans-serif`,
|
||||
},
|
||||
breakpoints: {
|
||||
base: '0em', // 0px and onwards
|
||||
sm: '30em', // 480px and onwards
|
||||
md: '48em', // 768px and onwards
|
||||
lg: '62em', // 992px and onwards
|
||||
xl: '80em', // 1280px and onwards
|
||||
'2xl': '96em', // 1536px and onwards
|
||||
body: `'Inter Variable', sans-serif`,
|
||||
},
|
||||
shadows: {
|
||||
light: {
|
||||
@ -69,7 +78,18 @@ export const theme: ThemeOverride = {
|
||||
nodeSelectedOutline: `0 0 0 2px var(--invokeai-colors-base-500)`,
|
||||
},
|
||||
colors: {
|
||||
...invokeAIThemeColors,
|
||||
base: generateColorPalette(BASE.H, BASE.S),
|
||||
baseAlpha: generateColorPalette(BASE.H, BASE.S, true),
|
||||
accent: generateColorPalette(ACCENT.H, ACCENT.S),
|
||||
accentAlpha: generateColorPalette(ACCENT.H, ACCENT.S, true),
|
||||
working: generateColorPalette(WORKING.H, WORKING.S),
|
||||
workingAlpha: generateColorPalette(WORKING.H, WORKING.S, true),
|
||||
warning: generateColorPalette(WARNING.H, WARNING.S),
|
||||
warningAlpha: generateColorPalette(WARNING.H, WARNING.S, true),
|
||||
ok: generateColorPalette(OK.H, OK.S),
|
||||
okAlpha: generateColorPalette(OK.H, OK.S, true),
|
||||
error: generateColorPalette(ERROR.H, ERROR.S),
|
||||
errorAlpha: generateColorPalette(ERROR.H, ERROR.S, true),
|
||||
},
|
||||
components: {
|
||||
Button: buttonTheme, // Button and IconButton
|
||||
@ -88,5 +108,6 @@ export const theme: ThemeOverride = {
|
||||
Checkbox: checkboxTheme,
|
||||
Menu: menuTheme,
|
||||
Text: textTheme,
|
||||
Tooltip: tooltipTheme,
|
||||
},
|
||||
};
|
||||
|
@ -2,46 +2,35 @@ import { InvokeAIPaletteSteps } from 'theme/themeTypes';
|
||||
|
||||
/**
|
||||
* Add two numbers together
|
||||
* @param {String | Number} hue Hue of the color (0-360) - Reds 0, Greens 120, Blues 240
|
||||
* @param {String | Number} saturation Saturation of the color (0-100)
|
||||
* @param {boolean} light True to generate light color palette
|
||||
* @param {String | Number} H Hue of the color (0-360) - Reds 0, Greens 120, Blues 240
|
||||
* @param {String | Number} L Saturation of the color (0-100)
|
||||
* @param {Boolean} alpha Whether or not to generate this palette as a transparency palette
|
||||
*/
|
||||
export function generateColorPalette(
|
||||
hue: string | number,
|
||||
saturation: string | number,
|
||||
light = false,
|
||||
H: string | number,
|
||||
S: string | number,
|
||||
alpha = false
|
||||
) {
|
||||
hue = String(hue);
|
||||
saturation = String(saturation);
|
||||
H = String(H);
|
||||
S = String(S);
|
||||
|
||||
const colorSteps = Array.from({ length: 21 }, (_, i) => i * 50);
|
||||
|
||||
const lightnessSteps = [
|
||||
0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 59, 64, 68, 73, 77, 82, 86,
|
||||
95, 100,
|
||||
];
|
||||
|
||||
const darkPalette: Partial<InvokeAIPaletteSteps> = {};
|
||||
const lightPalette: Partial<InvokeAIPaletteSteps> = {};
|
||||
|
||||
colorSteps.forEach((colorStep, index) => {
|
||||
const p = colorSteps.reduce((palette, step, index) => {
|
||||
const A = alpha ? lightnessSteps[index] / 100 : 1;
|
||||
|
||||
// Lightness should be 50% for alpha colors
|
||||
const darkPaletteLightness = alpha
|
||||
? 50
|
||||
: lightnessSteps[colorSteps.length - 1 - index];
|
||||
const L = alpha ? 50 : lightnessSteps[colorSteps.length - 1 - index];
|
||||
|
||||
darkPalette[
|
||||
colorStep as keyof typeof darkPalette
|
||||
] = `hsl(${hue} ${saturation}% ${darkPaletteLightness}% / ${A})`;
|
||||
palette[step as keyof typeof palette] = `hsl(${H} ${S}% ${L}% / ${A})`;
|
||||
|
||||
const lightPaletteLightness = alpha ? 50 : lightnessSteps[index];
|
||||
return palette;
|
||||
}, {} as InvokeAIPaletteSteps);
|
||||
|
||||
lightPalette[
|
||||
colorStep as keyof typeof lightPalette
|
||||
] = `hsl(${hue} ${saturation}% ${lightPaletteLightness}% / ${A})`;
|
||||
});
|
||||
|
||||
return light ? lightPalette : darkPalette;
|
||||
return p;
|
||||
}
|
||||
|
@ -1,40 +1,40 @@
|
||||
import { StyleFunctionProps } from '@chakra-ui/theme-tools';
|
||||
import { StyleFunctionProps, mode } from '@chakra-ui/theme-tools';
|
||||
|
||||
export const getInputOutlineStyles = (_props?: StyleFunctionProps) => ({
|
||||
export const getInputOutlineStyles = (props: StyleFunctionProps) => ({
|
||||
outline: 'none',
|
||||
borderWidth: 2,
|
||||
borderStyle: 'solid',
|
||||
borderColor: 'base.800',
|
||||
bg: 'base.900',
|
||||
borderColor: mode('base.200', 'base.800')(props),
|
||||
bg: mode('base.50', 'base.900')(props),
|
||||
borderRadius: 'base',
|
||||
color: 'base.100',
|
||||
color: mode('base.900', 'base.100')(props),
|
||||
boxShadow: 'none',
|
||||
_hover: {
|
||||
borderColor: 'base.600',
|
||||
borderColor: mode('base.300', 'base.600')(props),
|
||||
},
|
||||
_focus: {
|
||||
borderColor: 'accent.700',
|
||||
borderColor: mode('accent.200', 'accent.600')(props),
|
||||
boxShadow: 'none',
|
||||
_hover: {
|
||||
borderColor: 'accent.600',
|
||||
borderColor: mode('accent.300', 'accent.500')(props),
|
||||
},
|
||||
},
|
||||
_invalid: {
|
||||
borderColor: 'error.700',
|
||||
borderColor: mode('error.300', 'error.600')(props),
|
||||
boxShadow: 'none',
|
||||
_hover: {
|
||||
borderColor: 'error.600',
|
||||
borderColor: mode('error.400', 'error.500')(props),
|
||||
},
|
||||
},
|
||||
_disabled: {
|
||||
borderColor: 'base.700',
|
||||
bg: 'base.700',
|
||||
color: 'base.400',
|
||||
borderColor: mode('base.300', 'base.700')(props),
|
||||
bg: mode('base.300', 'base.700')(props),
|
||||
color: mode('base.600', 'base.400')(props),
|
||||
_hover: {
|
||||
borderColor: 'base.700',
|
||||
borderColor: mode('base.300', 'base.700')(props),
|
||||
},
|
||||
},
|
||||
_placeholder: {
|
||||
color: 'base.500',
|
||||
color: mode('base.700', 'base.400')(props),
|
||||
},
|
||||
});
|
||||
|
3
invokeai/frontend/web/src/theme/util/mode.ts
Normal file
3
invokeai/frontend/web/src/theme/util/mode.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export const mode =
|
||||
(light: string, dark: string) => (colorMode: 'light' | 'dark') =>
|
||||
colorMode === 'light' ? light : dark;
|
Loading…
Reference in New Issue
Block a user