Skip to content

Commit

Permalink
Merge pull request #1240 from dpc-sdp/bugfix/dropdown-count
Browse files Browse the repository at this point in the history
[R20-1433] improve accuracy of more count for dropdowns
  • Loading branch information
dylankelly committed Jul 1, 2024
2 parents e6baaf9 + 424018a commit 79791b1
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 24 deletions.
4 changes: 2 additions & 2 deletions examples/nuxt-app/test/features/maps/maps.feature
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ Feature: Custom collection map component
Scenario: A loading screen is shown while the map loads
Given I load the page fixture with "/maps/basic-page"
And the page endpoint for path "/map" returns fixture "/maps/basic-page" with status 200
And the "/api/tide/elasticsearch/elasticsearch_index_develop_node/_search" network request is delayed by 500 milliseconds and stubbed with fixture "/site/search-response", status 200 and alias "searchReq"
And the "/api/tide/elasticsearch/elasticsearch_index_develop_node/_search" network request is delayed by 1000 milliseconds and stubbed with fixture "/site/search-response", status 200 and alias "searchReq"
Given I visit the page "/map"
Then the map loading screen should be displayed
When I wait 500 milliseconds
When I wait 2 seconds
Then the map should be displayed

@mockserver
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,9 @@ Then(
.invoke('attr', 'for')
.then((dropdownId) => {
cy.get(`#${dropdownId}`).as('selectedDropdown')
cy.get('@selectedDropdown').should('have.text', value)
cy.get('@selectedDropdown').should(($div) => {
expect($div.get(0).innerText).to.eq(value)
})
})
}
)
Expand Down
12 changes: 2 additions & 10 deletions packages/ripple-ui-forms/cypress/support/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,12 @@ import { plugin, defaultConfig } from '@formkit/vue'

import { mount } from 'cypress/vue'
import { h } from 'vue'
import { RplIconSprite } from '@dpc-sdp/ripple-ui-core/vue'

const RplAppWrapper = {
components: { RplIconSprite },
template: `<div style="margin: 1rem;">
<RplIconSprite style="display: none;" />
<slot></slot>
</div>`
}
import RplFauxForm from './components/RplFauxForm.vue'

