Skip to content

Commit

Permalink
Add props liUserMsgClass and liUserMsgActiveClass (#274)
Browse files Browse the repository at this point in the history
* add more props to facilitate styling with CSS Framework
`liActiveUserMsgClass``liActiveUserMsgClass`

* create corresponding test for the new props

* hover user message for liActiveUserMsgClass test

* update docs for new style props

* update simplified dom structure in docs

* remove accidental css declaration

* update deps

* refactor liUserMsgClass

* tweak liUserMsgClass readme desc

---------

Co-authored-by: Janosh Riebesell <[email protected]>
  • Loading branch information
acidMyke and janosh authored Nov 15, 2023
1 parent 54963ec commit dd67fb1
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 26 deletions.
10 changes: 5 additions & 5 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ default_install_hook_types: [pre-commit, commit-msg]

repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
rev: v4.5.0
hooks:
- id: check-case-conflict
- id: check-symlinks
Expand All @@ -19,7 +19,7 @@ repos:
- id: trailing-whitespace

- repo: https://github.com/pre-commit/mirrors-prettier
rev: v3.0.3
rev: v3.1.0
hooks:
- id: prettier
args: [--write] # edit files in-place
Expand All @@ -29,15 +29,15 @@ repos:
- svelte

- repo: https://github.com/codespell-project/codespell
rev: v2.2.5
rev: v2.2.6
hooks:
- id: codespell
stages: [commit, commit-msg]
args: [--ignore-words-list, falsy]
args: [--ignore-words-list, falsy, --check-filenames]
exclude: changelog\.md

- repo: https://github.com/pre-commit/mirrors-eslint
rev: v8.49.0
rev: v8.53.0
hooks:
- id: eslint
types: [file]
Expand Down
36 changes: 18 additions & 18 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,37 +23,37 @@
"update-coverage": "vitest tests/unit --run --coverage && npx istanbul-badges-readme"
},
"dependencies": {
"svelte": "^4.2.0"
"svelte": "4.2.3"
},
"devDependencies": {
"@iconify/svelte": "^3.1.4",
"@playwright/test": "^1.37.1",
"@playwright/test": "^1.39.0",
"@sveltejs/adapter-static": "^2.0.3",
"@sveltejs/kit": "^1.24.1",
"@sveltejs/kit": "^1.27.6",
"@sveltejs/package": "2.2.2",
"@sveltejs/vite-plugin-svelte": "2.4.5",
"@typescript-eslint/eslint-plugin": "^6.7.0",
"@typescript-eslint/parser": "^6.7.0",
"@vitest/coverage-v8": "^0.34.4",
"eslint": "^8.49.0",
"eslint-plugin-svelte": "^2.33.1",
"@sveltejs/vite-plugin-svelte": "2.5.2",
"@typescript-eslint/eslint-plugin": "^6.11.0",
"@typescript-eslint/parser": "^6.11.0",
"@vitest/coverage-v8": "^0.34.6",
"eslint": "^8.53.0",
"eslint-plugin-svelte": "^2.35.0",
"hastscript": "^8.0.0",
"highlight.js": "^11.8.0",
"highlight.js": "^11.9.0",
"jsdom": "^22.1.0",
"mdsvex": "^0.11.0",
"mdsvexamples": "^0.4.1",
"prettier": "^3.0.3",
"prettier-plugin-svelte": "^3.0.3",
"rehype-autolink-headings": "^7.0.0",
"prettier": "^3.1.0",
"prettier-plugin-svelte": "^3.1.0",
"rehype-autolink-headings": "^7.1.0",
"rehype-slug": "^6.0.0",
"svelte-check": "^3.5.1",
"svelte-preprocess": "^5.0.4",
"svelte-check": "^3.6.0",
"svelte-preprocess": "^5.1.0",
"svelte-toc": "^0.5.6",
"svelte-zoo": "^0.4.9",
"svelte2tsx": "^0.6.21",
"svelte2tsx": "^0.6.25",
"typescript": "5.2.2",
"vite": "^4.4.9",
"vitest": "^0.34.4"
"vite": "^4.5.0",
"vitest": "^0.34.6"
},
"keywords": [
"svelte",
Expand Down
6 changes: 6 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,8 @@ The second method allows you to pass in custom classes to the important DOM elem
- `ulOptionsClass`: available options listed in the dropdown when component is in `open` state
- `liOptionClass`: list items selectable from dropdown list
- `liActiveOptionClass`: the currently active dropdown list item (i.e. hovered or navigated to with arrow keys)
- `liUserMsgClass`: user message (last child of dropdown list when no options match user input)
- `liActiveUserMsgClass`: user message when active (i.e. hovered or navigated to with arrow keys)
- `maxSelectMsgClass`: small span towards the right end of the input field displaying to the user how many of the allowed number of options they've already selected
This simplified version of the DOM structure of the component shows where these classes are inserted:
Expand All @@ -622,6 +624,10 @@ This simplified version of the DOM structure of the component shows where these
<li class="{liOptionClass} {liActiveOptionClass}">
Option 2 (currently active)
</li>
...
<li class="{liUserMsgClass} {liActiveUserMsgClass}">
Create this option...
</li>
</ul>
</div>
```
Expand Down
6 changes: 5 additions & 1 deletion src/lib/MultiSelect.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@
export let inputmode: string | null = null
export let invalid: boolean = false
export let liActiveOptionClass: string = ``
export let liActiveUserMsgClass: string = ``
export let liOptionClass: string = ``
export let liSelectedClass: string = ``
export let liUserMsgClass: string = ``
export let loading: boolean = false
export let matchingOptions: Option[] = []
export let maxOptions: number | undefined = undefined
Expand Down Expand Up @@ -695,7 +697,9 @@
on:blur={() => (option_msg_is_active = false)}
role="option"
aria-selected="false"
class="user-msg"
class="user-msg {liUserMsgClass} {option_msg_is_active
? liActiveUserMsgClass
: ``}"
style:cursor={{
dupe: `not-allowed`,
create: `pointer`,
Expand Down
7 changes: 7 additions & 0 deletions src/routes/(demos)/css-classes/+page.svx
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@
inputClass="search-text-input"
liSelectedClass="selected-li"
liActiveOptionClass="hovered-or-arrow-keyed-li"
liUserMsgClass="selectable-msg-li"
liActiveUserMsgClass="hovered-or-arrow-keyed-msg-li"
maxSelectMsgClass="user-hint-max-selected-reached"
placeholder="Which foods do you like?"
selected={options.slice(0, 2)}
allowUserOptions
maxSelect={2}
/>
<!-- maxSelect={2} needed for maxSelectMsg to show up -->
Expand Down Expand Up @@ -57,6 +60,10 @@ This simplified DOM structure of the component shows where these classes are ins
<li class="{liOptionClass} {liActiveOptionClass}">
Option 2 (currently active)
</li>
...
<li class="{liUserMsgClass} {liActiveUserMsgClass}">
Create this option...
</li>
</ul>

</div>
Expand Down
14 changes: 13 additions & 1 deletion tests/MultiSelect.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,17 +119,29 @@ test.describe(`external CSS classes`, async () => {
[`ulSelected`, `ul.selected`, `user-choices`],
[`ulOptions`, `ul.options`, `dropdown`],
[`liOption`, `ul.options > li`, `selectable-li`],
[`liUserMsgClass`, `ul.options > li.user-msg`, `selectable-msg-li`],
[`input`, `input[autocomplete]`, `search-text-input`],
// below classes requires component interaction before appearing in DOM
[`liSelected`, `ul.selected > li`, `selected-li`],
[`liActiveOption`, `ul.options > li.active`, `hovered-or-arrow-keyed-li`],
[
`liActiveUserMsgClass`,
`ul.options > li.active.user-msg`,
`hovered-or-arrow-keyed-msg-li`,
],
[`maxSelectMsg`, `span.max-select-msg`, `user-hint-max-selected-reached`],
]) {
test(`${prop}Class`, async ({ page }) => {
await page.goto(`/css-classes`, { waitUntil: `networkidle` })

await page.click(`#foods input[autocomplete]`)
await page.hover(`ul.options > li`) // hover any option to give it active state
await page.keyboard.type(`O`) // type a word so that the user message shows up

if (prop !== `liActiveUserMsgClass`) {
await page.hover(`ul.options > li`) // hover any option to give it active state
} else {
await page.hover(`ul.options > li:last-child`) // hover last option to give it active state
}

const node = await page.$(`${selector}.${cls}`)
expect(node).toBeTruthy()
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/MultiSelect.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,7 @@ test(`can't select disabled options`, async () => {
})

test.each([2, 5, 10])(
`cant select more than maxSelect options`,
`can't select more than maxSelect options`,
async (maxSelect: number) => {
new MultiSelect({
target: document.body,
Expand Down

0 comments on commit dd67fb1

Please sign in to comment.