Detent web components
By Shane Logsdon

Media & effects

Profile Card

Implemented

Dark social profile card with painted blue cover art

detent-profile-card

Port status
Catalog status
implemented
Origin
upstream
Phase
2
Wave
phase-2-cards
Group
Media & effects

4.6 KB gzip for the class module

Variants

Tab reaches the action button first, then the website link; both draw a visible focus ring and the link opens in a new tab. With reduced motion the press scale and the avatar lift are skipped. The narrow layout collapses the cover and avatar under 600px.

Recorded states

  • focus-visible recorded state; no setter
  • disabled recorded state; no setter
  • collapsed recorded state; no setter
  • reduced motion recorded state; no setter

Usage

Import

import '/components/profile-card/define.js';

// or register it yourself
import { DetentProfileCard } from '/components/profile-card/profile-card.js';

Attributes

  • action-label
  • description
  • followers
  • name
  • posts
  • username
  • website

Properties

  • name
  • username
  • description
  • followers
  • posts
  • website
  • actionLabel
  • onAction

Slots

No slots are recorded for this component.

Events

  • detent-action — {}

Example

Runnable example: site/examples/profile-card.ts. The snippet below is generated from the catalogued attributes.

<detent-profile-card
  action-label="Follow"
  description="Building Detent. Engineer."
  followers="200K"
  name="Suraj"
  posts="72"
  username="@surajmaurya_m"
  website="easyui.site"
></detent-profile-card>

Property-only values

const element = document.querySelector('detent-profile-card');
if (element !== null) {
  // onAction: () => void
  element.onAction = () => {};
}

Source

The pinned upstream source for this row:

  • src/components/ui/ProfileCard.tsx sha256 4a1632683fb8…

Native files

The native module and its artifacts:

  • src/components/profile-card/profile-card.ts
  • src/components/profile-card/styles.css
  • src/components/profile-card/define.ts
  • docs/components/profile-card.md
  • site/examples/profile-card.ts
  • tests/browser/profile-card.spec.ts
  • evidence/components/profile-card.md

API

Boolean attributes follow HTML presence semantics: present means true, absent means false, and disabled="false" still means disabled.

Attributes

Attributes
AttributePropertyTypeDefaultNotes
action-labelactionLabelstring'Follow'Kebab-case attribute; camelCase property.
descriptiondescriptionstring'Building Detent. Engineer.'Kebab-case attribute; camelCase property.
followersfollowersstring'200K'Kebab-case attribute; camelCase property.
namenamestring'Suraj'Kebab-case attribute; camelCase property.
postspostsstring'72'Kebab-case attribute; camelCase property.
usernameusernamestring'@surajmaurya_m'Kebab-case attribute; camelCase property.
websitewebsitestring'easyui.site'Kebab-case attribute; camelCase property.

Properties

Properties
PropertyTypeDefaultNotes
namestring'Suraj'Property-only: assign from script; not accepted as an attribute.
usernamestring'@surajmaurya_m'Property-only: assign from script; not accepted as an attribute.
descriptionstring'Building Detent. Engineer.'Property-only: assign from script; not accepted as an attribute.
followersstring'200K'Property-only: assign from script; not accepted as an attribute.
postsstring'72'Property-only: assign from script; not accepted as an attribute.
websitestring'easyui.site'Property-only: assign from script; not accepted as an attribute.
actionLabelstring'Follow'Property-only: assign from script; not accepted as an attribute.
onAction() => voidundefinedProperty-only: assign from script; not accepted as an attribute.

Events

Events
EventUpstream propPayload typeNotes
detent-actiononAction() => voidComposed, bubbles; fires only for a user action.

Slots

No slots are recorded for this component.

CSS customisation

  • `className` prop is replaced by documented CSS parts/custom properties; no Tailwind in consumers.
  • React callback props become typed composed CustomEvents; programmatic state assignment emits none.
  • Framer Motion springs/AnimatePresence ported to CSS transitions, WAAPI or the shared rAF spring helper.
  • React state/hooks replaced by element-owned state with pre-upgrade property preservation.
  • The upstream secondary "X (Twitter)" button (no handler, no href, no state) is not ported: a dead control in the tab order is fake interactivity.
  • `disabled` is not implemented because no such upstream prop exists; `collapsed` is the sub-600px responsive layout.
  • The palette derives from --detent-color-* tokens instead of hard-coded dark Tailwind colours (hex fallbacks reproduce upstream).
  • Outbound `href` is normalised: absolute kept, a bare domain gets https://, executable schemes are refused with a warning and an inert link (PC-11.3).
  • Framer whileTap becomes CSS :active 0.97 and the avatar hover lift becomes CSS.
  • Default demo copy and labels use Detent branding instead of EasyUI (pre-release rebrand).
  • Upstream tagline says dark; the native card follows the Detent theme (light by default).

What it does

A painted profile card: a gradient cover with a single action button, and a detail panel with avatar, verified name, handle, bio, follower/post counts and an outbound website link.

Upstream behaviour
  • Painted blue cover-art surface built from layered radial / linear gradients — no image assets required
  • Spring-tap response on the primary action button (0.97 scale) via framer-motion
  • Avatar and outbound link are keyboard-focusable with visible focus rings
  • Outbound link uses rel="noreferrer noopener" for safe new-tab behaviour
  • Responsive: cover height, padding, avatar size, and type scale all collapse cleanly under 600px
  • Decorative artwork and icons are aria-hidden; the section semantics are conveyed by the visible name and labels
  • Respects prefers-reduced-motion: spring tap is skipped entirely on the action button
Differences from upstream
  • `className` prop is replaced by documented CSS parts/custom properties; no Tailwind in consumers.
  • React callback props become typed composed CustomEvents; programmatic state assignment emits none.
  • Framer Motion springs/AnimatePresence ported to CSS transitions, WAAPI or the shared rAF spring helper.
  • React state/hooks replaced by element-owned state with pre-upgrade property preservation.
  • The upstream secondary "X (Twitter)" button (no handler, no href, no state) is not ported: a dead control in the tab order is fake interactivity.
  • `disabled` is not implemented because no such upstream prop exists; `collapsed` is the sub-600px responsive layout.
  • The palette derives from --detent-color-* tokens instead of hard-coded dark Tailwind colours (hex fallbacks reproduce upstream).
  • Outbound `href` is normalised: absolute kept, a bare domain gets https://, executable schemes are refused with a warning and an inert link (PC-11.3).
  • Framer whileTap becomes CSS :active 0.97 and the avatar hover lift becomes CSS.
  • Default demo copy and labels use Detent branding instead of EasyUI (pre-release rebrand).
  • Upstream tagline says dark; the native card follows the Detent theme (light by default).
Previous: Product Tour Next: Pull to Refresh

Docs

Components

Project