zdp-design-system 0.43.8 → 0.44.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/CHANGELOG.md +4 -0
- package/README.md +5 -0
- package/dist/ad-slot.ts +3 -0
- package/dist/components/AdSlot.svelte +135 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/index.ts +2 -0
- package/dist/styles/components.css +69 -0
- package/docs/CONSUMER_CONTRACT.md +6 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
- Added `AdSlot` plus static `.zdp-ad-slot` utilities for provider-neutral ad or sponsorship placement reservation while keeping provider scripts, consent, slot ids, `ads.txt`, personalized ads, and automatic content insertion in consuming apps.
|
|
6
|
+
- Documented the dependency adoption policy: active ZDP sibling consumers may keep `file:../zdp-design-system`, while standalone consumers, public templates, and external examples should use the npm package from `^0.44.0`.
|
|
7
|
+
- Added a single-component consumer fixture proof so the root barrel keeps tree-shaking unused component exports out of Button-only bundles.
|
|
8
|
+
|
|
5
9
|
## 0.43.8
|
|
6
10
|
|
|
7
11
|
- Added a publish-readiness check for package metadata, export targets, dist entries, and packaged public documents before npm release work.
|
package/README.md
CHANGED
|
@@ -99,6 +99,8 @@ import 'zdp-design-system/expressive-fonts.css';
|
|
|
99
99
|
|
|
100
100
|
패키지 export는 `dist/` 산출물을 가리킨다. root runtime entry는 `dist/index.js`, type entry는 `dist/index.d.ts`다. 원천은 `src/lib`, `src/styles`, `tokens/zdp.tokens.json`, `src/lib/share.ts`이고 `bun run package:build`가 소비자용 `dist/` 표면을 다시 만든다. 소비 저장소와 문서 예시는 `zdp-design-system` public export만 쓰고 내부 `src/` 경로를 직접 import하지 않는다.
|
|
101
101
|
|
|
102
|
+
ZDP monorepo 안의 active sibling 소비처는 `file:../zdp-design-system` 의존성을 유지할 수 있다. 이 방식은 release 전 변경을 같이 검증하기 위한 local workspace 계약이므로 CI에서 sibling checkout과 `bun run package:build`를 먼저 수행해야 한다. sibling checkout을 전제로 하지 않는 standalone consumer, public template, external example은 npm registry의 `zdp-design-system: ^0.44.0`을 기본으로 쓴다.
|
|
103
|
+
|
|
102
104
|
## 소비 컴포넌트 계약
|
|
103
105
|
|
|
104
106
|
- Breadcrumb는 현재 위치 탐색을 `nav`로 표현하고, 제품 라우팅 판단은 소비 앱이 한다.
|
|
@@ -108,6 +110,7 @@ import 'zdp-design-system/expressive-fonts.css';
|
|
|
108
110
|
- Avatar와 IdentityChip은 사람, 팀, 계정의 짧은 식별 표면이다.
|
|
109
111
|
- CommandField는 검색 입력 primitive이며 shortcut keycap, `ariaKeyShortcuts`, `ariaAutocomplete`, result id 연결, 입력 keydown callback은 제공하되 실제 검색 로직, 결과 목록, command palette 실행은 소비 앱이 소유한다.
|
|
110
112
|
- Combobox는 검색 가능한 단일 선택 입력의 frame, listbox, keyboard navigation, disabled option skip, hidden submitted value만 제공한다. 실제 필터링, async search, command 실행, 권한 판단은 소비 앱이 계속 소유한다.
|
|
113
|
+
- AdSlot은 광고나 후원 자리의 reserved layout, accessible label, placement/state data attribute만 제공한다. provider script, consent, slot id, ads.txt, personalized ads 판단은 소비 앱이 계속 소유한다.
|
|
111
114
|
- InlineCode와 CodeBlock은 문서, 보안, 아키텍처 화면의 코드 표면이다.
|
|
112
115
|
- Icon은 장식용 glyph 기본값을 갖고, 의미 있는 아이콘은 소비 컴포넌트가 접근성 이름을 제공한다.
|
|
113
116
|
- Link는 일반 텍스트 링크이며 버튼처럼 보이는 destructive action으로 쓰지 않는다.
|
|
@@ -142,6 +145,7 @@ Svelte 또는 Tauri(Svelte) 표면은 컴포넌트를 직접 가져온다.
|
|
|
142
145
|
<script lang="ts">
|
|
143
146
|
import {
|
|
144
147
|
Accordion,
|
|
148
|
+
AdSlot,
|
|
145
149
|
Avatar,
|
|
146
150
|
Badge,
|
|
147
151
|
Breadcrumb,
|
|
@@ -456,6 +460,7 @@ Astro는 `styles.css`를 전역으로 불러오고, Svelte island가 필요한
|
|
|
456
460
|
| 시트 / 드로어 | `.zdp-sheet` |
|
|
457
461
|
| 상태 알림 | `.zdp-toast` `.zdp-status-toast` |
|
|
458
462
|
| 로딩 / 진행 | `.zdp-progress` `.zdp-spinner` `.zdp-skeleton` |
|
|
463
|
+
| 광고 / 후원 자리 | `.zdp-ad-slot` `.zdp-ad-slot--inline|banner|rail|between-sections` |
|
|
459
464
|
| 아이콘 | `.zdp-icon` `.zdp-icon--sm|md` |
|
|
460
465
|
| 표 | `.zdp-table-wrap` `.zdp-table` `.zdp-sort-header` `.zdp-table-toolbar` |
|
|
461
466
|
| 페이지네이션 | `.zdp-pagination` |
|
package/dist/ad-slot.ts
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { ZdpAdSlotPlacement, ZdpAdSlotState } from '../ad-slot';
|
|
3
|
+
|
|
4
|
+
type DescribedBy = string | readonly string[] | null;
|
|
5
|
+
|
|
6
|
+
export let placement: ZdpAdSlotPlacement = 'inline';
|
|
7
|
+
export let state: ZdpAdSlotState = 'pending';
|
|
8
|
+
export let label = 'Advertisement';
|
|
9
|
+
export let fallbackText: string | null = null;
|
|
10
|
+
export let minHeight: string | null = null;
|
|
11
|
+
export let reserved = true;
|
|
12
|
+
export let id: string | null = null;
|
|
13
|
+
export let describedBy: DescribedBy = null;
|
|
14
|
+
|
|
15
|
+
// Only blocked/empty states render a neutral fallback; provider markup stays consumer-owned.
|
|
16
|
+
$: showFallback = state === 'blocked' || state === 'empty';
|
|
17
|
+
$: resolvedFallbackText = fallbackText ?? label;
|
|
18
|
+
$: reservedHeight = reserved ? minHeight ?? defaultMinHeight(placement) : null;
|
|
19
|
+
$: ariaDescribedBy = normalizeIdRefs(describedBy);
|
|
20
|
+
|
|
21
|
+
function defaultMinHeight(currentPlacement: ZdpAdSlotPlacement): string {
|
|
22
|
+
switch (currentPlacement) {
|
|
23
|
+
case 'banner':
|
|
24
|
+
return '5.5rem';
|
|
25
|
+
case 'rail':
|
|
26
|
+
return '12rem';
|
|
27
|
+
case 'between-sections':
|
|
28
|
+
return '4rem';
|
|
29
|
+
default:
|
|
30
|
+
return '4rem';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function normalizeIdRefs(value: DescribedBy): string | null {
|
|
35
|
+
if (value === null) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (typeof value === 'string') {
|
|
40
|
+
const normalized = value.trim();
|
|
41
|
+
return normalized ? normalized : null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const normalized = value.map((entry) => entry.trim()).filter(Boolean);
|
|
45
|
+
return normalized.length > 0 ? normalized.join(' ') : null;
|
|
46
|
+
}
|
|
47
|
+
</script>
|
|
48
|
+
|
|
49
|
+
<aside
|
|
50
|
+
class={`zdp-ad-slot zdp-ad-slot--${placement} zdp-ad-slot--${state}${reserved ? ' zdp-ad-slot--reserved' : ''}`}
|
|
51
|
+
id={id ?? undefined}
|
|
52
|
+
aria-label={label}
|
|
53
|
+
aria-describedby={ariaDescribedBy ?? undefined}
|
|
54
|
+
data-zdp-ad-slot
|
|
55
|
+
data-zdp-ad-placement={placement}
|
|
56
|
+
data-zdp-ad-state={state}
|
|
57
|
+
data-zdp-ad-reserved={reserved ? 'true' : 'false'}
|
|
58
|
+
style:min-height={reservedHeight}
|
|
59
|
+
>
|
|
60
|
+
{#if showFallback}
|
|
61
|
+
<p class="zdp-ad-slot__fallback">{resolvedFallbackText}</p>
|
|
62
|
+
{/if}
|
|
63
|
+
<slot />
|
|
64
|
+
</aside>
|
|
65
|
+
|
|
66
|
+
<style>
|
|
67
|
+
.zdp-ad-slot {
|
|
68
|
+
align-content: center;
|
|
69
|
+
align-items: center;
|
|
70
|
+
background: var(--zdp-color-surface-panel);
|
|
71
|
+
border: var(--zdp-control-border-width) solid var(--zdp-color-line-subtle);
|
|
72
|
+
border-radius: var(--zdp-control-radius);
|
|
73
|
+
box-sizing: border-box;
|
|
74
|
+
color: var(--zdp-color-ink-muted);
|
|
75
|
+
display: grid;
|
|
76
|
+
font-family: var(--zdp-font-family-sans);
|
|
77
|
+
justify-items: stretch;
|
|
78
|
+
min-width: 0;
|
|
79
|
+
overflow-wrap: var(--zdp-i18n-overflow-wrap);
|
|
80
|
+
padding: var(--zdp-space-3);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.zdp-ad-slot--reserved {
|
|
84
|
+
overflow: hidden;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.zdp-ad-slot--banner {
|
|
88
|
+
inline-size: 100%;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.zdp-ad-slot--between-sections {
|
|
92
|
+
inline-size: 100%;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.zdp-ad-slot--rail {
|
|
96
|
+
align-content: start;
|
|
97
|
+
block-size: 100%;
|
|
98
|
+
inline-size: 100%;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.zdp-ad-slot--filled {
|
|
102
|
+
color: var(--zdp-color-ink-normal);
|
|
103
|
+
padding: 0;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.zdp-ad-slot--filled :global(*) {
|
|
107
|
+
margin: 0;
|
|
108
|
+
max-inline-size: 100%;
|
|
109
|
+
min-width: 0;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.zdp-ad-slot__fallback {
|
|
113
|
+
color: var(--zdp-color-ink-muted);
|
|
114
|
+
font-size: var(--zdp-type-caption-size);
|
|
115
|
+
justify-self: center;
|
|
116
|
+
line-height: var(--zdp-type-caption-line-height);
|
|
117
|
+
margin: 0;
|
|
118
|
+
text-align: center;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.zdp-ad-slot--blocked {
|
|
122
|
+
border-color: var(--zdp-color-line-strong);
|
|
123
|
+
border-style: dashed;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.zdp-ad-slot--empty .zdp-ad-slot__fallback {
|
|
127
|
+
opacity: 0.72;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
@media (max-width: 48rem) {
|
|
131
|
+
.zdp-ad-slot--rail {
|
|
132
|
+
block-size: auto;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
</style>
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { default as Accordion } from './components/Accordion.svelte';
|
|
2
|
+
export { default as AdSlot } from './components/AdSlot.svelte';
|
|
2
3
|
export { default as Avatar } from './components/Avatar.svelte';
|
|
3
4
|
export { default as Badge } from './components/Badge.svelte';
|
|
4
5
|
export { default as Breadcrumb } from './components/Breadcrumb.svelte';
|
|
@@ -68,6 +69,7 @@ export type { ZdpComboboxOption, ZdpComboboxSize } from './combobox';
|
|
|
68
69
|
export type { ZdpCommandFieldSize } from './command';
|
|
69
70
|
export type { ZdpCodeBlockSize, ZdpCodeBlockTone } from './code';
|
|
70
71
|
export type { ZdpAccordionItem, ZdpAccordionMode, ZdpDisclosureHeadingLevel } from './disclosure';
|
|
72
|
+
export type { ZdpAdSlotPlacement, ZdpAdSlotState } from './ad-slot';
|
|
71
73
|
export type {
|
|
72
74
|
ZdpAvatarSize,
|
|
73
75
|
ZdpAvatarTone,
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { default as Accordion } from './components/Accordion.svelte';
|
|
2
|
+
export { default as AdSlot } from './components/AdSlot.svelte';
|
|
2
3
|
export { default as Avatar } from './components/Avatar.svelte';
|
|
3
4
|
export { default as Badge } from './components/Badge.svelte';
|
|
4
5
|
export { default as Breadcrumb } from './components/Breadcrumb.svelte';
|
package/dist/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { default as Accordion } from './components/Accordion.svelte';
|
|
2
|
+
export { default as AdSlot } from './components/AdSlot.svelte';
|
|
2
3
|
export { default as Avatar } from './components/Avatar.svelte';
|
|
3
4
|
export { default as Badge } from './components/Badge.svelte';
|
|
4
5
|
export { default as Breadcrumb } from './components/Breadcrumb.svelte';
|
|
@@ -68,6 +69,7 @@ export type { ZdpComboboxOption, ZdpComboboxSize } from './combobox';
|
|
|
68
69
|
export type { ZdpCommandFieldSize } from './command';
|
|
69
70
|
export type { ZdpCodeBlockSize, ZdpCodeBlockTone } from './code';
|
|
70
71
|
export type { ZdpAccordionItem, ZdpAccordionMode, ZdpDisclosureHeadingLevel } from './disclosure';
|
|
72
|
+
export type { ZdpAdSlotPlacement, ZdpAdSlotState } from './ad-slot';
|
|
71
73
|
export type {
|
|
72
74
|
ZdpAvatarSize,
|
|
73
75
|
ZdpAvatarTone,
|
|
@@ -4684,3 +4684,72 @@
|
|
|
4684
4684
|
}
|
|
4685
4685
|
|
|
4686
4686
|
}
|
|
4687
|
+
|
|
4688
|
+
.zdp-ad-slot {
|
|
4689
|
+
align-content: center;
|
|
4690
|
+
align-items: center;
|
|
4691
|
+
background: var(--zdp-color-surface-panel);
|
|
4692
|
+
border: var(--zdp-control-border-width) solid var(--zdp-color-line-subtle);
|
|
4693
|
+
border-radius: var(--zdp-control-radius);
|
|
4694
|
+
box-sizing: border-box;
|
|
4695
|
+
color: var(--zdp-color-ink-muted);
|
|
4696
|
+
display: grid;
|
|
4697
|
+
font-family: var(--zdp-font-family-sans);
|
|
4698
|
+
justify-items: stretch;
|
|
4699
|
+
min-width: 0;
|
|
4700
|
+
overflow-wrap: var(--zdp-i18n-overflow-wrap);
|
|
4701
|
+
padding: var(--zdp-space-3);
|
|
4702
|
+
}
|
|
4703
|
+
|
|
4704
|
+
.zdp-ad-slot--reserved {
|
|
4705
|
+
overflow: hidden;
|
|
4706
|
+
}
|
|
4707
|
+
|
|
4708
|
+
.zdp-ad-slot--banner {
|
|
4709
|
+
inline-size: 100%;
|
|
4710
|
+
}
|
|
4711
|
+
|
|
4712
|
+
.zdp-ad-slot--between-sections {
|
|
4713
|
+
inline-size: 100%;
|
|
4714
|
+
}
|
|
4715
|
+
|
|
4716
|
+
.zdp-ad-slot--rail {
|
|
4717
|
+
align-content: start;
|
|
4718
|
+
block-size: 100%;
|
|
4719
|
+
inline-size: 100%;
|
|
4720
|
+
}
|
|
4721
|
+
|
|
4722
|
+
.zdp-ad-slot--filled {
|
|
4723
|
+
color: var(--zdp-color-ink-normal);
|
|
4724
|
+
padding: 0;
|
|
4725
|
+
}
|
|
4726
|
+
|
|
4727
|
+
.zdp-ad-slot--filled > * {
|
|
4728
|
+
margin: 0;
|
|
4729
|
+
max-inline-size: 100%;
|
|
4730
|
+
min-width: 0;
|
|
4731
|
+
}
|
|
4732
|
+
|
|
4733
|
+
.zdp-ad-slot__fallback {
|
|
4734
|
+
color: var(--zdp-color-ink-muted);
|
|
4735
|
+
font-size: var(--zdp-type-caption-size);
|
|
4736
|
+
justify-self: center;
|
|
4737
|
+
line-height: var(--zdp-type-caption-line-height);
|
|
4738
|
+
margin: 0;
|
|
4739
|
+
text-align: center;
|
|
4740
|
+
}
|
|
4741
|
+
|
|
4742
|
+
.zdp-ad-slot--blocked {
|
|
4743
|
+
border-color: var(--zdp-color-line-strong);
|
|
4744
|
+
border-style: dashed;
|
|
4745
|
+
}
|
|
4746
|
+
|
|
4747
|
+
.zdp-ad-slot--empty .zdp-ad-slot__fallback {
|
|
4748
|
+
opacity: 0.72;
|
|
4749
|
+
}
|
|
4750
|
+
|
|
4751
|
+
@media (max-width: 48rem) {
|
|
4752
|
+
.zdp-ad-slot--rail {
|
|
4753
|
+
block-size: auto;
|
|
4754
|
+
}
|
|
4755
|
+
}
|
|
@@ -10,6 +10,8 @@ Default component text is English. 소비 앱은 화면 locale에 맞춰 user-fa
|
|
|
10
10
|
- 디자인 시스템은 색상, 타입, 간격, radius, focus, i18n, control metric, shared component API만 제공한다.
|
|
11
11
|
- 소비 저장소는 `zdp-design-system`의 public export만 사용하고 내부 `src/` deep import를 만들지 않는다.
|
|
12
12
|
- package export는 `dist/` 산출물을 통해 소비한다. root runtime entry는 `dist/index.js`, type entry는 `dist/index.d.ts`다. 원천은 `src/lib`, `src/styles`, `tokens/zdp.tokens.json`, `src/lib/share.ts`이고 `dist/`는 release 전 `bun run package:build`로 다시 만든다.
|
|
13
|
+
- ZDP monorepo 안의 active sibling 소비처는 unpublished local changes와 package surface를 함께 검증하기 위해 `file:../zdp-design-system`을 유지할 수 있다. 이 경우 CI는 sibling `zdp-design-system`을 checkout하고 `bun run package:build`를 먼저 실행해야 한다.
|
|
14
|
+
- standalone consumer, public template, external example처럼 sibling checkout을 전제로 하지 않는 표면은 npm registry package를 사용한다. 0.44.0 이상에서는 `zdp-design-system: ^0.44.0`을 기본 semver 범위로 쓰고, 재현 가능한 release proof가 필요한 곳만 exact version을 pin한다.
|
|
13
15
|
- `zdpTokenNames`, `share.js`, `share.d.ts`는 손으로 맞추지 않고 `tokens:generate`, `share-icons:generate` 산출물로 유지한다.
|
|
14
16
|
- 새 버전은 소비 저장소가 opt-in으로 채택한다. broad adoption 전에는 대표 소비처에서 시각과 build를 확인한다.
|
|
15
17
|
- keyboard focus, flat UI, framed control, Pretendard-first font stack은 소비처에서 임의로 낮추지 않는다.
|
|
@@ -56,6 +58,7 @@ Svelte island 없이 정적 HTML만 쓰는 곳은 스크린리더 전용 보조
|
|
|
56
58
|
반복 카드나 요약 묶음은 `.zdp-grid`, 가까운 화면 도구와 액션 묶음은 `.zdp-toolbar` utility로 맞춘다.
|
|
57
59
|
CommandField는 검색, 빠른 이동, 명령 팔레트 진입처럼 짧은 keyboard affordance가 필요한 입력에 `CommandField` 또는 `.zdp-command-field-shell`, `.zdp-command-field`, `.zdp-command-field__input`, `.zdp-command-field__shortcut`, `.zdp-kbd`, `.zdp-shortcut-hint` utility로 맞춘다.
|
|
58
60
|
Combobox는 검색 가능한 단일 선택에 `Combobox` 또는 `.zdp-combobox`, `.zdp-combobox__control`, `.zdp-combobox__input`, `.zdp-combobox__listbox`, `.zdp-combobox__option` utility로 맞춘다. option source, filtering, async loading, command 실행, 권한 판단은 소비처가 소유한다.
|
|
61
|
+
AdSlot은 광고나 후원 자리의 reserved layout, accessible label, placement/state data attribute만 제공한다. `AdSlot` 또는 `.zdp-ad-slot`, `data-zdp-ad-slot`, `data-zdp-ad-placement`, `data-zdp-ad-state` utility로 자리를 예약하되 provider script, consent, slot id, ads.txt, personalized ads 판단은 소비 앱이 계속 소유한다.
|
|
59
62
|
문서, 보안, 아키텍처 페이지의 코드 조각은 `InlineCode`, `CodeBlock`, `.zdp-inline-code`, `.zdp-code-block`, `.zdp-code-block__copy` utility로 맞춘다.
|
|
60
63
|
사람, 팀, 조직의 짧은 표기는 `.zdp-avatar`, `.zdp-avatar__initials`, `.zdp-identity-chip`, `.zdp-identity-chip__label` utility로 맞추되 실제 계정 식별, 프로필 라우팅, 온라인 상태, 권한, 초대 가능 여부 판단은 소비처가 소유한다.
|
|
61
64
|
테마 전환 버튼은 `.zdp-theme-toggle`, `.zdp-theme-toggle__icon`, `data-zdp-theme-state` utility로 맞추되 초기 테마 결정, 사용자 저장소, 시스템 선호도, SSR/초기 paint 처리는 소비처가 소유한다.
|
|
@@ -84,6 +87,7 @@ Svelte, SvelteKit, Tauri Svelte WebView는 package root에서 shared component
|
|
|
84
87
|
<script lang="ts">
|
|
85
88
|
import {
|
|
86
89
|
Accordion,
|
|
90
|
+
AdSlot,
|
|
87
91
|
Avatar,
|
|
88
92
|
Breadcrumb,
|
|
89
93
|
Button,
|
|
@@ -390,6 +394,7 @@ Grid는 반복되는 카드, 요약, 선택지 묶음의 responsive columns와 g
|
|
|
390
394
|
Toolbar는 가까운 화면 도구와 액션 묶음의 wrapping, main/action 배치만 제공하며 저장, 삭제, 필터, 권한 판단은 소비 앱이 계속 소유한다.
|
|
391
395
|
CommandField는 검색 입력의 label, frame, focus-within, shortcut keycap, help/error id, `ariaKeyShortcuts`, `ariaAutocomplete`, result id 연결, 입력 keydown callback만 제공하며 검색 인덱스, 결과 정렬, command palette, 라우팅, 권한 판단은 소비 앱이 계속 소유한다. 결과 목록, keyboard dispatcher, command 실행 상태는 소비 앱이 계속 소유한다.
|
|
392
396
|
Combobox는 검색 가능한 단일 선택의 label, input frame, listbox, active option, disabled option skip, hidden submitted value만 제공한다. 실제 필터링, async search, command 실행, 권한 판단은 소비 앱이 계속 소유한다. 단순 상태 선택은 native `Select`를 유지하고, 사용자가 입력으로 후보를 좁히는 단일 선택일 때만 Combobox를 쓴다.
|
|
397
|
+
AdSlot은 광고나 후원 자리의 reserved layout, accessible label, placement/state data attribute만 제공한다. `placement`는 `inline`, `banner`, `rail`, `between-sections` 같은 layout hint이고, `state`는 `pending`, `filled`, `empty`, `blocked` 같은 표시 상태다. provider markup은 slot으로 소비 앱이 넣고, provider script, consent, slot id, ads.txt, personalized ads 판단은 소비 앱이 계속 소유한다.
|
|
393
398
|
InlineCode와 CodeBlock은 문서, 보안, 아키텍처 페이지의 코드 표시, language label, horizontal overflow, 선택적 복사 버튼만 제공하며 syntax highlighting, 코드 실행, 비밀값 탐지, 보안 분류, command palette는 소비 앱이나 문서 파이프라인이 계속 소유한다. CodeBlock은 `code` prop이 있을 때만 복사 버튼을 노출하므로 slot으로 표시한 코드의 복사 문자열은 소비 앱이 명시적으로 넘긴다. 긴 코드는 기본적으로 horizontal overflow 표면에서 스크롤되고, code body는 선택 가능해야 한다.
|
|
394
399
|
|
|
395
400
|
Kbd와 ShortcutHint는 `/`, `?`, `Enter`, `Esc`, `ArrowUp`, `ArrowDown`, `Ctrl/⌘+Enter` 같은 키캡 힌트만 제공한다. 실제 keydown dispatcher, command palette, 검색 focus 이동, 단축키 안내, 선택, 닫기, 파일 이동은 소비 앱이 소유한다. `ariaKeyShortcuts`와 `aria-keyshortcuts`는 실제 단축키가 동작하는 Button, IconButton, Link, CommandField에만 붙인다. 소비 앱의 전역 단축키 dispatcher는 `shouldZdpIgnoreShortcutEvent`, `isZdpTextEntryTarget`, `isZdpBrowserReservedShortcut`, `zdpShortcutRecommendations`, `zdpShortcutReservedExamples` 같은 shortcut policy helper로 입력창, IME 조합, 브라우저 예약 조합을 먼저 걸러낸다. `input, textarea, select, contenteditable`, `role="textbox"`, `role="searchbox"` 안에서는 전역 단축키를 꺼두고, `event.isComposing` 또는 `keyCode === 229`인 한국어 조합 입력도 무시한다. `Ctrl+K`, `Ctrl+S`처럼 Chrome과 브라우저가 기본 동작으로 가져가는 조합은 소비 앱에서 실제로 가로채고 검증한 경우가 아니면 예시나 UI 힌트로 보여주지 않는다.
|
|
@@ -441,6 +446,7 @@ Flutter와 native shell은 Svelte 컴포넌트를 직접 소비하지 않는다.
|
|
|
441
446
|
- Toolbar를 쓰는 화면은 가까운 도구와 액션 wrapping만 바뀌고 저장, 삭제, 필터, 권한 판단이 생기지 않는지 확인한다.
|
|
442
447
|
- CommandField를 쓰는 화면은 label, help/error id, Tab focus, `/` 같은 shortcut 표시가 맞고, 실제 검색/라우팅/command 실행 판단은 소비 앱에 남는지 확인한다.
|
|
443
448
|
- Combobox를 쓰는 화면은 combobox/listbox/option aria 구조, ArrowUp/ArrowDown/Enter/Escape 동작, disabled option skip, hidden submitted value가 맞고, 실제 필터링, async search, command 실행, 권한 판단은 소비 앱에 남는지 확인한다.
|
|
449
|
+
- AdSlot을 쓰는 화면은 `data-zdp-ad-slot`, placement/state attribute, reserved size가 남고, provider script, consent, slot id, ads.txt, personalized ads 판단이 소비 앱에 남는지 확인한다.
|
|
444
450
|
- Kbd와 ShortcutHint를 쓰는 화면은 보이는 단축키가 실제로 동작하는지 확인한다. 동작하지 않는 힌트는 제거하고, 실제 단축키가 있는 control에만 `ariaKeyShortcuts`를 붙인다.
|
|
445
451
|
- Avatar와 IdentityChip을 쓰는 화면은 이름, 이니셜, 보조 텍스트, 현재 링크 상태만 표면에 남고, 실제 계정 식별, 온라인 상태, 권한, 초대 가능 여부 판단은 소비 앱 상태와 맞는지 확인한다.
|
|
446
452
|
- Accordion과 Disclosure를 쓰는 화면은 trigger에 `aria-expanded`와 `aria-controls`가 남고, 실제 항목 노출, 권한, 데이터 fetch 판단은 소비 앱 상태와 맞는지 확인한다.
|