From d97d43d57ded97dfcd40c9201a3896ae827b0d82 Mon Sep 17 00:00:00 2001 From: Matthias Goudjil Date: Tue, 19 Sep 2023 11:16:32 +0200 Subject: [PATCH 01/10] feat: tag component (wip) --- packages/components/index.ts | 1 + packages/components/tag/index.ts | 8 ++++ packages/components/tag/src/tag.ts | 45 +++++++++++++++++++ packages/components/tag/src/tag.vue | 33 ++++++++++++++ .../components/tag/stories/tag.stories.ts | 34 ++++++++++++++ packages/components/tag/style/css.ts | 2 + packages/components/tag/style/index.ts | 2 + packages/components/tag/test/tag.spec.ts | 23 ++++++++++ packages/puik/component.ts | 2 + packages/theme/src/index.scss | 1 + packages/theme/src/tag.scss | 31 +++++++++++++ typings/global.d.ts | 1 + 12 files changed, 183 insertions(+) create mode 100644 packages/components/tag/index.ts create mode 100644 packages/components/tag/src/tag.ts create mode 100644 packages/components/tag/src/tag.vue create mode 100644 packages/components/tag/stories/tag.stories.ts create mode 100644 packages/components/tag/style/css.ts create mode 100644 packages/components/tag/style/index.ts create mode 100644 packages/components/tag/test/tag.spec.ts create mode 100644 packages/theme/src/tag.scss diff --git a/packages/components/index.ts b/packages/components/index.ts index bc6d7e31..c249eeaa 100644 --- a/packages/components/index.ts +++ b/packages/components/index.ts @@ -27,3 +27,4 @@ export * from './sidebar' export * from './textarea' export * from './tab-navigation' export * from './progress-stepper' +export * from './tag' diff --git a/packages/components/tag/index.ts b/packages/components/tag/index.ts new file mode 100644 index 00000000..69156075 --- /dev/null +++ b/packages/components/tag/index.ts @@ -0,0 +1,8 @@ +import { withInstall } from '@puik/utils' + +import Tag from './src/tag.vue' + +export const PuikTag = withInstall(Tag) +export default PuikTag + +export * from './src/tag' diff --git a/packages/components/tag/src/tag.ts b/packages/components/tag/src/tag.ts new file mode 100644 index 00000000..93390fc8 --- /dev/null +++ b/packages/components/tag/src/tag.ts @@ -0,0 +1,45 @@ +import { buildProps } from '@puik/utils' +import type { ExtractPropTypes, PropType } from 'vue' +import type Tag from './tag.vue' + +export const tagColorsVariants = [ + 'neutral', + 'blue', + 'yellow', + 'green', + 'purple', +] as const + +export type PuikTagColorVariant = (typeof tagColorsVariants)[number] + +export const tagProps = buildProps({ + id: { + type: String, + required: true, + default: '', + }, + variant: { + type: String as PropType, + required: false, + default: 'neutral', + }, + icon: { + type: String, + default: '', + required: false, + }, + closeable: { + type: Boolean, + required: false, + default: true, + }, + disable: { + type: Boolean, + required: false, + default: false, + }, +} as const) + +export type TagProps = ExtractPropTypes + +export type TagInstance = InstanceType diff --git a/packages/components/tag/src/tag.vue b/packages/components/tag/src/tag.vue new file mode 100644 index 00000000..17c9dba7 --- /dev/null +++ b/packages/components/tag/src/tag.vue @@ -0,0 +1,33 @@ + + + diff --git a/packages/components/tag/stories/tag.stories.ts b/packages/components/tag/stories/tag.stories.ts new file mode 100644 index 00000000..6a342559 --- /dev/null +++ b/packages/components/tag/stories/tag.stories.ts @@ -0,0 +1,34 @@ +import PuikTag from './../src/tag.vue' +import type { Meta, StoryFn, Args } from '@storybook/vue3' + +export default { + title: 'Components/Tag', + component: PuikTag, +} as Meta + +const Template: StoryFn = (args: Args) => ({ + components: { + PuikTag, + }, + setup() { + return { args } + }, + template: ``, +}) + +export const Default = { + render: Template, + args: {}, + parameters: { + docs: { + source: { + code: ` + + + + `, + language: 'html', + }, + }, + }, +} diff --git a/packages/components/tag/style/css.ts b/packages/components/tag/style/css.ts new file mode 100644 index 00000000..766ee1bf --- /dev/null +++ b/packages/components/tag/style/css.ts @@ -0,0 +1,2 @@ +import '@puik/components/base/style/css' +import '@puik/theme/puik-tag.css' diff --git a/packages/components/tag/style/index.ts b/packages/components/tag/style/index.ts new file mode 100644 index 00000000..7666132b --- /dev/null +++ b/packages/components/tag/style/index.ts @@ -0,0 +1,2 @@ +import '@puik/components/base/style' +import '@puik/theme/src/tag.scss' diff --git a/packages/components/tag/test/tag.spec.ts b/packages/components/tag/test/tag.spec.ts new file mode 100644 index 00000000..40611d9f --- /dev/null +++ b/packages/components/tag/test/tag.spec.ts @@ -0,0 +1,23 @@ +import { mount } from '@vue/test-utils' +import { describe, it, expect } from 'vitest' +import PuikTag from '../src/tag.vue' +import type { MountingOptions, VueWrapper } from '@vue/test-utils' + +describe('Tag tests', () => { + let wrapper: VueWrapper + const factory = ( + propsData: Record = {}, + options: MountingOptions = {} + ) => { + wrapper = mount(PuikTag, { + props: { + ...propsData, + }, + ...options, + }) + } + it('should be a vue instance', () => { + factory() + expect(wrapper).toBeTruthy() + }) +}) diff --git a/packages/puik/component.ts b/packages/puik/component.ts index 2354a794..24a4dc16 100644 --- a/packages/puik/component.ts +++ b/packages/puik/component.ts @@ -1,3 +1,4 @@ +import { PuikTag } from '@puik/components/tag' import { PuikTabNavigation, PuikTabNavigationGroupPanels, @@ -48,6 +49,7 @@ import type { Plugin } from 'vue' // prettier-ignore export default [ + PuikTag, PuikTabNavigationGroupPanels, PuikTabNavigationTitle, PuikTabNavigationGroupTitles, diff --git a/packages/theme/src/index.scss b/packages/theme/src/index.scss index 14e753de..b0391f42 100644 --- a/packages/theme/src/index.scss +++ b/packages/theme/src/index.scss @@ -40,3 +40,4 @@ @use 'tab-navigation-group-panels'; @use 'progress-stepper'; @use 'progress-stepper-step'; +@use 'tag'; diff --git a/packages/theme/src/tag.scss b/packages/theme/src/tag.scss new file mode 100644 index 00000000..d4b5ab4a --- /dev/null +++ b/packages/theme/src/tag.scss @@ -0,0 +1,31 @@ +@use './common/typography.scss'; + +.puik-tag { + @extend .puik-body-small; + @apply font-bold flex items-center px-2 py-1 space-x-2; + + &--neutral { + @apply bg-primary-300 text-primary; + } + &--blue { + @apply bg-ocean-blue-50 text-primary; + } + &--yellow { + @apply bg-amber-100 text-primary; + } + &--green { + @apply bg-green-50 text-primary; + } + &--purple { + @apply bg-purple-50 text-primary; + } + &__close { + @apply p-[3px] cursor-pointer rounded-[50%] hover:bg-primary-400; + } + &__disabled { + @apply bg-primary-200 text-primary-500; + .puik-tag__close { + @apply cursor-not-allowed hover:bg-primary-200; + } + } +} diff --git a/typings/global.d.ts b/typings/global.d.ts index 7252421a..df474081 100644 --- a/typings/global.d.ts +++ b/typings/global.d.ts @@ -1,6 +1,7 @@ // GlobalComponents for Volar declare module '@vue/runtime-core' { export interface GlobalComponents { + PuikTag: typeof import('@prestashopcorp/puik')['PuikTag'] PuikTabNavigationGroupPanels: typeof import('@prestashopcorp/puik')['PuikTabNavigationGroupPanels'] PuikTabNavigationTitle: typeof import('@prestashopcorp/puik')['PuikTabNavigationTitle'] PuikTabNavigationGroupTitles: typeof import('@prestashopcorp/puik')['PuikTabNavigationGroupTitles'] From b73f82d191ce5eb139409b9c4c26b6660bfe5fc2 Mon Sep 17 00:00:00 2001 From: Matthias Goudjil Date: Tue, 19 Sep 2023 14:55:21 +0200 Subject: [PATCH 02/10] docs: storyboob - tag-component (wip) --- packages/components/tag/src/tag.ts | 2 +- packages/components/tag/src/tag.vue | 8 +- .../components/tag/stories/tag.stories.ts | 167 +++++++++++++++++- packages/theme/src/tag.scss | 28 ++- 4 files changed, 193 insertions(+), 12 deletions(-) diff --git a/packages/components/tag/src/tag.ts b/packages/components/tag/src/tag.ts index 93390fc8..937293bd 100644 --- a/packages/components/tag/src/tag.ts +++ b/packages/components/tag/src/tag.ts @@ -33,7 +33,7 @@ export const tagProps = buildProps({ required: false, default: true, }, - disable: { + disabled: { type: Boolean, required: false, default: false, diff --git a/packages/components/tag/src/tag.vue b/packages/components/tag/src/tag.vue index 17c9dba7..d7152b23 100644 --- a/packages/components/tag/src/tag.vue +++ b/packages/components/tag/src/tag.vue @@ -3,16 +3,18 @@ :id="id" :class="[ `puik-tag puik-tag--${variant}`, - { 'puik-tag__disabled': disable }, + { 'puik-tag__disabled': disabled }, ]" > - + + + diff --git a/packages/components/tag/stories/tag.stories.ts b/packages/components/tag/stories/tag.stories.ts index 6a342559..b88a8742 100644 --- a/packages/components/tag/stories/tag.stories.ts +++ b/packages/components/tag/stories/tag.stories.ts @@ -1,32 +1,185 @@ +import { ref } from 'vue' +import { PuikIcon } from '@puik/components/icon' +import { tagColorsVariants } from '../src/tag' import PuikTag from './../src/tag.vue' import type { Meta, StoryFn, Args } from '@storybook/vue3' +const tagColorsVariantsSummary = tagColorsVariants.join('|') + export default { title: 'Components/Tag', component: PuikTag, + argTypes: { + id: { + description: + "Prop which will correspond to the component's html id attribute. NB: must not start with a number", + control: 'text', + table: { + type: { + summary: 'string', + }, + defaultValue: { + summary: 'none', + }, + }, + }, + variant: { + description: + 'Color variants of tag component (neutral by default, blue, yellow, green, purple)', + control: 'select', + options: tagColorsVariants, + table: { + type: { + summary: tagColorsVariantsSummary, + }, + defaultValue: { + summary: 'neutral', + }, + }, + }, + icon: { + description: 'Material icon name', + control: 'text', + table: { + type: { + summary: 'string', + }, + defaultValue: { + summary: 'none', + }, + }, + }, + closeable: { + description: + 'Add closeable feature for the tag component (close icon which trigger a close event to parent component)', + control: 'boolean', + table: { + type: { + summary: 'boolean', + }, + defaultValue: { + summary: 'true', + }, + }, + }, + disabled: { + description: 'Disables the Tag component ', + control: 'boolean', + table: { + type: { + summary: 'boolean', + }, + defaultValue: { + summary: 'false', + }, + }, + }, + }, } as Meta -const Template: StoryFn = (args: Args) => ({ +const DefaultTemplate: StoryFn = (args: Args) => ({ components: { + PuikIcon, PuikTag, }, setup() { - return { args } + const tags = ref([ + { + id: 'id-1', + variant: 'neutral', + icon: 'home', + closeable: true, + disable: false, + content: 'tag test', + }, + { + id: 'id-2', + variant: 'blue', + icon: 'settings', + closeable: true, + disable: false, + content: 'tag test', + }, + { + id: 'id-3', + variant: 'yellow', + icon: 'favorite', + closeable: true, + disable: false, + content: + 'long content long content long content long content long content ', + }, + { + id: 'id-4', + variant: 'green', + icon: 'key', + closeable: true, + disable: false, + content: 'tag test', + }, + { + id: 'id-5', + variant: 'purple', + icon: 'token', + closeable: true, + disable: true, + content: 'tag test', + }, + { + id: 'id-6', + variant: 'purple', + icon: 'public', + closeable: true, + disable: true, + content: 'tag test', + }, + ]) + const handleCloseTag = (payload: string) => { + tags.value.map((e, i) => { + e.id === payload && tags.value.splice(i, 1) + }) + } + return { tags, args } }, - template: ``, + template: ` + + {{ tag.content }} + +`, }) export const Default = { - render: Template, + render: DefaultTemplate, args: {}, parameters: { docs: { source: { code: ` - + + + {{ tag.content }} + - - `, + +`, language: 'html', }, }, diff --git a/packages/theme/src/tag.scss b/packages/theme/src/tag.scss index d4b5ab4a..d188fa4d 100644 --- a/packages/theme/src/tag.scss +++ b/packages/theme/src/tag.scss @@ -2,7 +2,7 @@ .puik-tag { @extend .puik-body-small; - @apply font-bold flex items-center px-2 py-1 space-x-2; + @apply max-w-[220px] font-bold flex items-center px-2 py-1 space-x-2; &--neutral { @apply bg-primary-300 text-primary; @@ -28,4 +28,30 @@ @apply cursor-not-allowed hover:bg-primary-200; } } + &__content { + @apply max-w-[150px] overflow-x-auto overflow-y-hidden whitespace-nowrap; + &::-webkit-scrollbar { + @apply bg-primary-100; + width: 12px; + } + &::-webkit-scrollbar:horizontal { + height: 4px; + } + &::-webkit-scrollbar-track { + border: none; + border-radius: 0; + -webkit-box-shadow: none; + } + &::-webkit-scrollbar-thumb { + @apply bg-primary-400; + border: none; + border-radius: 0; + } + &::-webkit-scrollbar-thumb:hover { + @apply bg-primary; + } + &::-webkit-scrollbar-thumb:active { + @apply bg-primary; + } + } } From 459d1451cf76e109b10c53639555e9e8214f69b9 Mon Sep 17 00:00:00 2001 From: Matthias Goudjil Date: Thu, 21 Sep 2023 17:29:47 +0200 Subject: [PATCH 03/10] fix: #191 tag-component --- packages/components/tag/src/tag.ts | 25 +- packages/components/tag/src/tag.vue | 30 +- .../components/tag/stories/tag.stories.ts | 533 ++++++++++++++++-- packages/components/tooltip/src/tooltip.ts | 2 +- packages/theme/src/tag.scss | 51 +- 5 files changed, 541 insertions(+), 100 deletions(-) diff --git a/packages/components/tag/src/tag.ts b/packages/components/tag/src/tag.ts index 937293bd..5d229647 100644 --- a/packages/components/tag/src/tag.ts +++ b/packages/components/tag/src/tag.ts @@ -1,4 +1,5 @@ import { buildProps } from '@puik/utils' +import type { PuikTooltipPosition } from '@puik/components' import type { ExtractPropTypes, PropType } from 'vue' import type Tag from './tag.vue' @@ -10,19 +11,32 @@ export const tagColorsVariants = [ 'purple', ] as const +export const tagSizeVariants = ['default', 'small'] as const + export type PuikTagColorVariant = (typeof tagColorsVariants)[number] +export type PuikTagSizeVariant = (typeof tagSizeVariants)[number] export const tagProps = buildProps({ id: { type: String, required: true, - default: '', + default: undefined, + }, + content: { + type: String, + required: true, + default: undefined, }, variant: { - type: String as PropType, + type: String, required: false, default: 'neutral', }, + size: { + type: String, + required: false, + default: 'default', + }, icon: { type: String, default: '', @@ -31,13 +45,18 @@ export const tagProps = buildProps({ closeable: { type: Boolean, required: false, - default: true, + default: false, }, disabled: { type: Boolean, required: false, default: false, }, + tooltipPosition: { + type: String as PropType, + Required: false, + default: 'bottom', + }, } as const) export type TagProps = ExtractPropTypes diff --git a/packages/components/tag/src/tag.vue b/packages/components/tag/src/tag.vue index d7152b23..9abbb48b 100644 --- a/packages/components/tag/src/tag.vue +++ b/packages/components/tag/src/tag.vue @@ -2,14 +2,22 @@
- - - - + +
+ + + {{ content }} + + {{ content }} +
import { PuikIcon } from '@puik/components/icon' -import { tagProps } from './tag' +import { PuikTooltip } from '@puik/components/tooltip' +import { + tagProps, + type PuikTagSizeVariant, + type PuikTagColorVariant, +} from './tag' +import type { PuikTooltipPosition } from '@puik/components/tooltip' defineOptions({ name: 'PuikTag', }) @@ -30,6 +44,6 @@ const props = defineProps(tagProps) const emit = defineEmits(['close']) const handleCloseEvent = () => { - emit('close', props.id) + emit('close') } diff --git a/packages/components/tag/stories/tag.stories.ts b/packages/components/tag/stories/tag.stories.ts index b88a8742..eddf193b 100644 --- a/packages/components/tag/stories/tag.stories.ts +++ b/packages/components/tag/stories/tag.stories.ts @@ -1,10 +1,12 @@ import { ref } from 'vue' -import { PuikIcon } from '@puik/components/icon' -import { tagColorsVariants } from '../src/tag' +import { PuikIcon, PuikButton, tooltipPositions } from '@puik/components' +import { tagColorsVariants, tagSizeVariants } from '../src/tag' import PuikTag from './../src/tag.vue' import type { Meta, StoryFn, Args } from '@storybook/vue3' const tagColorsVariantsSummary = tagColorsVariants.join('|') +const tagSizeVariantsSummary = tagSizeVariants.join('|') +const tooltipPositionsSummary = tooltipPositions.join('|') export default { title: 'Components/Tag', @@ -19,7 +21,33 @@ export default { summary: 'string', }, defaultValue: { - summary: 'none', + summary: 'undefined', + }, + }, + }, + content: { + description: + 'The text content (NB: if its length is equal to or greater than 30 characters it will be truncated and will be displayed entirely on hover in a tooltip)', + control: 'text', + table: { + type: { + summary: 'string', + }, + defaultValue: { + summary: 'undefined', + }, + }, + }, + size: { + description: 'Size variants of tag component (default, small)', + control: 'select', + options: tagSizeVariants, + table: { + type: { + summary: tagSizeVariantsSummary, + }, + defaultValue: { + summary: 'default', }, }, }, @@ -49,6 +77,20 @@ export default { }, }, }, + tooltipPosition: { + description: + 'Position of the tooltip (NB: a tooltip appears if the content length is equal to or greater than 30 characters).', + control: 'select', + options: tooltipPositions, + table: { + type: { + summary: tooltipPositionsSummary, + }, + defaultValue: { + summary: 'neutral', + }, + }, + }, closeable: { description: 'Add closeable feature for the tag component (close icon which trigger a close event to parent component)', @@ -58,7 +100,7 @@ export default { summary: 'boolean', }, defaultValue: { - summary: 'true', + summary: 'false', }, }, }, @@ -75,6 +117,16 @@ export default { }, }, }, + args: { + id: 'puik-tag-id', + content: 'default tag', + size: 'default', + variant: 'neutral', + icon: '', + closeable: false, + disabled: false, + tooltipPosition: 'bottom', + }, } as Meta const DefaultTemplate: StoryFn = (args: Args) => ({ @@ -82,103 +134,464 @@ const DefaultTemplate: StoryFn = (args: Args) => ({ PuikIcon, PuikTag, }, + setup() { + return { args } + }, + template: ``, +}) + +const HandleCloseEventTemplate: StoryFn = (args: Args) => ({ + components: { + PuikIcon, + PuikTag, + PuikButton, + }, setup() { const tags = ref([ { - id: 'id-1', variant: 'neutral', icon: 'home', closeable: true, - disable: false, - content: 'tag test', + disabled: true, + content: "can't close disabled", + }, + { + variant: 'neutral', + icon: 'home', + closeable: true, + disabled: false, + content: 'close me !', }, { - id: 'id-2', variant: 'blue', - icon: 'settings', + icon: 'home', closeable: true, - disable: false, - content: 'tag test', + disabled: false, + content: 'close me !', }, { - id: 'id-3', variant: 'yellow', - icon: 'favorite', + icon: 'home', closeable: true, - disable: false, - content: - 'long content long content long content long content long content ', + disabled: false, + content: 'close me !', }, { - id: 'id-4', variant: 'green', - icon: 'key', + icon: 'home', closeable: true, - disable: false, - content: 'tag test', + disabled: false, + content: 'close me !', }, { - id: 'id-5', variant: 'purple', - icon: 'token', + icon: 'home', closeable: true, - disable: true, - content: 'tag test', + disabled: false, + content: 'close me !', + }, + ]) + + const copyInitialTags = [...tags.value] + const handleCloseTag = (index: number) => { + tags.value.splice(index, 1) + } + const refreshTags = () => { + tags.value = [] + copyInitialTags.map((tag) => { + tags.value.push(tag) + }) + } + return { tags, args, handleCloseTag, refreshTags } + }, + template: ` +
+ +
+ + + Refresh + +`, +}) + +const ColorVariantsTemplate: StoryFn = (args: Args) => ({ + components: { + PuikIcon, + PuikTag, + }, + setup() { + const tags = ref([ + { + variant: 'neutral', + content: 'neutral tag', + }, + { + variant: 'blue', + content: 'blue tag', + }, + { + variant: 'yellow', + content: 'yellow tag', + }, + { + variant: 'green', + content: 'green tag', }, { - id: 'id-6', variant: 'purple', - icon: 'public', - closeable: true, - disable: true, - content: 'tag test', + content: 'purple tag', }, ]) - const handleCloseTag = (payload: string) => { - tags.value.map((e, i) => { - e.id === payload && tags.value.splice(i, 1) - }) - } + return { tags, args } }, template: ` +
+ +
+`, +}) + +const SizeVariantsTemplate: StoryFn = (args: Args) => ({ + components: { + PuikIcon, + PuikTag, + }, + setup() { + return { args } + }, + template: ` + + +`, +}) + +const CloseableTemplate: StoryFn = (args: Args) => ({ + components: { + PuikIcon, + PuikTag, + }, + setup() { + return { args } + }, + template: ` + +`, +}) + +const DisabledTemplate: StoryFn = (args: Args) => ({ + components: { + PuikIcon, + PuikTag, + }, + setup() { + return { args } + }, + template: ` + +`, +}) + +const WithIconTemplate: StoryFn = (args: Args) => ({ + components: { + PuikIcon, + PuikTag, + }, + setup() { + return { args } + }, + template: ` + +`, +}) + +const WithLongTextTemplate: StoryFn = (args: Args) => ({ + components: { + PuikIcon, + PuikTag, + }, + setup() { + return { args } + }, + template: ` + +`, +}) + +export const Default = { + render: DefaultTemplate, + args: {}, + parameters: { + docs: { + source: { + code: ` + + +
+ + +
+
+ default tag +
+
+`, + language: 'html', + }, + }, + }, +} + +export const HandleCloseEvent = { + render: HandleCloseEventTemplate, + args: {}, + parameters: { + docs: { + source: { + code: ` + +
- {{ tag.content }} - + :disabled="tag.disabled" + @close="handleCloseTag(index)" + /> +
+ + +const handleCloseTag = (index: number) => { + // Do stuff before closing + // Then + tags.value.splice(index, 1) +} `, -}) + language: 'html', + }, + }, + }, +} -export const Default = { - render: DefaultTemplate, +export const ColorVariants = { + render: ColorVariantsTemplate, + args: {}, + parameters: { + docs: { + source: { + code: ` + + + + + + + +
+
+ {$variant} tag +
+
+`, + language: 'html', + }, + }, + }, +} + +export const SizeVariants = { + render: SizeVariantsTemplate, + args: {}, + parameters: { + docs: { + source: { + code: ` + + + + + + + +
+
+ {$size} tag +
+
+`, + language: 'html', + }, + }, + }, +} + +export const Closeable = { + render: CloseableTemplate, + args: {}, + parameters: { + docs: { + source: { + code: ` + + + + + + + +
+
+ closeable tag +
+
close
+
+`, + language: 'html', + }, + }, + }, +} + +export const Disabled = { + render: DisabledTemplate, + args: {}, + parameters: { + docs: { + source: { + code: ` + + + + + +
+
+ disabled tag +
+
+`, + language: 'html', + }, + }, + }, +} + +export const WithIcon = { + render: WithIconTemplate, + args: {}, + parameters: { + docs: { + source: { + code: ` + + + + + +
+
+ favorite +
+
with icon tag
+
+`, + language: 'html', + }, + }, + }, +} + +export const WithLongText = { + render: WithLongTextTemplate, args: {}, parameters: { docs: { source: { code: ` - - - {{ tag.content }} - - - + + + `, language: 'html', }, diff --git a/packages/components/tooltip/src/tooltip.ts b/packages/components/tooltip/src/tooltip.ts index ab24ac2e..ec2a5c35 100644 --- a/packages/components/tooltip/src/tooltip.ts +++ b/packages/components/tooltip/src/tooltip.ts @@ -18,7 +18,7 @@ export const tooltipProps = buildProps({ position: { type: String as PropType, required: false, - default: 'top', + default: 'bottom', }, isDisabled: { type: Boolean, diff --git a/packages/theme/src/tag.scss b/packages/theme/src/tag.scss index d188fa4d..f5d8a57a 100644 --- a/packages/theme/src/tag.scss +++ b/packages/theme/src/tag.scss @@ -2,8 +2,17 @@ .puik-tag { @extend .puik-body-small; - @apply max-w-[220px] font-bold flex items-center px-2 py-1 space-x-2; + @apply max-w-fit font-bold flex items-center; + &--default { + @apply px-2 py-[3px]; + } + &--small { + @apply px-1 py-0; + .puik-tag__close { + @apply p-[1px]; + } + } &--neutral { @apply bg-primary-300 text-primary; } @@ -19,39 +28,25 @@ &--purple { @apply bg-purple-50 text-primary; } - &__close { - @apply p-[3px] cursor-pointer rounded-[50%] hover:bg-primary-400; - } - &__disabled { + &--disabled { @apply bg-primary-200 text-primary-500; .puik-tag__close { @apply cursor-not-allowed hover:bg-primary-200; } } + &__close { + @apply p-[3px] ml-auto cursor-pointer rounded-[50%] hover:bg-primary-400; + } + &__icon { + @apply mr-1; + } &__content { - @apply max-w-[150px] overflow-x-auto overflow-y-hidden whitespace-nowrap; - &::-webkit-scrollbar { - @apply bg-primary-100; - width: 12px; - } - &::-webkit-scrollbar:horizontal { - height: 4px; - } - &::-webkit-scrollbar-track { - border: none; - border-radius: 0; - -webkit-box-shadow: none; - } - &::-webkit-scrollbar-thumb { - @apply bg-primary-400; - border: none; - border-radius: 0; - } - &::-webkit-scrollbar-thumb:hover { - @apply bg-primary; - } - &::-webkit-scrollbar-thumb:active { - @apply bg-primary; + @apply max-w-[150px] pr-[2px] overflow-hidden whitespace-nowrap text-ellipsis; + & > .puik-tooltip { + @apply max-w-[150px] overflow-hidden whitespace-nowrap text-ellipsis; } } + &__content .puik-tooltip__wrapper { + @apply max-w-[150px] mr-1 pr-[2px] overflow-hidden whitespace-nowrap text-ellipsis; + } } From aa51f799520acac06b7eafd5915dd98af300c13a Mon Sep 17 00:00:00 2001 From: Matthias Goudjil Date: Fri, 22 Sep 2023 10:18:34 +0200 Subject: [PATCH 04/10] test: #191 - tests for tag component --- packages/components/tag/src/tag.vue | 2 +- packages/components/tag/test/tag.spec.ts | 44 ++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/packages/components/tag/src/tag.vue b/packages/components/tag/src/tag.vue index 9abbb48b..1e2aba20 100644 --- a/packages/components/tag/src/tag.vue +++ b/packages/components/tag/src/tag.vue @@ -9,7 +9,7 @@
diff --git a/packages/components/tag/test/tag.spec.ts b/packages/components/tag/test/tag.spec.ts index 40611d9f..22c20b89 100644 --- a/packages/components/tag/test/tag.spec.ts +++ b/packages/components/tag/test/tag.spec.ts @@ -5,6 +5,14 @@ import type { MountingOptions, VueWrapper } from '@vue/test-utils' describe('Tag tests', () => { let wrapper: VueWrapper + const findTag = () => wrapper.find('.puik-tag') + const findTagContent = () => wrapper.find('.puik-tag__content') + const findCloseBtn = () => wrapper.find('.puik-tag__close') + const findLeftIcon = () => wrapper.find('.puik-tag__icon') + + // const findButtonLeftIcon = () => wrapper.find('.puik-button__left-icon') + // const findButtonRightIcon = () => wrapper.find('.puik-button__right-icon') + const factory = ( propsData: Record = {}, options: MountingOptions = {} @@ -16,8 +24,44 @@ describe('Tag tests', () => { ...options, }) } + it('should be a vue instance', () => { factory() expect(wrapper).toBeTruthy() }) + + it('as id prop value is "puik-tag-example", id html attribute of puik-tag should be "puik-tag-example"', () => { + factory({ id: 'puik-tag-example' }) + expect(findTag().attributes().id).toBe('puik-tag-example') + }) + + it('Tag text should be "content"', () => { + factory({ content: 'content' }) + expect(findTagContent().text()).toBe('content') + }) + + it('should display a blue version of the tag', () => { + factory({ variant: 'blue' }) + expect(findTag().classes()).toContain('puik-tag--blue') + }) + + it('should display a tag small version', () => { + factory({ size: 'small' }) + expect(findTag().classes()).toContain('puik-tag--small') + }) + + it('should display a tag version with left icon', () => { + factory({ icon: 'home' }) + expect(findLeftIcon().text()).toBe('home') + }) + + it('should display a tag closeable version', () => { + factory({ closeable: true }) + expect(findCloseBtn().text()).toBe('close') + }) + + it('should display a tag disabled version', () => { + factory({ disabled: true }) + expect(findTag().classes()).toContain('puik-tag--disabled') + }) }) From f9896dae6a7ceb1dfb75951d4bda283ded38f436 Mon Sep 17 00:00:00 2001 From: Matthias Goudjil Date: Fri, 22 Sep 2023 10:24:55 +0200 Subject: [PATCH 05/10] test: #191 - remove comments --- packages/components/tag/test/tag.spec.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/components/tag/test/tag.spec.ts b/packages/components/tag/test/tag.spec.ts index 22c20b89..9857a71e 100644 --- a/packages/components/tag/test/tag.spec.ts +++ b/packages/components/tag/test/tag.spec.ts @@ -10,9 +10,6 @@ describe('Tag tests', () => { const findCloseBtn = () => wrapper.find('.puik-tag__close') const findLeftIcon = () => wrapper.find('.puik-tag__icon') - // const findButtonLeftIcon = () => wrapper.find('.puik-button__left-icon') - // const findButtonRightIcon = () => wrapper.find('.puik-button__right-icon') - const factory = ( propsData: Record = {}, options: MountingOptions = {} From 5a9eb3273d8934e5cdd9d5732c1160e5bfc07d30 Mon Sep 17 00:00:00 2001 From: Matthias Goudjil Date: Wed, 4 Oct 2023 09:42:02 +0200 Subject: [PATCH 06/10] fix: renaming tag to chip --- packages/components/chip/index.ts | 8 + .../{tag/src/tag.ts => chip/src/chip.ts} | 16 +- .../{tag/src/tag.vue => chip/src/chip.vue} | 22 +- .../stories/chip.stories.ts} | 224 +++++++++--------- .../components/{tag => chip}/style/css.ts | 2 +- .../components/{tag => chip}/style/index.ts | 2 +- .../tag.spec.ts => chip/test/chip.spec.ts} | 0 packages/components/index.ts | 2 +- packages/components/tag/index.ts | 8 - packages/puik/component.ts | 4 +- packages/theme/src/{tag.scss => chip.scss} | 6 +- packages/theme/src/index.scss | 2 +- 12 files changed, 148 insertions(+), 148 deletions(-) create mode 100644 packages/components/chip/index.ts rename packages/components/{tag/src/tag.ts => chip/src/chip.ts} (68%) rename packages/components/{tag/src/tag.vue => chip/src/chip.vue} (69%) rename packages/components/{tag/stories/tag.stories.ts => chip/stories/chip.stories.ts} (67%) rename packages/components/{tag => chip}/style/css.ts (53%) rename packages/components/{tag => chip}/style/index.ts (51%) rename packages/components/{tag/test/tag.spec.ts => chip/test/chip.spec.ts} (100%) delete mode 100644 packages/components/tag/index.ts rename packages/theme/src/{tag.scss => chip.scss} (94%) diff --git a/packages/components/chip/index.ts b/packages/components/chip/index.ts new file mode 100644 index 00000000..2305c20f --- /dev/null +++ b/packages/components/chip/index.ts @@ -0,0 +1,8 @@ +import { withInstall } from '@puik/utils' + +import Chip from './src/chip.vue' + +export const PuikChip = withInstall(Chip) +export default PuikChip + +export * from './src/chip' diff --git a/packages/components/tag/src/tag.ts b/packages/components/chip/src/chip.ts similarity index 68% rename from packages/components/tag/src/tag.ts rename to packages/components/chip/src/chip.ts index 5d229647..ddf7be8a 100644 --- a/packages/components/tag/src/tag.ts +++ b/packages/components/chip/src/chip.ts @@ -1,9 +1,9 @@ import { buildProps } from '@puik/utils' import type { PuikTooltipPosition } from '@puik/components' import type { ExtractPropTypes, PropType } from 'vue' -import type Tag from './tag.vue' +import type Chip from './chip.vue' -export const tagColorsVariants = [ +export const chipColorsVariants = [ 'neutral', 'blue', 'yellow', @@ -11,12 +11,12 @@ export const tagColorsVariants = [ 'purple', ] as const -export const tagSizeVariants = ['default', 'small'] as const +export const chipSizeVariants = ['default', 'small'] as const -export type PuikTagColorVariant = (typeof tagColorsVariants)[number] -export type PuikTagSizeVariant = (typeof tagSizeVariants)[number] +export type PuikChipColorVariant = (typeof chipColorsVariants)[number] +export type PuikChipSizeVariant = (typeof chipSizeVariants)[number] -export const tagProps = buildProps({ +export const chipProps = buildProps({ id: { type: String, required: true, @@ -59,6 +59,6 @@ export const tagProps = buildProps({ }, } as const) -export type TagProps = ExtractPropTypes +export type ChipProps = ExtractPropTypes -export type TagInstance = InstanceType +export type ChipInstance = InstanceType diff --git a/packages/components/tag/src/tag.vue b/packages/components/chip/src/chip.vue similarity index 69% rename from packages/components/tag/src/tag.vue rename to packages/components/chip/src/chip.vue index 1e2aba20..ee92d61d 100644 --- a/packages/components/tag/src/tag.vue +++ b/packages/components/chip/src/chip.vue @@ -2,12 +2,12 @@
- -
+ +
@@ -31,16 +31,16 @@ import { PuikIcon } from '@puik/components/icon' import { PuikTooltip } from '@puik/components/tooltip' import { - tagProps, - type PuikTagSizeVariant, - type PuikTagColorVariant, -} from './tag' + chipProps, + type PuikChipSizeVariant, + type PuikChipColorVariant, +} from './chip' import type { PuikTooltipPosition } from '@puik/components/tooltip' defineOptions({ - name: 'PuikTag', + name: 'PuikChip', }) -const props = defineProps(tagProps) +const props = defineProps(chipProps) const emit = defineEmits(['close']) const handleCloseEvent = () => { diff --git a/packages/components/tag/stories/tag.stories.ts b/packages/components/chip/stories/chip.stories.ts similarity index 67% rename from packages/components/tag/stories/tag.stories.ts rename to packages/components/chip/stories/chip.stories.ts index eddf193b..62219cfc 100644 --- a/packages/components/tag/stories/tag.stories.ts +++ b/packages/components/chip/stories/chip.stories.ts @@ -1,16 +1,16 @@ import { ref } from 'vue' import { PuikIcon, PuikButton, tooltipPositions } from '@puik/components' -import { tagColorsVariants, tagSizeVariants } from '../src/tag' -import PuikTag from './../src/tag.vue' +import { chipColorsVariants, chipSizeVariants } from '../src/chip' +import PuikChip from './../src/chip.vue' import type { Meta, StoryFn, Args } from '@storybook/vue3' -const tagColorsVariantsSummary = tagColorsVariants.join('|') -const tagSizeVariantsSummary = tagSizeVariants.join('|') +const chipColorsVariantsSummary = chipColorsVariants.join('|') +const chipSizeVariantsSummary = chipSizeVariants.join('|') const tooltipPositionsSummary = tooltipPositions.join('|') export default { - title: 'Components/Tag', - component: PuikTag, + title: 'Components/Chip', + component: PuikChip, argTypes: { id: { description: @@ -39,12 +39,12 @@ export default { }, }, size: { - description: 'Size variants of tag component (default, small)', + description: 'Size variants of chip component (default, small)', control: 'select', - options: tagSizeVariants, + options: chipSizeVariants, table: { type: { - summary: tagSizeVariantsSummary, + summary: chipSizeVariantsSummary, }, defaultValue: { summary: 'default', @@ -53,12 +53,12 @@ export default { }, variant: { description: - 'Color variants of tag component (neutral by default, blue, yellow, green, purple)', + 'Color variants of chip component (neutral by default, blue, yellow, green, purple)', control: 'select', - options: tagColorsVariants, + options: chipColorsVariants, table: { type: { - summary: tagColorsVariantsSummary, + summary: chipColorsVariantsSummary, }, defaultValue: { summary: 'neutral', @@ -87,13 +87,13 @@ export default { summary: tooltipPositionsSummary, }, defaultValue: { - summary: 'neutral', + summary: 'bottom', }, }, }, closeable: { description: - 'Add closeable feature for the tag component (close icon which trigger a close event to parent component)', + 'Add closeable feature for the chip component (close icon which trigger a close event to parent component)', control: 'boolean', table: { type: { @@ -105,7 +105,7 @@ export default { }, }, disabled: { - description: 'Disables the Tag component ', + description: 'Disables the Chip component ', control: 'boolean', table: { type: { @@ -118,8 +118,8 @@ export default { }, }, args: { - id: 'puik-tag-id', - content: 'default tag', + id: 'puik-chip-id', + content: 'default chip', size: 'default', variant: 'neutral', icon: '', @@ -132,22 +132,22 @@ export default { const DefaultTemplate: StoryFn = (args: Args) => ({ components: { PuikIcon, - PuikTag, + PuikChip, }, setup() { return { args } }, - template: ``, + template: ``, }) const HandleCloseEventTemplate: StoryFn = (args: Args) => ({ components: { PuikIcon, - PuikTag, + PuikChip, PuikButton, }, setup() { - const tags = ref([ + const chips = ref([ { variant: 'neutral', icon: 'home', @@ -192,33 +192,33 @@ const HandleCloseEventTemplate: StoryFn = (args: Args) => ({ }, ]) - const copyInitialTags = [...tags.value] - const handleCloseTag = (index: number) => { - tags.value.splice(index, 1) + const copyInitialChips = [...chips.value] + const handleCloseChip = (index: number) => { + chips.value.splice(index, 1) } - const refreshTags = () => { - tags.value = [] - copyInitialTags.map((tag) => { - tags.value.push(tag) + const refreshChips = () => { + chips.value = [] + copyInitialChips.map((chip) => { + chips.value.push(chip) }) } - return { tags, args, handleCloseTag, refreshTags } + return { chips, args, handleCloseChip, refreshChips } }, template: `
-
- + Refresh @@ -228,42 +228,42 @@ const HandleCloseEventTemplate: StoryFn = (args: Args) => ({ const ColorVariantsTemplate: StoryFn = (args: Args) => ({ components: { PuikIcon, - PuikTag, + PuikChip, }, setup() { - const tags = ref([ + const chips = ref([ { variant: 'neutral', - content: 'neutral tag', + content: 'neutral chip', }, { variant: 'blue', - content: 'blue tag', + content: 'blue chip', }, { variant: 'yellow', - content: 'yellow tag', + content: 'yellow chip', }, { variant: 'green', - content: 'green tag', + content: 'green chip', }, { variant: 'purple', - content: 'purple tag', + content: 'purple chip', }, ]) - return { tags, args } + return { chips, args } }, template: `
-
`, @@ -272,21 +272,21 @@ const ColorVariantsTemplate: StoryFn = (args: Args) => ({ const SizeVariantsTemplate: StoryFn = (args: Args) => ({ components: { PuikIcon, - PuikTag, + PuikChip, }, setup() { return { args } }, template: ` - - @@ -296,15 +296,15 @@ const SizeVariantsTemplate: StoryFn = (args: Args) => ({ const CloseableTemplate: StoryFn = (args: Args) => ({ components: { PuikIcon, - PuikTag, + PuikChip, }, setup() { return { args } }, template: ` - `, @@ -313,15 +313,15 @@ const CloseableTemplate: StoryFn = (args: Args) => ({ const DisabledTemplate: StoryFn = (args: Args) => ({ components: { PuikIcon, - PuikTag, + PuikChip, }, setup() { return { args } }, template: ` - `, @@ -330,15 +330,15 @@ const DisabledTemplate: StoryFn = (args: Args) => ({ const WithIconTemplate: StoryFn = (args: Args) => ({ components: { PuikIcon, - PuikTag, + PuikChip, }, setup() { return { args } }, template: ` - `, @@ -347,14 +347,14 @@ const WithIconTemplate: StoryFn = (args: Args) => ({ const WithLongTextTemplate: StoryFn = (args: Args) => ({ components: { PuikIcon, - PuikTag, + PuikChip, }, setup() { return { args } }, template: ` - @@ -369,7 +369,7 @@ export const Default = { source: { code: ` -
-
-
- default tag +
+
+ default chip
`, @@ -404,24 +404,24 @@ export const HandleCloseEvent = { code: `
-
-const handleCloseTag = (index: number) => { +const handleCloseChip = (index: number) => { // Do stuff before closing // Then - tags.value.splice(index, 1) + chips.value.splice(index, 1) } `, language: 'html', @@ -438,8 +438,8 @@ export const ColorVariants = { source: { code: ` - - + - -
-
- {$variant} tag + +
+
+ {$variant} chip
`, @@ -468,8 +468,8 @@ export const SizeVariants = { source: { code: ` - - + - -
-
- {$size} tag + +
+
+ {$size} chip
`, @@ -499,7 +499,7 @@ export const Closeable = { code: ` - -
-
- closeable tag +
+
+ closeable chip
-
close
+
close
`, language: 'html', @@ -529,7 +529,7 @@ export const Disabled = { source: { code: ` - -
-
- disabled tag +
+
+ disabled chip
`, @@ -557,7 +557,7 @@ export const WithIcon = { source: { code: ` - -
-
+
+
favorite
-
with icon tag
+
with icon chip
`, language: 'html', @@ -587,7 +587,7 @@ export const WithLongText = { code: ` - Date: Wed, 4 Oct 2023 10:01:47 +0200 Subject: [PATCH 07/10] fix: #191 - chip component with tests --- packages/components/chip/test/chip.spec.ts | 40 +++++++++++----------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/packages/components/chip/test/chip.spec.ts b/packages/components/chip/test/chip.spec.ts index 9857a71e..d5899b02 100644 --- a/packages/components/chip/test/chip.spec.ts +++ b/packages/components/chip/test/chip.spec.ts @@ -1,20 +1,20 @@ import { mount } from '@vue/test-utils' import { describe, it, expect } from 'vitest' -import PuikTag from '../src/tag.vue' +import PuikChip from '../src/chip.vue' import type { MountingOptions, VueWrapper } from '@vue/test-utils' -describe('Tag tests', () => { +describe('Chip tests', () => { let wrapper: VueWrapper - const findTag = () => wrapper.find('.puik-tag') - const findTagContent = () => wrapper.find('.puik-tag__content') - const findCloseBtn = () => wrapper.find('.puik-tag__close') - const findLeftIcon = () => wrapper.find('.puik-tag__icon') + const findChip = () => wrapper.find('.puik-chip') + const findChipContent = () => wrapper.find('.puik-chip__content') + const findCloseBtn = () => wrapper.find('.puik-chip__close') + const findLeftIcon = () => wrapper.find('.puik-chip__icon') const factory = ( propsData: Record = {}, options: MountingOptions = {} ) => { - wrapper = mount(PuikTag, { + wrapper = mount(PuikChip, { props: { ...propsData, }, @@ -27,38 +27,38 @@ describe('Tag tests', () => { expect(wrapper).toBeTruthy() }) - it('as id prop value is "puik-tag-example", id html attribute of puik-tag should be "puik-tag-example"', () => { - factory({ id: 'puik-tag-example' }) - expect(findTag().attributes().id).toBe('puik-tag-example') + it('as id prop value is "puik-chip-example", id html attribute of puik-chip should be "puik-chip-example"', () => { + factory({ id: 'puik-chip-example' }) + expect(findChip().attributes().id).toBe('puik-chip-example') }) - it('Tag text should be "content"', () => { + it('Chip text should be "content"', () => { factory({ content: 'content' }) - expect(findTagContent().text()).toBe('content') + expect(findChipContent().text()).toBe('content') }) - it('should display a blue version of the tag', () => { + it('should display a blue version of the chip', () => { factory({ variant: 'blue' }) - expect(findTag().classes()).toContain('puik-tag--blue') + expect(findChip().classes()).toContain('puik-chip--blue') }) - it('should display a tag small version', () => { + it('should display a chip small version', () => { factory({ size: 'small' }) - expect(findTag().classes()).toContain('puik-tag--small') + expect(findChip().classes()).toContain('puik-chip--small') }) - it('should display a tag version with left icon', () => { + it('should display a chip version with left icon', () => { factory({ icon: 'home' }) expect(findLeftIcon().text()).toBe('home') }) - it('should display a tag closeable version', () => { + it('should display a chip closeable version', () => { factory({ closeable: true }) expect(findCloseBtn().text()).toBe('close') }) - it('should display a tag disabled version', () => { + it('should display a chip disabled version', () => { factory({ disabled: true }) - expect(findTag().classes()).toContain('puik-tag--disabled') + expect(findChip().classes()).toContain('puik-chip--disabled') }) }) From 460ab09aefc2dbdbc17ef7bd26932a1ec2717707 Mon Sep 17 00:00:00 2001 From: Matthias Goudjil Date: Fri, 6 Oct 2023 15:15:26 +0200 Subject: [PATCH 08/10] feat: create tag component --- packages/components/tag/index.ts | 8 + packages/components/tag/src/tag.ts | 64 ++ packages/components/tag/src/tag.vue | 50 ++ .../components/tag/stories/tag.stories.ts | 600 ++++++++++++++++++ packages/components/tag/style/css.ts | 2 + packages/components/tag/style/index.ts | 2 + packages/components/tag/test/tag.spec.ts | 64 ++ packages/puik/component.ts | 2 + packages/theme/src/tag.scss | 52 ++ 9 files changed, 844 insertions(+) create mode 100644 packages/components/tag/index.ts create mode 100644 packages/components/tag/src/tag.ts create mode 100644 packages/components/tag/src/tag.vue create mode 100644 packages/components/tag/stories/tag.stories.ts create mode 100644 packages/components/tag/style/css.ts create mode 100644 packages/components/tag/style/index.ts create mode 100644 packages/components/tag/test/tag.spec.ts create mode 100644 packages/theme/src/tag.scss diff --git a/packages/components/tag/index.ts b/packages/components/tag/index.ts new file mode 100644 index 00000000..69156075 --- /dev/null +++ b/packages/components/tag/index.ts @@ -0,0 +1,8 @@ +import { withInstall } from '@puik/utils' + +import Tag from './src/tag.vue' + +export const PuikTag = withInstall(Tag) +export default PuikTag + +export * from './src/tag' diff --git a/packages/components/tag/src/tag.ts b/packages/components/tag/src/tag.ts new file mode 100644 index 00000000..5d229647 --- /dev/null +++ b/packages/components/tag/src/tag.ts @@ -0,0 +1,64 @@ +import { buildProps } from '@puik/utils' +import type { PuikTooltipPosition } from '@puik/components' +import type { ExtractPropTypes, PropType } from 'vue' +import type Tag from './tag.vue' + +export const tagColorsVariants = [ + 'neutral', + 'blue', + 'yellow', + 'green', + 'purple', +] as const + +export const tagSizeVariants = ['default', 'small'] as const + +export type PuikTagColorVariant = (typeof tagColorsVariants)[number] +export type PuikTagSizeVariant = (typeof tagSizeVariants)[number] + +export const tagProps = buildProps({ + id: { + type: String, + required: true, + default: undefined, + }, + content: { + type: String, + required: true, + default: undefined, + }, + variant: { + type: String, + required: false, + default: 'neutral', + }, + size: { + type: String, + required: false, + default: 'default', + }, + icon: { + type: String, + default: '', + required: false, + }, + closeable: { + type: Boolean, + required: false, + default: false, + }, + disabled: { + type: Boolean, + required: false, + default: false, + }, + tooltipPosition: { + type: String as PropType, + Required: false, + default: 'bottom', + }, +} as const) + +export type TagProps = ExtractPropTypes + +export type TagInstance = InstanceType diff --git a/packages/components/tag/src/tag.vue b/packages/components/tag/src/tag.vue new file mode 100644 index 00000000..4c0855fc --- /dev/null +++ b/packages/components/tag/src/tag.vue @@ -0,0 +1,50 @@ + + + +./tag diff --git a/packages/components/tag/stories/tag.stories.ts b/packages/components/tag/stories/tag.stories.ts new file mode 100644 index 00000000..6998af27 --- /dev/null +++ b/packages/components/tag/stories/tag.stories.ts @@ -0,0 +1,600 @@ +import { ref } from 'vue' +import { PuikIcon, PuikButton, tooltipPositions } from '@puik/components' +import { tagColorsVariants, tagSizeVariants } from '../src/tag' +import PuikTag from './../src/tag.vue' +import type { Meta, StoryFn, Args } from '@storybook/vue3' + +const tagColorsVariantsSummary = tagColorsVariants.join('|') +const tagSizeVariantsSummary = tagSizeVariants.join('|') +const tooltipPositionsSummary = tooltipPositions.join('|') + +export default { + title: 'Components/Tag', + component: PuikTag, + argTypes: { + id: { + description: + "Prop which will correspond to the component's html id attribute. NB: must not start with a number", + control: 'text', + table: { + type: { + summary: 'string', + }, + defaultValue: { + summary: 'undefined', + }, + }, + }, + content: { + description: + 'The text content (NB: if its length is equal to or greater than 30 characters it will be truncated and will be displayed entirely on hover in a tooltip)', + control: 'text', + table: { + type: { + summary: 'string', + }, + defaultValue: { + summary: 'undefined', + }, + }, + }, + size: { + description: 'Size variants of tag component (default, small)', + control: 'select', + options: tagSizeVariants, + table: { + type: { + summary: tagSizeVariantsSummary, + }, + defaultValue: { + summary: 'default', + }, + }, + }, + variant: { + description: + 'Color variants of tag component (neutral by default, blue, yellow, green, purple)', + control: 'select', + options: tagColorsVariants, + table: { + type: { + summary: tagColorsVariantsSummary, + }, + defaultValue: { + summary: 'neutral', + }, + }, + }, + icon: { + description: 'Material icon name', + control: 'text', + table: { + type: { + summary: 'string', + }, + defaultValue: { + summary: 'none', + }, + }, + }, + tooltipPosition: { + description: + 'Position of the tooltip (NB: a tooltip appears if the content length is equal to or greater than 30 characters).', + control: 'select', + options: tooltipPositions, + table: { + type: { + summary: tooltipPositionsSummary, + }, + defaultValue: { + summary: 'bottom', + }, + }, + }, + closeable: { + description: + 'Add closeable feature for the tag component (close icon which trigger a close event to parent component)', + control: 'boolean', + table: { + type: { + summary: 'boolean', + }, + defaultValue: { + summary: 'false', + }, + }, + }, + disabled: { + description: 'Disables the Tag component ', + control: 'boolean', + table: { + type: { + summary: 'boolean', + }, + defaultValue: { + summary: 'false', + }, + }, + }, + }, + args: { + id: 'puik-tag-id', + content: 'default tag', + size: 'default', + variant: 'neutral', + icon: '', + closeable: false, + disabled: false, + tooltipPosition: 'bottom', + }, +} as Meta + +const DefaultTemplate: StoryFn = (args: Args) => ({ + components: { + PuikIcon, + PuikTag, + }, + setup() { + return { args } + }, + template: ``, +}) + +const HandleCloseEventTemplate: StoryFn = (args: Args) => ({ + components: { + PuikIcon, + PuikTag, + PuikButton, + }, + setup() { + const tags = ref([ + { + variant: 'neutral', + icon: 'home', + closeable: true, + disabled: true, + content: "can't close disabled", + }, + { + variant: 'neutral', + icon: 'home', + closeable: true, + disabled: false, + content: 'close me !', + }, + { + variant: 'blue', + icon: 'home', + closeable: true, + disabled: false, + content: 'close me !', + }, + { + variant: 'yellow', + icon: 'home', + closeable: true, + disabled: false, + content: 'close me !', + }, + { + variant: 'green', + icon: 'home', + closeable: true, + disabled: false, + content: 'close me !', + }, + { + variant: 'purple', + icon: 'home', + closeable: true, + disabled: false, + content: 'close me !', + }, + ]) + + const copyInitialTags = [...tags.value] + const handleCloseTag = (index: number) => { + tags.value.splice(index, 1) + } + const refreshTags = () => { + tags.value = [] + copyInitialTags.map((tag) => { + tags.value.push(tag) + }) + } + return { tags, args, handleCloseTag, refreshTags } + }, + template: ` +
+ +
+ + + Refresh + +`, +}) + +const ColorVariantsTemplate: StoryFn = (args: Args) => ({ + components: { + PuikIcon, + PuikTag, + }, + setup() { + const tags = ref([ + { + variant: 'neutral', + content: 'neutral tag', + }, + { + variant: 'blue', + content: 'blue tag', + }, + { + variant: 'yellow', + content: 'yellow tag', + }, + { + variant: 'green', + content: 'green tag', + }, + { + variant: 'purple', + content: 'purple tag', + }, + ]) + + return { tags, args } + }, + template: ` +
+ +
+`, +}) + +const SizeVariantsTemplate: StoryFn = (args: Args) => ({ + components: { + PuikIcon, + PuikTag, + }, + setup() { + return { args } + }, + template: ` + + +`, +}) + +const CloseableTemplate: StoryFn = (args: Args) => ({ + components: { + PuikIcon, + PuikTag, + }, + setup() { + return { args } + }, + template: ` + +`, +}) + +const DisabledTemplate: StoryFn = (args: Args) => ({ + components: { + PuikIcon, + PuikTag, + }, + setup() { + return { args } + }, + template: ` + +`, +}) + +const WithIconTemplate: StoryFn = (args: Args) => ({ + components: { + PuikIcon, + PuikTag, + }, + setup() { + return { args } + }, + template: ` + +`, +}) + +const WithLongTextTemplate: StoryFn = (args: Args) => ({ + components: { + PuikIcon, + PuikTag, + }, + setup() { + return { args } + }, + template: ` + +`, +}) + +export const Default = { + render: DefaultTemplate, + args: {}, + parameters: { + docs: { + source: { + code: ` + + +
+ + +
+
+ default tag +
+
+`, + language: 'html', + }, + }, + }, +} + +export const HandleCloseEvent = { + render: HandleCloseEventTemplate, + args: {}, + parameters: { + docs: { + source: { + code: ` + +
+ +
+ + +const handleCloseTag = (index: number) => { + // Do stuff before closing + // Then + tags.value.splice(index, 1) +} +`, + language: 'html', + }, + }, + }, +} + +export const ColorVariants = { + render: ColorVariantsTemplate, + args: {}, + parameters: { + docs: { + source: { + code: ` + + + +
+ + + +
+
+ {$variant} tag +
+
+`, + language: 'html', + }, + }, + }, +} + +export const SizeVariants = { + render: SizeVariantsTemplate, + args: {}, + parameters: { + docs: { + source: { + code: ` + + + +
+ + + +
+
+ {$size} tag +
+
+`, + language: 'html', + }, + }, + }, +} + +export const Closeable = { + render: CloseableTemplate, + args: {}, + parameters: { + docs: { + source: { + code: ` + + + +
+ + + +
+
+ closeable tag +
+
close
+
+`, + language: 'html', + }, + }, + }, +} + +export const Disabled = { + render: DisabledTemplate, + args: {}, + parameters: { + docs: { + source: { + code: ` + + +
+ + +
+
+ disabled tag +
+
+`, + language: 'html', + }, + }, + }, +} + +export const WithIcon = { + render: WithIconTemplate, + args: {}, + parameters: { + docs: { + source: { + code: ` + + +
+ + +
+
+ favorite +
+
with icon tag
+
+`, + language: 'html', + }, + }, + }, +} + +export const WithLongText = { + render: WithLongTextTemplate, + args: {}, + parameters: { + docs: { + source: { + code: ` + + + +`, + language: 'html', + }, + }, + }, +} diff --git a/packages/components/tag/style/css.ts b/packages/components/tag/style/css.ts new file mode 100644 index 00000000..766ee1bf --- /dev/null +++ b/packages/components/tag/style/css.ts @@ -0,0 +1,2 @@ +import '@puik/components/base/style/css' +import '@puik/theme/puik-tag.css' diff --git a/packages/components/tag/style/index.ts b/packages/components/tag/style/index.ts new file mode 100644 index 00000000..7666132b --- /dev/null +++ b/packages/components/tag/style/index.ts @@ -0,0 +1,2 @@ +import '@puik/components/base/style' +import '@puik/theme/src/tag.scss' diff --git a/packages/components/tag/test/tag.spec.ts b/packages/components/tag/test/tag.spec.ts new file mode 100644 index 00000000..9857a71e --- /dev/null +++ b/packages/components/tag/test/tag.spec.ts @@ -0,0 +1,64 @@ +import { mount } from '@vue/test-utils' +import { describe, it, expect } from 'vitest' +import PuikTag from '../src/tag.vue' +import type { MountingOptions, VueWrapper } from '@vue/test-utils' + +describe('Tag tests', () => { + let wrapper: VueWrapper + const findTag = () => wrapper.find('.puik-tag') + const findTagContent = () => wrapper.find('.puik-tag__content') + const findCloseBtn = () => wrapper.find('.puik-tag__close') + const findLeftIcon = () => wrapper.find('.puik-tag__icon') + + const factory = ( + propsData: Record = {}, + options: MountingOptions = {} + ) => { + wrapper = mount(PuikTag, { + props: { + ...propsData, + }, + ...options, + }) + } + + it('should be a vue instance', () => { + factory() + expect(wrapper).toBeTruthy() + }) + + it('as id prop value is "puik-tag-example", id html attribute of puik-tag should be "puik-tag-example"', () => { + factory({ id: 'puik-tag-example' }) + expect(findTag().attributes().id).toBe('puik-tag-example') + }) + + it('Tag text should be "content"', () => { + factory({ content: 'content' }) + expect(findTagContent().text()).toBe('content') + }) + + it('should display a blue version of the tag', () => { + factory({ variant: 'blue' }) + expect(findTag().classes()).toContain('puik-tag--blue') + }) + + it('should display a tag small version', () => { + factory({ size: 'small' }) + expect(findTag().classes()).toContain('puik-tag--small') + }) + + it('should display a tag version with left icon', () => { + factory({ icon: 'home' }) + expect(findLeftIcon().text()).toBe('home') + }) + + it('should display a tag closeable version', () => { + factory({ closeable: true }) + expect(findCloseBtn().text()).toBe('close') + }) + + it('should display a tag disabled version', () => { + factory({ disabled: true }) + expect(findTag().classes()).toContain('puik-tag--disabled') + }) +}) diff --git a/packages/puik/component.ts b/packages/puik/component.ts index 8c506564..ee5533d9 100644 --- a/packages/puik/component.ts +++ b/packages/puik/component.ts @@ -1,3 +1,4 @@ +import { PuikTag } from '@puik/components/tag' import { PuikChip } from '@puik/components/chip' import { PuikTabNavigation, @@ -49,6 +50,7 @@ import type { Plugin } from 'vue' // prettier-ignore export default [ + PuikTag, PuikChip, PuikTabNavigationGroupPanels, PuikTabNavigationTitle, diff --git a/packages/theme/src/tag.scss b/packages/theme/src/tag.scss new file mode 100644 index 00000000..f5d8a57a --- /dev/null +++ b/packages/theme/src/tag.scss @@ -0,0 +1,52 @@ +@use './common/typography.scss'; + +.puik-tag { + @extend .puik-body-small; + @apply max-w-fit font-bold flex items-center; + + &--default { + @apply px-2 py-[3px]; + } + &--small { + @apply px-1 py-0; + .puik-tag__close { + @apply p-[1px]; + } + } + &--neutral { + @apply bg-primary-300 text-primary; + } + &--blue { + @apply bg-ocean-blue-50 text-primary; + } + &--yellow { + @apply bg-amber-100 text-primary; + } + &--green { + @apply bg-green-50 text-primary; + } + &--purple { + @apply bg-purple-50 text-primary; + } + &--disabled { + @apply bg-primary-200 text-primary-500; + .puik-tag__close { + @apply cursor-not-allowed hover:bg-primary-200; + } + } + &__close { + @apply p-[3px] ml-auto cursor-pointer rounded-[50%] hover:bg-primary-400; + } + &__icon { + @apply mr-1; + } + &__content { + @apply max-w-[150px] pr-[2px] overflow-hidden whitespace-nowrap text-ellipsis; + & > .puik-tooltip { + @apply max-w-[150px] overflow-hidden whitespace-nowrap text-ellipsis; + } + } + &__content .puik-tooltip__wrapper { + @apply max-w-[150px] mr-1 pr-[2px] overflow-hidden whitespace-nowrap text-ellipsis; + } +} From ef85f3443c4d5c78353c1cd094da51bbe020af2f Mon Sep 17 00:00:00 2001 From: Matthias Goudjil Date: Fri, 6 Oct 2023 16:40:25 +0200 Subject: [PATCH 09/10] feat: refactor chip/tag twins components (close feat only for chip) --- packages/components/chip/src/chip.ts | 5 - packages/components/chip/src/chip.vue | 1 - .../components/chip/stories/chip.stories.ts | 75 +------ packages/components/index.ts | 1 + packages/components/tag/src/tag.ts | 5 - packages/components/tag/src/tag.vue | 7 - .../components/tag/stories/tag.stories.ts | 186 +----------------- packages/components/tag/test/tag.spec.ts | 6 - packages/theme/src/index.scss | 1 + 9 files changed, 5 insertions(+), 282 deletions(-) diff --git a/packages/components/chip/src/chip.ts b/packages/components/chip/src/chip.ts index ddf7be8a..a4cd571d 100644 --- a/packages/components/chip/src/chip.ts +++ b/packages/components/chip/src/chip.ts @@ -42,11 +42,6 @@ export const chipProps = buildProps({ default: '', required: false, }, - closeable: { - type: Boolean, - required: false, - default: false, - }, disabled: { type: Boolean, required: false, diff --git a/packages/components/chip/src/chip.vue b/packages/components/chip/src/chip.vue index ee92d61d..217369ed 100644 --- a/packages/components/chip/src/chip.vue +++ b/packages/components/chip/src/chip.vue @@ -19,7 +19,6 @@ {{ content }}
({ { variant: 'neutral', icon: 'home', - closeable: true, disabled: true, content: "can't close disabled", }, { variant: 'neutral', icon: 'home', - closeable: true, disabled: false, content: 'close me !', }, { variant: 'blue', icon: 'home', - closeable: true, disabled: false, content: 'close me !', }, { variant: 'yellow', icon: 'home', - closeable: true, disabled: false, content: 'close me !', }, { variant: 'green', icon: 'home', - closeable: true, disabled: false, content: 'close me !', }, { variant: 'purple', icon: 'home', - closeable: true, disabled: false, content: 'close me !', }, @@ -213,7 +193,6 @@ const HandleCloseEventTemplate: StoryFn = (args: Args) => ({ :content="chip.content" :variant="chip.variant" :icon="chip.icon" - :closeable="true" :disabled="chip.disabled" @close="handleCloseChip(index)" /> @@ -278,35 +257,18 @@ const SizeVariantsTemplate: StoryFn = (args: Args) => ({ return { args } }, template: ` +
-`, -}) - -const CloseableTemplate: StoryFn = (args: Args) => ({ - components: { - PuikIcon, - PuikChip, - }, - setup() { - return { args } - }, - template: ` - +
`, }) @@ -375,7 +337,6 @@ export const Default = { :size="args.size" :variant="args.variant" :icon="args.icon" - :closeable="args.closeable" :disabled="args.disabled" :tooltipPosition="args.tooltipPosition" @close="handleCloseChip()" @@ -411,7 +372,6 @@ export const HandleCloseEvent = { :content="chip.content" :variant="chip.variant" :icon="chip.icon" - :closeable="true" :disabled="chip.disabled" @close="handleCloseChip(index)" /> @@ -490,37 +450,6 @@ export const SizeVariants = { }, } -export const Closeable = { - render: CloseableTemplate, - args: {}, - parameters: { - docs: { - source: { - code: ` - - - -
- - - -
-
- closeable chip -
-
close
-
-`, - language: 'html', - }, - }, - }, -} - export const Disabled = { render: DisabledTemplate, args: {}, diff --git a/packages/components/index.ts b/packages/components/index.ts index 184e2aff..d0a24516 100644 --- a/packages/components/index.ts +++ b/packages/components/index.ts @@ -28,3 +28,4 @@ export * from './textarea' export * from './tab-navigation' export * from './progress-stepper' export * from './chip' +export * from './tag' diff --git a/packages/components/tag/src/tag.ts b/packages/components/tag/src/tag.ts index 5d229647..f0b1ec83 100644 --- a/packages/components/tag/src/tag.ts +++ b/packages/components/tag/src/tag.ts @@ -42,11 +42,6 @@ export const tagProps = buildProps({ default: '', required: false, }, - closeable: { - type: Boolean, - required: false, - default: false, - }, disabled: { type: Boolean, required: false, diff --git a/packages/components/tag/src/tag.vue b/packages/components/tag/src/tag.vue index 4c0855fc..21f7bc8e 100644 --- a/packages/components/tag/src/tag.vue +++ b/packages/components/tag/src/tag.vue @@ -18,12 +18,6 @@ {{ content }}
-
@@ -47,4 +41,3 @@ const handleCloseEvent = () => { emit('close') } -./tag diff --git a/packages/components/tag/stories/tag.stories.ts b/packages/components/tag/stories/tag.stories.ts index 6998af27..cc3d6251 100644 --- a/packages/components/tag/stories/tag.stories.ts +++ b/packages/components/tag/stories/tag.stories.ts @@ -1,5 +1,5 @@ import { ref } from 'vue' -import { PuikIcon, PuikButton, tooltipPositions } from '@puik/components' +import { PuikIcon, tooltipPositions } from '@puik/components' import { tagColorsVariants, tagSizeVariants } from '../src/tag' import PuikTag from './../src/tag.vue' import type { Meta, StoryFn, Args } from '@storybook/vue3' @@ -91,19 +91,6 @@ export default { }, }, }, - closeable: { - description: - 'Add closeable feature for the tag component (close icon which trigger a close event to parent component)', - control: 'boolean', - table: { - type: { - summary: 'boolean', - }, - defaultValue: { - summary: 'false', - }, - }, - }, disabled: { description: 'Disables the Tag component ', control: 'boolean', @@ -123,7 +110,6 @@ export default { size: 'default', variant: 'neutral', icon: '', - closeable: false, disabled: false, tooltipPosition: 'bottom', }, @@ -140,91 +126,6 @@ const DefaultTemplate: StoryFn = (args: Args) => ({ template: ``, }) -const HandleCloseEventTemplate: StoryFn = (args: Args) => ({ - components: { - PuikIcon, - PuikTag, - PuikButton, - }, - setup() { - const tags = ref([ - { - variant: 'neutral', - icon: 'home', - closeable: true, - disabled: true, - content: "can't close disabled", - }, - { - variant: 'neutral', - icon: 'home', - closeable: true, - disabled: false, - content: 'close me !', - }, - { - variant: 'blue', - icon: 'home', - closeable: true, - disabled: false, - content: 'close me !', - }, - { - variant: 'yellow', - icon: 'home', - closeable: true, - disabled: false, - content: 'close me !', - }, - { - variant: 'green', - icon: 'home', - closeable: true, - disabled: false, - content: 'close me !', - }, - { - variant: 'purple', - icon: 'home', - closeable: true, - disabled: false, - content: 'close me !', - }, - ]) - - const copyInitialTags = [...tags.value] - const handleCloseTag = (index: number) => { - tags.value.splice(index, 1) - } - const refreshTags = () => { - tags.value = [] - copyInitialTags.map((tag) => { - tags.value.push(tag) - }) - } - return { tags, args, handleCloseTag, refreshTags } - }, - template: ` -
- -
- - - Refresh - -`, -}) - const ColorVariantsTemplate: StoryFn = (args: Args) => ({ components: { PuikIcon, @@ -293,23 +194,6 @@ const SizeVariantsTemplate: StoryFn = (args: Args) => ({ `, }) -const CloseableTemplate: StoryFn = (args: Args) => ({ - components: { - PuikIcon, - PuikTag, - }, - setup() { - return { args } - }, - template: ` - -`, -}) - const DisabledTemplate: StoryFn = (args: Args) => ({ components: { PuikIcon, @@ -375,10 +259,8 @@ export const Default = { :size="args.size" :variant="args.variant" :icon="args.icon" - :closeable="args.closeable" :disabled="args.disabled" :tooltipPosition="args.tooltipPosition" - @close="handleCloseTag()" />
@@ -395,41 +277,6 @@ export const Default = { }, } -export const HandleCloseEvent = { - render: HandleCloseEventTemplate, - args: {}, - parameters: { - docs: { - source: { - code: ` - -
- -
- - -const handleCloseTag = (index: number) => { - // Do stuff before closing - // Then - tags.value.splice(index, 1) -} -`, - language: 'html', - }, - }, - }, -} - export const ColorVariants = { render: ColorVariantsTemplate, args: {}, @@ -490,37 +337,6 @@ export const SizeVariants = { }, } -export const Closeable = { - render: CloseableTemplate, - args: {}, - parameters: { - docs: { - source: { - code: ` - - - -
- - - -
-
- closeable tag -
-
close
-
-`, - language: 'html', - }, - }, - }, -} - export const Disabled = { render: DisabledTemplate, args: {}, diff --git a/packages/components/tag/test/tag.spec.ts b/packages/components/tag/test/tag.spec.ts index 9857a71e..bd3bd926 100644 --- a/packages/components/tag/test/tag.spec.ts +++ b/packages/components/tag/test/tag.spec.ts @@ -7,7 +7,6 @@ describe('Tag tests', () => { let wrapper: VueWrapper const findTag = () => wrapper.find('.puik-tag') const findTagContent = () => wrapper.find('.puik-tag__content') - const findCloseBtn = () => wrapper.find('.puik-tag__close') const findLeftIcon = () => wrapper.find('.puik-tag__icon') const factory = ( @@ -52,11 +51,6 @@ describe('Tag tests', () => { expect(findLeftIcon().text()).toBe('home') }) - it('should display a tag closeable version', () => { - factory({ closeable: true }) - expect(findCloseBtn().text()).toBe('close') - }) - it('should display a tag disabled version', () => { factory({ disabled: true }) expect(findTag().classes()).toContain('puik-tag--disabled') diff --git a/packages/theme/src/index.scss b/packages/theme/src/index.scss index bc435ce4..d888a495 100644 --- a/packages/theme/src/index.scss +++ b/packages/theme/src/index.scss @@ -41,3 +41,4 @@ @use 'progress-stepper'; @use 'progress-stepper-step'; @use 'chip'; +@use 'tag'; From e11ae5f4c63ea3548f040913192d243fcf6e0616 Mon Sep 17 00:00:00 2001 From: Matthias Goudjil Date: Mon, 9 Oct 2023 15:19:44 +0200 Subject: [PATCH 10/10] feat: [chip] - remove colors variants --- packages/components/chip/src/chip.ts | 14 --- packages/components/chip/src/chip.vue | 8 +- .../components/chip/stories/chip.stories.ts | 109 +----------------- packages/components/chip/test/chip.spec.ts | 10 -- packages/theme/src/chip.scss | 17 +-- 5 files changed, 8 insertions(+), 150 deletions(-) diff --git a/packages/components/chip/src/chip.ts b/packages/components/chip/src/chip.ts index a4cd571d..79441e21 100644 --- a/packages/components/chip/src/chip.ts +++ b/packages/components/chip/src/chip.ts @@ -3,17 +3,8 @@ import type { PuikTooltipPosition } from '@puik/components' import type { ExtractPropTypes, PropType } from 'vue' import type Chip from './chip.vue' -export const chipColorsVariants = [ - 'neutral', - 'blue', - 'yellow', - 'green', - 'purple', -] as const - export const chipSizeVariants = ['default', 'small'] as const -export type PuikChipColorVariant = (typeof chipColorsVariants)[number] export type PuikChipSizeVariant = (typeof chipSizeVariants)[number] export const chipProps = buildProps({ @@ -27,11 +18,6 @@ export const chipProps = buildProps({ required: true, default: undefined, }, - variant: { - type: String, - required: false, - default: 'neutral', - }, size: { type: String, required: false, diff --git a/packages/components/chip/src/chip.vue b/packages/components/chip/src/chip.vue index 217369ed..af8bcfdf 100644 --- a/packages/components/chip/src/chip.vue +++ b/packages/components/chip/src/chip.vue @@ -2,7 +2,7 @@
@@ -29,11 +29,7 @@