learningequality / learningequality/studio

[Remove Vuetify from Studio] Replace LanguageDropdown VAutocomplete with KDS KMultiSelect

Open
#6,142 1 comment 0 reactions 1 assignee View on GitHub

@adibmbrk is already working on this.

Since Sep 17, 2026.

community-contribution-in-progress DEV: frontend help wanted
Dominant language
Python
Stars
191
Forks
307
Avg merge
5d 6h
Merged PRs (30d)
10

Description

🙂 Looking for an issue? Welcome! This issue is open for contribution. If this is the first time you’re requesting an issue, please:

  • Read Contributing guidelines carefully. Pay extra attention to Using generative AI. Pull requests and comments that don’t follow the guidelines won’t be answered.
  • Confirm that you’ve read the guidelines in your comment.

Overview

LanguageDropdown uses the Vuetify component VAutocomplete. Replace it with KMultiSelect from the Kolibri Design System.

Complexity: Medium
Target branch: unstable

Context

File: contentcuration/contentcuration/frontend/shared/views/LanguageDropdown.vue

The component wraps VAutocomplete in DropdownWrapper. It shows a tooltip on each option. It validates with the Vuetify rules prop. It has style overrides that use ::v-deep.

Six files use this component:

File What it needs
channelEdit/components/edit/DetailsTabView.vue Shows hint text below the field
channelEdit/views/files/supplementaryLists/SupplementaryList.vue Hides languages with excludeLanguages
channelEdit/views/ImportFromChannels/SearchFilters.vue Selects more than one language
channelEdit/views/ImportFromChannels/ChannelList.vue Selects one language
shared/views/channel/ChannelModal.vue Makes the field required
administration/pages/Channels/ChannelTable.vue Reads the languages list from the component with a template ref

Key things to know before you start:

  1. KMultiSelect uses the props invalid and invalidText. It does not use the Vuetify rules prop.
  2. A Vuetify VForm cannot validate a KMultiSelect. ChannelModal needs a language, so it needs another way to validate the field. Studio already has a pattern for this. The field adds a public validate() method, and the parent calls it. ExpandableSelect.vue and MasteryCriteriaGoal.vue both do this. CompletionOptions/index.vue is an example of how a parent calls it.
  3. The languageText method returns early for arrays. A comment explains why. This works around a VAutocomplete behavior.

The tests in shared/views/__tests__/languageDropdown.spec.js use @vue/test-utils, but Studio no longer writes new tests with it.

The Change
  • LanguageDropdown renders KMultiSelect. It keeps the props value, required, excludeLanguages and multiple, so the six files change as little as possible.
  • Search must still find a language by its native name, its English name or its code. Use the searchKeys prop.
  • The accessibility strings in messages come from shared/strings/commonStrings.js. Add a string to $trs only when no shared string exists.
  • Remove DropdownWrapper, the tooltip template and the ::v-deep styles. Set the field width with appearanceOverrides.
  • LanguageDropdown gets a public validate() method that returns the error text, and ChannelModal calls it next to this.$refs.detailsform.validate(). A user must not save a channel without a language.
  • Remove the early return for arrays in languageText and its comment.
  • Remove the Vuetify props from the six files, such as box, hide-details, persistent-hint and dropAbove. KMultiSelect has no hint prop, so DetailsTabView needs another way to show its hint text.
How to Get There
  • Required field: Channel list, open a channel, Edit channel details. Clear the language and save.
  • Hint text: Channel editor, select a resource, Edit, Details tab, Audience, Language.
  • More than one language: Channel editor, Add, Import from channels, Search filters, Language.
  • Hidden languages: Channel editor, select a video or audio resource, Edit, Files, add a caption file.
  • Filter: Administration, Channels, Language filter.
Out of Scope
  • The other Vuetify components in the six files.
  • The VForm in ChannelModal and in DetailsTabView. Only the language field changes.
Acceptance Criteria
General
  • LanguageDropdown.vue renders KMultiSelect. It has no VAutocomplete, no VTooltip and no DropdownWrapper.
  • Single selection and multiple selection both work. The input event sends the same value as before in all six files.
  • excludeLanguages still hides languages.
  • ChannelModal does not save a channel when the language is empty, and the field shows the error text.
  • The language filter in ChannelTable still shows its options.
  • The six files no longer pass Vuetify props to the component.
  • DetailsTabView still shows its hint text.
  • The early return for arrays in languageText is gone.
Accessibility and i18n
  • messages has every key that KMultiSelect needs. Shared strings come from commonStrings.js.
  • Every new text string goes through $trs or a shared translator.
  • A keyboard user can open the list, type to filter it, move through the options, select an option and clear the field.
  • All colors come from theme tokens.
Testing
  • languageDropdown.spec.js uses Vue Testing Library.
  • A test covers the empty language error in ChannelModal.
  • pnpm test passes.
  • pre-commit run --all-files passes.
References

AI usage

I used Claude Code to draft this issue. It read the component and listed the files that use it. I reviewed the file references and edited the text.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.