mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-01-15 06:18:03 -05:00
feat(ui): iterate on model combobox (wip)
This commit is contained in:
@@ -13,6 +13,7 @@ import {
|
||||
useDisclosure,
|
||||
} from '@invoke-ai/ui-library';
|
||||
import { IAINoContentFallback } from 'common/components/IAIImageFallback';
|
||||
import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent';
|
||||
import { useStateImperative } from 'common/hooks/useStateImperative';
|
||||
import ModelBaseBadge from 'features/modelManagerV2/subpanels/ModelManagerPanel/ModelBaseBadge';
|
||||
import ModelImage from 'features/modelManagerV2/subpanels/ModelManagerPanel/ModelImage';
|
||||
@@ -82,7 +83,6 @@ const onSelect = (modelConfig: AnyModelConfig) => {
|
||||
};
|
||||
|
||||
export const ModelCombobox = memo(() => {
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const pickerRef = useRef<ImperativeModelPickerHandle>(null);
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
const [modelConfigs] = useAllModels();
|
||||
@@ -92,7 +92,14 @@ export const ModelCombobox = memo(() => {
|
||||
<Button onClick={onOpen} variant="outline">
|
||||
model
|
||||
</Button>
|
||||
<Modal isOpen={isOpen} onClose={onClose} useInert={false} initialFocusRef={inputRef} size="xl" isCentered>
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
useInert={false}
|
||||
initialFocusRef={pickerRef.current?.inputRef}
|
||||
size="xl"
|
||||
isCentered
|
||||
>
|
||||
<ModalOverlay />
|
||||
<ModalContent h="512" maxH="70%">
|
||||
<ModalBody p={0}>
|
||||
@@ -254,9 +261,9 @@ const ModelComboboxContent = memo(
|
||||
<Flex tabIndex={-1} ref={rootRef} flexDir="column" p={2} h="full" gap={2} onKeyDown={onKeyDown}>
|
||||
<Input ref={inputRef} value={searchTerm} onChange={onChangeSearchTerm} placeholder={t('nodes.nodeSearch')} />
|
||||
<Box tabIndex={-1} role="listbox" w="full" h="full">
|
||||
{/* <ScrollableContent> */}
|
||||
<ModelComboboxList items={items} value={value} setValue={setValue} onSelect={onSelect} />
|
||||
{/* </ScrollableContent> */}
|
||||
<ScrollableContent>
|
||||
<ModelComboboxList items={items} value={value} setValue={setValue} onSelect={onSelect} />
|
||||
</ScrollableContent>
|
||||
</Box>
|
||||
</Flex>
|
||||
);
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
import type { SystemStyleObject } from '@invoke-ai/ui-library';
|
||||
import { Box, Flex, Spacer, Text } from '@invoke-ai/ui-library';
|
||||
import ModelBaseBadge from 'features/modelManagerV2/subpanels/ModelManagerPanel/ModelBaseBadge';
|
||||
import ModelImage from 'features/modelManagerV2/subpanels/ModelManagerPanel/ModelImage';
|
||||
import { filesize } from 'filesize';
|
||||
import { memo, useCallback } from 'react';
|
||||
import type { AnyModelConfig } from 'services/api/types';
|
||||
|
||||
const itemSx: SystemStyleObject = {
|
||||
display: 'flex',
|
||||
flexDir: 'column',
|
||||
p: 2,
|
||||
cursor: 'pointer',
|
||||
borderRadius: 'base',
|
||||
'&[data-selected="true"]': {
|
||||
bg: 'base.700',
|
||||
},
|
||||
'&[data-disabled="true"]': {
|
||||
cursor: 'not-allowed',
|
||||
opacity: 0.5,
|
||||
},
|
||||
};
|
||||
|
||||
export const ModelComboboxItem = memo(
|
||||
(props: {
|
||||
model: AnyModelConfig;
|
||||
setActive: (key: string) => void;
|
||||
onSelect: (key: string) => void;
|
||||
isSelected: boolean;
|
||||
isDisabled: boolean;
|
||||
}) => {
|
||||
const { model, setActive, onSelect, isDisabled, isSelected } = props;
|
||||
const onPointerMove = useCallback(() => {
|
||||
setActive(model.key);
|
||||
}, [model.key, setActive]);
|
||||
const onClick = useCallback(() => {
|
||||
onSelect(model.key);
|
||||
}, [model.key, onSelect]);
|
||||
return (
|
||||
<Box
|
||||
role="option"
|
||||
sx={itemSx}
|
||||
id={model.key}
|
||||
aria-disabled={isDisabled}
|
||||
aria-selected={isSelected}
|
||||
data-disabled={isDisabled}
|
||||
data-selected={isSelected}
|
||||
onPointerMove={isDisabled ? undefined : onPointerMove}
|
||||
onClick={isDisabled ? undefined : onClick}
|
||||
>
|
||||
<ModelComboboxItemContent model={model} />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
);
|
||||
ModelComboboxItem.displayName = 'ModelComboboxItem';
|
||||
|
||||
const ModelComboboxItemContent = memo(({ model }: { model: AnyModelConfig }) => {
|
||||
return (
|
||||
<Flex tabIndex={-1} gap={2}>
|
||||
<ModelImage image_url={model.cover_image} />
|
||||
<Flex flexDir="column" gap={2} flex={1}>
|
||||
<Flex gap={2} alignItems="center">
|
||||
<Text fontSize="sm" fontWeight="semibold">
|
||||
{model.name}
|
||||
</Text>
|
||||
<Spacer />
|
||||
<Text variant="subtext" fontStyle="italic">
|
||||
{filesize(model.file_size)}
|
||||
</Text>
|
||||
<ModelBaseBadge base={model.base} />
|
||||
</Flex>
|
||||
{model.description && <Text color="base.200">{model.description}</Text>}
|
||||
</Flex>
|
||||
</Flex>
|
||||
);
|
||||
});
|
||||
ModelComboboxItemContent.displayName = 'ModelComboboxItemContent';
|
||||
@@ -46,7 +46,7 @@ const ScrollableContent = ({ children, maxHeight, overflowX = 'hidden', overflow
|
||||
return (
|
||||
<Flex w="full" h="full" maxHeight={maxHeight} position="relative">
|
||||
<Box position="absolute" top={0} left={0} right={0} bottom={0}>
|
||||
<OverlayScrollbarsComponent ref={os} style={styles} options={overlayscrollbarsOptions}>
|
||||
<OverlayScrollbarsComponent ref={os} style={styles} options={overlayscrollbarsOptions} defer>
|
||||
{children}
|
||||
</OverlayScrollbarsComponent>
|
||||
</Box>
|
||||
|
||||
Reference in New Issue
Block a user