Cypress.Commands.add('mount', (component, options = {}) => {
return mount(
() => {
return h(RplAppWrapper, null, () => h(component, { ...options.props }))
return h(RplFauxForm, { component, componentProps: options.props })
},
{
...options,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<script setup lang="ts">
import { ref } from 'vue'
import { RplIconSprite } from '@dpc-sdp/ripple-ui-core/vue'
interface Props {
component: any
componentProps: any
}
const props = defineProps<Props>()
const value = ref(props.componentProps?.value)
const handleChange = (val: string) => (value.value = val)
</script>

<template>
<div class="rpl-faux-form">
<RplIconSprite style="display: none" />
<component
:is="component"
v-bind="componentProps"
:value="value"
@onChange="handleChange"
/>
</div>
</template>

<style>
.rpl-faux-form {
padding: var(--rpl-sp-5);
}
</style>
3 changes: 2 additions & 1 deletion packages/ripple-ui-forms/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"build:vite": "vite build",
"build:types": "tsc -p tsconfig.json",
"clean": "(rimraf dist* && rimraf tsconfig.tsbuildinfo) | true",
"test:components": "cypress run --component"
"test:components": "cypress run --component",
"cy:components": "cypress open --component"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@
width: 100%;
}

.rpl-form-dropdown__multi-value-label-char {
position: absolute;
visibility: hidden;
pointer-events: none;
}

.rpl-form-dropdown__more-label {
display: block;
font-weight: bold;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const calculateNumberOfHiddenItems = async () => {
const containerBBox = itemsRef.value.getBoundingClientRect()
// Here we figure out how much space there is to fit the items in, it's
// important to factor in the the width of the '+# more' label here even
// important to factor in the width of the '+# more' label here even
// if it's not currently being rendered.
const widthToFill =
numItemsHidden.value === 0
Expand All @@ -55,7 +55,12 @@ const calculateNumberOfHiddenItems = async () => {
for (const labelEl of labelElements) {
const itemBBox = labelEl.getBoundingClientRect()
if (itemBBox.left - containerBBox.left > widthToFill) {
const itemCharWidth =
labelEl
.querySelector('.rpl-form-dropdown__multi-value-label-char')
?.getBoundingClientRect()?.width || 0
if (itemBBox.left - containerBBox.left > widthToFill - itemCharWidth) {
break
} else {
countShown += 1
Expand Down Expand Up @@ -90,18 +95,30 @@ useResizeObserver(itemsRef, (entries) => {
<template>
<div class="rpl-form-dropdown__multi-value-label-wrap">
<div ref="itemsRef" class="rpl-form-dropdown__multi-value-label rpl-type-p">
<span v-for="(option, i) in selectedOptions" :key="option.id" data-option-label="true">{{
option.label
}}{{ i === selectedOptions.length - 1 ? '' : ', ' }}</span>
<span
v-for="(option, i) in selectedOptions"
:key="option.id"
data-option-label="true"
>{{ option.label
}}<span
class="rpl-form-dropdown__multi-value-label-char"
aria-hidden="true"
>&hellip;{{ option.label?.charAt(0) }}</span
>{{ i === selectedOptions.length - 1 ? '' : ', ' }}</span
>
</div>
<div v-if="numItemsHidden > 0" :style="{
width: `${MORE_LABEL_WIDTH}px`
}" class="rpl-form-dropdown__more-label rpl-type-p">
<div
v-if="numItemsHidden > 0"
:style="{
width: `${MORE_LABEL_WIDTH}px`
}"
class="rpl-form-dropdown__more-label rpl-type-p"
>
+{{ numItemsHidden }} more
</div>
</div>
</template>

<style src="./MultiValueLabel.css">
<style src="./MultiValueLabel.css"></style>

</style>
<style></style>
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,47 @@ describe('RplFormDropDown', () => {
cy.get('.rpl-form-dropdown-menu').should('not.exist')
})

it('allows for single options to be selected', () => {
cy.mount(RplFormDropDown, { props })

cy.get('.rpl-form-dropdown-input').click()
cy.get('.rpl-form-dropdown-option').contains('Apple').click()
cy.get('.rpl-form-dropdown-input').should('contain', 'Apple')

cy.get('.rpl-form-dropdown-input').click()
cy.get('.rpl-form-dropdown-option').contains('Orange').click()
cy.get('.rpl-form-dropdown-input').should('contain', 'Orange')
})

it('allows for multiple options to be selected', () => {
cy.mount(RplFormDropDown, { props: { ...props, multiple: true } })

cy.get('.rpl-form-dropdown-input').click()
cy.get('.rpl-form-dropdown-option').contains('Apple').click()
cy.get('.rpl-form-dropdown-option').contains('Orange').click()

cy.get('.rpl-form-dropdown-input').should(($div) => {
expect($div.get(0).innerText).to.eq('Apple, Orange')
})
})

it('correctly displays the number of hidden selected options', () => {
cy.viewport(960, 680)
cy.mount(RplFormDropDown, { props: { ...props, multiple: true } })
cy.get('.rpl-form-dropdown-input').click()
cy.get('.rpl-form-dropdown-option').click({ multiple: true })
cy.get('.rpl-form-dropdown__more-label').contains('+2 more')

cy.viewport(746, 680)
cy.get('.rpl-form-dropdown__more-label').contains('+5 more')

cy.viewport(480, 680)
cy.get('.rpl-form-dropdown__more-label').contains('+8 more')

cy.viewport(370, 680)
cy.get('.rpl-form-dropdown__more-label').contains('+10 more')
})

it('can be "searched" by typing from the input', () => {
cy.mount(RplFormDropDown, { props })

Expand Down

0 comments on commit 79791b1

Please sign in to comment.