Skip to content

feat(ui): new model picker combobox #7904

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 54 commits into from
Apr 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
d83b9cf
feat(ui): accept callback to override navigate to model manager funct…
psychedelicious Apr 9, 2025
4e3f13b
fix(ui): useModelCombobox should use `null` for no value instead of `…
psychedelicious Apr 9, 2025
7136402
feat(ui): abstract out workflow editor model combobox, ensure consist…
psychedelicious Apr 9, 2025
5ec2421
feat(ui): add `<NavigateToModelManagerButton />` to model comboboxes …
psychedelicious Apr 9, 2025
89ca92c
feat(ui): remove go to mm button from node fields
psychedelicious Apr 10, 2025
c47d312
chore(ui): bump cmdk to latest
psychedelicious Apr 14, 2025
86bab0f
feat(ui): reworked model selection ui (WIP)
psychedelicious Apr 14, 2025
ad8f0e1
feat(ui): reworked model selection ui (WIP)
psychedelicious Apr 14, 2025
51bc5a6
feat(ui): reworked model selection ui (WIP)
psychedelicious Apr 14, 2025
8de93ef
feat(ui): just make the damn thing myself
psychedelicious Apr 14, 2025
94b6ffe
feat(ui): just make the damn thing myself
psychedelicious Apr 14, 2025
26680e6
feat(ui): toast on select for demo purposes
psychedelicious Apr 14, 2025
f059ff0
feat(ui): iterate on model combobox (wip)
psychedelicious Apr 15, 2025
39555f0
feat(ui): add useStateImperative
psychedelicious Apr 15, 2025
af467b6
feat(ui): iterate on model combobox (wip)
psychedelicious Apr 15, 2025
24cb13e
feat(ui): iterate on model combobox (wip)
psychedelicious Apr 15, 2025
102b177
feat(ui): simplify ScrollableContent
psychedelicious Apr 15, 2025
ad42dd8
feat(ui): iterate on model combobox (wip)
psychedelicious Apr 15, 2025
461a725
feat(ui): iterate on model combobox (wip)
psychedelicious Apr 15, 2025
c5642ab
feat(ui): iterate on model combobox (wip)
psychedelicious Apr 15, 2025
8a66140
feat(ui): iterate on model combobox (wip)
psychedelicious Apr 15, 2025
8530dc1
feat(ui): iterate on model combobox (wip)
psychedelicious Apr 15, 2025
06e07ae
feat(ui): iterate on model combobox (wip)
psychedelicious Apr 15, 2025
e9f52f7
feat(ui): iterate on model combobox (wip)
psychedelicious Apr 15, 2025
69a6750
feat(ui): iterate on model combobox (wip)
psychedelicious Apr 15, 2025
4e8b91e
feat(ui): iterate on model combobox (wip)
psychedelicious Apr 15, 2025
ae43ade
feat(ui): iterate on model combobox (wip)
psychedelicious Apr 15, 2025
200d508
feat(ui): iterate on model combobox (wip)
psychedelicious Apr 15, 2025
8f31ddc
feat(ui): iterate on model combobox (wip)
psychedelicious Apr 15, 2025
5bddc24
feat(ui): render picker in portal
psychedelicious Apr 16, 2025
5d9994f
feat(ui): use context for stable picker state
psychedelicious Apr 16, 2025
1c9d632
feat(ui): onSelectId -> onSelectById
psychedelicious Apr 16, 2025
be0367c
feat(ui): genericizing picker
psychedelicious Apr 16, 2025
b7da879
feat(ui): wip model picker
psychedelicious Apr 17, 2025
fd90745
feat(ui): wip model picker
psychedelicious Apr 17, 2025
99aa36e
feat(ui): wip model picker
psychedelicious Apr 17, 2025
84e6f61
chore(ui): bump react-resizable-panels to latest
psychedelicious Apr 17, 2025
bfa8849
tweak(ui): remove bg on ModelImage fallback
psychedelicious Apr 17, 2025
9563d1c
feat(ui): wip model picker
psychedelicious Apr 17, 2025
be96c61
feat(ui): model picker filter buttons
psychedelicious Apr 17, 2025
e35bfbc
feat(ui): remove description from model pciker for now
psychedelicious Apr 17, 2025
0f198a8
chore(ui): lint
psychedelicious Apr 17, 2025
5a62ccc
feat(ui): when no model bases selected, show all models
psychedelicious Apr 22, 2025
102f911
feat(ui): add clear search button to model combobox
psychedelicious Apr 22, 2025
4dadbd3
feat(ui): split out mainmodelpicker component
psychedelicious Apr 22, 2025
1b21978
fix(ui): flash of "select a model" when changing model
psychedelicious Apr 22, 2025
da619ec
feat(ui): tooltip for compact/full model picker view
psychedelicious Apr 22, 2025
c0aa781
feat(ui): more flexible fallbacks for model picker
psychedelicious Apr 22, 2025
e7685b6
docs(ui): add some comments for picker
psychedelicious Apr 22, 2025
7dec117
feat(ui): rename user-provided extra ctx for picker from `ctx` to `ex…
psychedelicious Apr 22, 2025
4ea8375
feat(ui): custom fallback for model picker when no models installed
psychedelicious Apr 22, 2025
ea96b43
feat(ui): disable search when no options
psychedelicious Apr 22, 2025
f1fb155
chore(ui): lint
psychedelicious Apr 22, 2025
7243d1e
fix(ui): hide file size on model picker when it is zero
psychedelicious Apr 23, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions invokeai/frontend/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
"@xyflow/react": "^12.5.3",
"async-mutex": "^0.5.0",
"chakra-react-select": "^4.9.2",
"cmdk": "^1.0.0",
"cmdk": "^1.1.1",
"compare-versions": "^6.1.1",
"filesize": "^10.1.6",
"fracturedjsonjs": "^4.0.2",
Expand Down Expand Up @@ -98,7 +98,7 @@
"react-i18next": "^15.0.2",
"react-icons": "^5.3.0",
"react-redux": "9.1.2",
"react-resizable-panels": "^2.1.4",
"react-resizable-panels": "^2.1.7",
"react-textarea-autosize": "^8.5.7",
"react-use": "^17.5.1",
"react-virtuoso": "^4.12.5",
Expand Down
297 changes: 175 additions & 122 deletions invokeai/frontend/web/pnpm-lock.yaml

