Skip to content

Commit

Permalink
Merge pull request #37 from LucasWerey/feat/15
Browse files Browse the repository at this point in the history
feat(dslib): add ranking container
  • Loading branch information
LucasWerey authored Jan 18, 2024
2 parents 4209e64 + 173d545 commit 70d9494
Show file tree
Hide file tree
Showing 11 changed files with 306 additions and 13 deletions.
48 changes: 37 additions & 11 deletions src/App.vue
Original file line number Diff line number Diff line change
@@ -1,20 +1,46 @@
<script setup lang="ts">
import './assets/index.css'
import CertifContainer from './components/Containment/CertifContainer'
import DeleteModal from './components/Indicators/DeleteModal'
const handleUpdate = (value: string) => {
console.log(value)
}
import RankingContainer from './components/Containment/RankingContainer'
</script>

<template>
<div class="h-[100vh] w-[100vw] bg-basic-lightgrey p-2">
<DeleteModal
description="Lorem ipsum dolor sit amet consectetur. Quis aliquet eget id quis lectus pellentesque. Porttitor."
title="Voulez-vous vraiment supprimer cet élément ?"
labelFirstButton="Annuler"
labelSecondButton="Oui, Supprimer"
<div class="flex h-[100vh] w-[100vw] flex-col gap-5 bg-basic-lightgrey p-2">
<RankingContainer title="Mots clés" :labels="['Yo', 'Suuuu']" />
<RankingContainer
title="Transports utilisés"
:labels="[
'Yo',
'Suuuu',
'Yo',
'Yo',
'Yo',
'Yo',
'Yo',
'Yo',
'Yo',
'Yo',
'Yo',
'Yo',
'Yo',
'Yo',
'Yo',
'Yo',
'Yo',
'Yo',
'Yo',
'Yo',
'Yo',
'Yo',
'Yo',
'Yo',
'Yo',
'Yo',
'Yo',
'Yo'
]"
top-rank
draggable
/>
</div>
</template>
2 changes: 2 additions & 0 deletions src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ declare module 'vue' {
'InputField.story': typeof import('./components/CTA/InputField/InputField.story.vue')['default']
Loader: typeof import('./components/Indicators/Loader/Loader.vue')['default']
'Loader.story': typeof import('./components/Indicators/Loader/Loader.story.vue')['default']
RankingContainer: typeof import('./components/Containment/RankingContainer/RankingContainer.vue')['default']
'RankingContainer.story': typeof import('./components/Containment/RankingContainer/RankingContainer.story.vue')['default']
SelectField: typeof import('./components/CTA/SelectField/SelectField.vue')['default']
'SelectField.story': typeof import('./components/CTA/SelectField/SelectField.story.vue')['default']
SnackBar: typeof import('./components/Indicators/SnackBar/SnackBar.vue')['default']
Expand Down
4 changes: 2 additions & 2 deletions src/components/Containment/ChipContainer/ChipContainer.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<template>
<div
class="flex h-[22px] min-w-[69px] max-w-[95px] items-center justify-between gap-2 overflow-hidden rounded-lg border-[0.25px] border-primary-moonstone bg-primary-light bg-opacity-10 px-2 py-1 text-2 font-normal leading-5 text-primary-moonstone"
class="border-primary-moonston bg-primary-lightmoonstone flex h-[22px] min-w-fit max-w-[95px] items-center justify-between gap-2 overflow-hidden rounded-lg border-[0.25px] bg-opacity-10 px-2 py-1 text-2 font-normal leading-5 text-primary-moonstone"
:class="setIconPosition"
>
<div class="flex cursor-default overflow-hidden overflow-ellipsis whitespace-nowrap">
<div class="flex overflow-hidden overflow-ellipsis whitespace-nowrap">
{{ label }}
</div>
<div
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { mount } from '@vue/test-utils'
import { it, describe, expect } from 'vitest'
import RankingContainer from '.'

describe('RankingContainer', () => {
it('renders the correct title', () => {
const wrapper = mount(RankingContainer, {
props: {
title: 'Test Title',
labels: [],
topRank: false,
draggable: false
}
})

const titleElement = wrapper.find('[data-test="title"]')
expect(titleElement.text()).toBe('Test Title')
})

it('renders the correct labels', () => {
const wrapper = mount(RankingContainer, {
props: {
title: 'Test Title',
labels: ['Label 1', 'Label 2'],
topRank: false,
draggable: false
}
})

const labelsElements = wrapper.findAll('[data-test="label"]')
expect(labelsElements[0].text()).toBe('Label 1')
expect(labelsElements[1].text()).toBe('Label 2')
})

it('applies the top rank class when topRank is true', () => {
const wrapper = mount(RankingContainer, {
props: {
title: 'Test Title',
labels: [],
topRank: true,
draggable: false
}
})

const containerElement = wrapper.find('[data-test="container"]')
expect(containerElement.classes()).toContain('border-primary-moonstone')
})

it('applies the draggable class when draggable is true', () => {
const wrapper = mount(RankingContainer, {
props: {
title: 'Test Title',
labels: [],
topRank: false,
draggable: true
}
})

const draggableIconElement = wrapper.find('[data-test="draggableIcon"]')
expect(draggableIconElement.classes()).toContain('cursor-move')
})
it('handles mouse down, move, and up events', async () => {
const wrapper = mount(RankingContainer, {
props: {
title: 'Test Title',
labels: [
'eazez',
'eazez',
'eazeza',
'eazezaeza',
'zaezaezaezaezae',
'eazezaezaezae',
'ezaezaezaezae',
'ezaezaezaezae',
'eazezaezaezae',
'ezaezaezae',
'ezaezaezaea',
'eazezaeza'
],
topRank: false,
draggable: true
}
})

const scrollContainer = wrapper.find('[data-test="scrollContainer"]')

await scrollContainer.trigger('mousedown', {
clientX: 100,
clientY: 100
})

await scrollContainer.trigger('mousemove', {
clientX: 200,
clientY: 200
})
await scrollContainer.trigger('mouseup')
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<template>
<Story
title="Ranking Container"
group="containment"
:layout="{
type: 'grid',
width: '80%'
}"
>
<template #controls>
<ControlDescription>
<HstInput v-model="controls.title" title="Title" />
</ControlDescription>
<ControlDescription>
<HstSelect v-model="controls.labels" :options="labelOptions" title="Labels" multiple />
</ControlDescription>
<ControlDescription>
<HstCheckbox v-model="controls.topRank" title="Top Rank" />
</ControlDescription>
<ControlDescription>
<HstCheckbox v-model="controls.draggable" title="Draggable" />
</ControlDescription>
</template>

<Variant title="Playground" auto-props-disabled>
<RankingContainer
:title="controls.title"
:labels="controls.labels"
:topRank="controls.topRank"
:draggable="controls.draggable"
/>
</Variant>
</Story>
</template>

<script setup lang="ts">
interface Controls {
title: string
labels: string[]
topRank: boolean
draggable: boolean
}
const controls = reactive<Controls>({
title: 'Ranking Container',
labels: ['Label 1', 'Label 2', 'Label 3', 'Label 4', 'Label 5'],
topRank: false,
draggable: false
})
const labelOptions = ['this is for testing the scroll container']
</script>
110 changes: 110 additions & 0 deletions src/components/Containment/RankingContainer/RankingContainer.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<template>
<div class="h-10 w-full overflow-hidden">
<div
class="flex h-full w-full shrink-0 flex-row items-center gap-3 rounded-[4px] border border-basic-grey bg-basic-white"
:class="topRankClassBorder"
data-test="container"
>
<div
class="flex h-full w-fit select-none items-center justify-center border-r border-basic-grey px-3 align-middle text-basic-grey"
:class="[topRankClassBorder, draggableClass]"
data-test="draggableIcon"
>
<p class="rotate-90" :class="topRankClassSeparator">|||</p>
</div>
<div class="flex h-full w-fit min-w-0 flex-row items-center gap-1 sm:gap-5">
<div
class="flex items-center font-eina1 text-1 font-semibold text-basic-black sm:whitespace-nowrap sm:text-4"
data-test="title"
>
{{ title }}
</div>
<div class="flex items-center text-4" :class="topRankClassSeparator">|</div>
<div
class="scrollbar-hide flex min-w-0 cursor-grab select-none flex-row items-center gap-2 overflow-x-scroll pr-2"
@mousedown="handleMouseDown"
@mousemove="handleMouseMove"
@mouseup="handleMouseUp"
@mouseleave="handleMouseUp"
ref="scrollContainer"
data-test="scrollContainer"
>
<ChipContainer v-for="label in labels" :label="label" :key="label" data-test="label" />
</div>
</div>
</div>
</div>
</template>

<script setup lang="ts">
const props = defineProps({
title: {
type: String as PropType<string>,
default: '',
required: true
},
labels: {
type: Array as PropType<string[]>,
default: () => []
},
topRank: {
type: Boolean as PropType<boolean>,
default: false
},
draggable: {
type: Boolean as PropType<boolean>,
default: false
}
})
const title = computed(() => props.title)
const labels = computed(() => props.labels)
const topRank = computed(() => props.topRank)
const draggable = computed(() => props.draggable)
let isDragging = false
let startX: number, scrollLeft: number
const scrollContainer: Ref<HTMLElement | null> = ref(null)
const topRankClassBorder = computed(() =>
topRank.value ? 'border-primary-moonstone' : 'border-basic-grey'
)
const topRankClassSeparator = computed(() =>
topRank.value ? 'text-primary-moonstone' : 'text-basic-grey'
)
const draggableClass = computed(() => (draggable.value ? 'cursor-move' : 'cursor-default'))
const handleMouseDown = (e: MouseEvent) => {
isDragging = true
startX = e.pageX - (scrollContainer.value?.offsetLeft || 0)
scrollLeft = scrollContainer.value?.scrollLeft || 0
}
const handleMouseMove = (e: MouseEvent) => {
if (!isDragging) return
e.preventDefault()
const x = e.pageX - (scrollContainer.value?.offsetLeft || 0)
const walk = (x - startX) * 1.2
if (scrollContainer.value) {
scrollContainer.value.scrollLeft = scrollLeft - walk
}
}
const handleMouseUp = () => {
isDragging = false
}
</script>

<style scoped>
.scrollbar-hide::-webkit-scrollbar {
display: none;
}
.scrollbar-hide {
-ms-overflow-style: none;
scrollbar-width: none;
}
</style>
1 change: 1 addition & 0 deletions src/components/Containment/RankingContainer/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './RankingContainer.vue';
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ export { default as chipContainer } from './components/Containment/ChipContaine
export { default as ChipContainer } from './components/Containment/ChipContainer';
export { default as CertifContainer } from './components/Containment/CertifContainer';
export { default as DeleteModal } from './components/Indicators/DeleteModal';
export { default as RankingContainer } from './components/Containment/RankingContainer';
1 change: 1 addition & 0 deletions src/tailwind/preset.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ module.exports = {
light: '#00F2A5',
charcoal: '#373F51',
moonstone: '#58A4B0',
lightmoonstone: '#58A4B0',
powder: '#A9BCD0',
platinum: '#D8DBE2'
},
Expand Down
1 change: 1 addition & 0 deletions src/tailwind/preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ module.exports = {
light: '#00F2A5',
charcoal: '#373F51',
moonstone: '#58A4B0',
lightmoonstone: '#58A4B0',
powder: '#A9BCD0',
platinum: '#D8DBE2'
},
Expand Down
1 change: 1 addition & 0 deletions src/tailwind/presetConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export default Object.freeze({
light: '#00F2A5',
charcoal: '#373F51',
moonstone: '#58A4B0',
lightmoonstone: '#58A4B0',
powder: '#A9BCD0',
platinum: '#D8DBE2'
},
Expand Down

0 comments on commit 70d9494

Please sign in to comment.