Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
d4a1704
Initial set up for ProfileCard component
sreidthomas Mar 25, 2025
c104eea
Fixed prettier issues in 3 files
sreidthomas Mar 25, 2025
eb6cd79
Created full profile-card component with completed javascript
sreidthomas Mar 26, 2025
3f31755
Fixed prettier issues in 1 file by removing the console.warn
sreidthomas Mar 26, 2025
0745bad
Added scss/css for profilecard
sreidthomas Mar 27, 2025
f320697
Fixed prettier issues in 2 files
sreidthomas Mar 27, 2025
d43edd2
Changed object fit to cover and pixels to rems
sreidthomas Mar 27, 2025
1bc632b
Fixed prettier issues in 1 file
sreidthomas Mar 27, 2025
3ce7e17
Added link-href as an attribute and the ability to click the profile …
sreidthomas Apr 3, 2025
9dc03b6
Fixed prettier issues in 2 files
sreidthomas Apr 3, 2025
cbe49d1
Removed text decoration from name and titles
sreidthomas Apr 8, 2025
dfd4343
Merge branch 'dev' into feature.issue.294
sreidthomas Apr 9, 2025
cfeabd5
Added documentation for Profile Card, updated attribute names for Pro…
sreidthomas Apr 9, 2025
9e551a2
Updated ProfileCard.js functions to work better with storybook tests.…
sreidthomas Apr 11, 2025
e9dd8d3
Fixed prettier issues in 3 files and removed unused variable in stori…
sreidthomas Apr 11, 2025
aa41b70
Changed reflect status in documentation
sreidthomas Apr 11, 2025
df34cea
Added Reflective JS properties for attributes
sreidthomas Apr 11, 2025
b17cadb
Fixed prettier issues in 1 file
sreidthomas Apr 15, 2025
1e93d2f
Removed duplicate cod-gov-banner.js file
sreidthomas Apr 17, 2025
0daceaa
Removed validate slot methods and sanity checks
sreidthomas Apr 17, 2025
aac6062
Removed validate slot test from stories file
sreidthomas Apr 17, 2025
b7394d3
Removed unused validationError function
sreidthomas Apr 17, 2025
519f948
Added margin to the bottom of profile card text and removed blue colo…
sreidthomas Apr 17, 2025
93527aa
Removed call to validateSlots function from connectedcallback, remove…
sreidthomas Apr 17, 2025
224bdee
Added drop shadow to profile card image, removed parameter that allow…
sreidthomas Apr 17, 2025
98741f1
Updated documentation to include Usage section
sreidthomas Apr 17, 2025
907e8ab
Fixed prettier issues in 1 file
sreidthomas Apr 17, 2025
402e0f6
Fixed Reflective JS issues
sreidthomas Apr 17, 2025
21b5bd9
Fixed prettier issues in 1 file
sreidthomas Apr 17, 2025
4281523
Updated slots for primary and secondary fields in multiple files
sreidthomas Apr 28, 2025
4924f26
Updated if/else for updateLink function
sreidthomas Apr 28, 2025
f5e92a3
Removed the default img for the updateImage function
sreidthomas Apr 28, 2025
c6abe6c
Fixed prettier issues in 1 file
sreidthomas Apr 28, 2025
b2461d1
Added slot styles to the light-dom
sreidthomas Apr 28, 2025
524bcac
Fixed prettier issues in 2 files
sreidthomas Apr 28, 2025
f8ac9c0
Added chevron as Bootstrap SVG. Added slight transform on hover for c…
sreidthomas Apr 28, 2025
48901ba
Added alt attribute to component
sreidthomas Apr 28, 2025
72abd05
Fixed prettier issues in 2 files
sreidthomas Apr 28, 2025
90528ac
Updated the ProfileCard.mdx file
sreidthomas Apr 28, 2025
1c0eb2d
Exposed target and rel attributes
sreidthomas Apr 28, 2025
c2a6c61
Fixed prettier issues in 1 file
sreidthomas Apr 28, 2025
7de4119
Removed second name slot field
sreidthomas May 13, 2025
bcb40ec
Removed all fallback values
sreidthomas May 13, 2025
6daf916
Updated scss so that chevron animation happens when on any part of th…
sreidthomas May 13, 2025
8d2fe0a
Merge branch 'dev' into feature.issue.294
sreidthomas May 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions src/stable/components/ProfileCard/ProfileCard.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/stable/components/ProfileCard/ProfileCard.css.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

