@teamblind-chorus/ui 1.0.1 โ 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agents/AGENTS.md +4 -6
- package/agents/DESIGN.md +2 -0
- package/agents/LOVABLE.md +167 -373
- package/agents/anti-patterns.md +2 -2
- package/agents/catalog.md +7 -3
- package/agents/components/avatar-rail/avatar-rail.md +2 -0
- package/agents/components/badge/badge.md +2 -0
- package/agents/components/badge/role.md +2 -0
- package/agents/components/badge/update.md +2 -0
- package/agents/components/banner/banner.md +72 -9
- package/agents/components/banner/banner.spec.json +40 -2
- package/agents/components/bottom-sheet/bottom-sheet.md +2 -0
- package/agents/components/bubble/bubble.md +2 -0
- package/agents/components/button/button.family.json +8 -2
- package/agents/components/button/button.md +2 -0
- package/agents/components/button/check.md +2 -0
- package/agents/components/button/fab.md +2 -0
- package/agents/components/button/group.spec.json +65 -0
- package/agents/components/button/icon.md +2 -0
- package/agents/components/button/standard.md +45 -19
- package/agents/components/button/text.md +2 -0
- package/agents/components/button/toggle.md +2 -0
- package/agents/components/button/toolbar.md +2 -0
- package/agents/components/carousel/carousel.md +2 -0
- package/agents/components/carousel/post.md +5 -3
- package/agents/components/carousel/post.spec.json +4 -6
- package/agents/components/carousel/profile.md +4 -2
- package/agents/components/carousel/profile.spec.json +4 -6
- package/agents/components/chip/chip.md +2 -0
- package/agents/components/chip/filter.md +2 -0
- package/agents/components/chip/tag.md +2 -0
- package/agents/components/dialog/dialog.md +2 -0
- package/agents/components/directory-list/directory-list.md +2 -0
- package/agents/components/divider/divider.md +2 -0
- package/agents/components/feed/ad.md +2 -0
- package/agents/components/feed/feed.md +2 -0
- package/agents/components/feed/post.md +2 -0
- package/agents/components/form-field/form-field.md +3 -1
- package/agents/components/form-field/input.md +2 -0
- package/agents/components/form-field/input.spec.json +2 -1
- package/agents/components/form-field/search.md +2 -0
- package/agents/components/form-field/search.spec.json +2 -1
- package/agents/components/form-field/select.md +2 -0
- package/agents/components/form-field/textarea.md +2 -0
- package/agents/components/form-field/textarea.spec.json +2 -1
- package/agents/components/header/header.md +2 -0
- package/agents/components/header/main.md +2 -0
- package/agents/components/header/sub.md +2 -0
- package/agents/components/list/accordion.md +2 -0
- package/agents/components/list/entry.md +2 -0
- package/agents/components/list/entry.spec.json +2 -1
- package/agents/components/list/list.md +3 -1
- package/agents/components/list/radio.md +2 -0
- package/agents/components/list/standard.md +2 -0
- package/agents/components/list/standard.spec.json +2 -1
- package/agents/components/metadata/compact.md +13 -7
- package/agents/components/metadata/compact.spec.json +19 -6
- package/agents/components/metadata/metadata.family.json +3 -3
- package/agents/components/metadata/metadata.md +4 -2
- package/agents/components/metadata/standard.md +24 -0
- package/agents/components/nav-card/nav-card.md +2 -0
- package/agents/components/nav-list/nav-list.md +2 -0
- package/agents/components/navigation-bar/main.md +2 -0
- package/agents/components/navigation-bar/navigation-bar.md +2 -0
- package/agents/components/navigation-bar/search.md +2 -0
- package/agents/components/navigation-bar/sub.md +2 -0
- package/agents/components/page-shell/page-shell.md +2 -0
- package/agents/components/pagination/pagination.family.json +26 -0
- package/agents/components/pagination/pagination.md +40 -0
- package/agents/components/pagination/pagination.spec.json +54 -0
- package/agents/components/profile-header/profile-header.md +2 -0
- package/agents/components/progress/progress.md +2 -0
- package/agents/components/side-sheet/side-sheet.md +2 -0
- package/agents/components/skeleton/skeleton.md +2 -0
- package/agents/components/status-tag/status-tag.md +2 -0
- package/agents/components/suggestion-list/suggestion-list.md +2 -0
- package/agents/components/switch/switch.md +2 -0
- package/agents/components/tab-bar/tab-bar.md +2 -0
- package/agents/components/tabs/rounded.md +2 -0
- package/agents/components/tabs/segmented.md +2 -0
- package/agents/components/tabs/tabs.md +2 -0
- package/agents/components/tabs/underline.md +2 -0
- package/agents/components/thumbnail/thumbnail.md +2 -0
- package/agents/components/toast/toast.md +2 -0
- package/agents/components/tooltip/tooltip.md +2 -0
- package/agents/compose.md +3 -3
- package/agents/manifest.json +1 -0
- package/agents/patterns/README.md +2 -0
- package/agents/patterns/actions.md +2 -0
- package/agents/patterns/browsing.md +2 -0
- package/agents/patterns/communications.md +2 -0
- package/agents/patterns/layout.md +2 -0
- package/agents/patterns/modals.md +2 -0
- package/agents/patterns/visual.md +2 -0
- package/agents/usage.json +15 -3
- package/dist/index.cjs +95 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -1
- package/dist/index.d.ts +28 -1
- package/dist/index.js +94 -40
- package/dist/index.js.map +1 -1
- package/dist/styles.css +183 -41
- package/package.json +1 -2
- package/agents/reconstruct.md +0 -55
- package/agents/scoped-adoption.md +0 -111
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Post
|
|
2
2
|
|
|
3
|
+
> ๐ฐ๐ท ํ๊ตญ์ด: [`i18n/ko/schema/components/carousel/post.md`](../../../i18n/ko/schema/components/carousel/post.md)
|
|
4
|
+
|
|
3
5
|
Sub-component of the [Carousel](./carousel.md) family. Horizontally-scrolling pager of up to 5 compact post cards โ surfaces curated popular posts or gives paid / verified accounts priority placement inside the [Post](../feed/post.md) feed column. The section heading and `See all` link live on the [Carousel](./carousel.md) wrapper โ PostCarousel is the *content* only.
|
|
4
6
|
|
|
5
7
|
**Reach for this when** spotlighting a small set (โค5) of curated or sponsored posts inside a feed column. **Skip when** the surface is a single feed stream ([Feed ยท Post](../feed/post.md)) or an entity directory ([List/entry](../list/entry.md)).
|
|
@@ -108,7 +110,7 @@ import { Carousel, PostCarousel } from '@teamblind-chorus/ui';
|
|
|
108
110
|
- **body** โ `sys.typo.body.sm` / `sys.color.onSurfaceVariant`. Three-line clamp.
|
|
109
111
|
- **mention** *(optional)* โ `sys.typo.body.sm` / `sys.color.primary` (not italic).
|
|
110
112
|
- **footer** โ leading 'See more' [Text Button](../button/text.md) (`xsmall` / `secondary`) + trailing view count (`EyeIcon` + count `<span>`).
|
|
111
|
-
- **pagination** โ one dot per card
|
|
113
|
+
- **pagination** โ [Pagination](../pagination/pagination.md) component, one dot per card (`count` = card count, `activeIndex` from scroll position). Decorative โ dot tokens and the `aria-hidden` contract live on its spec; the carousel centers the intrinsic-width row (`align-self: center`).
|
|
112
114
|
|
|
113
115
|
## Anatomy
|
|
114
116
|
|
|
@@ -123,7 +125,7 @@ import { Carousel, PostCarousel } from '@teamblind-chorus/ui';
|
|
|
123
125
|
| body / mention | `sys.typo.body.sm` / `sys.color.onSurfaceVariant` (three-line clamp) ยท mention in `sys.color.primary` |
|
|
124
126
|
| followAction | [Text Button](../button/text.md) `size={'xsmall'}`, `appearance={'accent'}` inactive โ `appearance={'default'}` active; state tokens delegate to Text Button |
|
|
125
127
|
| footer | Row: leading 'See more' Text Button (`xsmall` / `secondary`) + trailing view count `<span>`; `justify-content: space-between` |
|
|
126
|
-
| pagination dot | 6 ร 6,
|
|
128
|
+
| pagination dot | [Pagination](../pagination/pagination.md) component delegated verbatim โ 6 ร 6 dots, active/inactive colors, and row gap bind on its spec |
|
|
127
129
|
|
|
128
130
|
## Sizes
|
|
129
131
|
|
|
@@ -144,5 +146,5 @@ Inward โ cards tile inside a horizontal scroll viewport with hairline outlines
|
|
|
144
146
|
- **Card header renders the shared `EntryRow`.** The avatar + optional verified mark + channel label + trailing follow [Text Button](../button/text.md) row pinned to the top of each *card* is **the same `EntryRow` atom that [List/entry](../list/entry.md) rows render** โ not a look-alike, the literal shared component. The carousel passes `verified` (the inline `VerifiedFillIcon`, left of the label), a 40-rung `thumbnail`, and a `xsmall` follow Text Button (`accent` inactive โ `default` active) into `EntryRow`'s trailing slot; the leadingโlabel gap (12), identity column, and trailing-action pin all live on `EntryRow`. Only the surrounding card chrome (`chorus-post-carousel__card-header` wrapper) is carousel-specific. Retune the attribution shape on `EntryRow` / at [List/entry](../list/entry.md), not here.
|
|
145
147
|
- **One card per page, scroll-snap.** `scroll-snap-type: x mandatory`; each card declares `scroll-snap-align: start`. The pager re-pays the 16 left rail via `padding-left` and, as a full-bleed child, reaches the trailing edge intrinsically so the peek isn't clipped.
|
|
146
148
|
- **Guaranteed 40px peek.** Trailing-edge visibility of the next card pins to `ref.space.500` โ raw ref step so the floor is fixed-pixel across breakpoints. Card basis is `calc(100% - sys.layout.inline.md - ref.space.500)`. After every swipe, the snapped card aligns flush with the container's left padding; the trailing edge always holds the 40px peek.
|
|
147
|
-
- **Pagination dots are decorative.**
|
|
149
|
+
- **Pagination dots are decorative.** The dot row is the shared [Pagination](../pagination/pagination.md) component. The carousel derives the active index via `IntersectionObserver` on the pager's snap targets and passes it down; tapping a dot does not scroll.
|
|
148
150
|
- **Cards route via `onClick`.** When an item carries `onClick`, the card surface becomes the click target; header (follow action) and footer (more link) intercept the tap so each routes independently.
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
},
|
|
95
95
|
"pagination": {
|
|
96
96
|
"required": true,
|
|
97
|
-
"description": "Row of dots below the pager โ
|
|
97
|
+
"description": "Row of dots below the pager โ rendered by the [Pagination](../pagination/pagination.md) component (`count` = card count, `activeIndex` from the pager's scroll position via IntersectionObserver). Dot size / gap / colors and the `aria-hidden` decorative contract all come from the Pagination spec; Pagination renders nothing below two cards. Pagination is an intrinsic-width inline element โ the carousel centers it (`align-self: center` on the carousel's own selector).",
|
|
98
98
|
"intrinsic": true
|
|
99
99
|
}
|
|
100
100
|
},
|
|
@@ -134,10 +134,8 @@
|
|
|
134
134
|
"cardFooterColor": "sys.color.onSurfaceVariant",
|
|
135
135
|
"cardFooterIcon": "EyeIcon",
|
|
136
136
|
"cardFooterIconSize": "sys.icon.md",
|
|
137
|
-
"
|
|
138
|
-
"
|
|
139
|
-
"paginationActiveColor": "sys.color.onSurface",
|
|
140
|
-
"paginationInactiveColor": "sys.color.outlineVariant"
|
|
137
|
+
"paginationRendersAs": "Pagination component โ dot size / gap / radius and active / inactive colors all delegate to the [Pagination](../pagination/pagination.md) spec.",
|
|
138
|
+
"paginationAlign": "center โ Pagination is an intrinsic-width inline element; the carousel binds `align-self: center` on its own selector to center the row under the pager."
|
|
141
139
|
},
|
|
142
140
|
"itemProps": {
|
|
143
141
|
"id": {
|
|
@@ -210,7 +208,7 @@
|
|
|
210
208
|
"horizontalScrollSnap": "scroll-snap-type: x mandatory; each card declares scroll-snap-align: start.",
|
|
211
209
|
"nextCardPeek": "The Carousel host is full-bleed, so the pager spans the full surface width and reaches the trailing edge intrinsically (no negative margin); it re-pays the 16 left rail via `padding-left: sys.layout.container.md`. Card basis composes the inter-card gap (`sys.layout.inline.md`) plus the visible peek (`ref.space.500`, 40px) into one calc โ a minimum of 40px of the next card is guaranteed to remain visible at the trailing edge whenever a card is snapped to the leading edge. The peek is pinned to a raw ref step rather than a responsive sys-layout rung so the visibility floor is fixed-pixel and does not shift at the responsive breakpoint.",
|
|
212
210
|
"stickyToLeadingPadding": "After every swipe, the snapped card aligns flush with the pager's left padding (the 16 rail) โ it 'sticks' to the leading edge of the pager. `scroll-snap-align: start` plus the pager's `scroll-padding-left: sys.layout.container.md` together produce this behavior. The trailing edge of the same snap state always holds the 40px peek of the next card; the two are one geometry contract, not two independent rules.",
|
|
213
|
-
"paginationDecorative": "Dots are decorative (`aria-hidden`). They reflect the scroll position only; tapping a dot does not scroll.
|
|
211
|
+
"paginationDecorative": "Dots render via the [Pagination](../pagination/pagination.md) component and are decorative (`aria-hidden`). They reflect the scroll position only; tapping a dot does not scroll. The carousel derives the active index via IntersectionObserver on the pager's snap targets and passes it down as `activeIndex`.",
|
|
214
212
|
"cardClickRoutes": "When an item carries `onClick`, the card surface becomes the click target. Header affordances (follow action) and footer affordances (more link) intercept the tap so each can route independently.",
|
|
215
213
|
"insertionPolicy": "Editorial / ops control inserts the carousel between regular Feed cards according to placement policy โ the component does not own that decision."
|
|
216
214
|
},
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Profile
|
|
2
2
|
|
|
3
|
+
> ๐ฐ๐ท ํ๊ตญ์ด: [`i18n/ko/schema/components/carousel/profile.md`](../../../i18n/ko/schema/components/carousel/profile.md)
|
|
4
|
+
|
|
3
5
|
Sub-component of the [Carousel](./carousel.md) family. Horizontally-scrolling rail of fixed-width (176px) profile cards โ channels, user profiles, or company channels grouped under a single editorial heading. Each card carries a cover band, an overlapping 64-rung avatar, entity name + follower count, a metrics row or two-line description, and a trailing follow [Toggle Button](../button/text.md).
|
|
4
6
|
|
|
5
7
|
**Reach for this when** an editorial collection groups follow-able entities under a single heading โ hot companies, recommended channels, suggested people. **Skip when** the rail carries content posts ([Post carousel](./post.md)), the surface needs the full list scanned vertically ([SuggestionList](../suggestion-list/suggestion-list.md) / [DirectoryList](../directory-list/directory-list.md)), or the rung is a label-only nav strip ([AvatarRail](../avatar-rail/avatar-rail.md)).
|
|
@@ -152,7 +154,7 @@ import { Carousel, ProfileCarousel } from '@teamblind-chorus/ui';
|
|
|
152
154
|
- **metrics** *(optional)* โ row of `icon + value` chips: `star โ StarFillIcon (sys.color.icon.yellow)`, `pulse โ PulseFillIcon (sys.color.success)`, `heart โ HeartFillIcon (sys.color.icon.red)`. Mutually exclusive with `description`.
|
|
153
155
|
- **description** *(optional)* โ two-line clamped paragraph that replaces the metrics row when present. Block height fixed to two lines of `sys.typo.label.sm` regardless of copy length, so card height stays consistent across metrics-carrying and copy-carrying cards.
|
|
154
156
|
- **followAction** โ full-width [Toggle Button](../button/text.md) (`variant={'toggle'}`); `Follow` (inactive) / `Following` (active).
|
|
155
|
-
- **pagination** โ one dot per card.
|
|
157
|
+
- **pagination** โ [Pagination](../pagination/pagination.md) component, one dot per card (`count` = card count, `activeIndex` from scroll position). Decorative โ dot tokens and the `aria-hidden` contract live on its spec; the carousel centers the intrinsic-width row (`align-self: center`).
|
|
156
158
|
|
|
157
159
|
## Anatomy
|
|
158
160
|
|
|
@@ -168,7 +170,7 @@ import { Carousel, ProfileCarousel } from '@teamblind-chorus/ui';
|
|
|
168
170
|
| metric chip | `sys.icon.md` glyph + `sys.typo.label.sm` value; star โ `StarFillIcon` (`sys.color.icon.yellow`), pulse โ `PulseFillIcon` (`sys.color.success`), heart โ `HeartFillIcon` (`sys.color.icon.red`) |
|
|
169
171
|
| description | `sys.typo.label.sm` / `sys.color.onSurfaceVariant`, centered, two-line clamp with trailing ellipsis. Two-layer DOM โ outer container owns the same fixed-height slot as `metrics row` (min/max-height = 2 label.sm lines); inner `<p>` owns the `-webkit-line-clamp: 2` truncation. Split sidesteps a Chrome quirk where `display: -webkit-box` and explicit `height` on one element break the third-line clip. |
|
|
170
172
|
| followAction | [Toggle Button](../button/text.md) (Chip-toggle anatomy), stretched to full card width |
|
|
171
|
-
| pagination dot | 6ร6,
|
|
173
|
+
| pagination dot | [Pagination](../pagination/pagination.md) component delegated verbatim โ 6 ร 6 dots, active/inactive colors, and row gap bind on its spec |
|
|
172
174
|
|
|
173
175
|
## States
|
|
174
176
|
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
},
|
|
81
81
|
"pagination": {
|
|
82
82
|
"required": true,
|
|
83
|
-
"description": "Row of dots below the pager โ
|
|
83
|
+
"description": "Row of dots below the pager โ rendered by the [Pagination](../pagination/pagination.md) component (`count` = card count, `activeIndex` from the pager's scroll position via IntersectionObserver). Dot size / gap / colors and the `aria-hidden` decorative contract all come from the Pagination spec; Pagination renders nothing below two cards. Pagination is an intrinsic-width inline element โ the carousel centers it (`align-self: center` on the carousel's own selector).",
|
|
84
84
|
"intrinsic": true
|
|
85
85
|
}
|
|
86
86
|
},
|
|
@@ -123,10 +123,8 @@
|
|
|
123
123
|
"followActionRendersAs": "Button variant='toggle' โ Chip-toggle anatomy. Stretched to full card width via a wrapper rule. All state tokens delegate to the Toggle Button (Chip) family.",
|
|
124
124
|
"cardPaddingBlock": "sys.layout.stack.sm",
|
|
125
125
|
"cardPaddingInline": "sys.layout.container.md",
|
|
126
|
-
"
|
|
127
|
-
"
|
|
128
|
-
"paginationActiveColor": "sys.color.onSurface",
|
|
129
|
-
"paginationInactiveColor": "sys.color.outlineVariant"
|
|
126
|
+
"paginationRendersAs": "Pagination component โ dot size / gap / radius and active / inactive colors all delegate to the [Pagination](../pagination/pagination.md) spec.",
|
|
127
|
+
"paginationAlign": "center โ Pagination is an intrinsic-width inline element; the carousel binds `align-self: center` on its own selector to center the row under the pager."
|
|
130
128
|
},
|
|
131
129
|
"itemProps": {
|
|
132
130
|
"id": {
|
|
@@ -198,7 +196,7 @@
|
|
|
198
196
|
"fixedCardWidth": "Every profile card paints a fixed 176px footprint โ the carousel never reflows the card to fit the available inline width. The trailing peek (`ref.space.500`, 40px) of the next card is always visible regardless of viewport.",
|
|
199
197
|
"horizontalScrollSnap": "scroll-snap-type: x mandatory; each card declares scroll-snap-align: start.",
|
|
200
198
|
"stickyToLeadingPadding": "After every swipe, the snapped card aligns flush with the pager's left padding (the 16 rail) โ same geometry contract as PostCarousel.",
|
|
201
|
-
"paginationDecorative": "Dots are decorative; tapping a dot does not scroll.
|
|
199
|
+
"paginationDecorative": "Dots render via the [Pagination](../pagination/pagination.md) component and are decorative; tapping a dot does not scroll. The carousel derives the active index via IntersectionObserver on the snap targets and passes it down as `activeIndex`.",
|
|
202
200
|
"followToggleCommitsInPlace": "Tapping Follow flips the card's Toggle Button to Following and stays there. State is owned by the consumer via items[i].followed + onFollowChange.",
|
|
203
201
|
"cardClickRoutes": "When an item carries `onClick`, the card surface becomes the click target. The follow toggle intercepts the tap so it routes independently."
|
|
204
202
|
},
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Chip
|
|
2
2
|
|
|
3
|
+
> ๐ฐ๐ท ํ๊ตญ์ด: [`i18n/ko/schema/components/chip/chip.md`](../../../i18n/ko/schema/components/chip/chip.md)
|
|
4
|
+
|
|
3
5
|
A small, content-shaped control or label โ chip-shaped affordance for two anchoring roles. **Filter** is the selectable, capsule-shaped choice the user toggles to refine a set (search filters, taxonomy switches, faceted lists). **Tag** is the static, square-cornered label naming attached metadata (categories on a card, attributes on a profile, opt-in/out tokens on a settings row). Each family carries its own slot vocabulary, geometry, and tone; the cross-family contract is limited to the shared label rung (12px Semibold, 4px block padding, 4px label-slot inset producing the visible icon-to-label rhythm) and the Chorus-wide color / state / focus tokens in [`DESIGN.md`](../../DESIGN.md). The two diverge on min-height and horizontal padding by role โ **Filter** sits at 32 / 12 (tappable affordance, shared verbatim with [Toolbar Button](../button/toolbar.md) and [Tabs Segmented](../tabs/segmented.md)); **Tag** tightens to 24 / 8 (passive metadata that should not invite touch).
|
|
4
6
|
|
|
5
7
|
**Layout inset.** `inline` โ slot atom. A single Chip has no page-rail responsibility; the surrounding container places it (List row leading, Feed footer, FormField suffix). A Chip *group* โ multiple Filter chips arranged as a filter rail โ is rail-responsible: place the group as a direct child of the page shell (no `padding-inline` / `px-*` wrapper) and let its outer container pay the gutter once, so the first chip's leading edge aligns with section H2s and list-row leading content. See [`AGENTS.md` ยง Composition rules](../../../AGENTS.md#composition-rules).
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Filter
|
|
2
2
|
|
|
3
|
+
> ๐ฐ๐ท ํ๊ตญ์ด: [`i18n/ko/schema/components/chip/filter.md`](../../../i18n/ko/schema/components/chip/filter.md)
|
|
4
|
+
|
|
3
5
|
The selectable chip โ a capsule-shaped toggle for refining a set. Unselected is a transparent hairline-outlined pill that adopts whatever surface sits behind it; selected swaps to an inverse fill. Optional leading/trailing icons compose without changing footprint.
|
|
4
6
|
|
|
5
7
|
**Reach for this when** the user narrows a set by toggling one or more independent criteria โ multiple chips can be on at once. **Skip when** the choices are mutually-exclusive view modes โ use [Segmented](../tabs/segmented.md) instead.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Tag
|
|
2
2
|
|
|
3
|
+
> ๐ฐ๐ท ํ๊ตญ์ด: [`i18n/ko/schema/components/chip/tag.md`](../../../i18n/ko/schema/components/chip/tag.md)
|
|
4
|
+
|
|
3
5
|
The informational chip โ square-cornered label naming attached metadata (categories, statuses, content labels). Shorter than Filter (24 vs 32 min-height) with `sys.radius.sm` corners. Two appearances: `default` paints a translucent `sys.color.scrimSubtle` overlay (~8% inverse-tone, adopts whatever surface sits behind it); `accent` paints a tonal pale-primary container with primary label.
|
|
4
6
|
|
|
5
7
|
**Reach for this when** you're naming attached metadata on rows, cards, or profiles. **Skip when** the marker signals unread / new activity on a host rather than describing it โ use [Badge](../badge/badge.md) instead.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Dialog
|
|
2
2
|
|
|
3
|
+
> ๐ฐ๐ท ํ๊ตญ์ด: [`i18n/ko/schema/components/dialog/dialog.md`](../../../i18n/ko/schema/components/dialog/dialog.md)
|
|
4
|
+
|
|
3
5
|
A focused, opt-in interruption โ a centred card over a scrim that holds the flow until the user makes a single decision.
|
|
4
6
|
|
|
5
7
|
**Reach for this when** the flow must pause for a definitive response โ destructive actions, conflicts, consent gates, "Are you sure?". **Skip when** the same nudge can be delivered without halting the flow (use [Bottom sheet](../bottom-sheet/bottom-sheet.md)), the message is contextual to underlying content ([Banner](../banner/banner.md)), or the confirmation is post-action ([Toast](../toast/toast.md)).
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Directory list
|
|
2
2
|
|
|
3
|
+
> ๐ฐ๐ท ํ๊ตญ์ด: [`i18n/ko/schema/components/directory-list/directory-list.md`](../../../i18n/ko/schema/components/directory-list/directory-list.md)
|
|
4
|
+
|
|
3
5
|
A vertical follow-list โ labelled block where each row pairs a 48 [Thumbnail](../thumbnail/thumbnail.md), an identity column (name + `secondary` followers + `description`), and a trailing [Toggle Button](../button/toggle.md) flipping between "Follow" and "Following". Anatomy is entity-agnostic โ channels, people, companies, topics share one shape.
|
|
4
6
|
|
|
5
7
|
**Preset wrapper.** Internally this is `<Header /> + <List variant="entry" size="large" divider={false}>`. The wrapper exists to (a) map entity-flavored item keys (`name โ label`, `followers โ secondary`, `active/onToggle โ trailingIcon`) and (b) lock the rung + divider preset for the canonical Follow-able directory shape. There is no new visual grammar โ just a pinned set of `List` props plus item-key sugar.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Divider
|
|
2
2
|
|
|
3
|
+
> ๐ฐ๐ท ํ๊ตญ์ด: [`i18n/ko/schema/components/divider/divider.md`](../../../i18n/ko/schema/components/divider/divider.md)
|
|
4
|
+
|
|
3
5
|
A section-break band โ a single full-bleed block painted with `sys.color.scrimSubtle` (~8% inverse-tone overlay โ black in light mode, white in dark) at a fixed block thickness of `sys.layout.stack.xs` (8). Reach for it when two adjacent regions don't share an enclosing container and vertical rhythm alone doesn't read as a boundary โ a directory of suggested channels ending and a fresh recommendation list beginning, a feed segment ending and a followed-channels list resuming, a promo strip ending and content picking up below.
|
|
4
6
|
|
|
5
7
|
**Reach for this when** the boundary between two regions is ambiguous because they share the same surface and vertical rhythm โ the visitor's eye should *land* on the break, not infer it. **Skip when** the regions already sit on different surfaces (one card, one canvas โ the surface change is the break), when one region carries a heading that itself reads as the start of a new block, or when the separation is between *rows of the same list* (List's own `divider={true}` paints those as a hairline `outlineVariant` rule).
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Ad
|
|
2
2
|
|
|
3
|
+
> ๐ฐ๐ท ํ๊ตญ์ด: [`i18n/ko/schema/components/feed/ad.md`](../../../i18n/ko/schema/components/feed/ad.md)
|
|
4
|
+
|
|
3
5
|
Sub-component of the [Feed](./feed.md) family. A sponsored placement riding the same scrolling column as [Feed ยท Post](./post.md). The header trades a channel/author row for a brand row (32-rung [Thumbnail](../thumbnail/thumbnail.md) + brand name + `Sponsored` subtitle + trailing close affordance); the body stays the same shape as Feed's title + excerpt; hero media and CTA bond into a single rounded slab at the foot. No engagement row โ ads are not authored content.
|
|
4
6
|
|
|
5
7
|
**Reach for this when** a sponsored placement must ride inline in the feed column alongside authored posts โ a promoted brand post, an in-feed ad unit. **Skip when** the content is authored by a user (use [Feed ยท Post](./post.md)) or the promotion belongs in a dedicated surface outside the feed stream.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Feed
|
|
2
2
|
|
|
3
|
+
> ๐ฐ๐ท ํ๊ตญ์ด: [`i18n/ko/schema/components/feed/feed.md`](../../../i18n/ko/schema/components/feed/feed.md)
|
|
4
|
+
|
|
3
5
|
The unit of a scrolling stream. The family covers two card shapes that ride the same column: **[Post](./post.md)** โ the authored content card (channel header, title + body, optional thumbnail / poll / offer / citation / mention, engagement footer); **[Ad](./ad.md)** โ the sponsored placement (brand row, optional title + body, a hero + CTA slab, no engagement row).
|
|
4
6
|
|
|
5
7
|
Editorial collections of popular posts ride alongside Feed cards via the [Section ยท Post Carousel](../carousel/post.md) sub of the [Carousel](../carousel/carousel.md) family โ that pair owns the curated-collection placement, not Feed itself.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Post
|
|
2
2
|
|
|
3
|
+
> ๐ฐ๐ท ํ๊ตญ์ด: [`i18n/ko/schema/components/feed/post.md`](../../../i18n/ko/schema/components/feed/post.md)
|
|
4
|
+
|
|
3
5
|
Sub-component of the [Feed](./feed.md) family. The authored-content card โ the unit of a scrolling feed. Composes a flag, author row, body block (title + clamped excerpt + optional thumbnail), optional inline modules (poll, offer, citation, mention), and an engagement footer.
|
|
4
6
|
|
|
5
7
|
**Reach for this when** rendering a single user-authored entry โ text post, poll, offer evaluation, link share. **Skip when** the placement is sponsored ([Feed ยท Ad](./ad.md)) or the row is a metric summary rather than authored content.
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Form field
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> ๐ฐ๐ท ํ๊ตญ์ด: [`i18n/ko/schema/components/form-field/form-field.md`](../../../i18n/ko/schema/components/form-field/form-field.md)
|
|
4
|
+
|
|
5
|
+
The text-entry primitives โ controls the user types into or picks a value from. **Input** is single-line text; **Search Bar** is its search-shaped sibling; **Select** is the Input-shaped picker that opens a sheet. Cross-family contract: bordered surface-toned container, hairline rest stroke that thickens while active, `error` appearance re-tones the whole field. The trailing clear ("ร") is an independent nested action โ while the pointer hovers / presses it, the field's own hover stroke and pressed overlay are suppressed so the large field never reads as pressed alongside the small control. (The Select chevron is exempt: it fires the same action as clicking the field, so it lights the field.)
|
|
4
6
|
|
|
5
7
|
**Layout inset.** `inline` โ slot atom. No page-rail responsibility; the surrounding container places it. Sits inside a labelled form layout (vertical FormField stack) or another component's slot (NavigationBar centre for Search, BottomSheet body for quick-entry) โ never a sibling of `full-bleed` page rows. The form column pays the page gutter, not the field.
|
|
6
8
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Input
|
|
2
2
|
|
|
3
|
+
> ๐ฐ๐ท ํ๊ตญ์ด: [`i18n/ko/schema/components/form-field/input.md`](../../../i18n/ko/schema/components/form-field/input.md)
|
|
4
|
+
|
|
3
5
|
Single-line text field โ a bordered, transparent-fill box for short values. Optional `label`, `helper`, or `maxLength` compose it into a labeled group; `appearance="error"` re-tones fill, text, and stroke.
|
|
4
6
|
|
|
5
7
|
**Reach for this when** capturing a short single-line value โ name, email, search query, comment subject. **Skip when** the value is multi-line (use a textarea), a one-of-many selection (use a select), or a free-form search with built-in results (use the [search](./search.md) sub).
|
|
@@ -151,7 +151,8 @@
|
|
|
151
151
|
"overlay": {
|
|
152
152
|
"color": "text",
|
|
153
153
|
"opacity": "sys.state.pressed"
|
|
154
|
-
}
|
|
154
|
+
},
|
|
155
|
+
"nestedActionScope": "The pressed overlay (and hover stroke) is suppressed while the pointer presses / hovers the trailing clear button โ that 'ร' is an independent nested action, so the small control owns the state and the large field does not also read as pressed. The visual-state boundary matches the action boundary."
|
|
155
156
|
},
|
|
156
157
|
"active": {
|
|
157
158
|
"overlay": null,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Search bar
|
|
2
2
|
|
|
3
|
+
> ๐ฐ๐ท ํ๊ตญ์ด: [`i18n/ko/schema/components/form-field/search.md`](../../../i18n/ko/schema/components/form-field/search.md)
|
|
4
|
+
|
|
3
5
|
Search-shaped single-line field โ sibling of [Input](./input.md) with a leading `SearchIcon` and `sys.radius.full` pill corner. Box, stroke, placeholder rule, clear button, and focus ring inherited from Input unchanged. **Bare box only โ no `label`, `helper`, `maxLength`, or `error` appearance.** Error reporting belongs to a labelled Input.
|
|
4
6
|
|
|
5
7
|
**Reach for this when** the rung is a query against an open set โ directory search, post filter, command palette entry. **Skip when** the value is a labelled form field ([Input](./input.md)), the user picks from a known closed set ([Select](./select.md)), or the surface needs error reporting (a bare search rung has nowhere to host it โ use a labelled [Input](./input.md)).
|
|
@@ -92,7 +92,8 @@
|
|
|
92
92
|
"overlay": {
|
|
93
93
|
"color": "text",
|
|
94
94
|
"opacity": "sys.state.pressed"
|
|
95
|
-
}
|
|
95
|
+
},
|
|
96
|
+
"nestedActionScope": "The pressed overlay (and hover stroke) is suppressed while the pointer presses / hovers the trailing clear button โ that 'ร' is an independent nested action, so the small control owns the state and the large field does not also read as pressed. The visual-state boundary matches the action boundary."
|
|
96
97
|
},
|
|
97
98
|
"active": {
|
|
98
99
|
"overlay": null,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Select
|
|
2
2
|
|
|
3
|
+
> ๐ฐ๐ท ํ๊ตญ์ด: [`i18n/ko/schema/components/form-field/select.md`](../../../i18n/ko/schema/components/form-field/select.md)
|
|
4
|
+
|
|
3
5
|
Input-shaped picker โ same box, label, helper, and error re-tone as [Input](./input.md), but read-only and ending in an `ArrowDownIcon` chevron. Clicking opens a Bottom Sheet with the option list; chosen value is echoed back through `value`.
|
|
4
6
|
|
|
5
7
|
**Reach for this when** the user picks one value from a known set that's too long for inline chips โ country, currency, sort order, equity tier. **Skip when** the value is free text ([Input](./input.md)), the user searches an open set ([Search bar](./search.md)), or the list is short enough to surface inline as a [Radio list](../list/radio.md).
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Textarea
|
|
2
2
|
|
|
3
|
+
> ๐ฐ๐ท ํ๊ตญ์ด: [`i18n/ko/schema/components/form-field/textarea.md`](../../../i18n/ko/schema/components/form-field/textarea.md)
|
|
4
|
+
|
|
3
5
|
Multi-line cousin of [input](./input.md) โ identical chrome contract (transparent fill, inset box-shadow stroke, optional `label` / `helper` / `maxLength` group rungs); the inner element is a `<textarea>` with configurable `rows` (default 4) and vertical-only resize.
|
|
4
6
|
|
|
5
7
|
**Reach for this when** the value naturally spans multiple lines: compose surfaces, bug reports, profile bios, comment composers. **Skip when** the value is single-line ([input](./input.md)), needs a leading magnifier glyph ([search](./search.md)), or opens a sheet-driven option list ([select](./select.md)).
|
|
@@ -133,7 +133,8 @@
|
|
|
133
133
|
"hovered": { "overlay": null, "border": "borderHover" },
|
|
134
134
|
"pressed": {
|
|
135
135
|
"border": "borderHover",
|
|
136
|
-
"overlay": { "color": "text", "opacity": "sys.state.pressed" }
|
|
136
|
+
"overlay": { "color": "text", "opacity": "sys.state.pressed" },
|
|
137
|
+
"nestedActionScope": "The pressed overlay (and hover stroke) is suppressed while the pointer presses / hovers the trailing clear button โ that 'ร' is an independent nested action, so the small control owns the state and the large field does not also read as pressed. The visual-state boundary matches the action boundary."
|
|
137
138
|
},
|
|
138
139
|
"active": {
|
|
139
140
|
"overlay": null,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Header
|
|
2
2
|
|
|
3
|
+
> ๐ฐ๐ท ํ๊ตญ์ด: [`i18n/ko/schema/components/header/header.md`](../../../i18n/ko/schema/components/header/header.md)
|
|
4
|
+
|
|
3
5
|
The labelled header that names a region and exposes its one highest-priority affordance. Two members share this contract and split on a **tone/weight axis**: **[Main](./main.md)** (`<Header>`) โ the louder `onSurface` section heading at 16 / 20 that owns the See-all action, the icon drill-in, and the sort/filter dropdown โ and **[Sub](./sub.md)** (`<SubHeader>`) โ the quieter muted `onSurfaceVariant` group label at 14 that names the rows beneath it and carries at most a single Text Button action.
|
|
4
6
|
|
|
5
7
|
**Layout inset.** `full-bleed` โ both members have a transparent background and own their `container.md` (16) inline rail, so the label lands on the same rail as the List rows / Feed items it heads with no host help. Drop the header directly above the labelled region as a sibling; do **not** wrap it in a `padding-inline` / `px-*` / `style={{ padding }}` div, and do not pay the rail again on the host. A bundling host (Carousel, DirectoryList, NavList, SideSheet column) stays full-bleed and absorbs only the header's block padding into its stack rhythm. See [`AGENTS.md` ยง Composition rules](../../../AGENTS.md#composition-rules).
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Main
|
|
2
2
|
|
|
3
|
+
> ๐ฐ๐ท ํ๊ตญ์ด: [`i18n/ko/schema/components/header/main.md`](../../../i18n/ko/schema/components/header/main.md)
|
|
4
|
+
|
|
3
5
|
The louder member of the [Header](./header.md) family โ a labelled `onSurface` heading + an optional trailing affordance, reached as `<Header>`. The composable header anatomy reused across [Carousel](../carousel/carousel.md), in-sheet sub-sections, bounded cards, [SideSheet](../side-sheet/side-sheet.md) drawer columns, and any host that needs a leading title + one trailing commit.
|
|
4
6
|
|
|
5
7
|
**Reach for this when** a labelled block needs an `onSurface` heading and at most one trailing commit (See-all link, drill-in chevron, or sort dropdown). **Skip when** the block needs only a quiet muted group label โ that is the family's [Sub](./sub.md) (`<SubHeader>`); when the block has multiple actions; the trailing affordance is a destructive commit; or the surrounding host already owns a heading at the same rung.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Sub
|
|
2
2
|
|
|
3
|
+
> ๐ฐ๐ท ํ๊ตญ์ด: [`i18n/ko/schema/components/header/sub.md`](../../../i18n/ko/schema/components/header/sub.md)
|
|
4
|
+
|
|
3
5
|
Quiet section-dividing label โ a 14px (`sys.typo.label.md`, 14 / Semibold) line in the muted `sys.color.onSurfaceVariant` tone that names the group of rows beneath it ("Following", "More Topics to follow"). The muted tone is the dividing device: it reads as a region label rather than a heading that competes with the page title, while the label-weight typo keeps it from dissolving into body copy. Rendered as a semantic `<h3>` by default so screen-reader heading navigation lands on the group label.
|
|
4
6
|
|
|
5
7
|
It may carry one quiet trailing affordance โ a single [Text Button](../button/text.md) `action` ("See all", "Edit", "Manage") โ for a region-level commit that stays subordinate to the muted label. Icon drill-in and dropdown disclosure are *not* SubHeader's: those belong on [Main](./main.md), whose louder `onSurface` heading earns the heavier affordance set.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Accordion
|
|
2
2
|
|
|
3
|
+
> ๐ฐ๐ท ํ๊ตญ์ด: [`i18n/ko/schema/components/list/accordion.md`](../../../i18n/ko/schema/components/list/accordion.md)
|
|
4
|
+
|
|
3
5
|
Expandable-row List sub. Each item exposes a List-row trigger (label + auto-rendered trailing chevron that rotates `180ยฐ` on expand) and a body that paints below it when open. Rows tile flush with the family hairline `outlineVariant` divider between them; an extra rule paints between the open trigger and its child row group.
|
|
4
6
|
|
|
5
7
|
**Reach for this when** a list of titled sections is too long to keep open at once โ FAQs, T&C sections, expandable filter groups, settings groups with infrequent edits, hierarchical menus (companies โ channels, regions โ cities). **Skip when** bodies are short enough to read inline (use [Carousel](../carousel/carousel.md) per group), the user needs to act on labels (use a [List/standard](./standard.md) drill-in row or [List/radio](./radio.md)), or every item should be visible at once (stack [Carousel](../carousel/carousel.md)s).
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Entry
|
|
2
2
|
|
|
3
|
+
> ๐ฐ๐ท ํ๊ตญ์ด: [`i18n/ko/schema/components/list/entry.md`](../../../i18n/ko/schema/components/list/entry.md)
|
|
4
|
+
|
|
3
5
|
Directory-entry [List](./list.md) sub โ an entity row pairing an optional leading [Thumbnail](../thumbnail/thumbnail.md) avatar with an identity group (label, optional inline `count` Badge, optional `secondary` line and `description`). Same click semantics as the [Standard sub](./standard.md); geometry, state overlays, and inward focus ring delegate to the [family-wide rules](./list.md). Slots and Anatomy below carry the rung and slot detail.
|
|
4
6
|
|
|
5
7
|
**Reach for this when** rendering an entity-row directory โ follow suggestion, member directory, subscription / channel / topic / playlist directory, mention / recipient picker, entity search result โ or, with `thumbnail` omitted, label-only nav rows (settings menu, category index). **Skip when** you need a Feed-specific attribution cluster (use [Metadata](../metadata/metadata.md) for Post / Ad card heads).
|
|
@@ -194,6 +194,7 @@
|
|
|
194
194
|
"opacity": "sys.state.pressed"
|
|
195
195
|
}
|
|
196
196
|
},
|
|
197
|
+
"nestedActionScope": "The hover / pressed overlay is suppressed while the pointer sits on the independent trailing action (a favorite / follow / overflow control). The small control owns the state; the large row does NOT also read as hovered / pressed. The visual-state boundary matches the event boundary (the trailing action already stops propagation).",
|
|
197
198
|
"disabled": {
|
|
198
199
|
"containerOpacity": "sys.state.disabled",
|
|
199
200
|
"containerOpacityScope": "Dims the row content only โ the inter-row divider and the focus overlay keep full opacity, so a disabled row never fades the hairline rule between it and the next row.",
|
|
@@ -224,7 +225,7 @@
|
|
|
224
225
|
"rowClickTarget": "Whole row is clickable when an `onClick` is bound to the item. The thumbnail is never a separate hit target.",
|
|
225
226
|
"identityGroupFlush": "Label and inline count tile flush on the primary line with `sys.layout.inline.sm` (4) horizontal separation and no vertical gap โ they read as one tight identity block.",
|
|
226
227
|
"descriptionSingleLine": "Description always renders on a single line and truncates with ellipsis. The row never grows to fit longer description copy โ overflow truncates against the trailing slot if present.",
|
|
227
|
-
"trailingSlotIndependent": "Clicks inside `trailingIcon` stop propagating before they reach the row's `onClick`. Wire a favorite / follow / overflow action there without it committing the row's primary action."
|
|
228
|
+
"trailingSlotIndependent": "Clicks inside `trailingIcon` stop propagating before they reach the row's `onClick`. Wire a favorite / follow / overflow action there without it committing the row's primary action. The slot is also visually independent: while the pointer hovers / presses it, the row's own hover / pressed overlay is suppressed so the large row never reads as active alongside the small control."
|
|
228
229
|
},
|
|
229
230
|
"forbidden": [
|
|
230
231
|
"thumbnail rendered as a raw <img> outside the chorus-thumbnail slot wrapper",
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# List
|
|
2
2
|
|
|
3
|
+
> ๐ฐ๐ท ํ๊ตญ์ด: [`i18n/ko/schema/components/list/list.md`](../../../i18n/ko/schema/components/list/list.md)
|
|
4
|
+
|
|
3
5
|
A vertically-stacked sequence of rows for menus, settings panels, picker sheets, inline option groups, directory entries, and expandable hierarchies. Four sub-components share one anatomy and diverge on the leading slot, the selection contract, and the expand contract.
|
|
4
6
|
|
|
5
7
|
**Reach for this when** the rows are same-kind chrome โ settings entries, menu options, single-select picker rows, drill-in navigation, directory rows, expandable section headers. **Skip when** the rows are authored content with author + body + footer (use [Feed](../feed/feed.md)) or a horizontal collection of curated cards (use [Carousel](../carousel/carousel.md)). Pick the sub by the trailing affordance and the leading slot: display / navigation rows โ [Standard](./standard.md) (no `thumbnail` for text-only; pass `thumbnail` for the 40px avatar-leading image type, label + optional `supportingText`); single-select radio โ [Radio](./radio.md); 32 / 40 / 48 avatar leading with identity-group (label + inline `count`) + optional single-line description โ [Entry](./entry.md); drill-in chevron โ any [Standard](./standard.md) / [Radio](./radio.md) row with `nav: true`; expand chevron that rotates on click โ [Accordion](./accordion.md).
|
|
@@ -12,7 +14,7 @@ A vertically-stacked sequence of rows for menus, settings panels, picker sheets,
|
|
|
12
14
|
- **Row geometry.** 8px block / 16px inline padding (`layout.container.xs` / `layout.container.md`); min-height 48px. Row spacing is **role-based**, not a single flex gap: the **text group โ trailing action** gap is a fixed `layout.inline.md` (8px) in every sub, while the **leading โ text group** gap depends on the leading *type* โ `layout.inline.md` (8px) for an icon leading (Radio's indicator), `layout.inline.lg` (12px) for an image leading (a Standard row's `thumbnail` image type / Entry Thumbnail). A label-only Entry row (no `thumbnail`) drops the leading gap to 0. Row grows when `supportingText` is present.
|
|
13
15
|
- **Label column.** Label: 16px / Regular / `onSurface` (sub-list rows compressed inside an accordion render at 14px / Regular โ see [accordion.md](./accordion.md) ยง Nested list; Entry rows promote the label to 14px / Semibold so the inline `count` reads as part of the identity group). SupportingText: 14px / Regular / `onSurfaceVariant`, sits directly under the label with no extra gap โ the two lines stack on the label-column's intrinsic line-box rhythm. The Entry sub replaces the second line with a single-line `description` (12px / Regular / `onSurfaceVariant`, separated from the identity group by `ref.space.25` (2) โ see [entry.md](./entry.md)). All secondary lines truncate with ellipsis.
|
|
14
16
|
- **Strong-label opt-in.** Pass `strong={true}` on a row (`<Accordion.Item strong>` on the accordion sub) to promote the label's weight from Regular (`body.*-weight`, 400) to Semibold (`label.*-weight`, 600) at the same size and line-height โ `body.md โ label.lg` at the 16 rung, `body.sm โ label.md` at the 14 rung. The row's geometry (height, dividers, slot positions) is unchanged; only the label glyphs gain stroke weight. Reach for it when one row needs to read as the primary entry within a denser scan โ the active company in a directory, the canonical answer in an FAQ, the user's own row in a member list. Use sparingly โ a stack where every row is strong reads as the default again, defeating the marker.
|
|
15
|
-
- **States.** `selected` exists only on Radio. The whole row is the interactive surface.
|
|
17
|
+
- **States.** `selected` exists only on Radio. The whole row is the interactive surface โ except where a trailing slot carries an *independent action* (a Follow / mute / favorite button, an overflow control). That action is a nested touch target: it stops click / key propagation so it never commits the row, and while the pointer hovers / presses it the row's own hover / pressed overlay is **suppressed** so the large row never reads as active alongside the small control. The decorative `nav: true` chevron is exempt โ it is the row's drill-in affordance, so hovering it still lights the whole row.
|
|
16
18
|
- **Focus indicator.** Composition: Inward (see [Focus ring composition](../../DESIGN.md#focus-ring-composition)) โ inset shadows entirely inside the row's box. Trigger: `:focus-visible`.
|
|
17
19
|
- **Accessibility.** Every non-Radio sub (Standard / Entry / Accordion) exposes `role="list"`; Radio exposes `role="radiogroup"` with each row `role="radio"` + `aria-checked`. A `nav: true` row's trailing chevron is decorative (`aria-hidden`) โ the whole row stays the single interactive target. Keyboard navigation (Arrow โ/โ, Home/End) is handled by the container; Radio also commits on Space / Enter.
|
|
18
20
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Radio
|
|
2
2
|
|
|
3
|
+
> ๐ฐ๐ท ํ๊ตญ์ด: [`i18n/ko/schema/components/list/radio.md`](../../../i18n/ko/schema/components/list/radio.md)
|
|
4
|
+
|
|
3
5
|
Single-select picker List sub-component. Each row carries a leading 24px (`sys.icon.lg`) radio indicator; clicking commits that row's value via `onChange(value)`. Exactly one row is selected at a time. Row geometry, typography, divider, state overlays, and inward focus ring all delegate to the [family-wide rules](./list.md); this sub documents the Radio-specific leading indicator and selection contract.
|
|
4
6
|
|
|
5
7
|
**Reach for this when** the user picks exactly one value from a short, fully-visible set โ sort order, range filter, equity tier. **Skip when** multiple values may be selected (use [`Chip variant="filter"`](../chip/filter.md) or [`Button variant="check"`](../button/check.md)), the set is long enough to demand a sheet-driven picker ([Select](../form-field/select.md)), or the row *only* navigates without selecting (use a [Standard](./standard.md) row with `nav: true`). When a value both selects *and* opens a deeper screen โ a major category โ keep Radio and add `nav: true` (see [Major category with a second screen](#major-category-with-a-second-screen)).
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Standard
|
|
2
2
|
|
|
3
|
+
> ๐ฐ๐ท ํ๊ตญ์ด: [`i18n/ko/schema/components/list/standard.md`](../../../i18n/ko/schema/components/list/standard.md)
|
|
4
|
+
|
|
3
5
|
The default [List](./list.md) sub โ display or navigation rows over the shared List anatomy. The whole row is the click target; there is no selection model. A row is text-only by default, opting into a **leading image** (40px [Thumbnail](../thumbnail/thumbnail.md) via `thumbnail`) or a **leading icon** (`sys.icon.lg` glyph via `icon`). Geometry, typography, divider, state overlays, and inward focus ring delegate to the [family-wide rules](./list.md).
|
|
4
6
|
|
|
5
7
|
**Layout inset.** `full-bleed` โ sits as a direct child of the page shell. Each row pays its own `16px inline / 8px block` padding via `layout.container.*`; do **not** wrap the list in another `padding-inline` / `px-*` / `style={{ padding: โฆ }}` div. Inside a bounded surface (Card / Dialog / BottomSheet / Sheet), apply the negative-margin opt-out โ see [`AGENTS.md` ยง Composition rules](../../../AGENTS.md#composition-rules).
|
|
@@ -179,6 +179,7 @@
|
|
|
179
179
|
"opacity": "sys.state.pressed"
|
|
180
180
|
}
|
|
181
181
|
},
|
|
182
|
+
"nestedActionScope": "The hover / pressed overlay is suppressed while the pointer sits on an independent trailing action (a `trailingIcon` button โ favorite / mute / Follow). The small control owns the state; the large row does NOT also read as hovered / pressed. The decorative nav chevron is exempt โ it is the row's own drill-in affordance, so hovering it still lights the whole row. The visual-state boundary matches the event boundary (the trailing action already stops propagation).",
|
|
182
183
|
"disabled": {
|
|
183
184
|
"containerOpacity": "sys.state.disabled",
|
|
184
185
|
"containerOpacityScope": "Dims the row content only โ the inter-row divider and the focus overlay keep full opacity, so a disabled row never fades the hairline rule between it and the next row.",
|
|
@@ -208,7 +209,7 @@
|
|
|
208
209
|
"keyboardNavigation": "Arrow up/down moves focus between rows. Home and End jump to first / last.",
|
|
209
210
|
"rowClickTarget": "Whole row is clickable when an `onClick` is bound to the item. A leading thumbnail is never a separate hit target.",
|
|
210
211
|
"navDrillIn": "A row with `nav: true` renders the trailing chevron and routes the user to another surface on click (consumer wires `onClick`). The chevron is decorative โ the whole row is the single click target, never the chevron alone.",
|
|
211
|
-
"trailingHitTarget": "Clicks inside `trailingIcon` stop propagating before they reach the row โ wire a favorite / mute / pin toggle or a Follow button there without it committing the row's primary action.",
|
|
212
|
+
"trailingHitTarget": "Clicks inside `trailingIcon` stop propagating before they reach the row โ wire a favorite / mute / pin toggle or a Follow button there without it committing the row's primary action. The slot is a separate hit target visually too: while the pointer hovers / presses it, the row's own hover / pressed overlay is suppressed so the large row never reads as active alongside the small control (the decorative nav chevron is exempt โ it lights the row).",
|
|
212
213
|
"truncationNotWrap": "Both label and supportingText truncate; the row never grows to fit long text."
|
|
213
214
|
},
|
|
214
215
|
"forbidden": [
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
# Compact
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> ๐ฐ๐ท ํ๊ตญ์ด: [`i18n/ko/schema/components/metadata/compact.md`](../../../i18n/ko/schema/components/metadata/compact.md)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
One-line channel-detail attribution. The slimmed [Standard](./standard.md) head โ it keeps the leading 32-rung avatar but drops the primary name line, follow toggle, and subtitle (the info that is unnecessary once the channel context is established). A leading avatar plus the meta-link row, with the posting time relocated to the line's trailing edge: avatar, then company name ยท nickname (optional role badge), then the timestamp โ the timestamp carries no leading middot, separated from the identity cluster by an 8px gap so it reads as a distinct trailing element.
|
|
6
6
|
|
|
7
|
-
**
|
|
7
|
+
**Reach for this when** a single text line is the budget and the channel context is already on screen โ channel-detail attribution, comment / reply rows. **Skip when** composing the head of a Feed Post or Feed Ad โ the avatar + two-line cluster (use [Standard](./standard.md)) โ or when the row is a generic entity directory entry with a trailing commit (use [list/entry](../list/entry.md)).
|
|
8
|
+
|
|
9
|
+
**Layout inset.** `inline` โ Compact ships no padding of its own. Sits inside whichever host row composes it; the host pays surrounding rhythm, divider, and tap target.
|
|
8
10
|
|
|
9
11
|
## Default
|
|
10
12
|
|
|
11
|
-
The canonical fill โ company name and nickname as independent links, plain timestamp last. Each middot keeps the family's `line-height: 1` rule so the dot never inflates the text line.
|
|
13
|
+
The canonical fill โ a leading 32-rung avatar, company name and nickname as independent links, plain timestamp last. Each middot keeps the family's `line-height: 1` rule so the dot never inflates the text line.
|
|
12
14
|
|
|
13
15
|
```preview
|
|
14
16
|
metadata/compact/default
|
|
@@ -17,6 +19,7 @@ import { Metadata } from '@teamblind-chorus/ui';
|
|
|
17
19
|
|
|
18
20
|
<Metadata
|
|
19
21
|
variant="compact"
|
|
22
|
+
avatar={{ src: '/bread-avatar.png', alt: 'Maple Mill Bakery' }}
|
|
20
23
|
meta={['Maple Mill Bakery', 'ryestarter']}
|
|
21
24
|
timestamp="35m"
|
|
22
25
|
/>
|
|
@@ -35,6 +38,7 @@ import { Metadata, Badge } from '@teamblind-chorus/ui';
|
|
|
35
38
|
|
|
36
39
|
<Metadata
|
|
37
40
|
variant="compact"
|
|
41
|
+
avatar={{ src: '/bread-avatar.png', alt: 'Maple Mill Bakery' }}
|
|
38
42
|
meta={[
|
|
39
43
|
'Maple Mill Bakery',
|
|
40
44
|
{ label: 'ryestarter', href: '#', badge: <Badge variant="role">Verified</Badge> },
|
|
@@ -45,7 +49,8 @@ import { Metadata, Badge } from '@teamblind-chorus/ui';
|
|
|
45
49
|
|
|
46
50
|
## Slots
|
|
47
51
|
|
|
48
|
-
- **
|
|
52
|
+
- **avatar** *(optional)* โ leading [Thumbnail](../thumbnail/thumbnail.md) at `size={32}`, identical to the Standard head. Vertically centered against the one-line meta cluster.
|
|
53
|
+
- **container** โ outer flex row (`align-items: center`) hosting the avatar and the single text line. `min-width: 0` so the line truncates inside a flexed host row.
|
|
49
54
|
- **meta** โ identity link row: company name then nickname, each its own `<a>`; siblings separate by middot; never wraps. An object item may carry `badge` โ one presentational mark after the link, outside the `<a>`.
|
|
50
55
|
- **timestamp** โ trailing plain-text posting time after the last middot. Never a link.
|
|
51
56
|
|
|
@@ -53,6 +58,7 @@ import { Metadata, Badge } from '@teamblind-chorus/ui';
|
|
|
53
58
|
|
|
54
59
|
| Slot | Token bindings |
|
|
55
60
|
|---------------|----------------|
|
|
61
|
+
| avatar | [Thumbnail](../thumbnail/thumbnail.md) `size={32}` |
|
|
56
62
|
| meta | `sys.typo.label.sm` / `sys.color.onSurfaceVariant`, links inherit; underline on hover |
|
|
57
63
|
| timestamp | `sys.typo.label.sm` / `sys.color.outline` |
|
|
58
64
|
| dot separator | `ยท` glyph, `color: sys.color.outline`, **`line-height: 1`** so its line-box equals its font-size โ never inflates the text line |
|
|
@@ -63,7 +69,7 @@ Compact Metadata itself has no lifecycle state. Each identity link carries its o
|
|
|
63
69
|
|
|
64
70
|
## Behavior
|
|
65
71
|
|
|
66
|
-
- **Dot height constrained.** Every middot separator (between identity items
|
|
72
|
+
- **Dot height constrained.** Every middot separator (between identity items) uses `line-height: 1` so its line-box matches its font-size โ same family-wide rule as the standard head. The timestamp carries no leading middot โ it is separated from the identity cluster by an 8px (`inline.md`) gap.
|
|
67
73
|
- **Independent affordances.** Identity items are independent `<a>` links โ taps land on the link, not the host row. The timestamp is plain text and never intercepts the row's own tap target.
|
|
68
74
|
- **Single line.** The cluster never wraps. When the host row is narrower than the cluster, the identity links truncate; the timestamp keeps its full width.
|
|
69
|
-
- **Time last.** The canonical order is company ยท nickname
|
|
75
|
+
- **Time last.** The canonical order is company ยท nickname, then the timestamp (no leading middot) โ the posting time always closes the line.
|