From d4a1704d5afdda336ad43666266d56b5f732682c Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Tue, 25 Mar 2025 17:49:18 -0400 Subject: [PATCH 01/43] Initial set up for ProfileCard component --- src/experimental/cod-gov-banner.js | 2 ++ .../components/ProfileCard/ProfileCard.css | 0 .../components/ProfileCard/ProfileCard.js | 24 +++++++++++++++++++ .../components/ProfileCard/ProfileCard.scss | 0 .../ProfileCard/cod-profile-card.js | 2 ++ src/stable/stories/profilecard.stories.js | 12 ++++++++++ 6 files changed, 40 insertions(+) create mode 100644 src/experimental/cod-gov-banner.js create mode 100644 src/stable/components/ProfileCard/ProfileCard.css create mode 100644 src/stable/components/ProfileCard/ProfileCard.js create mode 100644 src/stable/components/ProfileCard/ProfileCard.scss create mode 100644 src/stable/components/ProfileCard/cod-profile-card.js create mode 100644 src/stable/stories/profilecard.stories.js diff --git a/src/experimental/cod-gov-banner.js b/src/experimental/cod-gov-banner.js new file mode 100644 index 00000000..6bc7a117 --- /dev/null +++ b/src/experimental/cod-gov-banner.js @@ -0,0 +1,2 @@ +import GovBanner from './GovBanner'; +customElements.define('cod-gov-banner', GovBanner); diff --git a/src/stable/components/ProfileCard/ProfileCard.css b/src/stable/components/ProfileCard/ProfileCard.css new file mode 100644 index 00000000..e69de29b diff --git a/src/stable/components/ProfileCard/ProfileCard.js b/src/stable/components/ProfileCard/ProfileCard.js new file mode 100644 index 00000000..ce5f7412 --- /dev/null +++ b/src/stable/components/ProfileCard/ProfileCard.js @@ -0,0 +1,24 @@ +import styles from '!!raw-loader!./ProfileCard.css'; + +const template = document.createElement('template'); +template.innerHTML = ` + + +
+

PROFILE CARD HERE

+
+`; + +class ProfileCard extends HTMLElement { + constructor(){ + super(); + const shadow = this.attachShadow({ mode: 'open'}); + shadow.appendChild(template.content.cloneNode(true)); + } +} + + + +export { ProfileCard as default }; \ No newline at end of file diff --git a/src/stable/components/ProfileCard/ProfileCard.scss b/src/stable/components/ProfileCard/ProfileCard.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/stable/components/ProfileCard/cod-profile-card.js b/src/stable/components/ProfileCard/cod-profile-card.js new file mode 100644 index 00000000..e8dc69d2 --- /dev/null +++ b/src/stable/components/ProfileCard/cod-profile-card.js @@ -0,0 +1,2 @@ +import ProfileCard from './ProfileCard'; +customElements.define('cod-profile-card', ProfileCard); \ No newline at end of file diff --git a/src/stable/stories/profilecard.stories.js b/src/stable/stories/profilecard.stories.js new file mode 100644 index 00000000..3c2659f2 --- /dev/null +++ b/src/stable/stories/profilecard.stories.js @@ -0,0 +1,12 @@ +import { html } from 'lit-html'; +import '../components/ProfileCard/cod-profile-card'; + +export default { + tags: ['stable'], + title: 'Components/ProfileCard' +}; + +export const ProfileCard = { + tags: ['autodocs'], + render: () => html ``, +}; \ No newline at end of file From c104eea3a384176efe242459239384b056027898 Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Tue, 25 Mar 2025 17:52:51 -0400 Subject: [PATCH 02/43] Fixed prettier issues in 3 files --- src/stable/components/ProfileCard/ProfileCard.js | 14 ++++++-------- .../components/ProfileCard/cod-profile-card.js | 2 +- src/stable/stories/profilecard.stories.js | 10 +++++----- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.js b/src/stable/components/ProfileCard/ProfileCard.js index ce5f7412..0b2bc92d 100644 --- a/src/stable/components/ProfileCard/ProfileCard.js +++ b/src/stable/components/ProfileCard/ProfileCard.js @@ -12,13 +12,11 @@ ${styles} `; class ProfileCard extends HTMLElement { - constructor(){ - super(); - const shadow = this.attachShadow({ mode: 'open'}); - shadow.appendChild(template.content.cloneNode(true)); - } + constructor() { + super(); + const shadow = this.attachShadow({ mode: 'open' }); + shadow.appendChild(template.content.cloneNode(true)); + } } - - -export { ProfileCard as default }; \ No newline at end of file +export { ProfileCard as default }; diff --git a/src/stable/components/ProfileCard/cod-profile-card.js b/src/stable/components/ProfileCard/cod-profile-card.js index e8dc69d2..069f785e 100644 --- a/src/stable/components/ProfileCard/cod-profile-card.js +++ b/src/stable/components/ProfileCard/cod-profile-card.js @@ -1,2 +1,2 @@ import ProfileCard from './ProfileCard'; -customElements.define('cod-profile-card', ProfileCard); \ No newline at end of file +customElements.define('cod-profile-card', ProfileCard); diff --git a/src/stable/stories/profilecard.stories.js b/src/stable/stories/profilecard.stories.js index 3c2659f2..372639f1 100644 --- a/src/stable/stories/profilecard.stories.js +++ b/src/stable/stories/profilecard.stories.js @@ -2,11 +2,11 @@ import { html } from 'lit-html'; import '../components/ProfileCard/cod-profile-card'; export default { - tags: ['stable'], - title: 'Components/ProfileCard' + tags: ['stable'], + title: 'Components/ProfileCard', }; export const ProfileCard = { - tags: ['autodocs'], - render: () => html ``, -}; \ No newline at end of file + tags: ['autodocs'], + render: () => html``, +}; From eb6cd79d0508f0700080f331384f5c10ae76b275 Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Wed, 26 Mar 2025 16:15:33 -0400 Subject: [PATCH 03/43] Created full profile-card component with completed javascript --- .../components/ProfileCard/ProfileCard.js | 45 ++++++++++++++++++- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.js b/src/stable/components/ProfileCard/ProfileCard.js index 0b2bc92d..7b2f72f2 100644 --- a/src/stable/components/ProfileCard/ProfileCard.js +++ b/src/stable/components/ProfileCard/ProfileCard.js @@ -6,8 +6,13 @@ template.innerHTML = ` ${styles} -
-

PROFILE CARD HERE

