@hjmds/design-contracts 1.15.0 → 1.16.1
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/dist/collection-rail.d.ts +42 -0
- package/dist/collection-rail.d.ts.map +1 -0
- package/dist/collection-rail.js +88 -0
- package/dist/collection-rail.js.map +1 -0
- package/dist/design-profile.d.ts +2 -5
- package/dist/design-profile.d.ts.map +1 -1
- package/dist/design-profile.js +16 -3
- package/dist/design-profile.js.map +1 -1
- package/dist/effect-surface.d.ts +7 -1
- package/dist/effect-surface.d.ts.map +1 -1
- package/dist/effect-surface.js +7 -1
- package/dist/effect-surface.js.map +1 -1
- package/dist/foundations.d.ts +13 -2
- package/dist/foundations.d.ts.map +1 -1
- package/dist/foundations.js +22 -2
- package/dist/foundations.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/docs/auth-screen.md +6 -1
- package/docs/collection-rail.md +48 -0
- package/docs/design-profile.md +40 -3
- package/docs/effect-surface.md +27 -1
- package/docs/file-picker.md +6 -0
- package/docs/floating-action-button.md +9 -0
- package/docs/font-roles.md +50 -0
- package/docs/generated/component-maturity.md +1 -1
- package/docs/generated/renderer-evidence.json +3 -3
- package/docs/generated/renderer-evidence.md +1 -1
- package/docs/generated/showcase-manifest.json +1 -1
- package/docs/menubar.md +6 -0
- package/docs/screen-patterns.md +4 -0
- package/docs/sidebar.md +6 -0
- package/docs/skip-nav.md +6 -0
- package/docs/toast.md +9 -0
- package/docs/toggle-group.md +5 -0
- package/docs/top.md +6 -0
- package/docs/transfer-list.md +6 -0
- package/docs/upload-item.md +6 -0
- package/docs/usage/README.md +8 -5
- package/docs/usage/components/auth-screen-layout.md +6 -2
- package/docs/usage/components/comment-thread-screen.md +12 -5
- package/docs/usage/components/design-system-provider.md +10 -1
- package/docs/usage/components/effect-surface.md +5 -1
- package/docs/usage/components/file-picker.md +7 -1
- package/docs/usage/components/floating-action-button.md +11 -1
- package/docs/usage/components/heading.md +3 -0
- package/docs/usage/components/list.md +77 -0
- package/docs/usage/components/menubar.md +6 -0
- package/docs/usage/components/overview-screen.md +6 -4
- package/docs/usage/components/sidebar.md +7 -1
- package/docs/usage/components/skip-nav.md +7 -1
- package/docs/usage/components/surface.md +9 -0
- package/docs/usage/components/text.md +2 -1
- package/docs/usage/components/toast.md +9 -0
- package/docs/usage/components/toggle-group.md +9 -1
- package/docs/usage/components/top.md +7 -1
- package/docs/usage/components/transfer-list.md +7 -1
- package/docs/usage/components/upload-item.md +6 -0
- package/docs/usage/compositions/collection-detail.md +91 -0
- package/docs/usage/compositions/command-records.md +4 -4
- package/docs/usage/compositions/content-transition-comparison.md +11 -5
- package/docs/usage/compositions/date-time-selection.md +4 -4
- package/docs/usage/compositions/design-profile-comparison.md +15 -4
- package/docs/usage/compositions/paper-surface.md +101 -0
- package/docs/usage/screens/common-comments.md +6 -2
- package/docs/usage/tokens/font-roles.md +87 -0
- package/docs/usage/tokens/typography.md +3 -0
- package/package.json +7 -1
package/dist/foundations.js
CHANGED
|
@@ -18,8 +18,8 @@ export const radius = {
|
|
|
18
18
|
};
|
|
19
19
|
/**
|
|
20
20
|
* Ordered fallbacks keep the contract platform-neutral: Web renderers join
|
|
21
|
-
* the list as a CSS stack, while native renderers
|
|
22
|
-
*
|
|
21
|
+
* the list as a CSS stack, while native renderers request the first named
|
|
22
|
+
* family (or their OS default mapping), rather than receiving a CSS stack.
|
|
23
23
|
*/
|
|
24
24
|
export const fontFamily = {
|
|
25
25
|
ui: [
|
|
@@ -38,6 +38,13 @@ export const fontFamily = {
|
|
|
38
38
|
"monospace",
|
|
39
39
|
],
|
|
40
40
|
};
|
|
41
|
+
export function resolveFontFamilyStack(families, role) {
|
|
42
|
+
if (!["ui", "display", "reading", "code"].includes(role))
|
|
43
|
+
throw new TypeError("Unsupported font role");
|
|
44
|
+
// Unspecified reading/display follow the current ui stack, rather than a
|
|
45
|
+
// frozen neutral stack that would silently undo an app's existing ui override.
|
|
46
|
+
return families[role] ?? families.ui;
|
|
47
|
+
}
|
|
41
48
|
/** String weights translate unchanged to CSS and React Native text styles. */
|
|
42
49
|
export const fontWeight = {
|
|
43
50
|
regular: "400",
|
|
@@ -66,6 +73,19 @@ export const typography = {
|
|
|
66
73
|
titleLarge: { fontSize: 20, lineHeight: 28, fontWeight: fontWeight.heavy },
|
|
67
74
|
heading: { fontSize: 24, lineHeight: 32, fontWeight: fontWeight.heavy },
|
|
68
75
|
};
|
|
76
|
+
/** Visual variants choose a default family role; semantics and sizes remain independent. */
|
|
77
|
+
export function resolveTextFontRole(variant, role) {
|
|
78
|
+
if (role !== undefined) {
|
|
79
|
+
if (!["ui", "display", "reading", "code"].includes(role))
|
|
80
|
+
throw new TypeError("Unsupported font role");
|
|
81
|
+
return role;
|
|
82
|
+
}
|
|
83
|
+
if (variant === "body" || variant === "bodyLarge")
|
|
84
|
+
return "reading";
|
|
85
|
+
if (variant === "title" || variant === "titleLarge" || variant === "heading")
|
|
86
|
+
return "display";
|
|
87
|
+
return "ui";
|
|
88
|
+
}
|
|
69
89
|
/**
|
|
70
90
|
* Document heading hierarchy without widening the established `TextVariant`
|
|
71
91
|
* union. Levels 3–5 reuse the existing semantic styles; larger levels are
|
package/dist/foundations.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"foundations.js","sourceRoot":"","sources":["../src/foundations.ts"],"names":[],"mappings":"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","sourcesContent":["/** Numeric units are consumed as CSS pixels on web and density-independent points on native. */\nexport const spacing = {\n xxs: 4,\n xs: 8,\n sm: 12,\n md: 16,\n lg: 20,\n xl: 24,\n xxl: 32,\n xxxl: 40,\n} as const;\n\nexport const radius = {\n sm: 8,\n md: 12,\n lg: 16,\n xl: 24,\n full: 999,\n} as const;\n\n/**\n * Ordered fallbacks keep the contract platform-neutral: Web renderers join\n * the list as a CSS stack, while native renderers select the first family\n * available on the device instead of receiving a CSS-only string.\n */\nexport const fontFamily = {\n ui: [\n \"Inter\",\n \"Pretendard\",\n \"-apple-system\",\n \"BlinkMacSystemFont\",\n \"Segoe UI\",\n \"sans-serif\",\n ],\n code: [\n \"ui-monospace\",\n \"SFMono-Regular\",\n \"Consolas\",\n \"Liberation Mono\",\n \"monospace\",\n ],\n} as const;\n\nexport type FontFamily = keyof typeof fontFamily;\n\n/** String weights translate unchanged to CSS and React Native text styles. */\nexport const fontWeight = {\n regular: \"400\",\n medium: \"500\",\n semibold: \"600\",\n bold: \"700\",\n heavy: \"800\",\n} as const;\n\nexport type FontWeight = keyof typeof fontWeight;\nexport type FontWeightValue = (typeof fontWeight)[FontWeight];\n\n/** Numeric tracking uses CSS pixels on Web and density-independent points on Native. */\nexport const letterSpacing = {\n tight: -0.2,\n normal: 0,\n wide: 0.2,\n} as const;\n\nexport type LetterSpacing = keyof typeof letterSpacing;\n\n/** Renderers map the shared intent to `font-variant-numeric` / `fontVariant`. */\nexport const numeric = {\n proportional: \"proportional-nums\",\n tabular: \"tabular-nums\",\n} as const;\n\nexport type NumericVariant = keyof typeof numeric;\n\nexport const typography = {\n caption: { fontSize: 11, lineHeight: 16, fontWeight: fontWeight.regular },\n label: { fontSize: 12, lineHeight: 18, fontWeight: fontWeight.semibold },\n body: { fontSize: 14, lineHeight: 20, fontWeight: fontWeight.regular },\n bodyLarge: { fontSize: 16, lineHeight: 24, fontWeight: fontWeight.regular },\n title: { fontSize: 18, lineHeight: 26, fontWeight: fontWeight.bold },\n titleLarge: { fontSize: 20, lineHeight: 28, fontWeight: fontWeight.heavy },\n heading: { fontSize: 24, lineHeight: 32, fontWeight: fontWeight.heavy },\n} as const;\n\nexport type TextVariant = keyof typeof typography;\n\n/**\n * Document heading hierarchy without widening the established `TextVariant`\n * union. Levels 3–5 reuse the existing semantic styles; larger levels are\n * additive display roles for dense product pages and documentation.\n */\nexport const heading = {\n level1: { fontSize: 40, lineHeight: 48, fontWeight: fontWeight.heavy },\n level2: { fontSize: 32, lineHeight: 40, fontWeight: fontWeight.heavy },\n level3: typography.heading,\n level4: typography.titleLarge,\n level5: typography.title,\n} as const;\n\nexport type HeadingLevel = keyof typeof heading;\n\n/** Glyphs include icons and avatars; they do not inherit paragraph line-height. */\nexport const glyph = {\n xs: 14,\n sm: 20,\n md: 24,\n lg: 28,\n xl: 32,\n xxl: 44,\n xxxl: 48,\n} as const;\n\nexport type GlyphSize = keyof typeof glyph;\n\nexport const motion = {\n fast: 120,\n normal: 200,\n slow: 320,\n} as const;\n\n/**\n * Curves are stored as normalized cubic-bezier tuples so CSS and native\n * animation drivers can translate the same motion intent without sharing a\n * renderer dependency.\n */\nexport const easing = {\n standard: [0.2, 0, 0, 1],\n enter: [0, 0, 0, 1],\n exit: [0.3, 0, 1, 1],\n emphasized: [0.2, 0, 0, 1],\n} as const;\n\nexport type ReducedMotionBehavior = \"instant\" | \"opacity\" | \"static\";\n\n/** Shared transition intent; renderers translate easing tuples to their animation API. */\nexport const motionPreset = {\n micro: {\n duration: motion.fast,\n easing: \"standard\",\n reducedMotion: \"instant\",\n },\n enter: {\n duration: motion.normal,\n easing: \"enter\",\n reducedMotion: \"opacity\",\n },\n exit: {\n duration: motion.fast,\n easing: \"exit\",\n reducedMotion: \"instant\",\n },\n context: {\n duration: motion.slow,\n easing: \"emphasized\",\n reducedMotion: \"opacity\",\n },\n} as const satisfies Record<\n \"micro\" | \"enter\" | \"exit\" | \"context\",\n {\n duration: number;\n easing: keyof typeof easing;\n reducedMotion: ReducedMotionBehavior;\n }\n>;\n\n/** Native renderers may use these values directly; web renderers use easing. */\nexport const spring = {\n responsive: { stiffness: 760, damping: 52, mass: 1 },\n expressive: { stiffness: 520, damping: 38, mass: 1 },\n} as const;\n\n/** Reusable state strengths. Components still decide which states are valid. */\nexport const opacity = {\n disabled: 0.5,\n muted: 0.72,\n pressed: 0.86,\n dragged: 0.64,\n} as const;\n\n/** Overlaying the content color at these strengths creates predictable states. */\nexport const stateLayer = {\n hover: 0.06,\n focus: 0.08,\n pressed: 0.1,\n selected: 0.1,\n} as const;\n\nexport const stroke = {\n subtle: 1,\n default: 1,\n strong: 2,\n focus: 2,\n} as const;\n\nexport const control = {\n minTouchTarget: 44,\n buttonHeight: {\n small: 36,\n medium: 44,\n large: 52,\n },\n buttonHitSlop: {\n small: 4,\n medium: 0,\n large: 0,\n },\n fieldHeight: 44,\n chipHeight: {\n small: 36,\n medium: 44,\n },\n selectionIndicator: 24,\n} as const;\n\n/**\n * Font scale at which components switch to a large-text layout. One decision,\n * previously two literals in `segmentedControlRecipe` and `topBarRecipe`; see\n * issue #20 for why it sits with the tokens instead of beside the scale axis.\n */\nexport const largeTextThreshold = 1.6;\n\n/** Product renderers may narrow these widths, but should not invent new rhythm. */\nexport const layout = {\n pagePadding: {\n compact: spacing.md,\n regular: spacing.lg,\n spacious: spacing.xl,\n },\n sectionGap: spacing.xl,\n contentGap: spacing.md,\n rowHeight: {\n singleLine: 56,\n twoLine: 68,\n },\n readingMaxWidth: 720,\n contentMaxWidth: 1200,\n} as const;\n\n/** Width thresholds use CSS pixels on Web and density-independent points on Native. */\nexport const breakpoint = {\n compact: 0,\n medium: 600,\n expanded: 960,\n wide: 1280,\n} as const;\n\n/** Shared stacking intent. Values remain sparse to leave room for app layers. */\nexport const layer = {\n base: 0,\n sticky: 100,\n dropdown: 400,\n overlay: 800,\n modal: 900,\n tooltip: 950,\n toast: 1000,\n} as const;\n\nexport const overlay = {\n scrim: 0.6,\n veil: 0.25,\n} as const;\n\nexport type BackdropReference = Readonly<{\n color: \"#000000\";\n opacity: number;\n}>;\n\n/** Fixed backdrop contracts avoid renderer-specific names such as CSS `scrim`. */\nexport const backdrop = {\n modal: { color: \"#000000\", opacity: overlay.scrim },\n veil: { color: \"#000000\", opacity: overlay.veil },\n} as const satisfies Record<\"modal\" | \"veil\", BackdropReference>;\n\nexport const scrim = `rgba(0, 0, 0, ${overlay.scrim})`;\n\n/** Renderers translate this contract to box-shadow or native shadow/elevation properties. */\nexport const shadow = {\n raised: {\n color: \"#000000\",\n opacity: 0.08,\n radius: 4,\n offsetY: 1,\n },\n floating: {\n color: \"#000000\",\n opacity: 0.12,\n radius: 12,\n offsetY: 4,\n },\n overlay: {\n color: \"#000000\",\n opacity: 0.16,\n radius: 24,\n offsetY: 8,\n },\n} as const;\n"]}
|
|
1
|
+
{"version":3,"file":"foundations.js","sourceRoot":"","sources":["../src/foundations.ts"],"names":[],"mappings":"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","sourcesContent":["/** Numeric units are consumed as CSS pixels on web and density-independent points on native. */\nexport const spacing = {\n xxs: 4,\n xs: 8,\n sm: 12,\n md: 16,\n lg: 20,\n xl: 24,\n xxl: 32,\n xxxl: 40,\n} as const;\n\nexport const radius = {\n sm: 8,\n md: 12,\n lg: 16,\n xl: 24,\n full: 999,\n} as const;\n\n/**\n * Ordered fallbacks keep the contract platform-neutral: Web renderers join\n * the list as a CSS stack, while native renderers request the first named\n * family (or their OS default mapping), rather than receiving a CSS stack.\n */\nexport const fontFamily = {\n ui: [\n \"Inter\",\n \"Pretendard\",\n \"-apple-system\",\n \"BlinkMacSystemFont\",\n \"Segoe UI\",\n \"sans-serif\",\n ],\n code: [\n \"ui-monospace\",\n \"SFMono-Regular\",\n \"Consolas\",\n \"Liberation Mono\",\n \"monospace\",\n ],\n} as const;\n\nexport type FontFamily = keyof typeof fontFamily;\n\n/** Display/reading roles are optional so existing ui/code product profiles retain their fonts. */\nexport type FontRole = \"ui\" | \"display\" | \"reading\" | \"code\";\nexport type FontFamilyRoles = Readonly<{ ui: readonly string[]; code: readonly string[]; display?: readonly string[]; reading?: readonly string[] }>;\n\nexport function resolveFontFamilyStack(families: FontFamilyRoles, role: FontRole): readonly string[] {\n if (![\"ui\", \"display\", \"reading\", \"code\"].includes(role)) throw new TypeError(\"Unsupported font role\");\n // Unspecified reading/display follow the current ui stack, rather than a\n // frozen neutral stack that would silently undo an app's existing ui override.\n return families[role] ?? families.ui;\n}\n\n\n/** String weights translate unchanged to CSS and React Native text styles. */\nexport const fontWeight = {\n regular: \"400\",\n medium: \"500\",\n semibold: \"600\",\n bold: \"700\",\n heavy: \"800\",\n} as const;\n\nexport type FontWeight = keyof typeof fontWeight;\nexport type FontWeightValue = (typeof fontWeight)[FontWeight];\n\n/** Numeric tracking uses CSS pixels on Web and density-independent points on Native. */\nexport const letterSpacing = {\n tight: -0.2,\n normal: 0,\n wide: 0.2,\n} as const;\n\nexport type LetterSpacing = keyof typeof letterSpacing;\n\n/** Renderers map the shared intent to `font-variant-numeric` / `fontVariant`. */\nexport const numeric = {\n proportional: \"proportional-nums\",\n tabular: \"tabular-nums\",\n} as const;\n\nexport type NumericVariant = keyof typeof numeric;\n\nexport const typography = {\n caption: { fontSize: 11, lineHeight: 16, fontWeight: fontWeight.regular },\n label: { fontSize: 12, lineHeight: 18, fontWeight: fontWeight.semibold },\n body: { fontSize: 14, lineHeight: 20, fontWeight: fontWeight.regular },\n bodyLarge: { fontSize: 16, lineHeight: 24, fontWeight: fontWeight.regular },\n title: { fontSize: 18, lineHeight: 26, fontWeight: fontWeight.bold },\n titleLarge: { fontSize: 20, lineHeight: 28, fontWeight: fontWeight.heavy },\n heading: { fontSize: 24, lineHeight: 32, fontWeight: fontWeight.heavy },\n} as const;\n\nexport type TextVariant = keyof typeof typography;\n\n/** Visual variants choose a default family role; semantics and sizes remain independent. */\nexport function resolveTextFontRole(variant: TextVariant, role?: FontRole): FontRole {\n if (role !== undefined) {\n if (![\"ui\", \"display\", \"reading\", \"code\"].includes(role)) throw new TypeError(\"Unsupported font role\");\n return role;\n }\n if (variant === \"body\" || variant === \"bodyLarge\") return \"reading\";\n if (variant === \"title\" || variant === \"titleLarge\" || variant === \"heading\") return \"display\";\n return \"ui\";\n}\n\n\n/**\n * Document heading hierarchy without widening the established `TextVariant`\n * union. Levels 3–5 reuse the existing semantic styles; larger levels are\n * additive display roles for dense product pages and documentation.\n */\nexport const heading = {\n level1: { fontSize: 40, lineHeight: 48, fontWeight: fontWeight.heavy },\n level2: { fontSize: 32, lineHeight: 40, fontWeight: fontWeight.heavy },\n level3: typography.heading,\n level4: typography.titleLarge,\n level5: typography.title,\n} as const;\n\nexport type HeadingLevel = keyof typeof heading;\n\n/** Glyphs include icons and avatars; they do not inherit paragraph line-height. */\nexport const glyph = {\n xs: 14,\n sm: 20,\n md: 24,\n lg: 28,\n xl: 32,\n xxl: 44,\n xxxl: 48,\n} as const;\n\nexport type GlyphSize = keyof typeof glyph;\n\nexport const motion = {\n fast: 120,\n normal: 200,\n slow: 320,\n} as const;\n\n/**\n * Curves are stored as normalized cubic-bezier tuples so CSS and native\n * animation drivers can translate the same motion intent without sharing a\n * renderer dependency.\n */\nexport const easing = {\n standard: [0.2, 0, 0, 1],\n enter: [0, 0, 0, 1],\n exit: [0.3, 0, 1, 1],\n emphasized: [0.2, 0, 0, 1],\n} as const;\n\nexport type ReducedMotionBehavior = \"instant\" | \"opacity\" | \"static\";\n\n/** Shared transition intent; renderers translate easing tuples to their animation API. */\nexport const motionPreset = {\n micro: {\n duration: motion.fast,\n easing: \"standard\",\n reducedMotion: \"instant\",\n },\n enter: {\n duration: motion.normal,\n easing: \"enter\",\n reducedMotion: \"opacity\",\n },\n exit: {\n duration: motion.fast,\n easing: \"exit\",\n reducedMotion: \"instant\",\n },\n context: {\n duration: motion.slow,\n easing: \"emphasized\",\n reducedMotion: \"opacity\",\n },\n} as const satisfies Record<\n \"micro\" | \"enter\" | \"exit\" | \"context\",\n {\n duration: number;\n easing: keyof typeof easing;\n reducedMotion: ReducedMotionBehavior;\n }\n>;\n\n/** Native renderers may use these values directly; web renderers use easing. */\nexport const spring = {\n responsive: { stiffness: 760, damping: 52, mass: 1 },\n expressive: { stiffness: 520, damping: 38, mass: 1 },\n} as const;\n\n/** Reusable state strengths. Components still decide which states are valid. */\nexport const opacity = {\n disabled: 0.5,\n muted: 0.72,\n pressed: 0.86,\n dragged: 0.64,\n} as const;\n\n/** Overlaying the content color at these strengths creates predictable states. */\nexport const stateLayer = {\n hover: 0.06,\n focus: 0.08,\n pressed: 0.1,\n selected: 0.1,\n} as const;\n\nexport const stroke = {\n subtle: 1,\n default: 1,\n strong: 2,\n focus: 2,\n} as const;\n\nexport const control = {\n minTouchTarget: 44,\n buttonHeight: {\n small: 36,\n medium: 44,\n large: 52,\n },\n buttonHitSlop: {\n small: 4,\n medium: 0,\n large: 0,\n },\n fieldHeight: 44,\n chipHeight: {\n small: 36,\n medium: 44,\n },\n selectionIndicator: 24,\n} as const;\n\n/**\n * Font scale at which components switch to a large-text layout. One decision,\n * previously two literals in `segmentedControlRecipe` and `topBarRecipe`; see\n * issue #20 for why it sits with the tokens instead of beside the scale axis.\n */\nexport const largeTextThreshold = 1.6;\n\n/** Product renderers may narrow these widths, but should not invent new rhythm. */\nexport const layout = {\n pagePadding: {\n compact: spacing.md,\n regular: spacing.lg,\n spacious: spacing.xl,\n },\n sectionGap: spacing.xl,\n contentGap: spacing.md,\n rowHeight: {\n singleLine: 56,\n twoLine: 68,\n },\n readingMaxWidth: 720,\n contentMaxWidth: 1200,\n} as const;\n\n/** Width thresholds use CSS pixels on Web and density-independent points on Native. */\nexport const breakpoint = {\n compact: 0,\n medium: 600,\n expanded: 960,\n wide: 1280,\n} as const;\n\n/** Shared stacking intent. Values remain sparse to leave room for app layers. */\nexport const layer = {\n base: 0,\n sticky: 100,\n dropdown: 400,\n overlay: 800,\n modal: 900,\n tooltip: 950,\n toast: 1000,\n} as const;\n\nexport const overlay = {\n scrim: 0.6,\n veil: 0.25,\n} as const;\n\nexport type BackdropReference = Readonly<{\n color: \"#000000\";\n opacity: number;\n}>;\n\n/** Fixed backdrop contracts avoid renderer-specific names such as CSS `scrim`. */\nexport const backdrop = {\n modal: { color: \"#000000\", opacity: overlay.scrim },\n veil: { color: \"#000000\", opacity: overlay.veil },\n} as const satisfies Record<\"modal\" | \"veil\", BackdropReference>;\n\nexport const scrim = `rgba(0, 0, 0, ${overlay.scrim})`;\n\n/** Renderers translate this contract to box-shadow or native shadow/elevation properties. */\nexport const shadow = {\n raised: {\n color: \"#000000\",\n opacity: 0.08,\n radius: 4,\n offsetY: 1,\n },\n floating: {\n color: \"#000000\",\n opacity: 0.12,\n radius: 12,\n offsetY: 4,\n },\n overlay: {\n color: \"#000000\",\n opacity: 0.16,\n radius: 24,\n offsetY: 8,\n },\n} as const;\n"]}
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED
package/dist/version.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,MAAM,CAAC,MAAM,mBAAmB,GAAG,QAAiB,CAAC","sourcesContent":["/** Package release shown by documentation surfaces. Kept in sync by a test. */\nexport const designSystemVersion = \"1.
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,MAAM,CAAC,MAAM,mBAAmB,GAAG,QAAiB,CAAC","sourcesContent":["/** Package release shown by documentation surfaces. Kept in sync by a test. */\nexport const designSystemVersion = \"1.16.1\" as const;\n"]}
|
package/docs/auth-screen.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# AuthScreenLayout — 로그인 화면의 두 영역 골격
|
|
2
2
|
|
|
3
|
-
검토일: 2026-10-
|
|
3
|
+
검토일: 2026-10-07
|
|
4
4
|
|
|
5
5
|
## 문제
|
|
6
6
|
|
|
@@ -38,6 +38,11 @@ Web·Native `AuthScreenLayout`의 `mainCard`는 주 행동을 공통 카드로
|
|
|
38
38
|
카드를 공급하는 기존 화면과 중첩되지 않도록 기본값은 false이며, 새 조합은 mainCard를 켜고
|
|
39
39
|
main 슬롯에는 버튼 목록만 넣는다. 배경·padding·radius는 바깥 카드가 계속 소유한다.
|
|
40
40
|
|
|
41
|
+
2026-10-07 테마 소비 점검에서 Native 카드만 숫자로 확정된 recipe 모서리를 읽어
|
|
42
|
+
Web과 달리 profile을 무시했다. 카드의 모서리는 가장 가까운 Provider의 `tokens.radius.lg`를
|
|
43
|
+
따르며 profile이 없으면 기존 recipe 16을 유지한다. 제공자 버튼의 별도 브랜드/정렬
|
|
44
|
+
계약은 이 카드 역할과 구분하고, 테마 변경으로 main의 입력·인증 진행 상태를 재생성하지 않는다.
|
|
45
|
+
|
|
41
46
|
인증 시작 시 지역화된 `pendingLabel`(예: `로그인 중`)을 전달하면 모든 주 행동을 숨기고
|
|
42
47
|
같은 카드의 정중앙에 하나의 로딩 표시를 띄운다. 내용은 크기와 폼 상태를 유지하기 위해
|
|
43
48
|
mount된 채 남지만 Web inert와 Native touch/accessibility 제외로 조작할 수 없다.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Finite collection rail
|
|
2
|
+
|
|
3
|
+
검토일: 2026-10-08 · 공개 진입점: 1.16.0
|
|
4
|
+
|
|
5
|
+
2026-10-07 Aceternity 다중 카드 예제와 기존 API를 대조했다. 기존 List는 세로 행 의미/구분선,
|
|
6
|
+
Carousel/CarouselMotion은 단일 활성 패널의 숨김·inert·선택을 소유한다. 여러 카드가 함께 보이며
|
|
7
|
+
각 카드 입력/상세 행동이 독립적으로 작동하는 문제는 단일 선택 엔진을 복제해서 해결할 수 없다.
|
|
8
|
+
`CollectionRail`은 List의 companion인 유한 배치/탐색 계약이며 canonical catalog를 늘리지 않는다.
|
|
9
|
+
근거: [설계 결정](../../../docs/plans/aceternity-interaction-adoption-2026-10-07.md#가로-카드-목록과-상세--실제-원본-검토-후-설계-판단).
|
|
10
|
+
|
|
11
|
+
계약/두 renderer의 granular subpath는 `/collection-rail`이다. 추가 peer나 root export는 없다.
|
|
12
|
+
`validateItems`로 안정 ID·현지화 label을 검증하고, 공통 geometry/resolver가 항목 폭·논리 offset·끝 처리·초점 노출·키보드 방향을 소유한다.
|
|
13
|
+
Web은 실제 clientWidth/ResizeObserver 및 RTL의 음수 scrollLeft를, Native는 onLayout과 명시적 LTR ScrollView의 물리 좌표를 번역한다.
|
|
14
|
+
Native row만 RTL에서 역방향으로 배치하며 데이터/React key/읽기 순서를 역순 배열로 바꾸지 않는다.
|
|
15
|
+
|
|
16
|
+
## 상태 소유권
|
|
17
|
+
|
|
18
|
+
- 스크롤의 앞쪽 anchor는 선택값이 아니다. `defaultStartKey`는 초기 위치만 정하고 `onStartKeyChange`는
|
|
19
|
+
실제 앞쪽 항목 ID 또는 empty의 null을 관찰한다. 서버 선택/상세 대상/초안은 제품 또는 기존 공개 컴포넌트 소유다.
|
|
20
|
+
- `scrollTo` 요청 좌표와 실제 도착은 분리한다. 이동 중 연속 버튼은 대기 목적지를 이어가지만,
|
|
21
|
+
끝 비활성화와 관찰 callback은 실제 host scroll 응답에서만 갱신한다. 사용자 pointer/touch는 대기 목적지를 해제한다.
|
|
22
|
+
- 모든 항목은 stable id로 계속 마운트된다. hidden/inert, 단일 활성 panel, 자동 회전, loop, 가상화는 제공하지 않는다.
|
|
23
|
+
- pointer/touch는 host의 실제 스크롤로 처리하며 사용자 입력을 PanResponder로 덮지 않는다.
|
|
24
|
+
- previous/next는 항목 경계를 따라 한 단계 이동하고 끝에서 멈춘다. Web viewport/controls에서만
|
|
25
|
+
논리 ArrowLeft/Right·Home/End를 처리하며 카드의 input/widget 키를 가로채지 않는다.
|
|
26
|
+
- 초점 노출은 필요한 최소 offset으로 카드 전체를 보여 준다. 폭/방향/데이터 변경은 앞쪽 ID를 보존하며,
|
|
27
|
+
같은 viewport에 이전 anchor와 먼 초점 카드가 함께 들어갈 수 없으면 초점 카드 노출을 우선한다.
|
|
28
|
+
삭제된 anchor는 첫 항목으로 대체한다. key/remount로 입력을 초기화하지 않는다.
|
|
29
|
+
- 세부 모달은 `Card.actions`→기존 Dialog를 합성한다. rail은 body overflow·background lock·focus trap을 따로 구현하지 않는다.
|
|
30
|
+
|
|
31
|
+
## 배치와 플랫폼 경계
|
|
32
|
+
|
|
33
|
+
comfortable 최대 폭360은 `layout.readingMaxWidth / 2`, compact240은 `/3`이다. 실제 폭은 viewport와
|
|
34
|
+
`spacing.xl`24 hint를 함께 고려한다. 간격 `spacing.md`16을 유지하므로 viewport358에서 카드334와 다음 카드8이 노출된다.
|
|
35
|
+
뷰포트24 이하에서는 peek보다 내용 폭을 우선한다. 길고 많은 데이터는 VirtualList/제품별 가상화 계약을 사용한다.
|
|
36
|
+
브랜드 색·표면·폰트·카드 경계는 Provider와 Card가 소유한다. 가로 탐색을 테마의 미지원 screen/composition 축에 자동 연결하지 않는다.
|
|
37
|
+
|
|
38
|
+
Web 초기 unchanged ResizeObserver 알림은 초점 노출을 되돌리지 않는다. Native content-size 알림도 높이만
|
|
39
|
+
바뀌면 스크롤을 재정렬하지 않는다. 모션 감소에서 프로그램 탐색은 즉시 이동한다.
|
|
40
|
+
host subpixel 반올림을 위해 끝 판정은0.5 CSS px/dp 허용하며 rubber-band 입력은 유한 범위로 clamp한다.
|
|
41
|
+
이는 시간·픽셀값 복제 또는 OS 최대 글자 모사를 위한 보정이 아니다. 최대 글자 조건은 설계/검증/후속에서 제외한다.
|
|
42
|
+
|
|
43
|
+
Native host 번역 회귀는 실제 OS touch/VoiceOver/키보드 성능과 구분한다. 실험 검수 후 게시/소비 제품에서
|
|
44
|
+
지원 환경을 확인한다. [사용 지침](usage/components/list.md#collectionrail-가로-배치)과 [합성 구성](usage/compositions/collection-detail.md)을 따른다.
|
|
45
|
+
|
|
46
|
+
공식 host 근거: [React Native ScrollView](https://reactnative.dev/docs/scrollview),
|
|
47
|
+
[Web scrollLeft](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollLeft),
|
|
48
|
+
[ResizeObserver](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver).
|
package/docs/design-profile.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 디자인 프리셋 계약
|
|
2
2
|
|
|
3
|
-
검토일: 2026-10-
|
|
3
|
+
검토일: 2026-10-08 · 상태: 기본 10종 프로필 1.15.0 · 후속 글자/질감/토큰 소비 개선 1.16.0
|
|
4
4
|
|
|
5
5
|
사용자가 레트로·종이·숲 등의 테마에 따라 같은 기능의 상호작용·구성·화면 배치도 자동으로 달라지고, 앱이 자기 테마를 한 번 주입하기를 요청했다. 색상 프리셋만으로는 그 요구를 충족하지 못하므로 네 축을 하나의 데이터 계약으로 둔다. 기존 상태 엔진을 테마마다 복제하는 방식은 채택하지 않는다.
|
|
6
6
|
|
|
@@ -40,7 +40,7 @@ export const productDesign = defineHjmDesignProfile({
|
|
|
40
40
|
| --- | --- | --- |
|
|
41
41
|
| palette | 현재 HJM light/dark 17 semantic roles | 레트로의 잉크/황갈색, 종이의 따뜻한 중립색, 숲의 녹색 |
|
|
42
42
|
| tokens | 기존 radius/fontFamily/typography/heading/shadow | 모서리·글자 크기/행간/강조·그림자와 일반 monospace fallback; 폰트 자산은 번들하지 않음 |
|
|
43
|
-
| material | canvas/card/surface 모두 null | 레트로 noise, 종이 grain, 숲 mesh+glow; 오로라만 active=true, 나머지는 정적 |
|
|
43
|
+
| material | canvas/card/surface 모두 null | 레트로 noise, 종이 grain+ruled, 숲 mesh+glow; 오로라만 active=true, 나머지는 정적 |
|
|
44
44
|
| interactions | contentTransition=fade, selectionMotion=none | 레트로 slide, 종이 fade, 숲 rise와 slide 선택 배경 |
|
|
45
45
|
| compositions | collection=rows, toolbar=inline | 레트로 grid/inline, 종이 rows/collapsible, 숲 cards/collapsible |
|
|
46
46
|
| screens | overview=dashboard | 종이 editorial, 숲 landscape |
|
|
@@ -57,7 +57,9 @@ export const productDesign = defineHjmDesignProfile({
|
|
|
57
57
|
|
|
58
58
|
## 현재 증거와 남은 조건
|
|
59
59
|
|
|
60
|
-
공통 데이터·Provider·기본 토큰 소비·상호작용 기본값·OverviewScreen 구성과 화면·양쪽 Storybook 비교를 구현했다.
|
|
60
|
+
공통 데이터·Provider·기본 토큰 소비·상호작용 기본값·OverviewScreen 구성과 화면·양쪽 Storybook 비교를 구현했다. 2026-10-07 npm 1.15.0의 세 tarball integrity와 design-profile 진입점, 기본 10종 계약을 확인했다. 후속 CollectionRail·Text.fontRole·ruledSpacing과 토큰 소비 개선은 해당 1.15.0 게시본에 포함되지 않으며, 2026-10-08 npm 세 tarball을 검증한 1.16.0부터 제공한다. 필요한 후보 조사는 마감했고, 확인한 모서리·제목 메트릭·UI 라벨·Toast 행간 누락을 [후속 QA](../../../docs/qa/2026-10-07-design-profile-research.md)에 따라 수정했다. 이는 모든 공개 컴포넌트/플랫폼 자동 검수 완료가 아니다.
|
|
61
|
+
|
|
62
|
+
브라우저의 입력 유지·복구와 선택 환경은 위 QA에, 기존 iPhone 17 Pro/iOS26.5 개발 호스트에서 수행한 테마·카드/글자/종이·전환/날짜/명령·독립 OverviewScreen 선택 흐름은 [Native QA](../../../docs/qa/2026-10-07-native-reference-validation.md)에 있다. Android·실물/Release 성능·실제 VoiceOver 순회와 소비 앱 반영은 미확인이다. OS 최대 글자 및 최대값 모사는 검사·후속·완료 조건에서 제외한다. 기본 npm 게시와 실험 승급, 후속 npm 게시, 소비 제품 적용을 각각 구분한다.
|
|
61
63
|
|
|
62
64
|
## 10종 확장과 현재 연결
|
|
63
65
|
|
|
@@ -261,3 +263,38 @@ fallback은 유지한다. Web은 일반 Toast fallback이므로 Native 효과를
|
|
|
261
263
|
기존 테마 비교 구성의 Native 예제로 같은 visible 알림을 보존한 채 10종을 순회한다.
|
|
262
264
|
선택 peer는 optional subpath에 유지하며 새 공개 컴포넌트나 상태 엔진을 추가하지 않는다.
|
|
263
265
|
실제 기기 외형·제스처·음성·성능은 [QA](../../../docs/qa/2026-10-07-design-profile-research.md)의 미확인 범위다.
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
## 제목·읽기용 본문을 다른 서체로 지정하기
|
|
269
|
+
|
|
270
|
+
2026-10-07 A-05/C-T01 적용: optional `tokens.fontFamily.display/reading`은 제목과 본문 역할을
|
|
271
|
+
독립적으로 지정한다. 생략하면 현재 ui stack을 따르므로 기존 ui-only 제품 설정은 유지된다.
|
|
272
|
+
Heading/Text의 의미·크기·굵기와 입력/버튼의 ui는 바꾸지 않는다. `Text.fontRole`로 명시 역할을 선택한다.
|
|
273
|
+
[역할 계약](font-roles.md)과 [사용 지침](usage/tokens/font-roles.md)을 따른다. 이 추가 API는 1.16.0부터 제공한다.
|
|
274
|
+
|
|
275
|
+
## 종이 줄무늬와 앱 소유 표현
|
|
276
|
+
|
|
277
|
+
2026-10-07 A-02의 줄무늬는 기존 점/노이즈와 구분되는 표현이라 EffectSurface의 정적 ruled 레이어로 보완했다.
|
|
278
|
+
paper canvas는 grain+ruled/intensity0.06/ruledSpacing24다. 실제 내용은 회전하거나 선의 기준에 맞추지 않는다.
|
|
279
|
+
앱은 `material.canvas`를 grain만으로 교체하거나 ruledSpacing을 지정한다. 새로운 종이 상태/입력 엔진은 없다.
|
|
280
|
+
이 변경은 1.16.0부터 제공하며 [사용 지침](usage/compositions/paper-surface.md)과 [질감 계약](effect-surface.md)을 따른다.
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
## 플로팅 실행 버튼의 깊이 상속
|
|
284
|
+
|
|
285
|
+
2026-10-07 후속 소비 감사에서 FAB의 양 renderer가 floating recipe 값을 직접 읽어
|
|
286
|
+
무그림자 앱 테마에서도 그림자가 남았다. 기존 `shadow.floating`을 연결하며 Native는
|
|
287
|
+
공통 elevation 해석기를 재사용한다. 0-opacity는 Android 그림자도 제거한다. FAB의 원/pill은
|
|
288
|
+
고정된 행동 geometry라 radius 변경 축으로 흡수하지 않고, 클릭·포커스·접힘·여백은 유지한다.
|
|
289
|
+
새 공개 API 없이 같은 컴포넌트의 소비 경로를 고친 변경이며 npm 게시 상태는 별도다.
|
|
290
|
+
|
|
291
|
+
## 다중 토글의 모서리 상속
|
|
292
|
+
|
|
293
|
+
2026-10-07 후속 점검에서 ToggleGroup의 두 renderer가 숫자로 확정된 recipe 모서리를
|
|
294
|
+
읽어 profile 형태 변경을 놓쳤다. `tokens.radius.md`를 소비하며 profile이 없는 기존
|
|
295
|
+
사용과 standalone Web은 recipe 12를 유지한다. Web은 가까운 Provider의 기존 CSS 변수를
|
|
296
|
+
사용해 작은 optional 진입점의 Provider runtime 의존성을 늘리지 않는다. Native는 가까운
|
|
297
|
+
theme에서 역할을 읽는다. 다중 선택·비활성·같은 항목/초점은 그대로이며 새 엔진·prop은 없다.
|
|
298
|
+
Web 10종 light/dark 실제 스타일·키보드와 Native 모의 호스트의 상태 유지, 명시적 중첩
|
|
299
|
+
profile/neutral 복귀를 검증했다. 이 수정의 실제 Native 기기·AT·Release 성능·npm 게시는
|
|
300
|
+
[QA](../../../docs/qa/2026-10-07-design-profile-research.md)와 구분하는 미확인 범위다.
|
package/docs/effect-surface.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
by layered shader composition. No Shaders.com engine, presets or source is shipped.
|
|
5
5
|
|
|
6
6
|
Import `EffectSurface` from the renderer `/effect-surface` entry. The shared
|
|
7
|
-
`/effect-surface` contract accepts unique `layers` (`mesh`, `glow`, `grain`, `noise`), a
|
|
7
|
+
`/effect-surface` contract accepts one to four unique `layers` (`mesh`, `glow`, `grain`, `noise`, `ruled`), a
|
|
8
8
|
stable `seed`, `intensity` from 0 to 1, a cycle `period` from 2 to 120 seconds,
|
|
9
9
|
`active` (false by default), and three semantic color references. Web uses local
|
|
10
10
|
SVG/WAAPI; Native requires the existing optional SVG peer and core Animated.
|
|
@@ -64,3 +64,29 @@ peer or per-frame noise generation. Magic UI's reference motivated the compariso
|
|
|
64
64
|
but no source or asset from that component is included. Check actual readability
|
|
65
65
|
and rasterization cost before using it over product text. The comparison is at
|
|
66
66
|
`실험/구성/정보 표시/질감 비교`; it is not a promotion of the new layer.
|
|
67
|
+
|
|
68
|
+
## Static notebook ruling (unpublished after 1.15.0)
|
|
69
|
+
|
|
70
|
+
2026-10-07 A-02 paper findings distinguish ruling from grain/noise, tape and torn
|
|
71
|
+
edges. `ruled` adds a static one-host-unit line every `ruledSpacing` units (default
|
|
72
|
+
24, finite 8–128). This independent decoration recipe is not a text baseline grid:
|
|
73
|
+
content sizes, wrapping and spacing remain owned by existing HJM components.
|
|
74
|
+
The lower bound prevents the pattern from collapsing into dense fill; the upper
|
|
75
|
+
bound keeps the selected notebook treatment bounded. Existing four-layer composition
|
|
76
|
+
limits remain in place; adding the fifth available kind does not allow five layers.
|
|
77
|
+
|
|
78
|
+
Both renderers use their existing SVG Pattern/Rect host in userSpaceOnUse, outside
|
|
79
|
+
the atmospheric transform. Ruling never stretches or drifts with active mesh/grain
|
|
80
|
+
motion; a ruled-only descriptor starts no animation even if active is requested.
|
|
81
|
+
Seed changes grain/noise geometry, not line positions. Semantic theme.text tint and
|
|
82
|
+
intensity are shared, while Web pixels and Native logical units/rasterization differ.
|
|
83
|
+
The existing decoration failure boundary preserves product children. The optional
|
|
84
|
+
Native react-native-svg peer remains required; no new peer, asset or registry is added.
|
|
85
|
+
|
|
86
|
+
Paper's canvas now composes grain/ruled at intensity0.06 and spacing24. An app can
|
|
87
|
+
override canvas with plain grain or its chosen interval through its design profile.
|
|
88
|
+
`실험/구성/비교와 검증/종이 줄무늬 비교` uses the public OverviewScreen to compare
|
|
89
|
+
actual preset inheritance with explicit plain/ruled overrides and the same draft.
|
|
90
|
+
Neither tape, rotated content, perforation nor torn/hand-drawn boundaries are
|
|
91
|
+
provided by this layer. Put important content on an opaque Surface when needed;
|
|
92
|
+
arbitrary intensities and glyphs do not come with a readability guarantee.
|
package/docs/file-picker.md
CHANGED
|
@@ -59,3 +59,9 @@ FilePicker는 파일 선택 의도만 소유하고, 진행·성공·실패 표
|
|
|
59
59
|
document/image picker를 여는지는 제품 통합 책임이며 이 패키지는 이를 구현하거나 기기에서
|
|
60
60
|
검증했다고 주장하지 않는다. 소비 앱은 해당 adapter를 연결하고 제품별 릴리스 QA에서 OS
|
|
61
61
|
동작을 확인한다.
|
|
62
|
+
|
|
63
|
+
## 프로필 모서리·제목 소비
|
|
64
|
+
|
|
65
|
+
2026-10-07 소비 감사에서 Native 선택 버튼의 모서리 12가 프로필을 우회했다. Web 버튼의 기존 `radius.md`와 같은 역할을 Native도 가까운 프로필에서 읽으며, 프로필이 없으면 기존 12를 유지한다. 선택 어댑터·비활성/진행 상태·파일 검증은 바꾸지 않는다.
|
|
66
|
+
|
|
67
|
+
프로필 연결은 1.15.0 이후 미게시 변경이며, 기본 배포 계약과 실제 Native 기기 검증은 구분한다.
|
|
@@ -141,3 +141,12 @@ Web browser 테스트는 스크롤 방향, focus/ref 보존, 양방향 배치,
|
|
|
141
141
|
safe area와 마지막 내용의 도달 가능성을 검사한다. Native 테스트는 onScroll,
|
|
142
142
|
같은 Button 유지, logical end, onLayout clearance와 행동을 검사한다.
|
|
143
143
|
기기 스크린 리더/키보드 및 제품 배포 증거는 별도로 쌓으며 beta로 유지한다.
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
## 프로필 그림자의 실제 소비 — 2026-10-07
|
|
147
|
+
|
|
148
|
+
recipe는 기존 floating 역할을 정하며, designProfile이 있으면 양 renderer가 가장 가까운
|
|
149
|
+
Provider의 해당 역할 값을 읽는다. FAB에 별도 shadow prop을 추가하거나 recipe를 제품별로
|
|
150
|
+
복제하지 않는다. Web은 resolved floating CSS 변수, Native는 iOS shadow 및 기존 공통
|
|
151
|
+
Android elevation 변환을 사용한다. opacity0이면 elevation도0이며 프로필 없는 경우 기존
|
|
152
|
+
recipe/elevation을 유지한다. 위치·원/pill·접힘·동일 버튼 identity와 clearance 계약은 바뀌지 않는다.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Display, reading and technical font roles
|
|
2
|
+
|
|
3
|
+
검토일: 2026-10-08 · 추가 역할: 1.16.0
|
|
4
|
+
|
|
5
|
+
조사 후보 A-05/C-T01은 제목과 읽기 본문에 다른 서체를 사용하는 실제 차이를 남겼다.
|
|
6
|
+
기존 `tokens.fontFamily.ui/code`만으로는 크기를 변경해도 이 차이를 전달할 수 없었다.
|
|
7
|
+
크기/굵기·document level·초안 수명을 건드리지 않고 optional `display/reading` stack과 Text의
|
|
8
|
+
`fontRole`을 기존 프로필에 연결한다. 별도 서체 registry/테마 Provider/문단 상태 엔진은 추가하지 않는다.
|
|
9
|
+
|
|
10
|
+
## 호환성과 역할
|
|
11
|
+
|
|
12
|
+
기존 ui/code-only 설정의 표시와 읽기는 **현재 ui**를 따른다. 기본 stack을 새 역할에 복사하면
|
|
13
|
+
제품 ui override를 무시하게 되므로 역할 생략은 생략으로 보존하고 renderer에서 fallback을 해석한다.
|
|
14
|
+
설정과 모든 지정 배열은 복사·동결하며 호출자의 배열을 동결하지 않는다. persisted JSON의 알 수 없는 역할,
|
|
15
|
+
문자열 대신 stack 요구를 위반한 값, 비어 있는 배열/이름은 TypeError로 거부한다.
|
|
16
|
+
|
|
17
|
+
Heading 및 의미 제목은 display를 쓴다. Text의 heading/titleLarge/title 기본은 display,
|
|
18
|
+
body/bodyLarge는 reading, caption/label은 ui다. `fontRole` 명시값은 크기/굵기·의미를 바꾸지 않고
|
|
19
|
+
글꼴 역할만 바꾼다. heading role을 명시한 Text도 display를 쓰며 명시 fontRole이 우선한다.
|
|
20
|
+
입력과 버튼 등 조작 host는 기존 ui를 유지하고 CodeBlock 등 기술값은 code를 유지한다.
|
|
21
|
+
모든 임의 슬롯·제3자 raw host의 스타일을 HJM이 자동 변경한다고 주장하지 않는다.
|
|
22
|
+
|
|
23
|
+
Web은 nearest Provider가 CSS stack 변수를 내보내며 semantic h1~h6·Text가 소비한다.
|
|
24
|
+
portal도 기존 Provider 복사 경로를 따라간다. Native는 View에 글꼴을 주어 전파할 수 없으므로
|
|
25
|
+
기존 Text/TextInput host와 `resolveNativeFontStyle`을 사용한다. 제목·본문은 역할 stack의 첫 named font,
|
|
26
|
+
code의 기본 monospace는 iOS Menlo/다른 host monospace로 번역한다. ui 기본 stack은 OS 기본을 유지한다.
|
|
27
|
+
중첩 neutral Provider는 부모의 서체 역할도 중립으로 되돌린다.
|
|
28
|
+
|
|
29
|
+
Web stack과 Native 단일 이름은 같은 설치 지원을 뜻하지 않는다. 폰트 파일·등록·다운로드·라이선스·
|
|
30
|
+
한글/숫자 글리프·굵기/italic font-face의 실제 표현은 제품 소유다. 참고 fixture는 Web Georgia/Palatino stack,
|
|
31
|
+
iOS는 Apple이 열거한 동일 시스템 이름, 다른 Native host는 serif를 요청한다. Native 기기 검증 완료를 뜻하지 않는다.
|
|
32
|
+
|
|
33
|
+
공식 host 근거: [React Native Text의 제한된 상속](https://reactnative.dev/docs/text#limited-style-inheritance),
|
|
34
|
+
[CSS font-family](https://developer.mozilla.org/en-US/docs/Web/CSS/font-family),
|
|
35
|
+
[Apple system fonts](https://developer.apple.com/fonts/system-fonts/).
|
|
36
|
+
|
|
37
|
+
[사용 지침](usage/tokens/font-roles.md)·[프로필](design-profile.md)·[타이포그래피](usage/tokens/typography.md)를 함께 따른다.
|
|
38
|
+
|
|
39
|
+
## 조작 라벨과 읽기 본문의 구분 — 1.16.0
|
|
40
|
+
|
|
41
|
+
2026-10-07 소비 감사에서 Native 조작 라벨 24곳이 body/bodyLarge 크기를 사용하면서 읽기 서체로 해석됐다.
|
|
42
|
+
Button의 내부 라벨·제공자 버튼·ToggleGroup·선택 컨트롤·Switch·SegmentedControl·Chip·Tabs·Menu·Select·
|
|
43
|
+
Combobox·동의·Toast 행동·Link·날짜 선택/Calendar 날짜·disclosure·멘션/태그 후보·TransferList는 기존
|
|
44
|
+
Text의 `fontRole="ui"`를 명시한다. 크기 variant는 그대로 유지하고 가까운 Provider의 ui stack을 읽는다.
|
|
45
|
+
본문/description의 reading, 의미 제목의 display, label/caption의 기존 ui와 고정 glyph는 바꾸지 않는다.
|
|
46
|
+
일반 Text의 기본값을 ui로 바꾸는 대안은 실제 읽기 본문의 제품 서체를 잃으므로 채택하지 않았다.
|
|
47
|
+
|
|
48
|
+
추가 1곳인 TopBar 제목은 Web과 같은 경계를 유지한다. 클릭형 제목은 일반 버튼 라벨이므로 ui,
|
|
49
|
+
비클릭형 제목은 의미 heading이므로 display다. 제목 행동·접근성 이름·정적 heading 역할은 유지한다.
|
|
50
|
+
서체 선택 검사는 Native host 모사에서 수행했으며 폰트 자산 설치·실제 기기 표시 검증을 뜻하지 않는다.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Component maturity and evidence manifest
|
|
2
2
|
|
|
3
|
-
> Generated from `@hjmds/design-contracts` 1.
|
|
3
|
+
> Generated from `@hjmds/design-contracts` 1.16.1. Do not edit this file directly; run `pnpm contracts:sync`.
|
|
4
4
|
|
|
5
5
|
This document is the human-readable projection of the same catalog and Showcase manifest consumed by product CI.
|
|
6
6
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"designSystemVersion": "1.
|
|
3
|
+
"designSystemVersion": "1.16.1",
|
|
4
4
|
"source": "packages/design-contracts/docs/generated/showcase-manifest.json",
|
|
5
5
|
"surfaces": {
|
|
6
6
|
"web": {
|
|
7
7
|
"packageName": "@hjmds/react",
|
|
8
|
-
"packageVersion": "1.
|
|
8
|
+
"packageVersion": "1.16.1",
|
|
9
9
|
"activeComponents": 103,
|
|
10
10
|
"claimedComponents": 103,
|
|
11
11
|
"completeScenarioComponents": 103,
|
|
@@ -5642,7 +5642,7 @@
|
|
|
5642
5642
|
},
|
|
5643
5643
|
"native": {
|
|
5644
5644
|
"packageName": "@hjmds/react-native",
|
|
5645
|
-
"packageVersion": "1.
|
|
5645
|
+
"packageVersion": "1.16.1",
|
|
5646
5646
|
"activeComponents": 83,
|
|
5647
5647
|
"claimedComponents": 83,
|
|
5648
5648
|
"completeScenarioComponents": 83,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Renderer evidence coverage
|
|
2
2
|
|
|
3
|
-
> Generated for HJM 1.
|
|
3
|
+
> Generated for HJM 1.16.1. Do not edit directly; run `pnpm evidence:sync`.
|
|
4
4
|
|
|
5
5
|
This projection joins the canonical surface maturity manifest with first-party renderer claims. Missing scenarios are explicit beta promotion debt; stable surfaces are blocked by CI until none remain.
|
|
6
6
|
|
package/docs/menubar.md
CHANGED
|
@@ -20,3 +20,9 @@
|
|
|
20
20
|
때 hover는 아무것도 열지 않는다 — 지나가다 메뉴가 펼쳐지는 것은 사고다.
|
|
21
21
|
|
|
22
22
|
**Web 전용.** 휴대폰에는 항상 떠 있는 메뉴 막대가 없고, 네이티브 앱 바는 OS의 것이다.
|
|
23
|
+
|
|
24
|
+
## 프로필 모서리·제목 소비
|
|
25
|
+
|
|
26
|
+
2026-10-07 소비 감사에서 Web 라벨의 숫자 recipe 모서리가 프로필을 우회했다. 기존 `radius.sm` 역할을 가까운 Provider의 CSS 변수로 읽고 변수 없는 독립 사용은 recipe 8을 유지한다. 열린 메뉴·roving focus·비활성 건너뛰기·행동과 Web 전용 범위는 바꾸지 않는다.
|
|
27
|
+
|
|
28
|
+
프로필 연결은 1.15.0 이후 미게시 변경이며, 기본 배포 계약과 실제 Native 기기 검증은 구분한다.
|
package/docs/screen-patterns.md
CHANGED
|
@@ -376,3 +376,7 @@ Web·Native가 같은 규칙이라 홈 actions 병합이나 콜백 분리는 양
|
|
|
376
376
|
- `./screens`, `./screen-flows`, `./saved-items`의 화면 루트는 ScreenLayout을 통해
|
|
377
377
|
`layoutStyle`을 받는다(Native ScreenLayout과 같음). ListDetailScreen·SavedItemsScreen은
|
|
378
378
|
목록·상세를 감싸는 바깥 host에 적용한다. PhotoSourceSheet는 portal Sheet라 제외한다.
|
|
379
|
+
|
|
380
|
+
CommentThreadItem.actions sits beside likeAction in one inline row, with spacing.xxs between them,
|
|
381
|
+
since the 2026-10-07 user requested a vertical-ellipsis overflow next to the heart. The slot remains
|
|
382
|
+
product-owned and nullable custom likeAction remains supported; action handlers are independent.
|
package/docs/sidebar.md
CHANGED
|
@@ -37,3 +37,9 @@
|
|
|
37
37
|
`appearance`는 standard(기본), bounce, hook, proximity를 지원한다. bounce는 새로 선택한 항목의 아이콘에 한 번만 적용하고, hook은 선택 항목의 시작 쪽 곡선 경계를 강조한다. proximity는 마우스/펜의 세로 거리에 따라 아이콘만 최대 18% 확대한다. 링크 경계와 키보드 순서는 변하지 않는다. 터치는 근접 효과를 만들지 않는다. HJM provider의 모션 줄이기에서 동적 표현을 끄며, provider 없이도 기본 정적 탐색은 가능하다.
|
|
38
38
|
|
|
39
39
|
독립적으로 구현한 제한된 표현이다. 원본 사이트의 모션 엔진을 복제하지 않았다. Web 전용이라는 기존 지원 범위를 유지하며 Native에서 새 사이드바를 만들지 않는다. Storybook `컴포넌트/탐색/Sidebar Motion`의 Default/Dark/LargeText에서 네 가지 표현과 접기를 비교한다. 기존 앱 셸 예제는 컴포넌트/탐색/Sidebar에 남는다.
|
|
40
|
+
|
|
41
|
+
## 프로필 모서리·제목 소비
|
|
42
|
+
|
|
43
|
+
2026-10-07 소비 감사에서 Web 항목의 숫자 recipe 모서리가 프로필을 우회했다. 기존 `radius.md` 역할을 가까운 Provider의 CSS 변수로 읽고 변수 없는 독립 사용은 recipe 12를 유지한다. 레일 폭·링크·현재 위치·접기·초점과 Web 전용 범위는 바꾸지 않는다.
|
|
44
|
+
|
|
45
|
+
프로필 연결은 1.15.0 이후 미게시 변경이며, 기본 배포 계약과 실제 Native 기기 검증은 구분한다.
|
package/docs/skip-nav.md
CHANGED
|
@@ -18,3 +18,9 @@ Blocks)이 요구하고, 키보드·스위치 사용자가 매 화면에서 내
|
|
|
18
18
|
그 배치는 renderer가 강제할 수 없으므로 계약의 scenario로 적어 둔다.
|
|
19
19
|
|
|
20
20
|
**Web 전용.** 네이티브에는 건너뛸 문서 흐름이 없고 화면 리더가 rotor로 이동한다.
|
|
21
|
+
|
|
22
|
+
## 프로필 모서리·제목 소비
|
|
23
|
+
|
|
24
|
+
2026-10-07 소비 감사에서 Web 링크의 숫자 recipe 모서리가 프로필을 우회했다. 기존 `radius.md` 역할을 가까운 Provider의 CSS 변수로 읽고 변수 없는 독립 사용은 recipe 12를 유지한다. 숨김·고정 위치·표시·본문 초점 이동과 Web 전용 범위는 바꾸지 않는다.
|
|
25
|
+
|
|
26
|
+
프로필 연결은 1.15.0 이후 미게시 변경이며, 기본 배포 계약과 실제 Native 기기 검증은 구분한다.
|
package/docs/toast.md
CHANGED
|
@@ -168,3 +168,12 @@ overflow와 update를 검증합니다.
|
|
|
168
168
|
|
|
169
169
|
- [Radix Toast](https://www.radix-ui.com/primitives/docs/components/toast)
|
|
170
170
|
- [React Spectrum Toast](https://react-spectrum.adobe.com/Toast)
|
|
171
|
+
|
|
172
|
+
## 프로필 행간 소비 — 미게시
|
|
173
|
+
|
|
174
|
+
2026-10-07 소비 감사에서 Web 제목/설명의 1.35/1.45 고정 행간이 `typography.body.lineHeight`를
|
|
175
|
+
우회하는 것을 확인했다. 두 slot은 기존 body 역할이므로 선택된 프로필의 `--hjm-type-body-line-height`를
|
|
176
|
+
기존 Provider/portal 토큰 경로로 읽는다. 프로필 없는 Provider와 독립 사용은 기존 1.35/1.45를 유지한다.
|
|
177
|
+
일괄 기본 행간 변경은 기존 알림 레이아웃까지 바꾸므로 채택하지 않았다. Native 본문 행간은 이미 body
|
|
178
|
+
토큰을 소비하며, 이번 Native 변경은 action 라벨의 ui 서체 역할만 명시한다. 알림 문구·큐·시간·닫기·
|
|
179
|
+
행동·초점 계약은 바꾸지 않는다.
|
package/docs/toggle-group.md
CHANGED
|
@@ -16,6 +16,11 @@ single 모드를 넣지 않는 것이 규칙이다.
|
|
|
16
16
|
|
|
17
17
|
**상태는 색이 아니라 `aria-pressed`(Native `selected`)가 말한다.** 색은 보강일 뿐이다.
|
|
18
18
|
|
|
19
|
+
**제품 모서리.** 2026-10-07 테마 소비 점검에서 숫자로 확정된 recipe를 양 renderer가
|
|
20
|
+
그대로 사용해 profile 변경이 누락됐다. 가장 가까운 Provider의 `tokens.radius.md`로
|
|
21
|
+
표현을 해결하고, profile이 없으면 기존 recipe 12를 유지한다. 선택 모델·눌림/비활성·
|
|
22
|
+
키보드 계약은 그대로이며 제품마다 별도 ToggleGroup을 만들 필요가 없다.
|
|
23
|
+
|
|
19
24
|
**tab stop.** 각 토글이 자기 tab stop이다. 도구 모음식 roving focus를 쓰지 않는 이유는
|
|
20
25
|
묶음이 대개 2~4개로 짧고, roving은 "그룹 안에서 화살표로 이동"이라는 추가 학습을
|
|
21
26
|
요구하기 때문이다. 항목이 많아지는 실제 화면이 나오면 그때 축을 연다.
|
package/docs/top.md
CHANGED
|
@@ -30,3 +30,9 @@
|
|
|
30
30
|
|
|
31
31
|
**상태가 없다.** controlled 축이 없고 키보드도 dismiss도 없다 — 화면이 제목을 바꾸면
|
|
32
32
|
다른 문자열을 넘기면 된다.
|
|
33
|
+
|
|
34
|
+
## 프로필 모서리·제목 소비
|
|
35
|
+
|
|
36
|
+
2026-10-07 소비 감사에서 두 renderer의 제목 크기·행간·굵기가 foundation으로 확정된 recipe를 직접 읽어 프로필을 우회했다. `large`는 가까운 프로필의 `heading.level2`, `medium`은 `typography.titleLarge`를 읽고 프로필이 없으면 기존 recipe를 유지한다. 시각 역할은 `headingLevel`과 독립이며 display 서체·제목 의미·보조 행동·초점은 바꾸지 않는다.
|
|
37
|
+
|
|
38
|
+
프로필 연결은 1.15.0 이후 미게시 변경이며, 기본 배포 계약과 실제 Native 기기 검증은 구분한다.
|
package/docs/transfer-list.md
CHANGED
|
@@ -115,3 +115,9 @@ they do not claim installed-device, VoiceOver, or TalkBack validation.
|
|
|
115
115
|
- **Shared behavior:** moved rows are not preselected at the destination, disabled rows cannot be
|
|
116
116
|
selected or moved, and select-all excludes disabled rows from its denominator. `onMove` gives
|
|
117
117
|
the product moved ids in source-panel order so it can compose an announcement.
|
|
118
|
+
|
|
119
|
+
## 프로필 모서리·제목 소비
|
|
120
|
+
|
|
121
|
+
2026-10-07 소비 감사에서 Native 패널의 모서리 12가 프로필을 우회했다. Web 패널의 기존 `radius.md`와 같은 역할을 Native도 가까운 프로필에서 읽으며, 프로필이 없으면 기존 12를 유지한다. 선택 집합·이동·비활성 항목·초점 계약은 바꾸지 않는다.
|
|
122
|
+
|
|
123
|
+
프로필 연결은 1.15.0 이후 미게시 변경이며, 기본 배포 계약과 실제 Native 기기 검증은 구분한다.
|
package/docs/upload-item.md
CHANGED
|
@@ -77,3 +77,9 @@
|
|
|
77
77
|
실제 취소, 재시도 lifecycle 검증은 소비 제품이 소유하므로 이 vertical slice의 부재는 HJM
|
|
78
78
|
renderer 승격을 막지 않는다. 2026-09-29 승격 기준 정리에서 adoption/deployment 조건을
|
|
79
79
|
분리했고, renderer 계약과 실제 제품 흐름을 중복 요구하지 않기로 했다.
|
|
80
|
+
|
|
81
|
+
## 프로필 모서리·제목 소비
|
|
82
|
+
|
|
83
|
+
2026-10-07 소비 감사에서 Native 행의 모서리 12가 프로필을 우회했다. Web의 기존 `radius.md`와 같은 역할을 Native도 가까운 프로필에서 읽으며, 프로필이 없으면 기존 12를 유지한다. 업로드 상태·취소/재시도·진행 알림은 바꾸지 않는다.
|
|
84
|
+
|
|
85
|
+
프로필 연결은 1.15.0 이후 미게시 변경이며, 기본 배포 계약과 실제 Native 기기 검증은 구분한다.
|