Row
A mark, the title with a badge and the time on one line, one muted line under it. The whole row is the link.
openvibe-shared/kitJSON
Build it
kit.list([kit.row({ href: '/@goosely', mark: kit.mark({ name: 'goosely' }), title: 'goosely', badge: kit.badge('live', 'live'), meta: '2 h', sub: 'Seattle at night, chat picks the route' })])Props
rel- string?
sub- string?
href- any?
mark- string?
meta- string?
attrs- any?
badge- string?
title- string?
trail- string?
unread- number?
metaIso- string?
subHtml- any?
titleHtml- any?
Anatomy
- marka picture, or up to two letters on a colour from the name; size size.avatar
- titlecolor color.text.primary; weight type.weight.bold
- metathe time, on the title's line; color color.text.muted; size type.size.meta
- subone line, cut with …; color color.text.muted; size type.size.meta
- traila count, a switch or a button
Behaviour and access
- Keyboard
- Standard focus order
- Outside tap
- Leaves it open
- Scroll
- The page still scrolls
- Reduced motion
- Remove movement; keep the state change.
- Name
- its title and sub-line
- Target
- the row, at least 56 px tall
- Focus
- Enter opens it
States
- default
- hover
- pressed
- focused
- disabled
Tokens
size.avatarcolor.text.primarytype.weight.boldcolor.text.mutedtype.size.meta
Android · Jetpack Compose
Row
@Composable fun OvRow(title: String, onOpen: (() -> Unit)? = null, sub: String? = null, meta: String? = null, mark: (@Composable () -> Unit)? = null, trail: (@Composable () -> Unit)? = null) { ListItem( headlineContent = { Text(title, fontWeight = FontWeight.Bold, maxLines = 1, overflow = TextOverflow.Ellipsis) }, supportingContent = sub?.let { { Text(it, maxLines = 1, overflow = TextOverflow.Ellipsis, fontSize = OvScale.TypeSizeMeta) } }, leadingContent = mark, trailingContent = trail ?: meta?.let { { Text(it, fontSize = OvScale.TypeSizeMeta) } }, modifier = (if (onOpen != null) Modifier.clickable(onClick = onOpen) else Modifier).heightIn(min = 56.dp), ) }
iOS · SwiftUI
struct OvRow: View { let title: String var sub: String? = nil var meta: String? = nil var body: some View { HStack(alignment: .firstTextBaseline) { VStack(alignment: .leading, spacing: 2) { Text(title).fontWeight(.bold).lineLimit(1) if let sub { Text(sub).font(.system(size: OvScale.typeSizeMeta)).foregroundStyle(OvTokens.colorTextMuted).lineLimit(1) } } Spacer() if let meta { Text(meta).font(.system(size: OvScale.typeSizeMeta)).foregroundStyle(OvTokens.colorTextMuted) } } .frame(minHeight: 56) .accessibilityElement(children: .combine) } }
Markup
Default
<ul class="ovk-list"><li class="ovk-row"><a href="/@goosely"><span class="ovk-mark" style="--ovk-hue:350" aria-hidden="true">GO</span><span class="ovk-row-main"><span class="ovk-row-top"><strong>goosely</strong><span class="ovk-badge ovk-badge--live">live</span><span class="ovk-row-meta">2 h</span></span><span class="ovk-row-sub"><span>Seattle at night, chat picks the route</span></span></span></a></li></ul>