Skip to content

Commit 2167d0e

Browse files
committed
Accessibility: improve HTML elements for manage models, preferences, closing the dialogs, model list, model selection, model unhide, #358
1 parent 977b144 commit 2167d0e

File tree

2 files changed

+70
-29
lines changed

2 files changed

+70
-29
lines changed

src/common/components/GoodModal.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@ export function GoodModal(props: {
3333
}}>
3434

3535
{!props.noTitleBar && <Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
36-
<Typography level={props.strongerTitle !== true ? 'title-md' : 'title-lg'} startDecorator={props.titleStartDecorator}>
36+
<Typography component='h1' level={props.strongerTitle !== true ? 'title-md' : 'title-lg'} startDecorator={props.titleStartDecorator}>
3737
{props.title || ''}
3838
</Typography>
39-
{!!props.onClose && <ModalClose sx={{ position: 'static', my: -1, mr: -0.5 }} />}
39+
{!!props.onClose && <ModalClose aria-label='Close Dialog' sx={{ position: 'static', my: -1, mr: -0.5 }} />}
4040
</Box>}
4141

4242
{props.dividers === true && <Divider />}
@@ -47,7 +47,7 @@ export function GoodModal(props: {
4747

4848
{(!!props.startButton || showBottomClose) && <Box sx={{ mt: 'auto', display: 'flex', flexWrap: 'wrap', gap: 1, justifyContent: 'space-between' }}>
4949
{props.startButton}
50-
{showBottomClose && <Button variant='solid' color='neutral' onClick={props.onClose} sx={{ ml: 'auto', minWidth: 100 }}>
50+
{showBottomClose && <Button aria-label='Close Dialog' variant='solid' color='neutral' onClick={props.onClose} sx={{ ml: 'auto', minWidth: 100 }}>
5151
Close
5252
</Button>}
5353
</Box>}

src/modules/llms/models-modal/ModelsList.tsx

+67-26
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,32 @@ import { IModelVendor } from '../vendors/IModelVendor';
1313
import { findVendorById } from '../vendors/vendors.registry';
1414

1515

16-
function ModelItem(props: { llm: DLLM, vendor: IModelVendor, chipChat: boolean, chipFast: boolean, chipFunc: boolean, onClick: () => void }) {
16+
function ModelItem(props: {
17+
llm: DLLM,
18+
vendor: IModelVendor,
19+
chipChat: boolean,
20+
chipFast: boolean,
21+
chipFunc: boolean,
22+
onModelClicked: (llmId: DLLMId) => void,
23+
onModelSetHidden: (llmId: DLLMId, hidden: boolean) => void,
24+
}) {
1725

1826
// derived
19-
const llm = props.llm;
27+
const { llm, onModelClicked, onModelSetHidden } = props;
28+
29+
const handleClick = React.useCallback((event: React.MouseEvent) => {
30+
event.stopPropagation();
31+
onModelClicked(llm.id);
32+
}, [llm.id, onModelClicked]);
33+
34+
const handleUnhide = React.useCallback((event: React.MouseEvent) => {
35+
event.stopPropagation();
36+
onModelSetHidden(llm.id, false);
37+
}, [llm.id, onModelSetHidden]);
38+
39+
2040
const label = llm.label;
41+
2142
let tooltip = llm._source.label;
2243
if (llm.description)
2344
tooltip += ' - ' + llm.description;
@@ -30,35 +51,45 @@ function ModelItem(props: { llm: DLLM, vendor: IModelVendor, chipChat: boolean,
3051
tooltip += 'token count not provided';
3152

3253
return (
33-
<ListItemButton color='primary' onClick={props.onClick} sx={{ alignItems: 'center', gap: 1 }}>
54+
<ListItem>
55+
<ListItemButton
56+
color='primary'
57+
aria-label='Configure LLM'
58+
onClick={handleClick}
59+
sx={{
60+
alignItems: 'center',
61+
gap: 1,
62+
}}
63+
>
64+
65+
{/* Model Name */}
66+
<GoodTooltip title={tooltip}>
67+
<Typography sx={llm.hidden ? { color: 'neutral.plainDisabledColor' } : undefined}>
68+
{label}
69+
</Typography>
70+
</GoodTooltip>
3471

35-
{/* Model Name */}
36-
<GoodTooltip title={tooltip}>
37-
<Typography sx={llm.hidden ? { color: 'neutral.plainDisabledColor' } : undefined}>
38-
{label}
39-
</Typography>
40-
</GoodTooltip>
72+
{/* --> */}
73+
<Box sx={{ flex: 1 }} />
4174

42-
{/* --> */}
43-
<Box sx={{ flex: 1 }} />
75+
{props.chipChat && <Chip size='sm' variant='plain' sx={{ boxShadow: 'sm' }}>chat</Chip>}
4476

45-
{props.chipChat && <Chip size='sm' variant='plain' sx={{ boxShadow: 'sm' }}>chat</Chip>}
77+
{props.chipFast && <Chip size='sm' variant='plain' sx={{ boxShadow: 'sm' }}>fast</Chip>}
4678

47-
{props.chipFast && <Chip size='sm' variant='plain' sx={{ boxShadow: 'sm' }}>fast</Chip>}
79+
{props.chipFunc && <Chip size='sm' variant='plain' sx={{ boxShadow: 'sm' }}>𝑓n</Chip>}
4880

49-
{props.chipFunc && <Chip size='sm' variant='plain' sx={{ boxShadow: 'sm' }}>𝑓n</Chip>}
81+
{llm.hidden && (
82+
<IconButton aria-label='Unhide' size='sm' onClick={handleUnhide}>
83+
<VisibilityOffOutlinedIcon />
84+
</IconButton>
85+
)}
5086

51-
{llm.hidden && (
52-
<IconButton disabled size='sm'>
53-
<VisibilityOffOutlinedIcon />
87+
<IconButton aria-label='Configure LLM' size='sm' onClick={handleClick}>
88+
<SettingsOutlinedIcon />
5489
</IconButton>
55-
)}
56-
57-
<IconButton size='sm'>
58-
<SettingsOutlinedIcon />
59-
</IconButton>
6090

61-
</ListItemButton>
91+
</ListItemButton>
92+
</ListItem>
6293
);
6394
}
6495

@@ -69,12 +100,21 @@ export function ModelsList(props: {
69100
}) {
70101

71102
// external state
72-
const { chatLLMId, fastLLMId, funcLLMId, llms } = useModelsStore(state => ({
103+
const { chatLLMId, fastLLMId, funcLLMId, llms, updateLLM } = useModelsStore(state => ({
73104
chatLLMId: state.chatLLMId,
74105
fastLLMId: state.fastLLMId,
75106
funcLLMId: state.funcLLMId,
76107
llms: state.llms.filter(llm => !props.filterSourceId || llm.sId === props.filterSourceId),
77-
}), shallow);
108+
updateLLM: state.updateLLM,
109+
}), (a, b) => a.chatLLMId === b.chatLLMId && a.fastLLMId === b.fastLLMId && a.funcLLMId === b.funcLLMId && shallow(a.llms, b.llms));
110+
111+
112+
const { onOpenLLMOptions } = props;
113+
114+
const handleModelClicked = React.useCallback((llmId: DLLMId) => onOpenLLMOptions(llmId), [onOpenLLMOptions]);
115+
116+
const handleModelSetHidden = React.useCallback((llmId: DLLMId, hidden: boolean) => updateLLM(llmId, { hidden }), [updateLLM]);
117+
78118

79119
// find out if there's more than 1 sourceLabel in the llms array
80120
const multiSources = llms.length >= 2 && llms.find(llm => llm._source !== llms[0]._source);
@@ -107,7 +147,8 @@ export function ModelsList(props: {
107147
chipChat={llm.id === chatLLMId}
108148
chipFast={llm.id === fastLLMId}
109149
chipFunc={llm.id === funcLLMId}
110-
onClick={() => props.onOpenLLMOptions(llm.id)}
150+
onModelClicked={handleModelClicked}
151+
onModelSetHidden={handleModelSetHidden}
111152
/>,
112153
);
113154
}

0 commit comments

Comments
 (0)