+
+ Profile Image +
+ + + +
`; @@ -17,6 +22,42 @@ class ProfileCard extends HTMLElement { const shadow = this.attachShadow({ mode: 'open' }); shadow.appendChild(template.content.cloneNode(true)); } + + static get observedAttributes() { + return ['image-src']; + } + + attributeChangedCallback(name, newValue) { + if (name === 'image-src') { + this._updateImage(newValue); + } + } + + connectedCallback() { + this._updateImage(this.getAttribute('image-src')); + this._validateNameSlot(); + } + + _updateImage(newValue) { + const img = this.shadowRoot.querySelector('.profile-image'); + if (img) { + img.src = newValue || ''; + } + } + + _validateNameSlot() { + const slot = this.shadowRoot.querySelector('slot[name="name"]'); + slot.addEventListener('slotchange', () => { + const assignedNodes = slot.assignedNodes({ flatten: true }); + if(assignedNodes.length > 0) { + const assignedElement = assignedNodes[0]; + if(!(assignedElement instanceof HTMLSpanElement || assignedElement instanceof HTMLAnchorElement)){ + console.warn('ProfileCard: The "name" slot should contain either a or an element.'); + } + } + }); + } + } export { ProfileCard as default }; From 3f317554aa6e5ba3d9beb0362b46c34d33337f7f Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Wed, 26 Mar 2025 16:18:57 -0400 Subject: [PATCH 04/43] Fixed prettier issues in 1 file by removing the console.warn --- src/stable/components/ProfileCard/ProfileCard.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.js b/src/stable/components/ProfileCard/ProfileCard.js index 7b2f72f2..0d1d50de 100644 --- a/src/stable/components/ProfileCard/ProfileCard.js +++ b/src/stable/components/ProfileCard/ProfileCard.js @@ -49,15 +49,21 @@ class ProfileCard extends HTMLElement { const slot = this.shadowRoot.querySelector('slot[name="name"]'); slot.addEventListener('slotchange', () => { const assignedNodes = slot.assignedNodes({ flatten: true }); - if(assignedNodes.length > 0) { + if (assignedNodes.length > 0) { const assignedElement = assignedNodes[0]; - if(!(assignedElement instanceof HTMLSpanElement || assignedElement instanceof HTMLAnchorElement)){ - console.warn('ProfileCard: The "name" slot should contain either a or an element.'); + if ( + !( + assignedElement instanceof HTMLSpanElement || + assignedElement instanceof HTMLAnchorElement + ) + ) { + throw new Error( + 'ProfileCard: The "name" slot should contain either a or an element.', + ); } } }); } - } export { ProfileCard as default }; From 0745badb02814b2911d513564e5bdc56541bc65b Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Thu, 27 Mar 2025 15:59:59 -0400 Subject: [PATCH 05/43] Added scss/css for profilecard --- .../components/ProfileCard/ProfileCard.css | 45 +++++++++++++++++++ .../ProfileCard/ProfileCard.css.map | 1 + .../components/ProfileCard/ProfileCard.scss | 43 ++++++++++++++++++ src/stable/stories/profilecard.stories.js | 24 ++++++++-- 4 files changed, 109 insertions(+), 4 deletions(-) create mode 100644 src/stable/components/ProfileCard/ProfileCard.css.map diff --git a/src/stable/components/ProfileCard/ProfileCard.css b/src/stable/components/ProfileCard/ProfileCard.css index e69de29b..51f26b89 100644 --- a/src/stable/components/ProfileCard/ProfileCard.css +++ b/src/stable/components/ProfileCard/ProfileCard.css @@ -0,0 +1,45 @@ +.profile-card { + display: flex; + align-items: center; + width: 100%; + max-width: 100%; + gap: 20px; +} + +.profile-image { + object-fit: contain; /* could be cover */ + width: 20%; + max-width: 120px; + height: auto; + border-radius: 50%; +} + +.profile-details { + display: flex; + flex-direction: column; + flex-grow: 1; + min-width: 0; +} + +::slotted([slot='name']) { + font-size: 20px; + line-height: 100%; + letter-spacing: 0%; + font-weight: 600; +} + +::slotted([slot='title-primary']) { + font-size: 16px; + line-height: 100%; + letter-spacing: 0%; + font-weight: 400; +} + +::slotted([slot='title-secondary']) { + font-size: 16px; + line-height: 100%; + letter-spacing: 0%; + font-weight: 400; +} + +/*# sourceMappingURL=ProfileCard.css.map */ diff --git a/src/stable/components/ProfileCard/ProfileCard.css.map b/src/stable/components/ProfileCard/ProfileCard.css.map new file mode 100644 index 00000000..d06697e8 --- /dev/null +++ b/src/stable/components/ProfileCard/ProfileCard.css.map @@ -0,0 +1 @@ +{"version":3,"sourceRoot":"","sources":["ProfileCard.scss"],"names":[],"mappings":"AAAA;EACI;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;;;AAGJ;EACA;EACA;EACA;EACA;;;AAGA;EACA;EACA;EACA;EACA","file":"ProfileCard.css"} \ No newline at end of file diff --git a/src/stable/components/ProfileCard/ProfileCard.scss b/src/stable/components/ProfileCard/ProfileCard.scss index e69de29b..d33fff9b 100644 --- a/src/stable/components/ProfileCard/ProfileCard.scss +++ b/src/stable/components/ProfileCard/ProfileCard.scss @@ -0,0 +1,43 @@ +.profile-card { + display: flex; + align-items: center; + width: 100%; + max-width: 100%; + gap: 20px; +} + +.profile-image { + object-fit: contain; /* could be cover */ + width: 20%; + max-width: 120px; + height: auto; + border-radius: 50%; +} + +.profile-details { + display: flex; + flex-direction: column; + flex-grow: 1; + min-width: 0; +} + +::slotted([slot="name"]) { + font-size: 20px; + line-height: 100%; + letter-spacing: 0%; + font-weight: 600; +} + +::slotted([slot="title-primary"]){ +font-size: 16px; +line-height: 100%; +letter-spacing: 0%; +font-weight: 400; +} + +::slotted([slot="title-secondary"]) { +font-size: 16px; +line-height: 100%; +letter-spacing: 0%; +font-weight: 400; +} \ No newline at end of file diff --git a/src/stable/stories/profilecard.stories.js b/src/stable/stories/profilecard.stories.js index 372639f1..dcfc88cf 100644 --- a/src/stable/stories/profilecard.stories.js +++ b/src/stable/stories/profilecard.stories.js @@ -2,11 +2,27 @@ import { html } from 'lit-html'; import '../components/ProfileCard/cod-profile-card'; export default { - tags: ['stable'], + tags: ['stable', 'autodocs'], title: 'Components/ProfileCard', + argTypes: { + imageSrc: { control: 'text', name: 'Image Source'}, + name: { control: 'text', name: 'Name'}, + titlePrimary: { control: 'text', name: 'Primary Title'}, + titleSecondary: { control: 'text', name: 'Secondary Title'}, + }, }; -export const ProfileCard = { - tags: ['autodocs'], - render: () => html``, +export const Default = (args) => html ` + + ${args.name} + ${args.titlePrimary} + ${args.titleSecondary} + +`; + +Default.args = { + imageSrc: 'https://placehold.co/400', + name: 'Jane Doe', + titlePrimary: 'Frontend Engineer', + titleSecondary: 'Frontend Developer', }; From f32069704d2d52d42466c35b5d1b2f0d1239be06 Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Thu, 27 Mar 2025 16:02:55 -0400 Subject: [PATCH 06/43] Fixed prettier issues in 2 files --- .../components/ProfileCard/ProfileCard.scss | 60 +++++++++---------- src/stable/stories/profilecard.stories.js | 20 +++---- 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.scss b/src/stable/components/ProfileCard/ProfileCard.scss index d33fff9b..9c27bd16 100644 --- a/src/stable/components/ProfileCard/ProfileCard.scss +++ b/src/stable/components/ProfileCard/ProfileCard.scss @@ -1,43 +1,43 @@ .profile-card { - display: flex; - align-items: center; - width: 100%; - max-width: 100%; - gap: 20px; + display: flex; + align-items: center; + width: 100%; + max-width: 100%; + gap: 20px; } .profile-image { - object-fit: contain; /* could be cover */ - width: 20%; - max-width: 120px; - height: auto; - border-radius: 50%; + object-fit: contain; /* could be cover */ + width: 20%; + max-width: 120px; + height: auto; + border-radius: 50%; } .profile-details { - display: flex; - flex-direction: column; - flex-grow: 1; - min-width: 0; + display: flex; + flex-direction: column; + flex-grow: 1; + min-width: 0; } -::slotted([slot="name"]) { - font-size: 20px; - line-height: 100%; - letter-spacing: 0%; - font-weight: 600; +::slotted([slot='name']) { + font-size: 20px; + line-height: 100%; + letter-spacing: 0%; + font-weight: 600; } -::slotted([slot="title-primary"]){ -font-size: 16px; -line-height: 100%; -letter-spacing: 0%; -font-weight: 400; +::slotted([slot='title-primary']) { + font-size: 16px; + line-height: 100%; + letter-spacing: 0%; + font-weight: 400; } -::slotted([slot="title-secondary"]) { -font-size: 16px; -line-height: 100%; -letter-spacing: 0%; -font-weight: 400; -} \ No newline at end of file +::slotted([slot='title-secondary']) { + font-size: 16px; + line-height: 100%; + letter-spacing: 0%; + font-weight: 400; +} diff --git a/src/stable/stories/profilecard.stories.js b/src/stable/stories/profilecard.stories.js index dcfc88cf..e4454512 100644 --- a/src/stable/stories/profilecard.stories.js +++ b/src/stable/stories/profilecard.stories.js @@ -5,19 +5,19 @@ export default { tags: ['stable', 'autodocs'], title: 'Components/ProfileCard', argTypes: { - imageSrc: { control: 'text', name: 'Image Source'}, - name: { control: 'text', name: 'Name'}, - titlePrimary: { control: 'text', name: 'Primary Title'}, - titleSecondary: { control: 'text', name: 'Secondary Title'}, + imageSrc: { control: 'text', name: 'Image Source' }, + name: { control: 'text', name: 'Name' }, + titlePrimary: { control: 'text', name: 'Primary Title' }, + titleSecondary: { control: 'text', name: 'Secondary Title' }, }, }; -export const Default = (args) => html ` - - ${args.name} - ${args.titlePrimary} - ${args.titleSecondary} - +export const Default = (args) => html` + + ${args.name} + ${args.titlePrimary} + ${args.titleSecondary} + `; Default.args = { From d43edd2c637230630e9b1323c1490b9f1416a71c Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Thu, 27 Mar 2025 17:05:08 -0400 Subject: [PATCH 07/43] Changed object fit to cover and pixels to rems --- src/stable/components/ProfileCard/ProfileCard.css | 10 +++++----- src/stable/components/ProfileCard/ProfileCard.css.map | 2 +- src/stable/components/ProfileCard/ProfileCard.scss | 10 +++++----- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.css b/src/stable/components/ProfileCard/ProfileCard.css index 51f26b89..eaee5a27 100644 --- a/src/stable/components/ProfileCard/ProfileCard.css +++ b/src/stable/components/ProfileCard/ProfileCard.css @@ -3,11 +3,11 @@ align-items: center; width: 100%; max-width: 100%; - gap: 20px; + gap: 1.25em; } .profile-image { - object-fit: contain; /* could be cover */ + object-fit: cover; width: 20%; max-width: 120px; height: auto; @@ -22,21 +22,21 @@ } ::slotted([slot='name']) { - font-size: 20px; + font-size: 1.25em; line-height: 100%; letter-spacing: 0%; font-weight: 600; } ::slotted([slot='title-primary']) { - font-size: 16px; + font-size: 1em; line-height: 100%; letter-spacing: 0%; font-weight: 400; } ::slotted([slot='title-secondary']) { - font-size: 16px; + font-size: 1em; line-height: 100%; letter-spacing: 0%; font-weight: 400; diff --git a/src/stable/components/ProfileCard/ProfileCard.css.map b/src/stable/components/ProfileCard/ProfileCard.css.map index d06697e8..3a1b18fc 100644 --- a/src/stable/components/ProfileCard/ProfileCard.css.map +++ b/src/stable/components/ProfileCard/ProfileCard.css.map @@ -1 +1 @@ -{"version":3,"sourceRoot":"","sources":["ProfileCard.scss"],"names":[],"mappings":"AAAA;EACI;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;;;AAGJ;EACA;EACA;EACA;EACA;;;AAGA;EACA;EACA;EACA;EACA","file":"ProfileCard.css"} \ No newline at end of file +{"version":3,"sourceRoot":"","sources":["ProfileCard.scss"],"names":[],"mappings":"AAAA;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA","file":"ProfileCard.css"} \ No newline at end of file diff --git a/src/stable/components/ProfileCard/ProfileCard.scss b/src/stable/components/ProfileCard/ProfileCard.scss index 9c27bd16..4e0bf71a 100644 --- a/src/stable/components/ProfileCard/ProfileCard.scss +++ b/src/stable/components/ProfileCard/ProfileCard.scss @@ -3,11 +3,11 @@ align-items: center; width: 100%; max-width: 100%; - gap: 20px; + gap: 1.25rem; } .profile-image { - object-fit: contain; /* could be cover */ + object-fit: cover; width: 20%; max-width: 120px; height: auto; @@ -22,21 +22,21 @@ } ::slotted([slot='name']) { - font-size: 20px; + font-size: 1.25rem; line-height: 100%; letter-spacing: 0%; font-weight: 600; } ::slotted([slot='title-primary']) { - font-size: 16px; + font-size: 1rem; line-height: 100%; letter-spacing: 0%; font-weight: 400; } ::slotted([slot='title-secondary']) { - font-size: 16px; + font-size: 1rem; line-height: 100%; letter-spacing: 0%; font-weight: 400; From 1bc632b510af7389115b6fac5bd93f704b8a9890 Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Thu, 27 Mar 2025 17:07:42 -0400 Subject: [PATCH 08/43] Fixed prettier issues in 1 file --- src/stable/components/ProfileCard/ProfileCard.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.scss b/src/stable/components/ProfileCard/ProfileCard.scss index 4e0bf71a..3a926be1 100644 --- a/src/stable/components/ProfileCard/ProfileCard.scss +++ b/src/stable/components/ProfileCard/ProfileCard.scss @@ -7,7 +7,7 @@ } .profile-image { - object-fit: cover; + object-fit: cover; width: 20%; max-width: 120px; height: auto; From 3ce7e172aa267a9214ed5c85e651a0e7f02d3df6 Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Thu, 3 Apr 2025 12:11:49 -0400 Subject: [PATCH 09/43] Added link-href as an attribute and the ability to click the profile card. also updated stories file to refelct new attributes and changes --- .../components/ProfileCard/ProfileCard.js | 23 ++++++++++++++++--- src/stable/stories/profilecard.stories.js | 4 +++- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.js b/src/stable/components/ProfileCard/ProfileCard.js index 0d1d50de..a61aa957 100644 --- a/src/stable/components/ProfileCard/ProfileCard.js +++ b/src/stable/components/ProfileCard/ProfileCard.js @@ -6,14 +6,14 @@ template.innerHTML = ` ${styles} - + `; class ProfileCard extends HTMLElement { @@ -24,17 +24,21 @@ class ProfileCard extends HTMLElement { } static get observedAttributes() { - return ['image-src']; + return ['image-src', 'link-href']; } attributeChangedCallback(name, newValue) { if (name === 'image-src') { this._updateImage(newValue); } + if (name === 'link-href') { + this._updateLink(newValue); + } } connectedCallback() { this._updateImage(this.getAttribute('image-src')); + this._updateLink(this.getAttribute('link-href')); this._validateNameSlot(); } @@ -64,6 +68,19 @@ class ProfileCard extends HTMLElement { } }); } + + _updateLink(newValue) { + const card = this.shadowRoot.querySelector('.profile-card'); + if (card) { + if (newValue) { + card.href = newValue; + card.target = '_blank'; + card.rel = 'noopener noreferrer'; + } else { + card.removeAttribute('href'); + } + } + } } export { ProfileCard as default }; diff --git a/src/stable/stories/profilecard.stories.js b/src/stable/stories/profilecard.stories.js index e4454512..92666f6d 100644 --- a/src/stable/stories/profilecard.stories.js +++ b/src/stable/stories/profilecard.stories.js @@ -9,11 +9,12 @@ export default { name: { control: 'text', name: 'Name' }, titlePrimary: { control: 'text', name: 'Primary Title' }, titleSecondary: { control: 'text', name: 'Secondary Title' }, + linkHref: { control: 'text', name: 'Profile Link' }, }, }; export const Default = (args) => html` - + ${args.name} ${args.titlePrimary} ${args.titleSecondary} @@ -25,4 +26,5 @@ Default.args = { name: 'Jane Doe', titlePrimary: 'Frontend Engineer', titleSecondary: 'Frontend Developer', + linkHref: 'https://example.com', }; From 9dc03b607d0edf14e37b2edba2a7dec708395e10 Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Thu, 3 Apr 2025 13:28:39 -0400 Subject: [PATCH 10/43] Fixed prettier issues in 2 files --- src/stable/components/ProfileCard/ProfileCard.js | 2 +- src/stable/stories/profilecard.stories.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.js b/src/stable/components/ProfileCard/ProfileCard.js index a61aa957..48db5f41 100644 --- a/src/stable/components/ProfileCard/ProfileCard.js +++ b/src/stable/components/ProfileCard/ProfileCard.js @@ -24,7 +24,7 @@ class ProfileCard extends HTMLElement { } static get observedAttributes() { - return ['image-src', 'link-href']; + return ['image-src', 'link-href']; } attributeChangedCallback(name, newValue) { diff --git a/src/stable/stories/profilecard.stories.js b/src/stable/stories/profilecard.stories.js index 92666f6d..202602a8 100644 --- a/src/stable/stories/profilecard.stories.js +++ b/src/stable/stories/profilecard.stories.js @@ -9,7 +9,7 @@ export default { name: { control: 'text', name: 'Name' }, titlePrimary: { control: 'text', name: 'Primary Title' }, titleSecondary: { control: 'text', name: 'Secondary Title' }, - linkHref: { control: 'text', name: 'Profile Link' }, + linkHref: { control: 'text', name: 'Profile Link' }, }, }; From cbe49d1c77a2bf51b7ad532cd7783870d4ea68ac Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Tue, 8 Apr 2025 19:23:39 -0400 Subject: [PATCH 11/43] Removed text decoration from name and titles --- src/stable/components/ProfileCard/ProfileCard.css | 1 + src/stable/components/ProfileCard/ProfileCard.css.map | 2 +- src/stable/components/ProfileCard/ProfileCard.scss | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.css b/src/stable/components/ProfileCard/ProfileCard.css index eaee5a27..9573a09c 100644 --- a/src/stable/components/ProfileCard/ProfileCard.css +++ b/src/stable/components/ProfileCard/ProfileCard.css @@ -4,6 +4,7 @@ width: 100%; max-width: 100%; gap: 1.25em; + text-decoration: none; } .profile-image { diff --git a/src/stable/components/ProfileCard/ProfileCard.css.map b/src/stable/components/ProfileCard/ProfileCard.css.map index 3a1b18fc..30950f34 100644 --- a/src/stable/components/ProfileCard/ProfileCard.css.map +++ b/src/stable/components/ProfileCard/ProfileCard.css.map @@ -1 +1 @@ -{"version":3,"sourceRoot":"","sources":["ProfileCard.scss"],"names":[],"mappings":"AAAA;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA","file":"ProfileCard.css"} \ No newline at end of file +{"version":3,"sourceRoot":"","sources":["ProfileCard.scss"],"names":[],"mappings":"AAAA;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA","file":"ProfileCard.css"} \ No newline at end of file diff --git a/src/stable/components/ProfileCard/ProfileCard.scss b/src/stable/components/ProfileCard/ProfileCard.scss index 3a926be1..f29e60fa 100644 --- a/src/stable/components/ProfileCard/ProfileCard.scss +++ b/src/stable/components/ProfileCard/ProfileCard.scss @@ -4,6 +4,7 @@ width: 100%; max-width: 100%; gap: 1.25rem; + text-decoration: none; } .profile-image { From cfeabd5ae67256ba627c822fce8b5d0becc58428 Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Wed, 9 Apr 2025 17:51:15 -0400 Subject: [PATCH 12/43] Added documentation for Profile Card, updated attribute names for ProfileCard.js and Stories file. Added commented out tests --- .../components/ProfileCard/ProfileCard.js | 10 +-- src/stable/docs/ProfileCard.mdx | 82 +++++++++++++++++ src/stable/stories/profilecard.stories.js | 88 +++++++++++++++++-- 3 files changed, 170 insertions(+), 10 deletions(-) create mode 100644 src/stable/docs/ProfileCard.mdx diff --git a/src/stable/components/ProfileCard/ProfileCard.js b/src/stable/components/ProfileCard/ProfileCard.js index 48db5f41..7412f97e 100644 --- a/src/stable/components/ProfileCard/ProfileCard.js +++ b/src/stable/components/ProfileCard/ProfileCard.js @@ -24,21 +24,21 @@ class ProfileCard extends HTMLElement { } static get observedAttributes() { - return ['image-src', 'link-href']; + return ['src', 'href']; } attributeChangedCallback(name, newValue) { - if (name === 'image-src') { + if (name === 'src') { this._updateImage(newValue); } - if (name === 'link-href') { + if (name === 'href') { this._updateLink(newValue); } } connectedCallback() { - this._updateImage(this.getAttribute('image-src')); - this._updateLink(this.getAttribute('link-href')); + this._updateImage(this.getAttribute('src')); + this._updateLink(this.getAttribute('href')); this._validateNameSlot(); } diff --git a/src/stable/docs/ProfileCard.mdx b/src/stable/docs/ProfileCard.mdx new file mode 100644 index 00000000..42d10a99 --- /dev/null +++ b/src/stable/docs/ProfileCard.mdx @@ -0,0 +1,82 @@ +import { + Meta, + Title, + Subtitle, + Description, + Primary, + Controls, + Stories, + Story, + Source, +} from '@storybook/blocks'; +import * as ProfileCardStories from '../stories/profilecard.stories'; + +import '../../../.storybook/docs'; // Import all documentation components + + + +# Profile Card +
+ Profile Cards are ... +
+ +# Examples + +### Default + + + + + + +## Slots + + + + +## HTML Attributes / JS Properties + +Supported HTML attributes. If the attribute is reflected in a JS property, that attribute will have a 'reflects' tag next to the name. + + + + +## Events + + + + +## Methods + + + + +## Custom CSS Properties + + + + +## CSS Parts + + + +## Dependencies + + + +## Accessibility + +Profile Card components are \ No newline at end of file diff --git a/src/stable/stories/profilecard.stories.js b/src/stable/stories/profilecard.stories.js index 202602a8..55c9f7cb 100644 --- a/src/stable/stories/profilecard.stories.js +++ b/src/stable/stories/profilecard.stories.js @@ -1,20 +1,21 @@ import { html } from 'lit-html'; import '../components/ProfileCard/cod-profile-card'; +import { expect } from '@storybook/test'; export default { tags: ['stable', 'autodocs'], title: 'Components/ProfileCard', argTypes: { - imageSrc: { control: 'text', name: 'Image Source' }, + src: { control: 'text', name: 'Image Source' }, name: { control: 'text', name: 'Name' }, titlePrimary: { control: 'text', name: 'Primary Title' }, titleSecondary: { control: 'text', name: 'Secondary Title' }, - linkHref: { control: 'text', name: 'Profile Link' }, + href: { control: 'text', name: 'Profile Link' }, }, }; export const Default = (args) => html` - + ${args.name} ${args.titlePrimary} ${args.titleSecondary} @@ -22,9 +23,86 @@ export const Default = (args) => html` `; Default.args = { - imageSrc: 'https://placehold.co/400', + src: 'https://placehold.co/400', name: 'Jane Doe', titlePrimary: 'Frontend Engineer', titleSecondary: 'Frontend Developer', - linkHref: 'https://example.com', + href: 'https://example.com', }; +// Login needed to run tests now? +// export const Test = { +// tags: ['!dev'], +// render: () => html` +// +// Jane Doe +// Frontend Engineer +// Frontend Developer +// +// `, +// play: async ({ canvasElement }) => { +// const profileCard = canvasElement.querySelector('cod-profile-card'); +// const shadow = profileCard.shadowRoot; + +// // ===== TEST 1: Image Presence Test ===== +// const img = shadow.querySelector('.profile-image'); +// expect(img).not.toBeNull(); +// expect(img.tagName).toBe('IMG'); +// expect(img.src).toContain('https://placehold.co/400'); + +// // ===== TEST 2: Slot Content Test ===== +// const nameSlot = shadow.querySelector('slot[name="name"]'); +// const titlePrimarySlot = shadow.querySelector('slot[name="title-primary"]'); +// const titleSecondarySlot = shadow.querySelector( +// 'slot[name="title-secondary"]', +// ); + +// // Check that slots exist +// expect(nameSlot).not.toBeNull(); +// expect(titlePrimarySlot).not.toBeNull(); +// expect(titleSecondarySlot).not.toBeNull(); + +// // Check slot content +// const nameNodes = nameSlot.assignedNodes({ flatten: true }); +// const titlePrimaryNodes = titlePrimarySlot.assignedNodes({ flatten: true }); +// const titleSecondaryNodes = titleSecondarySlot.assignedNodes({ +// flatten: true, +// }); + +// expect(nameNodes.length).toBeGreaterThan(0); +// expect(titlePrimaryNodes.length).toBeGreaterThan(0); +// expect(titleSecondaryNodes.length).toBeGreaterThan(0); + +// expect(nameNodes[0].textContent).toBe('Jane Doe'); +// expect(titlePrimaryNodes[0].textContent).toBe('Frontend Engineer'); +// expect(titleSecondaryNodes[0].textContent).toBe('Frontend Developer'); + +// // ===== TEST 3: Link Element Test ===== +// const link = shadow.querySelector('.profile-card'); +// expect(link).not.toBeNull(); +// expect(link.tagName).toBe('A'); + +// // Verify the href attribute +// expect(link.hasAttribute('href')).toBe(true); +// expect(link.getAttribute('href')).toBe(profileCard.getAttribute('link-href')); + +// // Verify the target and rel attributes +// expect(link.getAttribute('target')).toBe('_blank'); +// expect(link.getAttribute('rel')).toBe('noopener noreferrer'); + +// // ===== TEST 4: Error Handling Test ===== +// try { +// const invalidNameSlotContent = document.createElement('div'); +// nameSlot.appendChild(invalidNameSlotContent); +// throw new Error( +// 'Expected an error to be thrown for invalid slot content.', +// ); +// } catch (error) { +// expect(error.message).toContain( +// 'ProfileCard: The "name" slot should contain either a or an element.', +// ); +// } +// }, +// }; \ No newline at end of file From 9e551a293a3205256a532c923959c15e5cfdf755 Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Fri, 11 Apr 2025 16:27:59 -0400 Subject: [PATCH 13/43] Updated ProfileCard.js functions to work better with storybook tests. Updated link for ProfileCard.mdx and updated failing tests for stories file --- .../components/ProfileCard/ProfileCard.js | 59 +++--- src/stable/docs/ProfileCard.mdx | 13 +- src/stable/stories/profilecard.stories.js | 180 ++++++++++-------- 3 files changed, 145 insertions(+), 107 deletions(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.js b/src/stable/components/ProfileCard/ProfileCard.js index 7412f97e..5d407103 100644 --- a/src/stable/components/ProfileCard/ProfileCard.js +++ b/src/stable/components/ProfileCard/ProfileCard.js @@ -5,7 +5,6 @@ template.innerHTML = ` - Profile Image
@@ -15,19 +14,16 @@ ${styles}
`; - class ProfileCard extends HTMLElement { constructor() { super(); const shadow = this.attachShadow({ mode: 'open' }); shadow.appendChild(template.content.cloneNode(true)); } - static get observedAttributes() { return ['src', 'href']; } - - attributeChangedCallback(name, newValue) { + attributeChangedCallback(name, oldValue, newValue) { if (name === 'src') { this._updateImage(newValue); } @@ -35,40 +31,52 @@ class ProfileCard extends HTMLElement { this._updateLink(newValue); } } - connectedCallback() { this._updateImage(this.getAttribute('src')); this._updateLink(this.getAttribute('href')); this._validateNameSlot(); } - + + getValidationError() { + return this._validationError; + } + _updateImage(newValue) { const img = this.shadowRoot.querySelector('.profile-image'); if (img) { img.src = newValue || ''; } } - + _validateNameSlot() { const slot = this.shadowRoot.querySelector('slot[name="name"]'); - slot.addEventListener('slotchange', () => { - const assignedNodes = slot.assignedNodes({ flatten: true }); - if (assignedNodes.length > 0) { - const assignedElement = assignedNodes[0]; - if ( - !( - assignedElement instanceof HTMLSpanElement || - assignedElement instanceof HTMLAnchorElement - ) - ) { - throw new Error( - 'ProfileCard: The "name" slot should contain either a or an element.', - ); - } + if (slot) { + slot.addEventListener('slotchange', () => { + this._validateSlotContent(); + }); + + this._validateSlotContent(); + } + } + + _validateSlotContent() { + const slot = this.shadowRoot.querySelector('slot[name="name"]'); + if (!slot) return; + + const assignedNodes = slot.assignedNodes({ flatten: true }); + + if (assignedNodes.length > 0) { + const firstElement = assignedNodes.find(node => node.nodeType === Node.ELEMENT_NODE); + + if (firstElement && !(firstElement instanceof HTMLSpanElement || + firstElement instanceof HTMLAnchorElement)) { + throw new Error( + 'ProfileCard: The "name" slot should contain either a or an element.' + ); } - }); + } } - + _updateLink(newValue) { const card = this.shadowRoot.querySelector('.profile-card'); if (card) { @@ -82,5 +90,4 @@ class ProfileCard extends HTMLElement { } } } - -export { ProfileCard as default }; +export { ProfileCard as default }; \ No newline at end of file diff --git a/src/stable/docs/ProfileCard.mdx b/src/stable/docs/ProfileCard.mdx index 42d10a99..69ff14ba 100644 --- a/src/stable/docs/ProfileCard.mdx +++ b/src/stable/docs/ProfileCard.mdx @@ -17,7 +17,7 @@ import '../../../.storybook/docs'; // Import all documentation components # Profile Card
- Profile Cards are ... + Profile Cards are components used to display a user's profile information.
# Examples @@ -28,14 +28,13 @@ import '../../../.storybook/docs'; // Import all documentation components - ## Slots @@ -79,4 +78,6 @@ data={JSON.stringify([])}> ## Accessibility -Profile Card components are \ No newline at end of file +- **Images (`src`)**: When a profile image is included using the `src` attribute, it should be accompanied by an `alt` attribute describing the person (e.g., `alt="Photo of Jane Doe"`). This ensures screen readers can describe the image content. + +- **Links (`href`)**: When the card is made clickable with the `href` attribute, it becomes keyboard-accessible and can be navigated by screen readers. \ No newline at end of file diff --git a/src/stable/stories/profilecard.stories.js b/src/stable/stories/profilecard.stories.js index 55c9f7cb..a8759cf8 100644 --- a/src/stable/stories/profilecard.stories.js +++ b/src/stable/stories/profilecard.stories.js @@ -3,7 +3,7 @@ import '../components/ProfileCard/cod-profile-card'; import { expect } from '@storybook/test'; export default { - tags: ['stable', 'autodocs'], + tags: ['stable'], title: 'Components/ProfileCard', argTypes: { src: { control: 'text', name: 'Image Source' }, @@ -29,80 +29,110 @@ Default.args = { titleSecondary: 'Frontend Developer', href: 'https://example.com', }; -// Login needed to run tests now? -// export const Test = { -// tags: ['!dev'], -// render: () => html` -// -// Jane Doe -// Frontend Engineer -// Frontend Developer -// -// `, -// play: async ({ canvasElement }) => { -// const profileCard = canvasElement.querySelector('cod-profile-card'); -// const shadow = profileCard.shadowRoot; -// // ===== TEST 1: Image Presence Test ===== -// const img = shadow.querySelector('.profile-image'); -// expect(img).not.toBeNull(); -// expect(img.tagName).toBe('IMG'); -// expect(img.src).toContain('https://placehold.co/400'); - -// // ===== TEST 2: Slot Content Test ===== -// const nameSlot = shadow.querySelector('slot[name="name"]'); -// const titlePrimarySlot = shadow.querySelector('slot[name="title-primary"]'); -// const titleSecondarySlot = shadow.querySelector( -// 'slot[name="title-secondary"]', -// ); - -// // Check that slots exist -// expect(nameSlot).not.toBeNull(); -// expect(titlePrimarySlot).not.toBeNull(); -// expect(titleSecondarySlot).not.toBeNull(); - -// // Check slot content -// const nameNodes = nameSlot.assignedNodes({ flatten: true }); -// const titlePrimaryNodes = titlePrimarySlot.assignedNodes({ flatten: true }); -// const titleSecondaryNodes = titleSecondarySlot.assignedNodes({ -// flatten: true, -// }); - -// expect(nameNodes.length).toBeGreaterThan(0); -// expect(titlePrimaryNodes.length).toBeGreaterThan(0); -// expect(titleSecondaryNodes.length).toBeGreaterThan(0); - -// expect(nameNodes[0].textContent).toBe('Jane Doe'); -// expect(titlePrimaryNodes[0].textContent).toBe('Frontend Engineer'); -// expect(titleSecondaryNodes[0].textContent).toBe('Frontend Developer'); - -// // ===== TEST 3: Link Element Test ===== -// const link = shadow.querySelector('.profile-card'); -// expect(link).not.toBeNull(); -// expect(link.tagName).toBe('A'); - -// // Verify the href attribute -// expect(link.hasAttribute('href')).toBe(true); -// expect(link.getAttribute('href')).toBe(profileCard.getAttribute('link-href')); +export const Test = { + render: () => html` + + Jane Doe + Frontend Engineer + Frontend Developer + + `, + + parameters: { + test: { + // Tell Storybook to ignore unhandled errors for this test + dangerouslyIgnoreUnhandledErrors: true + } + }, + + play: async ({ canvasElement }) => { + const profileCard = canvasElement.querySelector('cod-profile-card'); + const shadow = profileCard.shadowRoot; + + // ===== TEST 1: Image Presence Test ===== + const img = shadow.querySelector('.profile-image'); + expect(img).not.toBeNull(); + expect(img.tagName).toBe('IMG'); + expect(img.src).toContain('https://placehold.co/400'); + + // ===== TEST 2: Slot Content Test ===== + const nameSlot = shadow.querySelector('slot[name="name"]'); + const titlePrimarySlot = shadow.querySelector('slot[name="title-primary"]'); + const titleSecondarySlot = shadow.querySelector( + 'slot[name="title-secondary"]', + ); + + // Check that slots exist + expect(nameSlot).not.toBeNull(); + expect(titlePrimarySlot).not.toBeNull(); + expect(titleSecondarySlot).not.toBeNull(); + + // Check slot content + const nameNodes = nameSlot.assignedNodes({ flatten: true }); + const titlePrimaryNodes = titlePrimarySlot.assignedNodes({ flatten: true }); + const titleSecondaryNodes = titleSecondarySlot.assignedNodes({ + flatten: true, + }); + + expect(nameNodes.length).toBeGreaterThan(0); + expect(titlePrimaryNodes.length).toBeGreaterThan(0); + expect(titleSecondaryNodes.length).toBeGreaterThan(0); + expect(nameNodes[0].textContent).toBe('Jane Doe'); + expect(titlePrimaryNodes[0].textContent).toBe('Frontend Engineer'); + expect(titleSecondaryNodes[0].textContent).toBe('Frontend Developer'); + + // ===== TEST 3: Link Element Test ===== + const link = shadow.querySelector('.profile-card'); + expect(link).not.toBeNull(); + expect(link.tagName).toBe('A'); + + // Verify the href attribute + expect(link.hasAttribute('href')).toBe(true); + expect(link.getAttribute('href')).toBe(profileCard.getAttribute('href')); + + // Verify the target and rel attributes + expect(link.getAttribute('target')).toBe('_blank'); + expect(link.getAttribute('rel')).toBe('noopener noreferrer'); -// // Verify the target and rel attributes -// expect(link.getAttribute('target')).toBe('_blank'); -// expect(link.getAttribute('rel')).toBe('noopener noreferrer'); + // ===== TEST 4: Error Handling Test ===== +// We need to test that the validation function works directly +const testValidationLogic = () => { + // 1. Create a component instance + const testCard = document.createElement('cod-profile-card'); + document.body.appendChild(testCard); + + // 2. Get a reference to the component's validation method + const validateMethod = testCard._validateSlotContent; + + // 3. Create an invalid element and add it to the slot + const invalidElement = document.createElement('div'); + invalidElement.slot = "name"; + invalidElement.textContent = "Invalid Element"; + testCard.appendChild(invalidElement); + + // 4. Try to validate manually and expect an error + try { + // Call validation directly + testCard._validateSlotContent(); + + // If we get here, the validation didn't throw an error (test should fail) + expect(false).toBe(true, 'Expected validation error was not thrown'); + } catch (error) { + // This is what we expect - validation should throw an error + expect(error.message).toContain( + 'ProfileCard: The "name" slot should contain either a or an
element.' + ); + } finally { + // Clean up + document.body.removeChild(testCard); + } +}; -// // ===== TEST 4: Error Handling Test ===== -// try { -// const invalidNameSlotContent = document.createElement('div'); -// nameSlot.appendChild(invalidNameSlotContent); -// throw new Error( -// 'Expected an error to be thrown for invalid slot content.', -// ); -// } catch (error) { -// expect(error.message).toContain( -// 'ProfileCard: The "name" slot should contain either a or an element.', -// ); -// } -// }, -// }; \ No newline at end of file +// Run the validation test +testValidationLogic(); + } +}; \ No newline at end of file From e9dd8d36c9cf5b64ea8e02409f57d8fe4df3c007 Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Fri, 11 Apr 2025 16:31:08 -0400 Subject: [PATCH 14/43] Fixed prettier issues in 3 files and removed unused variable in stories file --- .../components/ProfileCard/ProfileCard.js | 35 ++++--- src/stable/docs/ProfileCard.mdx | 34 ++++--- src/stable/stories/profilecard.stories.js | 98 +++++++++---------- 3 files changed, 85 insertions(+), 82 deletions(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.js b/src/stable/components/ProfileCard/ProfileCard.js index 5d407103..066b242b 100644 --- a/src/stable/components/ProfileCard/ProfileCard.js +++ b/src/stable/components/ProfileCard/ProfileCard.js @@ -36,47 +36,54 @@ class ProfileCard extends HTMLElement { this._updateLink(this.getAttribute('href')); this._validateNameSlot(); } - + getValidationError() { return this._validationError; } - + _updateImage(newValue) { const img = this.shadowRoot.querySelector('.profile-image'); if (img) { img.src = newValue || ''; } } - + _validateNameSlot() { const slot = this.shadowRoot.querySelector('slot[name="name"]'); if (slot) { slot.addEventListener('slotchange', () => { this._validateSlotContent(); }); - + this._validateSlotContent(); } } - + _validateSlotContent() { const slot = this.shadowRoot.querySelector('slot[name="name"]'); if (!slot) return; - + const assignedNodes = slot.assignedNodes({ flatten: true }); - + if (assignedNodes.length > 0) { - const firstElement = assignedNodes.find(node => node.nodeType === Node.ELEMENT_NODE); - - if (firstElement && !(firstElement instanceof HTMLSpanElement || - firstElement instanceof HTMLAnchorElement)) { + const firstElement = assignedNodes.find( + (node) => node.nodeType === Node.ELEMENT_NODE, + ); + + if ( + firstElement && + !( + firstElement instanceof HTMLSpanElement || + firstElement instanceof HTMLAnchorElement + ) + ) { throw new Error( - 'ProfileCard: The "name" slot should contain either a or an element.' + 'ProfileCard: The "name" slot should contain either a or an element.', ); } } } - + _updateLink(newValue) { const card = this.shadowRoot.querySelector('.profile-card'); if (card) { @@ -90,4 +97,4 @@ class ProfileCard extends HTMLElement { } } } -export { ProfileCard as default }; \ No newline at end of file +export { ProfileCard as default }; diff --git a/src/stable/docs/ProfileCard.mdx b/src/stable/docs/ProfileCard.mdx index 69ff14ba..798e9f18 100644 --- a/src/stable/docs/ProfileCard.mdx +++ b/src/stable/docs/ProfileCard.mdx @@ -1,13 +1,13 @@ import { - Meta, - Title, - Subtitle, - Description, - Primary, - Controls, - Stories, - Story, - Source, + Meta, + Title, + Subtitle, + Description, + Primary, + Controls, + Stories, + Story, + Source, } from '@storybook/blocks'; import * as ProfileCardStories from '../stories/profilecard.stories'; @@ -16,8 +16,9 @@ import '../../../.storybook/docs'; // Import all documentation components # Profile Card +
- Profile Cards are components used to display a user's profile information. + Profile Cards are components used to display a user's profile information.
# Examples @@ -32,9 +33,9 @@ import '../../../.storybook/docs'; // Import all documentation components @@ -44,8 +45,8 @@ Supported HTML attributes. If the attribute is reflected in a JS property, that @@ -68,6 +69,7 @@ data={JSON.stringify([])}> ## CSS Parts + @@ -80,4 +82,4 @@ data={JSON.stringify([])}> - **Images (`src`)**: When a profile image is included using the `src` attribute, it should be accompanied by an `alt` attribute describing the person (e.g., `alt="Photo of Jane Doe"`). This ensures screen readers can describe the image content. -- **Links (`href`)**: When the card is made clickable with the `href` attribute, it becomes keyboard-accessible and can be navigated by screen readers. \ No newline at end of file +- **Links (`href`)**: When the card is made clickable with the `href` attribute, it becomes keyboard-accessible and can be navigated by screen readers. diff --git a/src/stable/stories/profilecard.stories.js b/src/stable/stories/profilecard.stories.js index a8759cf8..c1a6c9b5 100644 --- a/src/stable/stories/profilecard.stories.js +++ b/src/stable/stories/profilecard.stories.js @@ -32,107 +32,101 @@ Default.args = { export const Test = { render: () => html` - + Jane Doe Frontend Engineer Frontend Developer `, - + parameters: { test: { // Tell Storybook to ignore unhandled errors for this test - dangerouslyIgnoreUnhandledErrors: true - } + dangerouslyIgnoreUnhandledErrors: true, + }, }, - + play: async ({ canvasElement }) => { const profileCard = canvasElement.querySelector('cod-profile-card'); const shadow = profileCard.shadowRoot; - + // ===== TEST 1: Image Presence Test ===== const img = shadow.querySelector('.profile-image'); expect(img).not.toBeNull(); expect(img.tagName).toBe('IMG'); expect(img.src).toContain('https://placehold.co/400'); - + // ===== TEST 2: Slot Content Test ===== const nameSlot = shadow.querySelector('slot[name="name"]'); const titlePrimarySlot = shadow.querySelector('slot[name="title-primary"]'); const titleSecondarySlot = shadow.querySelector( 'slot[name="title-secondary"]', ); - + // Check that slots exist expect(nameSlot).not.toBeNull(); expect(titlePrimarySlot).not.toBeNull(); expect(titleSecondarySlot).not.toBeNull(); - + // Check slot content const nameNodes = nameSlot.assignedNodes({ flatten: true }); const titlePrimaryNodes = titlePrimarySlot.assignedNodes({ flatten: true }); const titleSecondaryNodes = titleSecondarySlot.assignedNodes({ flatten: true, }); - + expect(nameNodes.length).toBeGreaterThan(0); expect(titlePrimaryNodes.length).toBeGreaterThan(0); expect(titleSecondaryNodes.length).toBeGreaterThan(0); expect(nameNodes[0].textContent).toBe('Jane Doe'); expect(titlePrimaryNodes[0].textContent).toBe('Frontend Engineer'); expect(titleSecondaryNodes[0].textContent).toBe('Frontend Developer'); - + // ===== TEST 3: Link Element Test ===== const link = shadow.querySelector('.profile-card'); expect(link).not.toBeNull(); expect(link.tagName).toBe('A'); - + // Verify the href attribute expect(link.hasAttribute('href')).toBe(true); expect(link.getAttribute('href')).toBe(profileCard.getAttribute('href')); - + // Verify the target and rel attributes expect(link.getAttribute('target')).toBe('_blank'); expect(link.getAttribute('rel')).toBe('noopener noreferrer'); // ===== TEST 4: Error Handling Test ===== -// We need to test that the validation function works directly -const testValidationLogic = () => { - // 1. Create a component instance - const testCard = document.createElement('cod-profile-card'); - document.body.appendChild(testCard); - - // 2. Get a reference to the component's validation method - const validateMethod = testCard._validateSlotContent; - - // 3. Create an invalid element and add it to the slot - const invalidElement = document.createElement('div'); - invalidElement.slot = "name"; - invalidElement.textContent = "Invalid Element"; - testCard.appendChild(invalidElement); - - // 4. Try to validate manually and expect an error - try { - // Call validation directly - testCard._validateSlotContent(); - - // If we get here, the validation didn't throw an error (test should fail) - expect(false).toBe(true, 'Expected validation error was not thrown'); - } catch (error) { - // This is what we expect - validation should throw an error - expect(error.message).toContain( - 'ProfileCard: The "name" slot should contain either a or an
element.' - ); - } finally { - // Clean up - document.body.removeChild(testCard); - } -}; + // We need to test that the validation function works directly + const testValidationLogic = () => { + // 1. Create a component instance + const testCard = document.createElement('cod-profile-card'); + document.body.appendChild(testCard); + + // 2. Create a invalid element and add it to the slot + const invalidElement = document.createElement('div'); + invalidElement.slot = 'name'; + invalidElement.textContent = 'Invalid Element'; + testCard.appendChild(invalidElement); -// Run the validation test -testValidationLogic(); - } -}; \ No newline at end of file + // 3. Try to validate manually and expect an error + try { + // Call validation directly + testCard._validateSlotContent(); + + // If we get here, the validation didn't throw an error (test should fail) + expect(false).toBe(true, 'Expected validation error was not thrown'); + } catch (error) { + // This is what we expect - validation should throw an error + expect(error.message).toContain( + 'ProfileCard: The "name" slot should contain either a or an element.', + ); + } finally { + // Clean up + document.body.removeChild(testCard); + } + }; + + // Run the validation test + testValidationLogic(); + }, +}; From aa41b70a222aa150c6261b1c4f21cc2bd74c7145 Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Fri, 11 Apr 2025 17:12:39 -0400 Subject: [PATCH 15/43] Changed reflect status in documentation --- src/stable/docs/ProfileCard.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stable/docs/ProfileCard.mdx b/src/stable/docs/ProfileCard.mdx index 798e9f18..1a7423c1 100644 --- a/src/stable/docs/ProfileCard.mdx +++ b/src/stable/docs/ProfileCard.mdx @@ -45,7 +45,7 @@ Supported HTML attributes. If the attribute is reflected in a JS property, that From df34cea5117a461e4ff82b621807d68222518f6f Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Fri, 11 Apr 2025 17:24:13 -0400 Subject: [PATCH 16/43] Added Reflective JS properties for attributes --- .../components/ProfileCard/ProfileCard.js | 166 +++++++++++++++--- 1 file changed, 144 insertions(+), 22 deletions(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.js b/src/stable/components/ProfileCard/ProfileCard.js index 066b242b..b88fecbd 100644 --- a/src/stable/components/ProfileCard/ProfileCard.js +++ b/src/stable/components/ProfileCard/ProfileCard.js @@ -1,3 +1,104 @@ +// import styles from '!!raw-loader!./ProfileCard.css'; + +// const template = document.createElement('template'); +// template.innerHTML = ` +// +// +// Profile Image +//
+// +// +// +//
+//
+// `; +// class ProfileCard extends HTMLElement { +// constructor() { +// super(); +// const shadow = this.attachShadow({ mode: 'open' }); +// shadow.appendChild(template.content.cloneNode(true)); +// } +// static get observedAttributes() { +// return ['src', 'href']; +// } +// attributeChangedCallback(name, oldValue, newValue) { +// if (name === 'src') { +// this._updateImage(newValue); +// } +// if (name === 'href') { +// this._updateLink(newValue); +// } +// } +// connectedCallback() { +// this._updateImage(this.getAttribute('src')); +// this._updateLink(this.getAttribute('href')); +// this._validateNameSlot(); +// } + +// getValidationError() { +// return this._validationError; +// } + +// _updateImage(newValue) { +// const img = this.shadowRoot.querySelector('.profile-image'); +// if (img) { +// img.src = newValue || ''; +// } +// } + +// _validateNameSlot() { +// const slot = this.shadowRoot.querySelector('slot[name="name"]'); +// if (slot) { +// slot.addEventListener('slotchange', () => { +// this._validateSlotContent(); +// }); + +// this._validateSlotContent(); +// } +// } + +// _validateSlotContent() { +// const slot = this.shadowRoot.querySelector('slot[name="name"]'); +// if (!slot) return; + +// const assignedNodes = slot.assignedNodes({ flatten: true }); + +// if (assignedNodes.length > 0) { +// const firstElement = assignedNodes.find( +// (node) => node.nodeType === Node.ELEMENT_NODE, +// ); + +// if ( +// firstElement && +// !( +// firstElement instanceof HTMLSpanElement || +// firstElement instanceof HTMLAnchorElement +// ) +// ) { +// throw new Error( +// 'ProfileCard: The "name" slot should contain either a or an element.', +// ); +// } +// } +// } + +// _updateLink(newValue) { +// const card = this.shadowRoot.querySelector('.profile-card'); +// if (card) { +// if (newValue) { +// card.href = newValue; +// card.target = '_blank'; +// card.rel = 'noopener noreferrer'; +// } else { +// card.removeAttribute('href'); +// } +// } +// } +// } +// export { ProfileCard as default }; + import styles from '!!raw-loader!./ProfileCard.css'; const template = document.createElement('template'); @@ -6,23 +107,42 @@ template.innerHTML = ` ${styles} - Profile Image -
- - - -
+ Profile Image +
+ + + +
`; + class ProfileCard extends HTMLElement { constructor() { super(); const shadow = this.attachShadow({ mode: 'open' }); shadow.appendChild(template.content.cloneNode(true)); } + static get observedAttributes() { return ['src', 'href']; } + + get src() { + return this.getAttribute('src'); + } + + set src(value) { + this.setAttribute('src', value); + } + + get href() { + return this.getAttribute('href'); + } + + set href(value) { + this.setAttribute('href', value); + } + attributeChangedCallback(name, oldValue, newValue) { if (name === 'src') { this._updateImage(newValue); @@ -31,9 +151,10 @@ class ProfileCard extends HTMLElement { this._updateLink(newValue); } } + connectedCallback() { - this._updateImage(this.getAttribute('src')); - this._updateLink(this.getAttribute('href')); + this._updateImage(this.src); + this._updateLink(this.href); this._validateNameSlot(); } @@ -48,6 +169,19 @@ class ProfileCard extends HTMLElement { } } + _updateLink(newValue) { + const card = this.shadowRoot.querySelector('.profile-card'); + if (card) { + if (newValue) { + card.href = newValue; + card.target = '_blank'; + card.rel = 'noopener noreferrer'; + } else { + card.removeAttribute('href'); + } + } + } + _validateNameSlot() { const slot = this.shadowRoot.querySelector('slot[name="name"]'); if (slot) { @@ -83,18 +217,6 @@ class ProfileCard extends HTMLElement { } } } - - _updateLink(newValue) { - const card = this.shadowRoot.querySelector('.profile-card'); - if (card) { - if (newValue) { - card.href = newValue; - card.target = '_blank'; - card.rel = 'noopener noreferrer'; - } else { - card.removeAttribute('href'); - } - } - } } -export { ProfileCard as default }; + +export { ProfileCard as default }; \ No newline at end of file From b17cadb3b51c1a44ff66971324d3cee28fab3a1a Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Mon, 14 Apr 2025 20:19:50 -0400 Subject: [PATCH 17/43] Fixed prettier issues in 1 file --- src/stable/components/ProfileCard/ProfileCard.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.js b/src/stable/components/ProfileCard/ProfileCard.js index b88fecbd..ad6c5aec 100644 --- a/src/stable/components/ProfileCard/ProfileCard.js +++ b/src/stable/components/ProfileCard/ProfileCard.js @@ -219,4 +219,4 @@ class ProfileCard extends HTMLElement { } } -export { ProfileCard as default }; \ No newline at end of file +export { ProfileCard as default }; From 1e93d2fc744b45c447be92c86f09705b14438a6b Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Thu, 17 Apr 2025 09:41:17 -0400 Subject: [PATCH 18/43] Removed duplicate cod-gov-banner.js file --- src/experimental/cod-gov-banner.js | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 src/experimental/cod-gov-banner.js diff --git a/src/experimental/cod-gov-banner.js b/src/experimental/cod-gov-banner.js deleted file mode 100644 index 6bc7a117..00000000 --- a/src/experimental/cod-gov-banner.js +++ /dev/null @@ -1,2 +0,0 @@ -import GovBanner from './GovBanner'; -customElements.define('cod-gov-banner', GovBanner); From 0daceaaeaabe8a905113558a989eaadd41ec752c Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Thu, 17 Apr 2025 09:44:11 -0400 Subject: [PATCH 19/43] Removed validate slot methods and sanity checks --- .../components/ProfileCard/ProfileCard.js | 36 ------------------- 1 file changed, 36 deletions(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.js b/src/stable/components/ProfileCard/ProfileCard.js index ad6c5aec..1c713f9e 100644 --- a/src/stable/components/ProfileCard/ProfileCard.js +++ b/src/stable/components/ProfileCard/ProfileCard.js @@ -181,42 +181,6 @@ class ProfileCard extends HTMLElement { } } } - - _validateNameSlot() { - const slot = this.shadowRoot.querySelector('slot[name="name"]'); - if (slot) { - slot.addEventListener('slotchange', () => { - this._validateSlotContent(); - }); - - this._validateSlotContent(); - } - } - - _validateSlotContent() { - const slot = this.shadowRoot.querySelector('slot[name="name"]'); - if (!slot) return; - - const assignedNodes = slot.assignedNodes({ flatten: true }); - - if (assignedNodes.length > 0) { - const firstElement = assignedNodes.find( - (node) => node.nodeType === Node.ELEMENT_NODE, - ); - - if ( - firstElement && - !( - firstElement instanceof HTMLSpanElement || - firstElement instanceof HTMLAnchorElement - ) - ) { - throw new Error( - 'ProfileCard: The "name" slot should contain either a or an element.', - ); - } - } - } } export { ProfileCard as default }; From aac6062cc39d9fd0b7b305e5bd37404358e6cb61 Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Thu, 17 Apr 2025 09:54:30 -0400 Subject: [PATCH 20/43] Removed validate slot test from stories file --- src/stable/stories/profilecard.stories.js | 30 ++--------------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/src/stable/stories/profilecard.stories.js b/src/stable/stories/profilecard.stories.js index c1a6c9b5..36d9ff9b 100644 --- a/src/stable/stories/profilecard.stories.js +++ b/src/stable/stories/profilecard.stories.js @@ -56,33 +56,7 @@ export const Test = { expect(img.tagName).toBe('IMG'); expect(img.src).toContain('https://placehold.co/400'); - // ===== TEST 2: Slot Content Test ===== - const nameSlot = shadow.querySelector('slot[name="name"]'); - const titlePrimarySlot = shadow.querySelector('slot[name="title-primary"]'); - const titleSecondarySlot = shadow.querySelector( - 'slot[name="title-secondary"]', - ); - - // Check that slots exist - expect(nameSlot).not.toBeNull(); - expect(titlePrimarySlot).not.toBeNull(); - expect(titleSecondarySlot).not.toBeNull(); - - // Check slot content - const nameNodes = nameSlot.assignedNodes({ flatten: true }); - const titlePrimaryNodes = titlePrimarySlot.assignedNodes({ flatten: true }); - const titleSecondaryNodes = titleSecondarySlot.assignedNodes({ - flatten: true, - }); - - expect(nameNodes.length).toBeGreaterThan(0); - expect(titlePrimaryNodes.length).toBeGreaterThan(0); - expect(titleSecondaryNodes.length).toBeGreaterThan(0); - expect(nameNodes[0].textContent).toBe('Jane Doe'); - expect(titlePrimaryNodes[0].textContent).toBe('Frontend Engineer'); - expect(titleSecondaryNodes[0].textContent).toBe('Frontend Developer'); - - // ===== TEST 3: Link Element Test ===== + // ===== TEST 2: Link Element Test ===== const link = shadow.querySelector('.profile-card'); expect(link).not.toBeNull(); expect(link.tagName).toBe('A'); @@ -95,7 +69,7 @@ export const Test = { expect(link.getAttribute('target')).toBe('_blank'); expect(link.getAttribute('rel')).toBe('noopener noreferrer'); - // ===== TEST 4: Error Handling Test ===== + // ===== TEST 3: Error Handling Test ===== // We need to test that the validation function works directly const testValidationLogic = () => { // 1. Create a component instance From b7394d3bfca29af6077d3d511a7a247e19db0352 Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Thu, 17 Apr 2025 09:55:23 -0400 Subject: [PATCH 21/43] Removed unused validationError function --- src/stable/components/ProfileCard/ProfileCard.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.js b/src/stable/components/ProfileCard/ProfileCard.js index 1c713f9e..e1c55caa 100644 --- a/src/stable/components/ProfileCard/ProfileCard.js +++ b/src/stable/components/ProfileCard/ProfileCard.js @@ -158,10 +158,6 @@ class ProfileCard extends HTMLElement { this._validateNameSlot(); } - getValidationError() { - return this._validationError; - } - _updateImage(newValue) { const img = this.shadowRoot.querySelector('.profile-image'); if (img) { From 519f948c38432dc27f9355da9851ddb5c48cef76 Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Thu, 17 Apr 2025 10:23:09 -0400 Subject: [PATCH 22/43] Added margin to the bottom of profile card text and removed blue color from links --- src/stable/components/ProfileCard/ProfileCard.css | 13 +++++++++++++ .../components/ProfileCard/ProfileCard.css.map | 2 +- src/stable/components/ProfileCard/ProfileCard.scss | 14 ++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.css b/src/stable/components/ProfileCard/ProfileCard.css index 9573a09c..b6c18924 100644 --- a/src/stable/components/ProfileCard/ProfileCard.css +++ b/src/stable/components/ProfileCard/ProfileCard.css @@ -7,6 +7,17 @@ text-decoration: none; } +a.profile-card { + color: inherit; + text-decoration: none; +} +a.profile-card:visited, +a.profile-card:active, +a.profile-card:hover { + color: inherit; + text-decoration: none; +} + .profile-image { object-fit: cover; width: 20%; @@ -27,6 +38,7 @@ line-height: 100%; letter-spacing: 0%; font-weight: 600; + margin-bottom: 5px; } ::slotted([slot='title-primary']) { @@ -34,6 +46,7 @@ line-height: 100%; letter-spacing: 0%; font-weight: 400; + margin-bottom: 5px; } ::slotted([slot='title-secondary']) { diff --git a/src/stable/components/ProfileCard/ProfileCard.css.map b/src/stable/components/ProfileCard/ProfileCard.css.map index 30950f34..4852c02b 100644 --- a/src/stable/components/ProfileCard/ProfileCard.css.map +++ b/src/stable/components/ProfileCard/ProfileCard.css.map @@ -1 +1 @@ -{"version":3,"sourceRoot":"","sources":["ProfileCard.scss"],"names":[],"mappings":"AAAA;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA","file":"ProfileCard.css"} \ No newline at end of file +{"version":3,"sourceRoot":"","sources":["ProfileCard.scss"],"names":[],"mappings":"AAAA;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;AAEA;EAGE;EACA;;;AAIJ;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA","file":"ProfileCard.css"} \ No newline at end of file diff --git a/src/stable/components/ProfileCard/ProfileCard.scss b/src/stable/components/ProfileCard/ProfileCard.scss index f29e60fa..20440fee 100644 --- a/src/stable/components/ProfileCard/ProfileCard.scss +++ b/src/stable/components/ProfileCard/ProfileCard.scss @@ -7,6 +7,18 @@ text-decoration: none; } +a.profile-card { + color: inherit; + text-decoration: none; + + &:visited, + &:active, + &:hover { + color: inherit; + text-decoration: none; + } +} + .profile-image { object-fit: cover; width: 20%; @@ -27,6 +39,7 @@ line-height: 100%; letter-spacing: 0%; font-weight: 600; + margin-bottom: 5px; } ::slotted([slot='title-primary']) { @@ -34,6 +47,7 @@ line-height: 100%; letter-spacing: 0%; font-weight: 400; + margin-bottom: 5px; } ::slotted([slot='title-secondary']) { From 93527aaa9c9ad5177a8c55fbb3ec0f5b2ec9b1ec Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Thu, 17 Apr 2025 10:41:23 -0400 Subject: [PATCH 23/43] Removed call to validateSlots function from connectedcallback, removed commented out profilecard code, added a name-container around name and chevron, updated scss to fix position of chevron --- .../components/ProfileCard/ProfileCard.css | 14 ++- .../ProfileCard/ProfileCard.css.map | 2 +- .../components/ProfileCard/ProfileCard.js | 107 +----------------- .../components/ProfileCard/ProfileCard.scss | 12 +- 4 files changed, 29 insertions(+), 106 deletions(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.css b/src/stable/components/ProfileCard/ProfileCard.css index b6c18924..b731388e 100644 --- a/src/stable/components/ProfileCard/ProfileCard.css +++ b/src/stable/components/ProfileCard/ProfileCard.css @@ -33,12 +33,24 @@ a.profile-card:hover { min-width: 0; } +.name-container { + display: flex; + align-items: center; + margin-bottom: 5px; +} + +.chevron { + font-size: 1.25em; + line-height: 100%; + font-weight: 600; +} + ::slotted([slot='name']) { font-size: 1.25em; line-height: 100%; letter-spacing: 0%; font-weight: 600; - margin-bottom: 5px; + margin-right: 5px; } ::slotted([slot='title-primary']) { diff --git a/src/stable/components/ProfileCard/ProfileCard.css.map b/src/stable/components/ProfileCard/ProfileCard.css.map index 4852c02b..e4ee9151 100644 --- a/src/stable/components/ProfileCard/ProfileCard.css.map +++ b/src/stable/components/ProfileCard/ProfileCard.css.map @@ -1 +1 @@ -{"version":3,"sourceRoot":"","sources":["ProfileCard.scss"],"names":[],"mappings":"AAAA;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;AAEA;EAGE;EACA;;;AAIJ;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA","file":"ProfileCard.css"} \ No newline at end of file +{"version":3,"sourceRoot":"","sources":["ProfileCard.scss"],"names":[],"mappings":"AAAA;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;AAEA;EAGE;EACA;;;AAIJ;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA","file":"ProfileCard.css"} \ No newline at end of file diff --git a/src/stable/components/ProfileCard/ProfileCard.js b/src/stable/components/ProfileCard/ProfileCard.js index e1c55caa..b4e55c40 100644 --- a/src/stable/components/ProfileCard/ProfileCard.js +++ b/src/stable/components/ProfileCard/ProfileCard.js @@ -1,104 +1,3 @@ -// import styles from '!!raw-loader!./ProfileCard.css'; - -// const template = document.createElement('template'); -// template.innerHTML = ` -// -// -// Profile Image -//
-// -// -// -//
-//
-// `; -// class ProfileCard extends HTMLElement { -// constructor() { -// super(); -// const shadow = this.attachShadow({ mode: 'open' }); -// shadow.appendChild(template.content.cloneNode(true)); -// } -// static get observedAttributes() { -// return ['src', 'href']; -// } -// attributeChangedCallback(name, oldValue, newValue) { -// if (name === 'src') { -// this._updateImage(newValue); -// } -// if (name === 'href') { -// this._updateLink(newValue); -// } -// } -// connectedCallback() { -// this._updateImage(this.getAttribute('src')); -// this._updateLink(this.getAttribute('href')); -// this._validateNameSlot(); -// } - -// getValidationError() { -// return this._validationError; -// } - -// _updateImage(newValue) { -// const img = this.shadowRoot.querySelector('.profile-image'); -// if (img) { -// img.src = newValue || ''; -// } -// } - -// _validateNameSlot() { -// const slot = this.shadowRoot.querySelector('slot[name="name"]'); -// if (slot) { -// slot.addEventListener('slotchange', () => { -// this._validateSlotContent(); -// }); - -// this._validateSlotContent(); -// } -// } - -// _validateSlotContent() { -// const slot = this.shadowRoot.querySelector('slot[name="name"]'); -// if (!slot) return; - -// const assignedNodes = slot.assignedNodes({ flatten: true }); - -// if (assignedNodes.length > 0) { -// const firstElement = assignedNodes.find( -// (node) => node.nodeType === Node.ELEMENT_NODE, -// ); - -// if ( -// firstElement && -// !( -// firstElement instanceof HTMLSpanElement || -// firstElement instanceof HTMLAnchorElement -// ) -// ) { -// throw new Error( -// 'ProfileCard: The "name" slot should contain either a or an element.', -// ); -// } -// } -// } - -// _updateLink(newValue) { -// const card = this.shadowRoot.querySelector('.profile-card'); -// if (card) { -// if (newValue) { -// card.href = newValue; -// card.target = '_blank'; -// card.rel = 'noopener noreferrer'; -// } else { -// card.removeAttribute('href'); -// } -// } -// } -// } -// export { ProfileCard as default }; - import styles from '!!raw-loader!./ProfileCard.css'; const template = document.createElement('template'); @@ -109,7 +8,10 @@ ${styles} Profile Image
- +
+ + +
@@ -155,7 +57,6 @@ class ProfileCard extends HTMLElement { connectedCallback() { this._updateImage(this.src); this._updateLink(this.href); - this._validateNameSlot(); } _updateImage(newValue) { diff --git a/src/stable/components/ProfileCard/ProfileCard.scss b/src/stable/components/ProfileCard/ProfileCard.scss index 20440fee..85137812 100644 --- a/src/stable/components/ProfileCard/ProfileCard.scss +++ b/src/stable/components/ProfileCard/ProfileCard.scss @@ -33,13 +33,23 @@ a.profile-card { flex-grow: 1; min-width: 0; } +.name-container { + display: flex; + align-items: center; + margin-bottom: 5px; +} +.chevron { + font-size: 1.25rem; + line-height: 100%; + font-weight: 600; +} ::slotted([slot='name']) { font-size: 1.25rem; line-height: 100%; letter-spacing: 0%; font-weight: 600; - margin-bottom: 5px; + margin-right: 5px; } ::slotted([slot='title-primary']) { From 224bdeefc9fdee74366dd49842aa9ccd281935a1 Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Thu, 17 Apr 2025 10:48:25 -0400 Subject: [PATCH 24/43] Added drop shadow to profile card image, removed parameter that allowed storybook to ignore error messages, removed the rest of the validation test code --- .../components/ProfileCard/ProfileCard.css | 3 ++ .../ProfileCard/ProfileCard.css.map | 2 +- .../components/ProfileCard/ProfileCard.scss | 1 + src/stable/stories/profilecard.stories.js | 41 ------------------- 4 files changed, 5 insertions(+), 42 deletions(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.css b/src/stable/components/ProfileCard/ProfileCard.css index b731388e..ca9e4dea 100644 --- a/src/stable/components/ProfileCard/ProfileCard.css +++ b/src/stable/components/ProfileCard/ProfileCard.css @@ -24,6 +24,9 @@ a.profile-card:hover { max-width: 120px; height: auto; border-radius: 50%; + box-shadow: + 0 4px 6px -1px rgba(0, 0, 0, 0.1), + 0 2px 4px -1px rgba(0, 0, 0, 0.06); } .profile-details { diff --git a/src/stable/components/ProfileCard/ProfileCard.css.map b/src/stable/components/ProfileCard/ProfileCard.css.map index e4ee9151..8ec16518 100644 --- a/src/stable/components/ProfileCard/ProfileCard.css.map +++ b/src/stable/components/ProfileCard/ProfileCard.css.map @@ -1 +1 @@ -{"version":3,"sourceRoot":"","sources":["ProfileCard.scss"],"names":[],"mappings":"AAAA;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;AAEA;EAGE;EACA;;;AAIJ;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA","file":"ProfileCard.css"} \ No newline at end of file +{"version":3,"sourceRoot":"","sources":["ProfileCard.scss"],"names":[],"mappings":"AAAA;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;AAEA;EAGE;EACA;;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA","file":"ProfileCard.css"} \ No newline at end of file diff --git a/src/stable/components/ProfileCard/ProfileCard.scss b/src/stable/components/ProfileCard/ProfileCard.scss index 85137812..077a106f 100644 --- a/src/stable/components/ProfileCard/ProfileCard.scss +++ b/src/stable/components/ProfileCard/ProfileCard.scss @@ -25,6 +25,7 @@ a.profile-card { max-width: 120px; height: auto; border-radius: 50%; + box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); } .profile-details { diff --git a/src/stable/stories/profilecard.stories.js b/src/stable/stories/profilecard.stories.js index 36d9ff9b..5f7076a4 100644 --- a/src/stable/stories/profilecard.stories.js +++ b/src/stable/stories/profilecard.stories.js @@ -39,13 +39,6 @@ export const Test = {
`, - parameters: { - test: { - // Tell Storybook to ignore unhandled errors for this test - dangerouslyIgnoreUnhandledErrors: true, - }, - }, - play: async ({ canvasElement }) => { const profileCard = canvasElement.querySelector('cod-profile-card'); const shadow = profileCard.shadowRoot; @@ -68,39 +61,5 @@ export const Test = { // Verify the target and rel attributes expect(link.getAttribute('target')).toBe('_blank'); expect(link.getAttribute('rel')).toBe('noopener noreferrer'); - - // ===== TEST 3: Error Handling Test ===== - // We need to test that the validation function works directly - const testValidationLogic = () => { - // 1. Create a component instance - const testCard = document.createElement('cod-profile-card'); - document.body.appendChild(testCard); - - // 2. Create a invalid element and add it to the slot - const invalidElement = document.createElement('div'); - invalidElement.slot = 'name'; - invalidElement.textContent = 'Invalid Element'; - testCard.appendChild(invalidElement); - - // 3. Try to validate manually and expect an error - try { - // Call validation directly - testCard._validateSlotContent(); - - // If we get here, the validation didn't throw an error (test should fail) - expect(false).toBe(true, 'Expected validation error was not thrown'); - } catch (error) { - // This is what we expect - validation should throw an error - expect(error.message).toContain( - 'ProfileCard: The "name" slot should contain either a or an element.', - ); - } finally { - // Clean up - document.body.removeChild(testCard); - } - }; - - // Run the validation test - testValidationLogic(); }, }; From 98741f118e06cca5b23e803946d60a9abe36a289 Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Thu, 17 Apr 2025 10:52:34 -0400 Subject: [PATCH 25/43] Updated documentation to include Usage section --- src/stable/docs/ProfileCard.mdx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/stable/docs/ProfileCard.mdx b/src/stable/docs/ProfileCard.mdx index 1a7423c1..b288d198 100644 --- a/src/stable/docs/ProfileCard.mdx +++ b/src/stable/docs/ProfileCard.mdx @@ -1,5 +1,6 @@ import { Meta, + Canvas, Title, Subtitle, Description, @@ -21,6 +22,12 @@ import '../../../.storybook/docs'; // Import all documentation components Profile Cards are components used to display a user's profile information.
+## Usage + + + + + # Examples ### Default From 907e8abc273f586fa5782905ac1f9531f09f32c3 Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Thu, 17 Apr 2025 10:54:14 -0400 Subject: [PATCH 26/43] Fixed prettier issues in 1 file --- src/stable/components/ProfileCard/ProfileCard.scss | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.scss b/src/stable/components/ProfileCard/ProfileCard.scss index 077a106f..ef61abb9 100644 --- a/src/stable/components/ProfileCard/ProfileCard.scss +++ b/src/stable/components/ProfileCard/ProfileCard.scss @@ -25,7 +25,9 @@ a.profile-card { max-width: 120px; height: auto; border-radius: 50%; - box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: + 0 4px 6px -1px rgba(0, 0, 0, 0.1), + 0 2px 4px -1px rgba(0, 0, 0, 0.06); } .profile-details { From 402e0f63231be08e611a1b3e0db20c7340491f15 Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Thu, 17 Apr 2025 11:10:53 -0400 Subject: [PATCH 27/43] Fixed Reflective JS issues --- .../components/ProfileCard/ProfileCard.js | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.js b/src/stable/components/ProfileCard/ProfileCard.js index b4e55c40..855c60f4 100644 --- a/src/stable/components/ProfileCard/ProfileCard.js +++ b/src/stable/components/ProfileCard/ProfileCard.js @@ -23,33 +23,32 @@ class ProfileCard extends HTMLElement { super(); const shadow = this.attachShadow({ mode: 'open' }); shadow.appendChild(template.content.cloneNode(true)); + + // Internal properties + this._href = this.getAttribute('href') || ''; + this._src = this.getAttribute('src') || ''; } static get observedAttributes() { return ['src', 'href']; } - get src() { - return this.getAttribute('src'); - } - - set src(value) { - this.setAttribute('src', value); - } - get href() { - return this.getAttribute('href'); + return this._href; } - set href(value) { - this.setAttribute('href', value); + get src() { + return this._src; } attributeChangedCallback(name, oldValue, newValue) { - if (name === 'src') { + if (name === 'src' && newValue !== oldValue) { + this._src = newValue; this._updateImage(newValue); } - if (name === 'href') { + + if (name === 'href' && newValue !== oldValue) { + this._href = newValue; this._updateLink(newValue); } } @@ -59,10 +58,10 @@ class ProfileCard extends HTMLElement { this._updateLink(this.href); } - _updateImage(newValue) { + _updateImage(src) { const img = this.shadowRoot.querySelector('.profile-image'); if (img) { - img.src = newValue || ''; + img.src = src || 'default-profile-image.jpg'; // Fallback image if src is invalid } } From 21b5bd99d27f8fed21f0b3b85e95a9ac968e727a Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Thu, 17 Apr 2025 11:23:42 -0400 Subject: [PATCH 28/43] Fixed prettier issues in 1 file --- src/stable/components/ProfileCard/ProfileCard.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.js b/src/stable/components/ProfileCard/ProfileCard.js index 855c60f4..48b06be5 100644 --- a/src/stable/components/ProfileCard/ProfileCard.js +++ b/src/stable/components/ProfileCard/ProfileCard.js @@ -24,9 +24,9 @@ class ProfileCard extends HTMLElement { const shadow = this.attachShadow({ mode: 'open' }); shadow.appendChild(template.content.cloneNode(true)); - // Internal properties - this._href = this.getAttribute('href') || ''; - this._src = this.getAttribute('src') || ''; + // Internal properties + this._href = this.getAttribute('href') || ''; + this._src = this.getAttribute('src') || ''; } static get observedAttributes() { From 4281523bb7ac772a1c9564c732435a6e65d35f18 Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Mon, 28 Apr 2025 12:58:20 -0400 Subject: [PATCH 29/43] Updated slots for primary and secondary fields in multiple files --- src/stable/components/ProfileCard/ProfileCard.css | 9 +-------- .../components/ProfileCard/ProfileCard.css.map | 2 +- src/stable/components/ProfileCard/ProfileCard.js | 4 ++-- src/stable/components/ProfileCard/ProfileCard.scss | 14 +++++++------- src/stable/docs/ProfileCard.mdx | 4 ++-- src/stable/stories/profilecard.stories.js | 8 ++++---- 6 files changed, 17 insertions(+), 24 deletions(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.css b/src/stable/components/ProfileCard/ProfileCard.css index ca9e4dea..6911ddb3 100644 --- a/src/stable/components/ProfileCard/ProfileCard.css +++ b/src/stable/components/ProfileCard/ProfileCard.css @@ -56,7 +56,7 @@ a.profile-card:hover { margin-right: 5px; } -::slotted([slot='title-primary']) { +::slotted([slot='title']) { font-size: 1em; line-height: 100%; letter-spacing: 0%; @@ -64,11 +64,4 @@ a.profile-card:hover { margin-bottom: 5px; } -::slotted([slot='title-secondary']) { - font-size: 1em; - line-height: 100%; - letter-spacing: 0%; - font-weight: 400; -} - /*# sourceMappingURL=ProfileCard.css.map */ diff --git a/src/stable/components/ProfileCard/ProfileCard.css.map b/src/stable/components/ProfileCard/ProfileCard.css.map index 8ec16518..aeadbea9 100644 --- a/src/stable/components/ProfileCard/ProfileCard.css.map +++ b/src/stable/components/ProfileCard/ProfileCard.css.map @@ -1 +1 @@ -{"version":3,"sourceRoot":"","sources":["ProfileCard.scss"],"names":[],"mappings":"AAAA;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;AAEA;EAGE;EACA;;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA","file":"ProfileCard.css"} \ No newline at end of file +{"version":3,"sourceRoot":"","sources":["ProfileCard.scss"],"names":[],"mappings":"AAAA;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;AAEA;EAGE;EACA;;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA,YACE;;;AAIJ;EACE;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA","file":"ProfileCard.css"} \ No newline at end of file diff --git a/src/stable/components/ProfileCard/ProfileCard.js b/src/stable/components/ProfileCard/ProfileCard.js index 48b06be5..bbcf49e9 100644 --- a/src/stable/components/ProfileCard/ProfileCard.js +++ b/src/stable/components/ProfileCard/ProfileCard.js @@ -12,8 +12,8 @@ ${styles} - - + + `; diff --git a/src/stable/components/ProfileCard/ProfileCard.scss b/src/stable/components/ProfileCard/ProfileCard.scss index ef61abb9..55e93390 100644 --- a/src/stable/components/ProfileCard/ProfileCard.scss +++ b/src/stable/components/ProfileCard/ProfileCard.scss @@ -55,7 +55,7 @@ a.profile-card { margin-right: 5px; } -::slotted([slot='title-primary']) { +::slotted([slot='title']) { font-size: 1rem; line-height: 100%; letter-spacing: 0%; @@ -63,9 +63,9 @@ a.profile-card { margin-bottom: 5px; } -::slotted([slot='title-secondary']) { - font-size: 1rem; - line-height: 100%; - letter-spacing: 0%; - font-weight: 400; -} +// ::slotted([slot='title-secondary']) { +// font-size: 1rem; +// line-height: 100%; +// letter-spacing: 0%; +// font-weight: 400; +// } diff --git a/src/stable/docs/ProfileCard.mdx b/src/stable/docs/ProfileCard.mdx index b288d198..8ec9a45a 100644 --- a/src/stable/docs/ProfileCard.mdx +++ b/src/stable/docs/ProfileCard.mdx @@ -41,8 +41,8 @@ import '../../../.storybook/docs'; // Import all documentation components diff --git a/src/stable/stories/profilecard.stories.js b/src/stable/stories/profilecard.stories.js index 5f7076a4..d3887aa5 100644 --- a/src/stable/stories/profilecard.stories.js +++ b/src/stable/stories/profilecard.stories.js @@ -17,8 +17,8 @@ export default { export const Default = (args) => html` ${args.name} - ${args.titlePrimary} - ${args.titleSecondary} + ${args.titlePrimary} + ${args.titleSecondary} `; @@ -34,8 +34,8 @@ export const Test = { render: () => html` Jane Doe - Frontend Engineer - Frontend Developer + Frontend Engineer + Frontend Developer `, From 4924f26403f3b5c9795166834ae643a7fe42e9a2 Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Mon, 28 Apr 2025 13:06:38 -0400 Subject: [PATCH 30/43] Updated if/else for updateLink function --- src/stable/components/ProfileCard/ProfileCard.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/stable/components/ProfileCard/ProfileCard.js b/src/stable/components/ProfileCard/ProfileCard.js index bbcf49e9..68aad92b 100644 --- a/src/stable/components/ProfileCard/ProfileCard.js +++ b/src/stable/components/ProfileCard/ProfileCard.js @@ -74,6 +74,8 @@ class ProfileCard extends HTMLElement { card.rel = 'noopener noreferrer'; } else { card.removeAttribute('href'); + card.removeAttribute('target'); + card.removeAttribute('rel'); } } } From f5e92a3cbc99922c9da0982cd7c49eb9cb81e7e6 Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Mon, 28 Apr 2025 13:09:35 -0400 Subject: [PATCH 31/43] Removed the default img for the updateImage function --- src/stable/components/ProfileCard/ProfileCard.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.js b/src/stable/components/ProfileCard/ProfileCard.js index 68aad92b..6bf559bf 100644 --- a/src/stable/components/ProfileCard/ProfileCard.js +++ b/src/stable/components/ProfileCard/ProfileCard.js @@ -61,7 +61,7 @@ class ProfileCard extends HTMLElement { _updateImage(src) { const img = this.shadowRoot.querySelector('.profile-image'); if (img) { - img.src = src || 'default-profile-image.jpg'; // Fallback image if src is invalid + img.src = src || ""; // Fallback image if src is invalid } } From c6abe6c2842f40abaa889d1fd2652bf0d5d84ba6 Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Mon, 28 Apr 2025 13:13:44 -0400 Subject: [PATCH 32/43] Fixed prettier issues in 1 file --- src/stable/components/ProfileCard/ProfileCard.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.js b/src/stable/components/ProfileCard/ProfileCard.js index 6bf559bf..c123632b 100644 --- a/src/stable/components/ProfileCard/ProfileCard.js +++ b/src/stable/components/ProfileCard/ProfileCard.js @@ -61,7 +61,7 @@ class ProfileCard extends HTMLElement { _updateImage(src) { const img = this.shadowRoot.querySelector('.profile-image'); if (img) { - img.src = src || ""; // Fallback image if src is invalid + img.src = src || ''; // Fallback if src is invalid } } From b2461d1a8073dea1f9f808720c3bc92e13eedc9c Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Mon, 28 Apr 2025 14:14:45 -0400 Subject: [PATCH 33/43] Added slot styles to the light-dom --- .../components/ProfileCard/ProfileCard.css | 16 ------- .../ProfileCard/ProfileCard.css.map | 2 +- .../components/ProfileCard/ProfileCard.scss | 25 +--------- src/stable/stories/profilecard.stories.js | 46 ++++++++++++++++--- 4 files changed, 42 insertions(+), 47 deletions(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.css b/src/stable/components/ProfileCard/ProfileCard.css index 6911ddb3..f668dd24 100644 --- a/src/stable/components/ProfileCard/ProfileCard.css +++ b/src/stable/components/ProfileCard/ProfileCard.css @@ -48,20 +48,4 @@ a.profile-card:hover { font-weight: 600; } -::slotted([slot='name']) { - font-size: 1.25em; - line-height: 100%; - letter-spacing: 0%; - font-weight: 600; - margin-right: 5px; -} - -::slotted([slot='title']) { - font-size: 1em; - line-height: 100%; - letter-spacing: 0%; - font-weight: 400; - margin-bottom: 5px; -} - /*# sourceMappingURL=ProfileCard.css.map */ diff --git a/src/stable/components/ProfileCard/ProfileCard.css.map b/src/stable/components/ProfileCard/ProfileCard.css.map index aeadbea9..5a358a02 100644 --- a/src/stable/components/ProfileCard/ProfileCard.css.map +++ b/src/stable/components/ProfileCard/ProfileCard.css.map @@ -1 +1 @@ -{"version":3,"sourceRoot":"","sources":["ProfileCard.scss"],"names":[],"mappings":"AAAA;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;AAEA;EAGE;EACA;;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA,YACE;;;AAIJ;EACE;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA","file":"ProfileCard.css"} \ No newline at end of file +{"version":3,"sourceRoot":"","sources":["ProfileCard.scss"],"names":[],"mappings":"AAAA;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;AAEA;EAGE;EACA;;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA,YACE;;;AAIJ;EACE;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;EACA;EACA","file":"ProfileCard.css"} \ No newline at end of file diff --git a/src/stable/components/ProfileCard/ProfileCard.scss b/src/stable/components/ProfileCard/ProfileCard.scss index 55e93390..536a21cc 100644 --- a/src/stable/components/ProfileCard/ProfileCard.scss +++ b/src/stable/components/ProfileCard/ProfileCard.scss @@ -45,27 +45,4 @@ a.profile-card { font-size: 1.25rem; line-height: 100%; font-weight: 600; -} - -::slotted([slot='name']) { - font-size: 1.25rem; - line-height: 100%; - letter-spacing: 0%; - font-weight: 600; - margin-right: 5px; -} - -::slotted([slot='title']) { - font-size: 1rem; - line-height: 100%; - letter-spacing: 0%; - font-weight: 400; - margin-bottom: 5px; -} - -// ::slotted([slot='title-secondary']) { -// font-size: 1rem; -// line-height: 100%; -// letter-spacing: 0%; -// font-weight: 400; -// } +} \ No newline at end of file diff --git a/src/stable/stories/profilecard.stories.js b/src/stable/stories/profilecard.stories.js index d3887aa5..7c23b153 100644 --- a/src/stable/stories/profilecard.stories.js +++ b/src/stable/stories/profilecard.stories.js @@ -15,10 +15,27 @@ export default { }; export const Default = (args) => html` + - ${args.name} - ${args.titlePrimary} - ${args.titleSecondary} + ${args.name} + ${args.titlePrimary} + ${args.titleSecondary} `; @@ -32,10 +49,27 @@ Default.args = { export const Test = { render: () => html` + - Jane Doe - Frontend Engineer - Frontend Developer + Jane Doe + Frontend Engineer + Frontend Developer `, From 524bcac93ecb90e667542d25d0cc19b9ce3b4467 Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Mon, 28 Apr 2025 14:16:24 -0400 Subject: [PATCH 34/43] Fixed prettier issues in 2 files --- .../components/ProfileCard/ProfileCard.scss | 2 +- src/stable/stories/profilecard.stories.js | 64 +++++++++---------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.scss b/src/stable/components/ProfileCard/ProfileCard.scss index 536a21cc..303adf22 100644 --- a/src/stable/components/ProfileCard/ProfileCard.scss +++ b/src/stable/components/ProfileCard/ProfileCard.scss @@ -45,4 +45,4 @@ a.profile-card { font-size: 1.25rem; line-height: 100%; font-weight: 600; -} \ No newline at end of file +} diff --git a/src/stable/stories/profilecard.stories.js b/src/stable/stories/profilecard.stories.js index 7c23b153..a4315d08 100644 --- a/src/stable/stories/profilecard.stories.js +++ b/src/stable/stories/profilecard.stories.js @@ -15,23 +15,23 @@ export default { }; export const Default = (args) => html` - + .profile-card-title { + font-size: 1rem; + line-height: 100%; + letter-spacing: 0%; + font-weight: 400; + margin-bottom: 5px; + } + ${args.name} ${args.titlePrimary} @@ -49,23 +49,23 @@ Default.args = { export const Test = { render: () => html` - + .profile-card-title { + font-size: 1rem; + line-height: 100%; + letter-spacing: 0%; + font-weight: 400; + margin-bottom: 5px; + } + Jane Doe Frontend Engineer From f8ac9c03f1257b02abde4737703d3460f7ae4ab4 Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Mon, 28 Apr 2025 15:14:13 -0400 Subject: [PATCH 35/43] Added chevron as Bootstrap SVG. Added slight transform on hover for chevron --- src/stable/components/ProfileCard/ProfileCard.css | 14 +++++++++++--- .../components/ProfileCard/ProfileCard.css.map | 2 +- src/stable/components/ProfileCard/ProfileCard.js | 2 +- .../components/ProfileCard/ProfileCard.scss | 15 ++++++++++++--- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.css b/src/stable/components/ProfileCard/ProfileCard.css index f668dd24..21b9c2c6 100644 --- a/src/stable/components/ProfileCard/ProfileCard.css +++ b/src/stable/components/ProfileCard/ProfileCard.css @@ -43,9 +43,17 @@ a.profile-card:hover { } .chevron { - font-size: 1.25em; - line-height: 100%; - font-weight: 600; + background-image: url('data:image/svg+xml,%3Csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20width=%2716%27%20height=%2716%27%20fill=%27currentColor%27%20class=%27bi%20bi-chevron-right%27%20viewBox=%270%200%2016%2016%27%3E%3Cpath%20fill-rule=%27evenodd%27%20d=%27M4.646%201.646a.5.5%200%200%201%20.708%200l6%206a.5.5%200%200%201%200%20.708l-6%206a.5.5%200%200%201-.708-.708L10.293%208%204.646%202.354a.5.5%200%200%201%200-.708%27/%3E%3C/svg%3E'); + display: inline-block; + width: 16px; + height: 16px; + background-size: contain; + background-repeat: no-repeat; + transition: transform 0.2s ease; +} + +.name-container:hover .chevron { + transform: translateX(4px); } /*# sourceMappingURL=ProfileCard.css.map */ diff --git a/src/stable/components/ProfileCard/ProfileCard.css.map b/src/stable/components/ProfileCard/ProfileCard.css.map index 5a358a02..254052d3 100644 --- a/src/stable/components/ProfileCard/ProfileCard.css.map +++ b/src/stable/components/ProfileCard/ProfileCard.css.map @@ -1 +1 @@ -{"version":3,"sourceRoot":"","sources":["ProfileCard.scss"],"names":[],"mappings":"AAAA;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;AAEA;EAGE;EACA;;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA,YACE;;;AAIJ;EACE;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;EACA;EACA","file":"ProfileCard.css"} \ No newline at end of file +{"version":3,"sourceRoot":"","sources":["ProfileCard.scss"],"names":[],"mappings":"AAAA;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;AAEA;EAGE;EACA;;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA,YACE;;;AAIJ;EACE;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE","file":"ProfileCard.css"} \ No newline at end of file diff --git a/src/stable/components/ProfileCard/ProfileCard.js b/src/stable/components/ProfileCard/ProfileCard.js index c123632b..7eae21fe 100644 --- a/src/stable/components/ProfileCard/ProfileCard.js +++ b/src/stable/components/ProfileCard/ProfileCard.js @@ -10,7 +10,7 @@ ${styles}
- +
diff --git a/src/stable/components/ProfileCard/ProfileCard.scss b/src/stable/components/ProfileCard/ProfileCard.scss index 303adf22..1f2d12ee 100644 --- a/src/stable/components/ProfileCard/ProfileCard.scss +++ b/src/stable/components/ProfileCard/ProfileCard.scss @@ -41,8 +41,17 @@ a.profile-card { align-items: center; margin-bottom: 5px; } + .chevron { - font-size: 1.25rem; - line-height: 100%; - font-weight: 600; + background-image: url('data:image/svg+xml,%3Csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20width=%2716%27%20height=%2716%27%20fill=%27currentColor%27%20class=%27bi%20bi-chevron-right%27%20viewBox=%270%200%2016%2016%27%3E%3Cpath%20fill-rule=%27evenodd%27%20d=%27M4.646%201.646a.5.5%200%200%201%20.708%200l6%206a.5.5%200%200%201%200%20.708l-6%206a.5.5%200%200%201-.708-.708L10.293%208%204.646%202.354a.5.5%200%200%201%200-.708%27/%3E%3C/svg%3E'); + display: inline-block; + width: 16px; + height: 16px; + background-size: contain; + background-repeat: no-repeat; + transition: transform 0.2s ease; +} + +.name-container:hover .chevron { + transform: translateX(4px); } From 48901ba6e43ce784bf5558cfe1289a96e4e2d70d Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Mon, 28 Apr 2025 15:24:21 -0400 Subject: [PATCH 36/43] Added alt attribute to component --- src/stable/components/ProfileCard/ProfileCard.js | 14 ++++++++++++-- src/stable/stories/profilecard.stories.js | 11 +++++++++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.js b/src/stable/components/ProfileCard/ProfileCard.js index 7eae21fe..21a5f2d5 100644 --- a/src/stable/components/ProfileCard/ProfileCard.js +++ b/src/stable/components/ProfileCard/ProfileCard.js @@ -27,10 +27,11 @@ class ProfileCard extends HTMLElement { // Internal properties this._href = this.getAttribute('href') || ''; this._src = this.getAttribute('src') || ''; + this._alt = this.getAttribute('alt') || 'Profile Image'; } static get observedAttributes() { - return ['src', 'href']; + return ['src', 'href', 'alt']; } get href() { @@ -41,6 +42,10 @@ class ProfileCard extends HTMLElement { return this._src; } + get alt() { + return this._alt; + } + attributeChangedCallback(name, oldValue, newValue) { if (name === 'src' && newValue !== oldValue) { this._src = newValue; @@ -51,6 +56,10 @@ class ProfileCard extends HTMLElement { this._href = newValue; this._updateLink(newValue); } + if (name === 'alt' && newValue !== oldValue) { + this._alt = newValue; + this._updateImage(); + } } connectedCallback() { @@ -61,7 +70,8 @@ class ProfileCard extends HTMLElement { _updateImage(src) { const img = this.shadowRoot.querySelector('.profile-image'); if (img) { - img.src = src || ''; // Fallback if src is invalid + img.src = src || ''; + img.alt = this._alt || 'Profile Image'; } } diff --git a/src/stable/stories/profilecard.stories.js b/src/stable/stories/profilecard.stories.js index a4315d08..0670dc58 100644 --- a/src/stable/stories/profilecard.stories.js +++ b/src/stable/stories/profilecard.stories.js @@ -7,6 +7,7 @@ export default { title: 'Components/ProfileCard', argTypes: { src: { control: 'text', name: 'Image Source' }, + alt: { control: 'text', name: 'Alt Text' }, name: { control: 'text', name: 'Name' }, titlePrimary: { control: 'text', name: 'Primary Title' }, titleSecondary: { control: 'text', name: 'Secondary Title' }, @@ -32,7 +33,7 @@ export const Default = (args) => html` margin-bottom: 5px; } - + ${args.name} ${args.titlePrimary} ${args.titleSecondary} @@ -41,6 +42,7 @@ export const Default = (args) => html` Default.args = { src: 'https://placehold.co/400', + alt: 'Photo of Jane Doe', name: 'Jane Doe', titlePrimary: 'Frontend Engineer', titleSecondary: 'Frontend Developer', @@ -66,7 +68,7 @@ export const Test = { margin-bottom: 5px; } - + Jane Doe Frontend Engineer Frontend Developer @@ -95,5 +97,10 @@ export const Test = { // Verify the target and rel attributes expect(link.getAttribute('target')).toBe('_blank'); expect(link.getAttribute('rel')).toBe('noopener noreferrer'); + + // ===== TEST 3: Image Alt Text Test ===== +const expectedAlt = profileCard.getAttribute('alt') || 'Profile Image'; +expect(img.alt).toBe(expectedAlt); + }, }; From 72abd05c4cf05de5e9a2e738b1416cd3ed067a01 Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Mon, 28 Apr 2025 15:25:50 -0400 Subject: [PATCH 37/43] Fixed prettier issues in 2 files --- src/stable/components/ProfileCard/ProfileCard.js | 2 +- src/stable/stories/profilecard.stories.js | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.js b/src/stable/components/ProfileCard/ProfileCard.js index 21a5f2d5..e3f88c79 100644 --- a/src/stable/components/ProfileCard/ProfileCard.js +++ b/src/stable/components/ProfileCard/ProfileCard.js @@ -70,7 +70,7 @@ class ProfileCard extends HTMLElement { _updateImage(src) { const img = this.shadowRoot.querySelector('.profile-image'); if (img) { - img.src = src || ''; + img.src = src || ''; img.alt = this._alt || 'Profile Image'; } } diff --git a/src/stable/stories/profilecard.stories.js b/src/stable/stories/profilecard.stories.js index 0670dc58..c845ed6a 100644 --- a/src/stable/stories/profilecard.stories.js +++ b/src/stable/stories/profilecard.stories.js @@ -68,7 +68,11 @@ export const Test = { margin-bottom: 5px; } - + Jane Doe Frontend Engineer Frontend Developer @@ -99,8 +103,7 @@ export const Test = { expect(link.getAttribute('rel')).toBe('noopener noreferrer'); // ===== TEST 3: Image Alt Text Test ===== -const expectedAlt = profileCard.getAttribute('alt') || 'Profile Image'; -expect(img.alt).toBe(expectedAlt); - + const expectedAlt = profileCard.getAttribute('alt') || 'Profile Image'; + expect(img.alt).toBe(expectedAlt); }, }; From 90528ac02ed52adf5d11c4c6a2693b83a2a71311 Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Mon, 28 Apr 2025 15:29:07 -0400 Subject: [PATCH 38/43] Updated the ProfileCard.mdx file --- src/stable/docs/ProfileCard.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stable/docs/ProfileCard.mdx b/src/stable/docs/ProfileCard.mdx index 8ec9a45a..5e76b082 100644 --- a/src/stable/docs/ProfileCard.mdx +++ b/src/stable/docs/ProfileCard.mdx @@ -53,7 +53,7 @@ Supported HTML attributes. If the attribute is reflected in a JS property, that From 1c0eb2db2e08c1bbf0b55831f2d26d147002d3b6 Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Mon, 28 Apr 2025 15:40:28 -0400 Subject: [PATCH 39/43] Exposed target and rel attributes --- .../components/ProfileCard/ProfileCard.js | 42 +++++++++++-------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.js b/src/stable/components/ProfileCard/ProfileCard.js index e3f88c79..2ad0220c 100644 --- a/src/stable/components/ProfileCard/ProfileCard.js +++ b/src/stable/components/ProfileCard/ProfileCard.js @@ -28,23 +28,20 @@ class ProfileCard extends HTMLElement { this._href = this.getAttribute('href') || ''; this._src = this.getAttribute('src') || ''; this._alt = this.getAttribute('alt') || 'Profile Image'; + this._target = this.getAttribute('target') || '_blank'; + this._rel = this.getAttribute('rel') || 'noopener noreferrer'; } static get observedAttributes() { - return ['src', 'href', 'alt']; + return ['src', 'href', 'alt', 'target', 'rel']; } - get href() { - return this._href; - } - - get src() { - return this._src; - } - get alt() { - return this._alt; - } + get href() { return this._href; } + get src() { return this._src; } + get alt() { return this._alt; } + get target() { return this._target; } + get rel() { return this._rel; } attributeChangedCallback(name, oldValue, newValue) { if (name === 'src' && newValue !== oldValue) { @@ -60,6 +57,15 @@ class ProfileCard extends HTMLElement { this._alt = newValue; this._updateImage(); } + if (name === 'target' && newValue !== oldValue) { + this._target = newValue; + this._updateLink(); + } + + if (name === 'rel' && newValue !== oldValue) { + this._rel = newValue; + this._updateLink(); + } } connectedCallback() { @@ -67,21 +73,21 @@ class ProfileCard extends HTMLElement { this._updateLink(this.href); } - _updateImage(src) { + _updateImage() { const img = this.shadowRoot.querySelector('.profile-image'); if (img) { - img.src = src || ''; + img.src = this._src || ''; img.alt = this._alt || 'Profile Image'; } } - _updateLink(newValue) { + _updateLink() { const card = this.shadowRoot.querySelector('.profile-card'); if (card) { - if (newValue) { - card.href = newValue; - card.target = '_blank'; - card.rel = 'noopener noreferrer'; + if (this._href) { + card.href = this._href; + card.target = this._target || '_blank'; + card.rel = this._rel || 'noopener noreferrer'; } else { card.removeAttribute('href'); card.removeAttribute('target'); From c2a6c61e6987884766d5469bf18b90c3e310ffb6 Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Mon, 28 Apr 2025 15:41:16 -0400 Subject: [PATCH 40/43] Fixed prettier issues in 1 file --- .../components/ProfileCard/ProfileCard.js | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.js b/src/stable/components/ProfileCard/ProfileCard.js index 2ad0220c..b584a7da 100644 --- a/src/stable/components/ProfileCard/ProfileCard.js +++ b/src/stable/components/ProfileCard/ProfileCard.js @@ -28,20 +28,29 @@ class ProfileCard extends HTMLElement { this._href = this.getAttribute('href') || ''; this._src = this.getAttribute('src') || ''; this._alt = this.getAttribute('alt') || 'Profile Image'; - this._target = this.getAttribute('target') || '_blank'; - this._rel = this.getAttribute('rel') || 'noopener noreferrer'; + this._target = this.getAttribute('target') || '_blank'; + this._rel = this.getAttribute('rel') || 'noopener noreferrer'; } static get observedAttributes() { return ['src', 'href', 'alt', 'target', 'rel']; } - - get href() { return this._href; } - get src() { return this._src; } - get alt() { return this._alt; } - get target() { return this._target; } - get rel() { return this._rel; } + get href() { + return this._href; + } + get src() { + return this._src; + } + get alt() { + return this._alt; + } + get target() { + return this._target; + } + get rel() { + return this._rel; + } attributeChangedCallback(name, oldValue, newValue) { if (name === 'src' && newValue !== oldValue) { @@ -86,8 +95,8 @@ class ProfileCard extends HTMLElement { if (card) { if (this._href) { card.href = this._href; - card.target = this._target || '_blank'; - card.rel = this._rel || 'noopener noreferrer'; + card.target = this._target || '_blank'; + card.rel = this._rel || 'noopener noreferrer'; } else { card.removeAttribute('href'); card.removeAttribute('target'); From 7de41199c1b89ef724b1e5a147f02b14cc7118e7 Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Tue, 13 May 2025 08:19:15 -0400 Subject: [PATCH 41/43] Removed second name slot field --- src/stable/components/ProfileCard/ProfileCard.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.js b/src/stable/components/ProfileCard/ProfileCard.js index b584a7da..566a8a4b 100644 --- a/src/stable/components/ProfileCard/ProfileCard.js +++ b/src/stable/components/ProfileCard/ProfileCard.js @@ -13,7 +13,6 @@ ${styles}
- `; From bcb40ec35a6780d635e4e117edf828faffa2c157 Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Tue, 13 May 2025 08:21:24 -0400 Subject: [PATCH 42/43] Removed all fallback values --- src/stable/components/ProfileCard/ProfileCard.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.js b/src/stable/components/ProfileCard/ProfileCard.js index 566a8a4b..4005835e 100644 --- a/src/stable/components/ProfileCard/ProfileCard.js +++ b/src/stable/components/ProfileCard/ProfileCard.js @@ -24,11 +24,11 @@ class ProfileCard extends HTMLElement { shadow.appendChild(template.content.cloneNode(true)); // Internal properties - this._href = this.getAttribute('href') || ''; - this._src = this.getAttribute('src') || ''; - this._alt = this.getAttribute('alt') || 'Profile Image'; - this._target = this.getAttribute('target') || '_blank'; - this._rel = this.getAttribute('rel') || 'noopener noreferrer'; + this._href = this.getAttribute('href'); + this._src = this.getAttribute('src'); + this._alt = this.getAttribute('alt'); + this._target = this.getAttribute('target'); + this._rel = this.getAttribute('rel'); } static get observedAttributes() { From 6daf916d2b57d1b9e2e74e2cfc20e5e0964b6b9d Mon Sep 17 00:00:00 2001 From: Shakira Reid-Thomas Date: Tue, 13 May 2025 08:27:00 -0400 Subject: [PATCH 43/43] Updated scss so that chevron animation happens when on any part of the link --- src/stable/components/ProfileCard/ProfileCard.css | 2 +- src/stable/components/ProfileCard/ProfileCard.scss | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/stable/components/ProfileCard/ProfileCard.css b/src/stable/components/ProfileCard/ProfileCard.css index 21b9c2c6..12ce7562 100644 --- a/src/stable/components/ProfileCard/ProfileCard.css +++ b/src/stable/components/ProfileCard/ProfileCard.css @@ -52,7 +52,7 @@ a.profile-card:hover { transition: transform 0.2s ease; } -.name-container:hover .chevron { +.profile-card:hover .chevron { transform: translateX(4px); } diff --git a/src/stable/components/ProfileCard/ProfileCard.scss b/src/stable/components/ProfileCard/ProfileCard.scss index 1f2d12ee..8fbf6601 100644 --- a/src/stable/components/ProfileCard/ProfileCard.scss +++ b/src/stable/components/ProfileCard/ProfileCard.scss @@ -52,6 +52,6 @@ a.profile-card { transition: transform 0.2s ease; } -.name-container:hover .chevron { +.profile-card:hover .chevron { transform: translateX(4px); }