108 changes: 108 additions & 0 deletions src/stable/components/ProfileCard/ProfileCard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import styles from '!!raw-loader!./ProfileCard.css';

const template = document.createElement('template');
template.innerHTML = `
<style>
${styles}
</style>
<a class="profile-card">
<img class="profile-image" alt="Profile Image">
<div class="profile-details">
<div class="name-container">
<slot name="name"></slot>
<span class="chevron"></span>
</div>
<slot name="title"></slot>
</div>
</a>
`;

class ProfileCard extends HTMLElement {
constructor() {
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');
this._alt = this.getAttribute('alt');
this._target = this.getAttribute('target');
this._rel = this.getAttribute('rel');
}

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;
}

attributeChangedCallback(name, oldValue, newValue) {
if (name === 'src' && newValue !== oldValue) {
this._src = newValue;
this._updateImage(newValue);
}

if (name === 'href' && newValue !== oldValue) {
this._href = newValue;
this._updateLink(newValue);
}
if (name === 'alt' && newValue !== oldValue) {
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() {
this._updateImage(this.src);
this._updateLink(this.href);
}

_updateImage() {
const img = this.shadowRoot.querySelector('.profile-image');
if (img) {
img.src = this._src || '';
img.alt = this._alt || 'Profile Image';
}
}

_updateLink() {
const card = this.shadowRoot.querySelector('.profile-card');
if (card) {
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');
card.removeAttribute('rel');
}
}
}
}

export { ProfileCard as default };
57 changes: 57 additions & 0 deletions src/stable/components/ProfileCard/ProfileCard.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
.profile-card {
display: flex;
align-items: center;
width: 100%;
max-width: 100%;
gap: 1.25rem;
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%;
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 {
display: flex;
flex-direction: column;
flex-grow: 1;
min-width: 0;
}
.name-container {
display: flex;
align-items: center;
margin-bottom: 5px;
}

.chevron {
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;
}

.profile-card:hover .chevron {
transform: translateX(4px);
}
2 changes: 2 additions & 0 deletions src/stable/components/ProfileCard/cod-profile-card.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import ProfileCard from './ProfileCard';
customElements.define('cod-profile-card', ProfileCard);
92 changes: 92 additions & 0 deletions src/stable/docs/ProfileCard.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import {
Meta,
Canvas,
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

<Meta of={ProfileCardStories} />

# Profile Card

<div className="component-summary">
Profile Cards are components used to display a user's profile information.
</div>

## Usage

<Canvas of={ProfileCardStories.Default} />

<Controls of={ProfileCardStories.Default} />

# Examples

### Default

<Description of={ProfileCardStories.Default} />
<Story of={ProfileCardStories.Default} inline={true} />
<Source of={ProfileCardStories.Default} />

## Slots

<doc-slots-table
data={JSON.stringify([
{"name": "name", "description": "This slot is used to display the person's name in the profile card."},
{"name": "Primary Title", "description": "This slot contains the person's primary title, like their job position or designation." },
{"name": "Secondary Title", "description": "This slot contains additional information about the person, such as a secondary job title, a department name, or an affiliation."}
])}>
</doc-slots-table>

## 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.

<doc-js-properties-table
data={JSON.stringify([
{"name": "href", "description": "A link to the page or site containing the person's information. See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#href", "type": "string", "default": "-", "reflects": false},
{"name": "src", "description": "The URL to an image asset representing the person's profile photo. See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#attr-src", "type": "string", "default": "-", "reflects": false}
])}>
</doc-js-properties-table>

## Events

<doc-events-table
data={JSON.stringify([])}>
</doc-events-table>

## Methods

<doc-methods-table
data={JSON.stringify([])}>
</doc-methods-table>

## Custom CSS Properties

<doc-css-custom-properties-table
data={JSON.stringify([])}>
</doc-css-custom-properties-table>

## CSS Parts

<doc-css-parts-table
data={JSON.stringify([])}>
</doc-css-parts-table>

## Dependencies

<doc-dependencies-list data={JSON.stringify([])}></doc-dependencies-list>

## Accessibility

- **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.
Loading
Loading