Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/components/display/chip.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ const events = ['click'];
const args = ref({
variant: 'red',
persistantActionIcon: false,
iconLeft: true
iconLeft: false,
triggerClickOnIcon: false
});
</script>
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@sysvale/cuida",
"version": "3.154.12",
"version": "3.155.0",
"description": "A design system built by Sysvale, using storybook and Vue components",
"repository": {
"type": "git",
Expand Down
145 changes: 104 additions & 41 deletions src/components/Chip.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
<template>
<div
class="chip__container"
:class="classList"
:class="chipClasses"
data-testid="chip-container"
@click="handleClick"
:style="{ cursor: !shouldApplyTriggerClickOnIconProp ? 'pointer' : 'default' }"
@click="handleContainerClick"
>
<div :class="`chip__content--${size}`">
<div
Expand All @@ -16,9 +17,13 @@
>
<transition name="fade">
<template v-if="internalValue || props.persistantActionIcon">
<div
<div
v-if="useHasSlot('icon')"
class="chip__content--icon"
:class="[
'chip__content--icon',
{'chip__content--icon--pointer': shouldApplyTriggerClickOnIconProp}
]"
@click="handleIconClick"
>
<!-- @slot Slot utilizado para alterar o ícone mostrado na chip. -->
<slot name="icon" />
Expand All @@ -28,6 +33,8 @@
name="check-outline"
:height="icon.height"
:width="icon.width"
:class="[{'chip__content--icon--pointer': shouldApplyTriggerClickOnIconProp}]"
@click="handleIconClick"
/>
</template>
</transition>
Expand All @@ -41,7 +48,7 @@
</template>

<script setup>
import { computed, ref, onMounted, useTemplateRef, watch } from 'vue';
import { computed, onMounted, ref, useTemplateRef, watch } from 'vue';
import { useHasSlot } from '../utils/composables/useHasSlot';
import { colorOptions } from '../utils/constants/colors';
import sizes from '../utils/constants/sizes';
Expand Down Expand Up @@ -83,35 +90,46 @@ const props = defineProps({
*/
iconLeft: {
type: Boolean,
default: true,
default: false,
},
/**
* Especifica o evento de click deve ser disparado ao clicar no ícone ou no componente. Só funciona caso a prop persistantActionIcon seja true.
*/
triggerClickOnIcon: {
type: Boolean,
default: false,
},
});

const emits = defineEmits([
/**
* Evento que indica que o Chip foi clicado.
* @event click
* @type {Event}
*/
'click',
]);

const slotContentRef = useTemplateRef('slot-content');
const predefinedColors = ref(colorOptions);
const predefinedSizes = ref(sizes);
const internalValue = ref(modelValue.value);
const classList = ref('');
const shouldUpdatePadding = ref(true);
const maxWidth = ref('0px');

const shouldApplyTriggerClickOnIconProp = computed(() => {
return props.triggerClickOnIcon && props.persistantActionIcon;
});

