Styling changes and settings modal minor refactor

This commit is contained in:
psychedelicious 2022-11-02 15:31:18 +11:00 committed by Lincoln Stein
parent 1e51c39928
commit cefe12f1df
21 changed files with 650 additions and 656 deletions

File diff suppressed because one or more lines are too long

517
frontend/dist/assets/index.552c95d8.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -6,8 +6,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>InvokeAI - A Stable Diffusion Toolkit</title>
<link rel="shortcut icon" type="icon" href="./assets/favicon.0d253ced.ico" />
<script type="module" crossorigin src="./assets/index.ae6d2a5e.js"></script>
<link rel="stylesheet" href="./assets/index.14c578ee.css">
<script type="module" crossorigin src="./assets/index.552c95d8.js"></script>
<link rel="stylesheet" href="./assets/index.67342d6d.css">
</head>
<body>

View File

@ -3,11 +3,7 @@ import {
IconButton,
Tooltip,
TooltipProps,
ResponsiveValue,
ThemingProps,
isChakraTheme,
} from '@chakra-ui/react';
import { Variant } from 'framer-motion';
interface Props extends IconButtonProps {
styleClass?: string;

View File

@ -1,8 +1,7 @@
@use '../../styles/Mixins/' as *;
.invokeai__select {
display: grid;
grid-template-columns: repeat(2, max-content);
display: flex;
column-gap: 1rem;
align-items: center;
width: max-content;

View File

@ -1,17 +1,17 @@
import { FormControl, FormLabel, Select, SelectProps } from '@chakra-ui/react';
import { MouseEvent } from 'react';
interface Props extends SelectProps {
type IAISelectProps = SelectProps & {
label: string;
styleClass?: string;
validValues:
| Array<number | string>
| Array<{ key: string; value: string | number }>;
}
};
/**
* Customized Chakra FormControl + Select multi-part component.
*/
const IAISelect = (props: Props) => {
const IAISelect = (props: IAISelectProps) => {
const {
label,
isDisabled,
@ -33,19 +33,19 @@ const IAISelect = (props: Props) => {
}}
>
<FormLabel
className="invokeai__select-label"
fontSize={fontSize}
marginBottom={1}
flexGrow={2}
whiteSpace="nowrap"
className="invokeai__select-label"
>
{label}
</FormLabel>
<Select
className="invokeai__select-picker"
fontSize={fontSize}
size={size}
{...rest}
className="invokeai__select-picker"
>
{validValues.map((opt) => {
return typeof opt === 'string' || typeof opt === 'number' ? (
@ -53,7 +53,11 @@ const IAISelect = (props: Props) => {
{opt}
</option>
) : (
<option key={opt.value} value={opt.value}>
<option
key={opt.value}
value={opt.value}
className="invokeai__select-option"
>
{opt.key}
</option>
);

View File

@ -22,8 +22,6 @@ const IAISwitch = (props: Props) => {
const {
label,
isDisabled = false,
// fontSize = 'md',
// size = 'md',
width = 'auto',
formControlProps,
formLabelProps,
@ -39,17 +37,11 @@ const IAISwitch = (props: Props) => {
>
<FormLabel
className="invokeai__switch-form-label"
// fontSize={fontSize}
whiteSpace="nowrap"
{...formLabelProps}
>
{label}
<Switch
className="invokeai__switch-root"
// size={size}
// className="switch-button"
{...rest}
/>
<Switch className="invokeai__switch-root" {...rest} />
</FormLabel>
</FormControl>
);

View File

@ -16,6 +16,7 @@
row-gap: 1rem;
align-items: center;
justify-content: center;
background-color: var(--background-color);
&.is-drag-accept {
box-shadow: inset 0 0 20rem 1rem var(--accent-color);

View File

@ -6,6 +6,7 @@ import { uploadImage } from '../../app/socketio/actions';
import { ImageUploadDestination, UploadImagePayload } from '../../app/invokeai';
import { ImageUploaderTriggerContext } from '../../app/contexts/ImageUploaderTriggerContext';
import { activeTabNameSelector } from '../../features/options/optionsSelectors';
import { tabDict } from '../../features/tabs/InvokeTabs';
type ImageUploaderProps = {
children: ReactNode;
@ -128,6 +129,12 @@ const ImageUploader = (props: ImageUploaderProps) => {
};
}, [dispatch, toast, activeTabName]);
const overlaySecondaryText = ['img2img', 'inpainting'].includes(
activeTabName
)
? ` to ${tabDict[activeTabName as keyof typeof tabDict].tooltip}`
: ``;
return (
<ImageUploaderTriggerContext.Provider value={open}>
<div {...getRootProps({ style: {} })}>
@ -137,7 +144,7 @@ const ImageUploader = (props: ImageUploaderProps) => {
<div className="dropzone-container">
{isDragAccept && (
<div className="dropzone-overlay is-drag-accept">
<Heading size={'lg'}>Drop Images</Heading>
<Heading size={'lg'}>Upload Image{overlaySecondaryText}</Heading>
</div>
)}
{isDragReject && (

View File

@ -26,6 +26,9 @@ export const imagesSelector = createSelector(
isOnLastImage:
!isNaN(currentImageIndex) && currentImageIndex === imagesLength - 1,
shouldShowImageDetails,
shouldShowPrevImageButton: currentImageIndex === 0,
shouldShowNextImageButton:
!isNaN(currentImageIndex) && currentImageIndex === imagesLength - 1,
};
},
{

View File

@ -19,8 +19,6 @@
}
.image-gallery-wrapper {
z-index: 100;
&[data-pinned='false'] {
position: fixed;
height: 100vh;

View File

@ -261,6 +261,7 @@ export default function ImageGallery() {
>
<div
className="image-gallery-wrapper"
style={{ zIndex: shouldPinGallery ? 1 : 100 }}
data-pinned={shouldPinGallery}
ref={galleryRef}
onMouseLeave={!shouldPinGallery ? setCloseGalleryTimer : undefined}

View File

@ -19,6 +19,7 @@
.main-option-block {
border-radius: 0.5rem;
display: grid !important;
grid-template-columns: auto !important;
row-gap: 0.4rem;

View File

@ -1,24 +1,37 @@
.model-list {
.chakra-accordion {
display: grid;
row-gap: 0.5rem;
}
// .chakra-accordion {
// display: grid;
// row-gap: 0.5rem;
// }
.chakra-accordion__item {
border: none;
border-radius: 0.3rem;
background-color: var(--tab-hover-color);
}
// .chakra-accordion__item {
// border: none;
// }
// button {
// border-radius: 0.3rem !important;
// &[aria-expanded='true'] {
// // background-color: var(--tab-hover-color);
// border-radius: 0.3rem;
// }
// }
.model-list-accordion {
outline: none;
padding: 0.25rem;
button {
border-radius: 0.3rem !important;
&[aria-expanded='true'] {
background-color: var(--tab-hover-color);
border-radius: 0.3rem;
padding: 0;
margin: 0;
&:hover {
background-color: unset;
}
}
div {
border: none !important;
}
.model-list-button {
display: flex;
flex-direction: row;
@ -64,6 +77,9 @@
}
}
.model-list-item-load-btn {
button {
padding: 0.5rem;
}
}
}
}

View File

@ -73,31 +73,33 @@ const ModelList = () => {
const { models } = useAppSelector(modelListSelector);
return (
<div className="model-list">
<Accordion allowToggle>
<AccordionItem>
<AccordionButton>
<div className="model-list-button">
<h2>Models</h2>
<AccordionIcon />
</div>
</AccordionButton>
<Accordion
allowToggle
className="model-list-accordion"
variant={'unstyled'}
>
<AccordionItem>
<AccordionButton>
<div className="model-list-button">
<h2>Models</h2>
<AccordionIcon />
</div>
</AccordionButton>
<AccordionPanel>
<div className="model-list-list">
{models.map((model, i) => (
<ModelListItem
key={i}
name={model.name}
status={model.status}
description={model.description}
/>
))}
</div>
</AccordionPanel>
</AccordionItem>
</Accordion>
</div>
<AccordionPanel>
<div className="model-list-list">
{models.map((model, i) => (
<ModelListItem
key={i}
name={model.name}
status={model.status}
description={model.description}
/>
))}
</div>
</AccordionPanel>
</AccordionItem>
</Accordion>
);
};

View File

@ -14,18 +14,18 @@ import {
} from '@chakra-ui/react';
import { createSelector } from '@reduxjs/toolkit';
import _, { isEqual } from 'lodash';
import { cloneElement, ReactElement } from 'react';
import { RootState, useAppSelector } from '../../../app/store';
import { ChangeEvent, cloneElement, ReactElement } from 'react';
import { RootState, useAppDispatch, useAppSelector } from '../../../app/store';
import { persistor } from '../../../main';
import {
setShouldConfirmOnDelete,
setShouldDisplayGuides,
setShouldDisplayInProgressType,
SystemState,
} from '../systemSlice';
import ModelList from './ModelList';
import { SettingsModalItem, SettingsModalSelectItem } from './SettingsModalItem';
import { IN_PROGRESS_IMAGE_TYPES } from '../../../app/constants';
import IAISwitch from '../../../common/components/IAISwitch';
import IAISelect from '../../../common/components/IAISelect';
const systemSelector = createSelector(
(state: RootState) => state.system,
@ -60,6 +60,8 @@ type SettingsModalProps = {
* Secondary post-reset modal is included here.
*/
const SettingsModal = ({ children }: SettingsModalProps) => {
const dispatch = useAppDispatch();
const {
isOpen: isSettingsModalOpen,
onOpen: onSettingsModalOpen,
@ -101,26 +103,32 @@ const SettingsModal = ({ children }: SettingsModalProps) => {
<ModalHeader className="settings-modal-header">Settings</ModalHeader>
<ModalCloseButton />
<ModalBody className="settings-modal-content">
<ModelList />
<div className="settings-modal-items">
<SettingsModalSelectItem
settingTitle="Display In-Progress Images"
<div className="settings-modal-item">
<ModelList />
</div>
<IAISelect
styleClass="settings-modal-item"
label={'Display In-Progress Images'}
validValues={IN_PROGRESS_IMAGE_TYPES}
defaultValue={shouldDisplayInProgressType}
dispatcher={setShouldDisplayInProgressType}
value={shouldDisplayInProgressType}
/>
<SettingsModalItem
settingTitle="Confirm on Delete"
<IAISwitch
styleClass="settings-modal-item"
label={'Confirm on Delete'}
isChecked={shouldConfirmOnDelete}
dispatcher={setShouldConfirmOnDelete}
onChange={(e: ChangeEvent<HTMLInputElement>) =>
dispatch(setShouldConfirmOnDelete(e.target.checked))
}
/>
<SettingsModalItem
settingTitle="Display Help Icons"
<IAISwitch
styleClass="settings-modal-item"
label={'Display Help Icons'}
isChecked={shouldDisplayGuides}
dispatcher={setShouldDisplayGuides}
onChange={(e: ChangeEvent<HTMLInputElement>) =>
dispatch(setShouldDisplayGuides(e.target.checked))
}
/>
</div>

View File

@ -1,50 +0,0 @@
import { useAppDispatch } from '../../../app/store';
import IAISelect from '../../../common/components/IAISelect';
import IAISwitch from '../../../common/components/IAISwitch';
export function SettingsModalItem({
settingTitle,
isChecked,
dispatcher,
}: {
settingTitle: string;
isChecked: boolean;
dispatcher: any;
}) {
const dispatch = useAppDispatch();
return (
<IAISwitch
styleClass="settings-modal-item"
label={settingTitle}
isChecked={isChecked}
onChange={(e) => dispatch(dispatcher(e.target.checked))}
/>
);
}
export function SettingsModalSelectItem({
settingTitle,
validValues,
defaultValue,
dispatcher,
}: {
settingTitle: string;
validValues:
Array<number | string>
| Array<{ key: string; value: string | number }>;
defaultValue: string;
dispatcher: any;
}) {
const dispatch = useAppDispatch();
return (
<IAISelect
styleClass="settings-modal-item"
label={settingTitle}
validValues={validValues}
defaultValue={defaultValue}
onChange={(e) => dispatch(dispatcher(e.target.value))}
/>
);
}

View File

@ -1,9 +1,9 @@
import { IconButton, Link, Tooltip, useColorMode } from '@chakra-ui/react';
import { Link, useColorMode } from '@chakra-ui/react';
import { useHotkeys } from 'react-hotkeys-hook';
import { FaSun, FaMoon, FaGithub, FaDiscord, FaBug } from 'react-icons/fa';
import { MdHelp, MdKeyboard, MdSettings } from 'react-icons/md';
import { MdKeyboard, MdSettings } from 'react-icons/md';
import InvokeAILogo from '../../assets/images/logo.png';
import IAIIconButton from '../../common/components/IAIIconButton';
@ -91,18 +91,18 @@ const SiteHeader = () => {
}
/>
<IAIIconButton
aria-label="Link to Discord Server"
tooltip="Discord"
variant="link"
fontSize={20}
size={'sm'}
icon={
<Link isExternal href="https://discord.gg/ZmtBAhwWhy">
<FaDiscord />
</Link>
}
/>
<IAIIconButton
aria-label="Link to Discord Server"
tooltip="Discord"
variant="link"
fontSize={20}
size={'sm'}
icon={
<Link isExternal href="https://discord.gg/ZmtBAhwWhy">
<FaDiscord />
</Link>
}
/>
<SettingsModal>
<IAIIconButton

View File

@ -17,7 +17,7 @@ import ImageToImageWorkarea from './ImageToImage';
import InpaintingWorkarea from './Inpainting';
import TextToImageWorkarea from './TextToImage';
export const tab_dict = {
export const tabDict = {
txt2img: {
title: <TextToImageIcon fill={'black'} boxSize={'2.5rem'} />,
workarea: <TextToImageWorkarea />,
@ -50,8 +50,8 @@ export const tab_dict = {
},
};
// Array where index maps to the key of tab_dict
export const tabMap = _.map(tab_dict, (tab, key) => key);
// Array where index maps to the key of tabDict
export const tabMap = _.map(tabDict, (tab, key) => key);
// Use tabMap to generate a union type of tab names
const tabMapTypes = [...tabMap] as const;
@ -89,15 +89,15 @@ export default function InvokeTabs() {
const renderTabs = () => {
const tabsToRender: ReactElement[] = [];
Object.keys(tab_dict).forEach((key) => {
Object.keys(tabDict).forEach((key) => {
tabsToRender.push(
<Tooltip
key={key}
hasArrow
label={tab_dict[key as keyof typeof tab_dict].tooltip}
label={tabDict[key as keyof typeof tabDict].tooltip}
placement={'right'}
>
<Tab>{tab_dict[key as keyof typeof tab_dict].title}</Tab>
<Tab>{tabDict[key as keyof typeof tabDict].title}</Tab>
</Tooltip>
);
});
@ -106,10 +106,10 @@ export default function InvokeTabs() {
const renderTabPanels = () => {
const tabPanelsToRender: ReactElement[] = [];
Object.keys(tab_dict).forEach((key) => {
Object.keys(tabDict).forEach((key) => {
tabPanelsToRender.push(
<TabPanel className="app-tabs-panel" key={key}>
{tab_dict[key as keyof typeof tab_dict].workarea}
{tabDict[key as keyof typeof tabDict].workarea}
</TabPanel>
);
});