Model Selector
model-selector
Model picker with reasoning effort levels, search, and runtime integration.
"use client";
import { memo, useEffect } from "react";
import { useAui } from "@assistant-ui/react";
import {
ModelSelectorRoot,
ModelSelectorTrigger,
ModelSelectorValue,
ModelSelectorContent,
ModelSelectorSearch,
ModelSelectorFocusAnchor,
ModelSelectorList,
ModelSelectorEmpty,
ModelSelectorGroup,
ModelSelectorSeparator,
ModelSelectorItem,
ModelSelectorEffort,
useModelSelectorContext,
type ModelSelectorProps,
} from "./model-selector";
export {
DEFAULT_EFFORT_OPTIONS,
modelSelectorTriggerVariants,
resolveModelEffort,
useModelSelectorEfforts,
ModelSelectorRoot,
ModelSelectorTrigger,
ModelSelectorValue,
ModelSelectorContent,
ModelSelectorSearch,
ModelSelectorFocusAnchor,
ModelSelectorList,
ModelSelectorEmpty,
ModelSelectorGroup,
ModelSelectorSeparator,
ModelSelectorItem,
ModelSelectorEffort,
} from "./model-selector";
export type {
ModelOption,
ModelSelectorEffortOption,
ModelSelectorProps,
ModelSelectorRootProps,
ModelSelectorTriggerProps,
ModelSelectorValueProps,
ModelSelectorContentProps,
ModelSelectorSearchProps,
ModelSelectorListProps,
ModelSelectorEmptyProps,
ModelSelectorGroupProps,
ModelSelectorSeparatorProps,
ModelSelectorItemProps,
ModelSelectorEffortProps,
} from "./model-selector";
/** Registers the selection with assistant-ui's ModelContext system. The
* context's effort is already resolved against the selected model. */
function ModelSelectorModelContext() {
const { value, effort } = useModelSelectorContext();
const api = useAui();
useEffect(() => {
if (value === undefined) return;
const config = {
config: {
modelName: value,
...(effort !== undefined ? { reasoningEffort: effort } : undefined),
},
};
return api.modelContext.register({
getModelContext: () => config,
});
}, [api, value, effort]);
return null;
}
const ModelSelectorImpl = ({
searchable,
variant,
size,
align,
className,
contentClassName,
...rootProps
}: ModelSelectorProps) => {
return (
<ModelSelectorRoot {...rootProps}>
<ModelSelectorModelContext />
<ModelSelectorTrigger
variant={variant}
size={size}
className={className}
/>
<ModelSelectorContent
{...(align !== undefined ? { align } : {})}
className={contentClassName}
searchable={searchable ?? false}
/>
</ModelSelectorRoot>
);
};
type ModelSelectorComponent = typeof ModelSelectorImpl & {
displayName?: string;
Root: typeof ModelSelectorRoot;
Trigger: typeof ModelSelectorTrigger;
Value: typeof ModelSelectorValue;
Content: typeof ModelSelectorContent;
Search: typeof ModelSelectorSearch;
FocusAnchor: typeof ModelSelectorFocusAnchor;
List: typeof ModelSelectorList;
Empty: typeof ModelSelectorEmpty;
Group: typeof ModelSelectorGroup;
Separator: typeof ModelSelectorSeparator;
Item: typeof ModelSelectorItem;
Effort: typeof ModelSelectorEffort;
};
const ModelSelector = memo(
ModelSelectorImpl,
) as unknown as ModelSelectorComponent;
ModelSelector.displayName = "ModelSelector";
ModelSelector.Root = ModelSelectorRoot;
ModelSelector.Trigger = ModelSelectorTrigger;
ModelSelector.Value = ModelSelectorValue;
ModelSelector.Content = ModelSelectorContent;
ModelSelector.Search = ModelSelectorSearch;
ModelSelector.FocusAnchor = ModelSelectorFocusAnchor;
ModelSelector.List = ModelSelectorList;
ModelSelector.Empty = ModelSelectorEmpty;
ModelSelector.Group = ModelSelectorGroup;
ModelSelector.Separator = ModelSelectorSeparator;
ModelSelector.Item = ModelSelectorItem;
ModelSelector.Effort = ModelSelectorEffort;
export { ModelSelector };
Similar components
Other registries' take on model-selector.
A standalone model picker — compare models in a dropdown with badges for speed, context length and what each supports.
More from @assistant-ui
A run that repeats on its own, with its cadence and how it has been doing.
Who you are about to talk to: its skills, its model, and the endpoint behind it.
A dot grid holds the frame while the image resolves out of a blur.
Streaming never steals your scroll position; a pill offers the way back down.
A checklist the agent works through, with progress you can glance.
Work measured in minutes: weighted stages, an ETA, and a way out.
A read-only transcript someone sent you, with a way to pick it up yourself.