diff --git a/src/stable/components/ProfileCard/ProfileCard.css b/src/stable/components/ProfileCard/ProfileCard.css
new file mode 100644
index 00000000..12ce7562
--- /dev/null
+++ b/src/stable/components/ProfileCard/ProfileCard.css
@@ -0,0 +1,59 @@
+.profile-card {
+ display: flex;
+ align-items: center;
+ width: 100%;
+ max-width: 100%;
+ gap: 1.25em;
+ 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%;
+ 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);
+}
+
+/*# 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..254052d3
--- /dev/null
+++ b/src/stable/components/ProfileCard/ProfileCard.css.map
@@ -0,0 +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;;;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
new file mode 100644
index 00000000..4005835e
--- /dev/null
+++ b/src/stable/components/ProfileCard/ProfileCard.js
@@ -0,0 +1,108 @@
+import styles from '!!raw-loader!./ProfileCard.css';
+
+const template = document.createElement('template');
+template.innerHTML = `
+
+
+
+
+
+`;
+
+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 };
diff --git a/src/stable/components/ProfileCard/ProfileCard.scss b/src/stable/components/ProfileCard/ProfileCard.scss
new file mode 100644
index 00000000..8fbf6601
--- /dev/null
+++ b/src/stable/components/ProfileCard/ProfileCard.scss
@@ -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);
+}
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..069f785e
--- /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);
diff --git a/src/stable/docs/ProfileCard.mdx b/src/stable/docs/ProfileCard.mdx
new file mode 100644
index 00000000..5e76b082
--- /dev/null
+++ b/src/stable/docs/ProfileCard.mdx
@@ -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
+
+
+
+# Profile Card
+
+
+ Profile Cards are components used to display a user's profile information.
+
+
+## Usage
+
+
+
+
+
+# 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
+
+- **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.
diff --git a/src/stable/stories/profilecard.stories.js b/src/stable/stories/profilecard.stories.js
new file mode 100644
index 00000000..c845ed6a
--- /dev/null
+++ b/src/stable/stories/profilecard.stories.js
@@ -0,0 +1,109 @@
+import { html } from 'lit-html';
+import '../components/ProfileCard/cod-profile-card';
+import { expect } from '@storybook/test';
+
+export default {
+ tags: ['stable'],
+ 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' },
+ href: { control: 'text', name: 'Profile Link' },
+ },
+};
+
+export const Default = (args) => html`
+
+
+ ${args.name}
+ ${args.titlePrimary}
+ ${args.titleSecondary}
+
+`;
+
+Default.args = {
+ src: 'https://placehold.co/400',
+ alt: 'Photo of Jane Doe',
+ name: 'Jane Doe',
+ titlePrimary: 'Frontend Engineer',
+ titleSecondary: 'Frontend Developer',
+ href: 'https://example.com',
+};
+
+export const Test = {
+ 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: 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 3: Image Alt Text Test =====
+ const expectedAlt = profileCard.getAttribute('alt') || 'Profile Image';
+ expect(img.alt).toBe(expectedAlt);
+ },
+};