@htmlbricks/hb-contact-card
v0.76.5
Published
A comprehensive contact card component that displays personal, contact, company, and social media information in a Bulma-styled card layout. Uses a single data object with structured arrays for phone numbers, addresses, and social media profiles. Features
Readme
hb-contact-card
Category: content · Tags: content, contact
The contact card web component renders a Bulma-styled card with a header (avatar or placeholder, name, optional title, collapse control, and optional actions menu) and a body of collapsible sections: company, contact details (email, phone, website), addresses, social links, and notes. Data is supplied as a single JSON object. Optional Bootstrap Icons are loaded for affordances.
Peer dependency (runtime): when actions_list is non-empty, the component registers and embeds hb-dropdown-simple for the overflow menu.
Custom element
<hb-contact-card></hb-contact-card>HTML attributes (snake_case, strings)
From HTML, complex values must be JSON strings on attributes (objects and arrays are not passed as live JS references).
| Attribute | Required | Description |
|-----------|----------|-------------|
| data | Yes | JSON string of the contact payload (see Contact data below). Parsed in the component; invalid JSON is logged and leaves internal data empty until fixed. |
| id | No | String passed through on custom event detail.id. |
| style | No | Inline style string applied on the root card wrapper. |
| actions_list | No | JSON string array of menu items for hb-dropdown-simple (key, label, optional badge, group, linkHref). If empty or omitted, the menu is not shown. |
| i18nlang | No | Language for built-in labels (e.g. section titles). Supported in authoring metadata: en, it. |
| show_header_collapse_button | No | yes (default) or no: show or hide the header button that collapses the entire card body. |
| start_collapsed | No | no (default) or yes: render the card body collapsed on first paint. |
Boolean strings: only the attributes above use yes / no. Inside the JSON data object, use normal JSON booleans for fields like clickable (true / false).
Contact data (data JSON)
The inner object is the contact record. Display name is computed as fullName, or firstName + lastName, or the literal "Unknown Contact".
| Field | Type | Description |
|-------|------|-------------|
| firstName, lastName | string (optional) | Used for display name when fullName is absent. |
| fullName | string (optional) | Preferred single-field name. |
| title | string (optional) | Subtitle under the name in the header. |
| emails | array (optional) | Items: address, type (home | work | personal | other), optional label. Rendered as mailto: links. |
| phones | array (optional) | Items: number, type (home | work | mobile | fax | other), optional label. Rendered as tel: links. |
| website | string (optional) | Opened in a new tab (rel="noopener noreferrer"). |
| addresses | array (optional) | Items: type (home | work | billing | shipping | other), optional label, street, city, state, postalCode, country. Rows are keyboard-activatable and dispatch addressClick. |
| company, department, jobTitle | string (optional) | Shown in the Company section if any is present. |
| notes | string (optional) | Notes section. |
| avatar | string (optional) | Image URL; if missing or blank, a gradient placeholder with a person icon is shown. |
| latitude, longitude | number (optional) | Accepted in typings; not rendered by the current template. |
| socialMedia | array (optional) | Items: platform, url, optional username. Platforms include linkedin, twitter, facebook, instagram, github, youtube, tiktok, signal, whatsapp, telegram, other. If url is empty but username is set, the component fills url using known per-platform patterns (e.g. wa.me for WhatsApp, t.me for Telegram). |
| clickable | boolean (optional) | When true, a full-card hit target dispatches contactClick on activation and the card gets hover / focus-visible affordances. |
Actions menu (actions_list)
Each entry is passed through to hb-dropdown-simple as its list prop (stringified JSON). Typical fields:
| Field | Description |
|-------|-------------|
| key | Stable id for the action (consumer-defined). |
| label | Visible label. |
| badge | Optional number shown on the item. |
| group | Optional grouping label in the menu. |
| linkHref | Optional navigation target for the item. |
Selecting items is handled inside hb-dropdown-simple; this card does not map menu key values to contactEdit / contactDelete automatically—you can coordinate behavior in your host app if needed.
Behavior
- Card collapse: The header chevron toggles the whole body (max-height / opacity animation). Toggling dispatches
collapseChangewith the new collapsed flag. - Section collapse: Company, Contact, Address, Social, and Notes each have their own expand/collapse; these are internal only (no custom event).
- Clickable card: With
clickable: true, a transparent button covers the card (z-indexbelow header actions). Header controls, section toggles, links, and the actions dropdown sit above it and stop propagation where appropriate. - Links: Email, phone, and website use normal anchors; click handlers still run to emit the corresponding events (in addition to default navigation where applicable).
- Social: Icon buttons link to
resolvedSocialMediaURLs (built fromurlor fromusername+platform).
Custom events
Listen with addEventListener on the element. All payloads include id from the element’s id attribute (string).
| Event | detail | When it fires |
|-------|----------|----------------|
| contactClick | { id, contact } | contact is the parsed inner contact object (same shape as data without the outer attribute wrapper). Fires when clickable is true and the card hit area is activated. |
| phoneClick | { id, phone } | Phone row link clicked. |
| emailClick | { id, email } | Email row link clicked. |
| websiteClick | { id, website } | Website link clicked. |
| socialClick | { id, social } | Social icon link clicked. |
| addressClick | { id, address } | Address row clicked or activated with Enter/Space. |
| collapseChange | { id, collapsed } | Card body toggled via the header control. |
| contactEdit | { id, contact } | Typings and dispatch helpers exist for an edit flow; the default markup does not wire this event to a control. |
| contactDelete | { id, contact } | Same as contactEdit for delete. |
Styling: CSS custom properties (:host)
Bulma-related tokens are documented in extra/docs.ts / styleSetup. The card and rows use:
| Variable | Role |
|----------|------|
| --bulma-border | Card border and separators. |
| --bulma-radius | Card corners, rows, section chrome. |
| --bulma-shadow | Default elevation. |
| --bulma-card-background-color | Card surface (falls back to --bulma-body-background). |
| --bulma-card-shadow | Stronger shadow on hover when the card is clickable. |
| --bulma-body-background | Fallback surface. |
| --bulma-link | Links, focus rings, accents. |
| --bulma-link-invert | Icon/text on social pills when hovered (solid link background). |
| --bulma-info | Second stop for avatar placeholder gradient. |
| --bulma-scheme-main-bis | Header strip and default social pill background. |
| --bulma-white | Placeholder icon color. |
| --bulma-text, --bulma-text-strong, --bulma-text-weak | Body, headings, muted labels. |
| --bulma-background-lighter | Hover on section headers and address rows. |
| --bulma-radius-rounded | Circular avatar and social pills. |
Theme setup follows Bulma 1.x CSS variables on :host (see project styles/bulma.scss).
Styling: ::part names
These names are published in component metadata (styleSetup.parts) for host-level styling:
| Part | Intended target |
|------|-----------------|
| card | Root card container. |
| header | Header strip (avatar, title, controls). |
| body | Scrollable / collapsible main content. |
| avatar | Avatar image or placeholder. |
| actions | Actions dropdown region. |
Slots
None.
Example: minimal host page
<hb-contact-card
id="c1"
i18nlang="en"
data='{"fullName":"Alex Doe","title":"Engineer","emails":[{"address":"[email protected]","type":"work"}],"phones":[{"number":"+15551234567","type":"mobile"}],"clickable":true}'
actions_list='[{"key":"edit","label":"Edit","group":"Actions"},{"key":"email","label":"Send email","group":"Actions"}]'
></hb-contact-card>
<script type="module">
const el = document.querySelector("hb-contact-card");
el.addEventListener("contactClick", (e) => {
console.log("contact", e.detail.contact);
});
el.addEventListener("collapseChange", (e) => {
console.log("collapsed", e.detail.collapsed);
});
</script>Example: collapsed by default, no menu
<hb-contact-card
id="c2"
start_collapsed="yes"
show_header_collapse_button="yes"
data='{"fullName":"Jamie Lee","company":"Acme","jobTitle":"CEO","clickable":false}'
></hb-contact-card>TypeScript authoring
For props and nested types (PhoneNumber, EmailAddress, Address, SocialMedia, ContactData, Component, Events), see types/webcomponent.type.d.ts next to this package.
Build note (monorepo)
From the builder folder, a single package build:
npm run build:wc -- contact-card