Large diffs are not rendered by default.

18 changes: 14 additions & 4 deletions invokeai/frontend/web/public/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@
"error": "Error",
"error_withCount_one": "{{count}} error",
"error_withCount_other": "{{count}} errors",
"model_withCount_one": "{{count}} model",
"model_withCount_other": "{{count}} models",
"file": "File",
"folder": "Folder",
"format": "format",
Expand All @@ -138,6 +140,8 @@
"localSystem": "Local System",
"learnMore": "Learn More",
"modelManager": "Model Manager",
"noMatches": "No matches",
"noOptions": "No options",
"nodes": "Workflows",
"notInstalled": "Not $t(common.installed)",
"openInNewTab": "Open in New Tab",
Expand Down Expand Up @@ -197,7 +201,9 @@
"column": "Column",
"value": "Value",
"label": "Label",
"systemInformation": "System Information"
"systemInformation": "System Information",
"compact": "Compact",
"full": "Full"
},
"hrf": {
"hrf": "High Resolution Fix",
Expand Down Expand Up @@ -768,6 +774,7 @@
"description": "Description",
"edit": "Edit",
"fileSize": "File Size",
"filterModels": "Filter models",
"fluxRedux": "FLUX Redux",
"height": "Height",
"huggingFace": "HuggingFace",
Expand Down Expand Up @@ -821,10 +828,12 @@
"modelUpdated": "Model Updated",
"modelUpdateFailed": "Model Update Failed",
"name": "Name",
"noModelsInstalled": "No Models Installed",
"modelPickerFallbackNoModelsInstalled": "No models installed.",
"modelPickerFallbackNoModelsInstalled2": "Visit the <LinkComponent>Model Manager</LinkComponent> to install models.",
"noModelsInstalledDesc1": "Install models with the",
"noModelSelected": "No Model Selected",
"noMatchingModels": "No matching Models",
"noMatchingModels": "No matching models",
"noModelsInstalled": "No models installed",
"none": "none",
"path": "Path",
"pathToConfig": "Path To Config",
Expand Down Expand Up @@ -871,7 +880,8 @@
"installingXModels_one": "Installing {{count}} model",
"installingXModels_other": "Installing {{count}} models",
"skippingXDuplicates_one": ", skipping {{count}} duplicate",
"skippingXDuplicates_other": ", skipping {{count}} duplicates"
"skippingXDuplicates_other": ", skipping {{count}} duplicates",
"manageModels": "Manage Models"
},
"models": {
"addLora": "Add LoRA",
Expand Down
16 changes: 16 additions & 0 deletions invokeai/frontend/web/src/app/components/InvokeAIUI.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type { CustomStarUi } from 'app/store/nanostores/customStarUI';
import { $customStarUI } from 'app/store/nanostores/customStarUI';
import { $isDebugging } from 'app/store/nanostores/isDebugging';
import { $logo } from 'app/store/nanostores/logo';
import { $onClickGoToModelManager } from 'app/store/nanostores/onClickGoToModelManager';
import { $openAPISchemaUrl } from 'app/store/nanostores/openAPISchemaUrl';
import { $projectId, $projectName, $projectUrl } from 'app/store/nanostores/projectId';
import { $queueId, DEFAULT_QUEUE_ID } from 'app/store/nanostores/queueId';
Expand Down Expand Up @@ -59,6 +60,10 @@ interface Props extends PropsWithChildren {
workflowTagCategories?: WorkflowTagCategory[];
workflowSortOptions?: WorkflowSortOption[];
loggingOverrides?: LoggingOverrides;
/**
* If provided, overrides in-app navigation to the model manager
*/
onClickGoToModelManager?: () => void;
}

const InvokeAIUI = ({
Expand All @@ -81,6 +86,7 @@ const InvokeAIUI = ({
workflowTagCategories,
workflowSortOptions,
loggingOverrides,
onClickGoToModelManager,
}: Props) => {
useLayoutEffect(() => {
/*
Expand Down Expand Up @@ -205,6 +211,16 @@ const InvokeAIUI = ({
};
}, [logo]);

useEffect(() => {
if (onClickGoToModelManager) {
$onClickGoToModelManager.set(onClickGoToModelManager);
}

return () => {
$onClickGoToModelManager.set(undefined);
};
}, [onClickGoToModelManager]);

useEffect(() => {
if (workflowCategories) {
$workflowLibraryCategoriesOptions.set(workflowCategories);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { atom } from 'nanostores';

export const $onClickGoToModelManager = atom<(() => void) | undefined>(undefined);
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { getOverlayScrollbarsParams } from 'common/components/OverlayScrollbars/
import type { OverlayScrollbarsComponentRef } from 'overlayscrollbars-react';
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
import type { CSSProperties, PropsWithChildren } from 'react';
import { memo, useEffect, useMemo, useState } from 'react';
import { memo, useEffect, useMemo, useRef } from 'react';

type Props = PropsWithChildren & {
maxHeight?: ChakraProps['maxHeight'];
Expand All @@ -22,9 +22,9 @@ const ScrollableContent = ({ children, maxHeight, overflowX = 'hidden', overflow
() => getOverlayScrollbarsParams({ overflowX, overflowY }).options,
[overflowX, overflowY]
);
const [os, osRef] = useState<OverlayScrollbarsComponentRef | null>(null);
const os = useRef<OverlayScrollbarsComponentRef>(null);
useEffect(() => {
const osInstance = os?.osInstance();
const osInstance = os.current?.osInstance();

if (!osInstance) {
return;
Expand All @@ -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={osRef} style={styles} options={overlayscrollbarsOptions}>
<OverlayScrollbarsComponent ref={os} style={styles} options={overlayscrollbarsOptions} defer>
{children}
</OverlayScrollbarsComponent>
</Box>
Expand Down
Loading
Loading