const predefinedStyle = computed(() => {
let dynamicClass = '';

if (!internalValue.value) {
dynamicClass += ' chip--not-selected';
}

if (predefinedColors.value.indexOf(props.variant) > -1) {
dynamicClass += ` chip--${props.variant}`;
}

if (predefinedSizes.value.indexOf(props.size) > -1) {
dynamicClass += ` chip--${props.size}`;
}

return dynamicClass;
const chipClasses = computed(() => {
return [
predefinedColors.value.includes(props.variant) ? `chip--${props.variant}` : '',
predefinedSizes.value.includes(props.size) ? `chip--${props.size}` : '',
{
'chip--not-selected': !internalValue.value,
'chip__container--interactive': !shouldApplyTriggerClickOnIconProp.value
}
];
});

const icon = computed(() => {
Expand Down Expand Up @@ -160,12 +178,6 @@ watch(
watch(
() => internalValue.value,
(newInternalValue) => {
if (!newInternalValue) {
classList.value += ' chip--not-selected';
} else {
classList.value = removeNotSelectedClass();
}

setTimeout(() => {
shouldUpdatePadding.value = !newInternalValue;
}, 300);
Expand All @@ -174,8 +186,13 @@ watch(
}
);

watch(() => shouldApplyTriggerClickOnIconProp.value, (newValue) => {
if (newValue && internalValue.value) {
internalValue.value = false;
}
});

onMounted(() => {
classList.value = predefinedStyle.value;
setTimeout(() => {
maxWidth.value =
(slotContentRef.value?.offsetWidth || 0) + 4 + icon.value.width + 'px';
Expand All @@ -186,9 +203,19 @@ function handleClick() {
internalValue.value = !internalValue.value;
}

function removeNotSelectedClass() {
let regex = new RegExp('chip--not-selected', 'g');
return classList.value.replace(regex, '');
function handleContainerClick() {
if (shouldApplyTriggerClickOnIconProp.value) {
return;
}
handleClick();
emits('click', true);
}

function handleIconClick(event) {
if(shouldApplyTriggerClickOnIconProp.value) {
event.stopPropagation();
emits('click', true);
}
}

</script>
Expand All @@ -200,7 +227,6 @@ function removeNotSelectedClass() {
&__container {
border-radius: 50px !important;
width: fit-content;
cursor: pointer;
}

&--not-selected {
Expand Down Expand Up @@ -236,16 +262,23 @@ function removeNotSelectedClass() {
@include tokens.button-1;
font-weight: tokens.$font-weight-semibold;
}

&--icon {
display: flex;
overflow: hidden;
align-items: center;
width: v-bind('icon.width');
height: v-bind('icon.height');
width: calc(v-bind('icon.width') * 1px);
height: calc(v-bind('icon.height') * 1px);

&--pointer {
cursor: pointer;
}
}

&--icon > :slotted(svg) {
height: 100%;
width: 100%;
pointer-events: none;
}
}

Expand Down Expand Up @@ -274,52 +307,82 @@ function removeNotSelectedClass() {
background-color: $shade-100;
outline: 1px solid $shade-600;

&:hover {
&.chip__container--interactive:hover {
color: color.adjust($shade-600, $lightness: -10%) !important;
background-color: $shade-100 !important;
}

&:not(.chip__container--interactive) .chip__content--icon--pointer:hover {
color: color.adjust($shade-600, $lightness: -10%) !important;
background-color: tokens.$n-40 !important;
border-radius: tokens.$border-radius-circle;
}
}

&--amber {
color: tokens.$al-700;
background-color: tokens.$al-100;

&:hover {
&.chip__container--interactive:hover {
color: color.adjust(tokens.$al-700, $lightness: -10%) !important;
background-color: tokens.$al-100 !important;
}

&:not(.chip__container--interactive) .chip__content--icon--pointer:hover {
color: color.adjust(tokens.$al-600, $lightness: -10%) !important;
background-color: tokens.$n-40 !important;
border-radius: tokens.$border-radius-circle;
}
}

&--gray {
color: tokens.$n-600;
background-color: tokens.$n-20;

&:hover {
&.chip__container--interactive:hover {
color: color.adjust(tokens.$n-600, $lightness: -10%) !important;
background-color: tokens.$n-20 !important;
}

&:not(.chip__container--interactive) .chip__content--icon--pointer:hover {
color: color.adjust(tokens.$n-600, $lightness: -10%) !important;
background-color: tokens.$n-40 !important;
border-radius: tokens.$border-radius-circle;
}
}

&--white {
color: tokens.$n-800;
background-color: tokens.$n-0;
outline: 1px solid tokens.$n-100;

&:hover {
&.chip__container--interactive:hover {
color: color.adjust(tokens.$n-600, $lightness: -10%) !important;
background-color: tokens.$n-0 !important;
}

&:not(.chip__container--interactive) .chip__content--icon--pointer:hover {
color: color.adjust(tokens.$n-600, $lightness: -10%) !important;
background-color: tokens.$n-40 !important;
border-radius: tokens.$border-radius-circle;
}
}

&--dark {
color: tokens.$n-10;
background-color: tokens.$n-700;
outline: 1px solid tokens.$n-800;

&:hover {
&.chip__container--interactive:hover {
color: color.adjust(tokens.$n-10, $lightness: -10%) !important;
background-color: tokens.$n-700 !important;
}

&:not(.chip__container--interactive) .chip__content--icon--pointer:hover {
color: color.adjust(tokens.$n-10, $lightness: -10%) !important;
background-color: tokens.$n-40 !important;
border-radius: tokens.$border-radius-circle;
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/tests/__snapshots__/Chip.spec.js.snap
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`Chip > renders correctly 1`] = `
"<div data-v-711c594a="" class="chip__container" data-testid="chip-container">
"<div data-v-711c594a="" class="chip__container chip--gray chip--md chip--not-selected chip__container--interactive" data-testid="chip-container" style="cursor: pointer;">
<div data-v-711c594a="" class="chip__content--md">
<div data-v-711c594a="" class="chip__content-container" style="max-width: 0px; padding-right: 11px; padding-left: 11px;">
<transition-stub data-v-711c594a="" name="fade" appear="false" persisted="false" css="true">
Expand Down
Loading