From 08c3f55db2169b093356fee856b2f1603d81ca2b Mon Sep 17 00:00:00 2001 From: Paul Valerie GOMA Date: Mon, 21 Jul 2025 10:40:51 +0200 Subject: [PATCH 01/12] =?UTF-8?q?=E2=9E=95=20Add=20vue-router=20dependency?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 24 +++++++++++++++++++++++- package.json | 3 ++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 21f7769..a49392c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,8 @@ "jsdom": "^26.1.0", "primevue": "^4.3.6", "vite-plugin-inspect": "^11.3.0", - "vue": "^3.5.17" + "vue": "^3.5.17", + "vue-router": "^4.5.1" }, "devDependencies": { "@tsconfig/node22": "^22.0.2", @@ -2424,6 +2425,12 @@ "he": "^1.2.0" } }, + "node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "license": "MIT" + }, "node_modules/@vue/devtools-core": { "version": "7.7.7", "resolved": "https://registry.npmjs.org/@vue/devtools-core/-/devtools-core-7.7.7.tgz", @@ -6305,6 +6312,21 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/vue-router": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.5.1.tgz", + "integrity": "sha512-ogAF3P97NPm8fJsE4by9dwSYtDwXIY1nFY9T6DyQnGHd1E2Da94w9JIolpe42LJGIl0DwOHBi8TcRPlPGwbTtw==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.4" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, "node_modules/vue-tsc": { "version": "2.2.12", "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.2.12.tgz", diff --git a/package.json b/package.json index 15bfe1f..aa23439 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,8 @@ "jsdom": "^26.1.0", "primevue": "^4.3.6", "vite-plugin-inspect": "^11.3.0", - "vue": "^3.5.17" + "vue": "^3.5.17", + "vue-router": "^4.5.1" }, "devDependencies": { "@tsconfig/node22": "^22.0.2", From 996f20136a35af9638b13fdf6e5abb9d4df31248 Mon Sep 17 00:00:00 2001 From: Paul Valerie GOMA Date: Mon, 21 Jul 2025 10:50:08 +0200 Subject: [PATCH 02/12] =?UTF-8?q?=F0=9F=8F=B7=EF=B8=8F=20=20link=20interfa?= =?UTF-8?q?ce=20added?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/button/IVLink.type.ts | 46 ++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 src/components/button/IVLink.type.ts diff --git a/src/components/button/IVLink.type.ts b/src/components/button/IVLink.type.ts new file mode 100644 index 0000000..a695255 --- /dev/null +++ b/src/components/button/IVLink.type.ts @@ -0,0 +1,46 @@ +import type { RouteLocationRaw } from "vue-router"; + +/** + * Interface representing a navigational link component. + * This can be used for both internal routing (via `to`) and external links (via `href`). + */ +export default interface ILink { + /** + * The text label displayed for the link. + */ + label: string; + + /** + * Internal route destination using Vue Router's RouteLocationRaw. + * Optional – used for client-side navigation. + */ + to?: RouteLocationRaw; + + /** + * External URL for the link. + * Optional – used for standard anchor navigation. + */ + href?: string; + + /** + * Optional icon name or path to be displayed alongside the label. + */ + icon?: string; + + /** + * Specifies where to open the linked document (e.g., "_blank", "_self"). + * Optional – applies to external links. + */ + target?: string; + + /** + * If true, the link is disabled and not clickable. + */ + disabled?: boolean; + + /** + * If true, the icon is displayed on the right side of the label. + * Defaults to false (icon on the left). + */ + iconRight?: boolean; +} From df400f03dd41260f9e1445f4bd7fe12756b6ecea Mon Sep 17 00:00:00 2001 From: Paul Valerie GOMA Date: Mon, 21 Jul 2025 10:56:02 +0200 Subject: [PATCH 03/12] =?UTF-8?q?=F0=9F=8F=B7=EF=B8=8F=20=20updated=20link?= =?UTF-8?q?=20interface?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/button/IVLink.type.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/button/IVLink.type.ts b/src/components/button/IVLink.type.ts index a695255..088230c 100644 --- a/src/components/button/IVLink.type.ts +++ b/src/components/button/IVLink.type.ts @@ -4,7 +4,7 @@ import type { RouteLocationRaw } from "vue-router"; * Interface representing a navigational link component. * This can be used for both internal routing (via `to`) and external links (via `href`). */ -export default interface ILink { +export default interface IVLink { /** * The text label displayed for the link. */ From 709fdac141ab6cbfe92b668b151875996a3f6039 Mon Sep 17 00:00:00 2001 From: Paul Valerie GOMA Date: Mon, 21 Jul 2025 11:13:50 +0200 Subject: [PATCH 04/12] =?UTF-8?q?=F0=9F=92=84=20Adding=20the=20style=20of?= =?UTF-8?q?=20the=20primevue=20link=20component?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/style/primevue-style/button.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/assets/style/primevue-style/button.css b/src/assets/style/primevue-style/button.css index 6d8fb80..29a687b 100644 --- a/src/assets/style/primevue-style/button.css +++ b/src/assets/style/primevue-style/button.css @@ -64,4 +64,8 @@ --p-button-primary-focus-ring-color: var(--focus-color); --p-button-secondary-focus-ring-color: var(--focus-color); --p-button-danger-focus-ring-color: var(--focus-color); + /* link */ + --p-button-link-color: var(--text-inverted-blue-france); + --p-button-link-hover-color: var(--text-inverted-blue-france); + --p-button-link-active-color: var(--text-inverted-blue-france); } From 47212b16882b6a9d412d8a1fc795304060b307b4 Mon Sep 17 00:00:00 2001 From: Paul Valerie GOMA Date: Mon, 21 Jul 2025 11:17:49 +0200 Subject: [PATCH 05/12] =?UTF-8?q?=E2=9C=A8=20feature:=20Link=20component?= =?UTF-8?q?=20added?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/button/VLink.vue | 50 +++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/components/button/VLink.vue diff --git a/src/components/button/VLink.vue b/src/components/button/VLink.vue new file mode 100644 index 0000000..6d506bf --- /dev/null +++ b/src/components/button/VLink.vue @@ -0,0 +1,50 @@ + + + + + From b20b6940128f2d88f51f9adc83874e6cabb492e6 Mon Sep 17 00:00:00 2001 From: Paul Valerie GOMA Date: Mon, 21 Jul 2025 12:02:52 +0200 Subject: [PATCH 06/12] =?UTF-8?q?=F0=9F=90=9B=20fix:=20fixed=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/button/VLink.vue | 54 +++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/src/components/button/VLink.vue b/src/components/button/VLink.vue index 6d506bf..c20a6c5 100644 --- a/src/components/button/VLink.vue +++ b/src/components/button/VLink.vue @@ -2,7 +2,7 @@ import Button from 'primevue/button'; import type IVLink from '@/components/button/IVLink.type'; import { computed } from 'vue'; -import styles from '@/assets/typography.module.css' +import styles from '@visua/typography.module.css'; const props = defineProps(); @@ -16,25 +16,25 @@ const htmlTag = computed(() => { return props.to ? 'RouterLink' : props.href ? ' From e2d9b96b69e72064c60ed0efcc0fe72e600656b5 Mon Sep 17 00:00:00 2001 From: Paul Valerie GOMA Date: Mon, 21 Jul 2025 12:05:33 +0200 Subject: [PATCH 07/12] =?UTF-8?q?=F0=9F=92=84=20Adding=20the=20style=20of?= =?UTF-8?q?=20the=20primevue=20link=20component?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/style/primevue-style/button.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/assets/style/primevue-style/button.css b/src/assets/style/primevue-style/button.css index 29a687b..f281ec1 100644 --- a/src/assets/style/primevue-style/button.css +++ b/src/assets/style/primevue-style/button.css @@ -65,7 +65,7 @@ --p-button-secondary-focus-ring-color: var(--focus-color); --p-button-danger-focus-ring-color: var(--focus-color); /* link */ - --p-button-link-color: var(--text-inverted-blue-france); - --p-button-link-hover-color: var(--text-inverted-blue-france); - --p-button-link-active-color: var(--text-inverted-blue-france); + --p-button-link-color: var(--text-action-high-blue-france); + --p-button-link-hover-color: var(--text-action-high-blue-france); + --p-button-link-active-color: var(--text-action-high-blue-france); } From 584cf4ea236526c75054b7c97123848b142cc7c4 Mon Sep 17 00:00:00 2001 From: Paul Valerie GOMA Date: Mon, 21 Jul 2025 12:06:18 +0200 Subject: [PATCH 08/12] Display some link component variants --- src/App.vue | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/App.vue b/src/App.vue index ac826ea..c7eecad 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,10 +1,12 @@ From 13dd0525541929fb4c04dc388cce4bb1e9f4bc4e Mon Sep 17 00:00:00 2001 From: Paul Valerie GOMA Date: Mon, 21 Jul 2025 12:28:37 +0200 Subject: [PATCH 09/12] =?UTF-8?q?=E2=9C=85=20test:=20Added=20displaying=20?= =?UTF-8?q?label=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/VLink.spec.ts | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 test/VLink.spec.ts diff --git a/test/VLink.spec.ts b/test/VLink.spec.ts new file mode 100644 index 0000000..a437551 --- /dev/null +++ b/test/VLink.spec.ts @@ -0,0 +1,24 @@ +import { mount } from '@vue/test-utils' +import VLink from '../src/components/button/VLink.vue' +import {test, expect, describe} from 'vitest' + +describe('VLink', () => { + test('renders the label correctly', () => { + const wrapper = mount(VLink, { + props: { + label: 'Link' + } + }) + expect(wrapper.text()).toContain('Link'); + }) + + test('renders as an anchor tag when `href` is provided', () => { + const wrapper = mount(VLink, { + props: {label: 'External', href: 'https://example.com' } + }); + + const a = wrapper.find('a') + expect(a.exists()).toBe(true); + expect(a.attributes('href')).toBe('https://example.com'); + }) +}) From 672e5ec36cb88f8569debdcc399da2bbd0938faa Mon Sep 17 00:00:00 2001 From: Paul Valerie GOMA Date: Mon, 21 Jul 2025 12:44:38 +0200 Subject: [PATCH 10/12] =?UTF-8?q?=E2=9C=85=20test:=20Added=20disabled=20li?= =?UTF-8?q?nk=20and=20anchor=20tag=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/VLink.spec.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/VLink.spec.ts b/test/VLink.spec.ts index a437551..fc91dce 100644 --- a/test/VLink.spec.ts +++ b/test/VLink.spec.ts @@ -21,4 +21,16 @@ describe('VLink', () => { expect(a.exists()).toBe(true); expect(a.attributes('href')).toBe('https://example.com'); }) + + test('disables the link when `disabled` is true', () => { + const wrapper = mount(VLink, { + props: {label: 'Disabled', disabled: true } + }) + + const button = wrapper.find('.p-button'); + expect(button.classes()).toContain('disabled'); + expect(button.attributes('aria-disabled')).toBe('true'); + }); + + }) From 020ac1bc8dbfce53cb3685274c452e64636a12f8 Mon Sep 17 00:00:00 2001 From: Paul Valerie GOMA Date: Mon, 21 Jul 2025 12:54:01 +0200 Subject: [PATCH 11/12] =?UTF-8?q?=E2=9C=85=20test:=20added=20a=20test=20th?= =?UTF-8?q?at=20prevents=20clicking=20when=20the=20link=20is=20disabled?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/VLink.spec.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/test/VLink.spec.ts b/test/VLink.spec.ts index fc91dce..838ced8 100644 --- a/test/VLink.spec.ts +++ b/test/VLink.spec.ts @@ -1,6 +1,6 @@ import { mount } from '@vue/test-utils' import VLink from '../src/components/button/VLink.vue' -import {test, expect, describe} from 'vitest' +import {test, expect, describe, vi} from 'vitest' describe('VLink', () => { test('renders the label correctly', () => { @@ -32,5 +32,14 @@ describe('VLink', () => { expect(button.attributes('aria-disabled')).toBe('true'); }); - + test('prevents click when disabled', async () => { + const clickHandler = vi.fn(); + const wrapper = mount(VLink, { + props: {label: 'Disabled', disabled: true, onClick: clickHandler} + }) + + await wrapper.trigger('click') + expect(clickHandler).not.toHaveBeenCalled(); + }); + }) From 8e3e422d14a89fff89c9abaa8c1c86b187fde1f0 Mon Sep 17 00:00:00 2001 From: Paul Valerie GOMA Date: Mon, 21 Jul 2025 13:09:44 +0200 Subject: [PATCH 12/12] =?UTF-8?q?=E2=9C=85=20test:=20added=20the=20IconRig?= =?UTF-8?q?ht=20props=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/VLink.spec.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/VLink.spec.ts b/test/VLink.spec.ts index 838ced8..f8b2578 100644 --- a/test/VLink.spec.ts +++ b/test/VLink.spec.ts @@ -42,4 +42,17 @@ describe('VLink', () => { expect(clickHandler).not.toHaveBeenCalled(); }); + test('places icon on the right when `iconRight` is true', () => { + const wrapper = mount(VLink, { + props: { + label: 'link', + icon: "ri-external-link-line", + iconRight: true, + } + }) + const icon = wrapper.find('.p-button-icon-right'); + expect(icon.exists()).toBe(true); + expect(icon.classes()).toContain('ri-external-link-line'); + }) }) +