@hjmds/design-contracts 1.27.2 → 1.28.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/activity-chip.d.ts +1 -1
- package/dist/activity-chip.js +1 -1
- package/dist/activity-chip.js.map +1 -1
- package/dist/auth-screen.d.ts +77 -5
- package/dist/auth-screen.d.ts.map +1 -1
- package/dist/auth-screen.js +63 -2
- package/dist/auth-screen.js.map +1 -1
- package/dist/base-recipes.d.ts +1 -1
- package/dist/base-recipes.js +1 -1
- package/dist/base-recipes.js.map +1 -1
- package/dist/behaviors.d.ts +1 -1
- package/dist/breadcrumb.d.ts +1 -1
- package/dist/breadcrumb.js +1 -1
- package/dist/breadcrumb.js.map +1 -1
- package/dist/calendar.d.ts +1 -1
- package/dist/calendar.js +2 -2
- package/dist/calendar.js.map +1 -1
- package/dist/catalog.d.ts +131 -87
- package/dist/catalog.d.ts.map +1 -1
- package/dist/component-contracts.d.ts +1 -1
- package/dist/component-contracts.js +1 -1
- package/dist/component-contracts.js.map +1 -1
- package/dist/component-recipes.d.ts +85 -57
- package/dist/component-recipes.d.ts.map +1 -1
- package/dist/component-recipes.js +98 -60
- package/dist/component-recipes.js.map +1 -1
- package/dist/conversation-row.d.ts +2 -2
- package/dist/conversation-row.d.ts.map +1 -1
- package/dist/conversation-row.js +6 -4
- package/dist/conversation-row.js.map +1 -1
- package/dist/counter-badge-recipe.d.ts +1 -1
- package/dist/counter-badge-recipe.js +1 -1
- package/dist/counter-badge-recipe.js.map +1 -1
- package/dist/data-table.d.ts +4 -4
- package/dist/data-table.js +4 -4
- package/dist/data-table.js.map +1 -1
- package/dist/date-picker.d.ts +1 -1
- package/dist/design-profile.d.ts.map +1 -1
- package/dist/design-profile.js +19 -16
- package/dist/design-profile.js.map +1 -1
- package/dist/file-picker.d.ts +1 -1
- package/dist/file-picker.js +1 -1
- package/dist/file-picker.js.map +1 -1
- package/dist/foundations.d.ts +18 -14
- package/dist/foundations.d.ts.map +1 -1
- package/dist/foundations.js +18 -13
- package/dist/foundations.js.map +1 -1
- package/dist/heading.d.ts +13 -13
- package/dist/heading.js.map +1 -1
- package/dist/number-field.d.ts +1 -1
- package/dist/otp-field.d.ts +1 -1
- package/dist/password-field.d.ts +1 -1
- package/dist/result.d.ts +1 -1
- package/dist/result.js +2 -2
- package/dist/result.js.map +1 -1
- package/dist/screen-patterns.d.ts +36 -0
- package/dist/screen-patterns.d.ts.map +1 -1
- package/dist/screen-patterns.js +20 -0
- package/dist/screen-patterns.js.map +1 -1
- package/dist/semantic-colors.d.ts +10 -0
- package/dist/semantic-colors.d.ts.map +1 -1
- package/dist/semantic-colors.js +6 -0
- package/dist/semantic-colors.js.map +1 -1
- package/dist/sheet.d.ts +7 -4
- package/dist/sheet.d.ts.map +1 -1
- package/dist/sheet.js +8 -5
- package/dist/sheet.js.map +1 -1
- package/dist/side-panel.d.ts +1 -1
- package/dist/side-panel.js +2 -2
- package/dist/side-panel.js.map +1 -1
- package/dist/steps.d.ts +1 -1
- package/dist/steps.js +1 -1
- package/dist/steps.js.map +1 -1
- package/dist/tag.d.ts +1 -1
- package/dist/tag.js +1 -1
- package/dist/tag.js.map +1 -1
- package/dist/timeline.d.ts +1 -1
- package/dist/timeline.js +1 -1
- package/dist/timeline.js.map +1 -1
- package/dist/top.d.ts +4 -4
- package/dist/top.d.ts.map +1 -1
- package/dist/top.js +3 -1
- package/dist/top.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/activity-chip.md +5 -1
- package/docs/auth-screen.md +2 -0
- package/docs/design-profile.md +14 -10
- package/docs/generated/component-maturity.md +1 -1
- package/docs/generated/renderer-evidence.json +9 -5
- package/docs/generated/renderer-evidence.md +1 -1
- package/docs/generated/showcase-manifest.json +1 -1
- package/docs/heading.md +14 -9
- package/docs/sheet.md +2 -0
- package/docs/top.md +4 -3
- package/docs/usage/README.md +1 -1
- package/docs/usage/SELECTION.md +1 -0
- package/docs/usage/components/auth-screen-layout.md +44 -11
- package/docs/usage/components/bottom-cta.md +6 -2
- package/docs/usage/components/breadcrumb.md +5 -1
- package/docs/usage/components/chat-screen.md +1 -0
- package/docs/usage/components/checkbox-group.md +5 -1
- package/docs/usage/components/collapsible.md +1 -0
- package/docs/usage/components/comment-thread-screen.md +2 -0
- package/docs/usage/components/dialog.md +1 -0
- package/docs/usage/components/editor-screen.md +1 -0
- package/docs/usage/components/effect-surface.md +2 -2
- package/docs/usage/components/field.md +1 -0
- package/docs/usage/components/heading.md +14 -12
- package/docs/usage/components/list-detail-screen.md +1 -0
- package/docs/usage/components/list-row.md +7 -3
- package/docs/usage/components/list.md +25 -4
- package/docs/usage/components/notification-item.md +5 -1
- package/docs/usage/components/onboarding-screen.md +1 -0
- package/docs/usage/components/photo-source-sheet.md +1 -1
- package/docs/usage/components/screen-layout.md +28 -3
- package/docs/usage/components/search-field.md +1 -0
- package/docs/usage/components/search-screen.md +4 -2
- package/docs/usage/components/section.md +5 -1
- package/docs/usage/components/segmented-control.md +1 -1
- package/docs/usage/components/sheet.md +18 -13
- package/docs/usage/components/skeleton.md +42 -15
- package/docs/usage/components/statistic.md +5 -1
- package/docs/usage/components/switch.md +3 -2
- package/docs/usage/components/tag.md +5 -1
- package/docs/usage/components/text-area.md +1 -0
- package/docs/usage/components/text.md +6 -4
- package/docs/usage/components/top.md +1 -1
- package/docs/usage/compositions/adaptive-content.md +5 -1
- package/docs/usage/compositions/compound-controls.md +2 -1
- package/docs/usage/compositions/design-profile-comparison.md +1 -1
- package/docs/usage/compositions/family-drawer.md +5 -3
- package/docs/usage/compositions/input-sheet.md +1 -1
- package/docs/usage/compositions/interaction-flow-apply.md +3 -3
- package/docs/usage/compositions/photo-source.md +3 -3
- package/docs/usage/compositions/selection-motion.md +5 -1
- package/docs/usage/compositions/visual-foundations.md +5 -4
- package/docs/usage/screens/common-login.md +9 -7
- package/docs/usage/screens/landing.md +15 -14
- package/docs/usage/screens/notification-settings.md +4 -2
- package/docs/usage/tokens/typography.md +21 -13
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { collectionItemContract, fieldFrameContract, floatingSurfaceContract, focusIndicatorContract, formSupportContract, } from "./component-contracts.js";
|
|
2
|
-
import { backdrop, breakpoint, control, glyph, layer, largeTextThreshold, layout, fontWeight, motion, motionPreset, opacity, radius, spacing, stroke, } from "./foundations.js";
|
|
2
|
+
import { backdrop, breakpoint, control, glyph, layer, largeTextThreshold, layout, fontWeight, motion, motionPreset, opacity, radius, spacing, stroke, typography, } from "./foundations.js";
|
|
3
|
+
import { buttonRecipe } from "./base-recipes.js";
|
|
3
4
|
import { semanticColors } from "./semantic-colors.js";
|
|
4
5
|
import { tooltipDescriptorDefaults } from "./tooltip.js";
|
|
5
6
|
import { bottomNavigationRecipeDefaults } from "./bottom-navigation-defaults.js";
|
|
@@ -19,14 +20,18 @@ export const textRecipe = {
|
|
|
19
20
|
danger: semanticColors.content.danger,
|
|
20
21
|
inverse: semanticColors.content.inverse,
|
|
21
22
|
},
|
|
23
|
+
// 2026-10-17 user decisions: the strongest inline emphasis matches the title weight. strong=700 made unread
|
|
24
|
+
// notification titles and labels heavier than every title after titles moved to 600 ("왜 폰트가 진해"), so
|
|
25
|
+
// strong became 600; the second round ("굵기 좀더 줄여") moved titles 600→500 and display headings 700→600,
|
|
26
|
+
// so strong follows the title role (500) and equals `medium`. Semibold 600 is the key-number/selected step.
|
|
22
27
|
emphasis: {
|
|
23
28
|
regular: fontWeight.regular,
|
|
24
|
-
medium: fontWeight.
|
|
25
|
-
strong: fontWeight
|
|
29
|
+
medium: fontWeight.medium,
|
|
30
|
+
strong: typography.title.fontWeight,
|
|
26
31
|
},
|
|
27
32
|
/**
|
|
28
33
|
* Variants whose omitted `emphasis` renders the variant's typography weight even without a design profile.
|
|
29
|
-
* Label's 500
|
|
34
|
+
* Label's 500 equals the `medium` emphasis step, but the shared `regular` default drew form labels at
|
|
30
35
|
* body weight (2026-10-17 user decision: label 500 on Web and Native). Other variants keep `regular`.
|
|
31
36
|
*/
|
|
32
37
|
variantWeight: ["label"],
|
|
@@ -86,7 +91,7 @@ export const linkRecipe = {
|
|
|
86
91
|
variants: {
|
|
87
92
|
inline: {
|
|
88
93
|
textVariant: "body",
|
|
89
|
-
fontWeight: fontWeight.
|
|
94
|
+
fontWeight: fontWeight.medium,
|
|
90
95
|
underline: "always",
|
|
91
96
|
minHeight: null,
|
|
92
97
|
minWidth: null,
|
|
@@ -94,7 +99,7 @@ export const linkRecipe = {
|
|
|
94
99
|
/** 그 자체가 동작이므로 두 축 모두 최소 터치 타깃. 높이만 잡으면 짧은 라벨이 좁아진다. */
|
|
95
100
|
standalone: {
|
|
96
101
|
textVariant: "body",
|
|
97
|
-
fontWeight: fontWeight.
|
|
102
|
+
fontWeight: fontWeight.medium,
|
|
98
103
|
underline: "hover",
|
|
99
104
|
minHeight: control.minTouchTarget,
|
|
100
105
|
minWidth: control.minTouchTarget,
|
|
@@ -218,7 +223,7 @@ export const badgeRecipe = {
|
|
|
218
223
|
},
|
|
219
224
|
radius: "full",
|
|
220
225
|
borderWidth: stroke.default,
|
|
221
|
-
fontWeight: fontWeight.
|
|
226
|
+
fontWeight: fontWeight.medium,
|
|
222
227
|
};
|
|
223
228
|
/** Search is a field specialization with stable affordance and clear targets. */
|
|
224
229
|
export const searchFieldRecipe = {
|
|
@@ -320,7 +325,8 @@ export const chipRecipe = {
|
|
|
320
325
|
},
|
|
321
326
|
radius: "full",
|
|
322
327
|
borderWidth: stroke.default,
|
|
323
|
-
|
|
328
|
+
// Selected keeps one step above idle (500 → 600) so the state still carries a weight cue on the lighter scale.
|
|
329
|
+
label: { fontWeight: fontWeight.medium, selectedFontWeight: fontWeight.semibold },
|
|
324
330
|
selectionIndicator: {
|
|
325
331
|
color: semanticColors.content.brand,
|
|
326
332
|
glyph: "xs",
|
|
@@ -346,15 +352,24 @@ export const dividerRecipe = {
|
|
|
346
352
|
* VirtualList) keep exactly this much inline room so the bleed is never cut.
|
|
347
353
|
*/
|
|
348
354
|
const listRowSurfaceBleed = spacing.xs;
|
|
355
|
+
/** ListRow leading frame and the gap before its text column; the indented separator reuses both. */
|
|
356
|
+
const listRowLeadingSize = 40;
|
|
357
|
+
const listRowGap = spacing.sm;
|
|
349
358
|
export const listRecipe = {
|
|
350
359
|
slots: ["root", "item", "separator"],
|
|
351
360
|
defaults: { separator: "indented" },
|
|
361
|
+
/**
|
|
362
|
+
* Separators are measured from the list's content edge, where the row text sits, and each one belongs to the row
|
|
363
|
+
* above it (iOS cell separator). "full" spans the row surface (content edge ± bleed). "indented" follows that row's
|
|
364
|
+
* text column: it starts at the text — `leadingInsetStart` (leading 40 + gap 12) when the row has a leading
|
|
365
|
+
* element, `insetStart` 0 when it has none — and ends on the row's trailing content edge (0).
|
|
366
|
+
* 2026-10-17 user report: a fixed 52 start cut the line off midway under rows without leading (text at 16, line
|
|
367
|
+
* from 68), and the −8 end ran past the trailing content.
|
|
368
|
+
*/
|
|
352
369
|
separators: {
|
|
353
370
|
none: null,
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
full: { insetStart: -listRowSurfaceBleed, insetEnd: -listRowSurfaceBleed },
|
|
357
|
-
indented: { insetStart: 40 + spacing.sm, insetEnd: -listRowSurfaceBleed },
|
|
371
|
+
full: { insetStart: -listRowSurfaceBleed, leadingInsetStart: -listRowSurfaceBleed, insetEnd: -listRowSurfaceBleed },
|
|
372
|
+
indented: { insetStart: 0, leadingInsetStart: listRowLeadingSize + listRowGap, insetEnd: 0 },
|
|
358
373
|
},
|
|
359
374
|
// A grouped list paints its own rounded surface and clips to it, so it leaves the row bleed as inline padding:
|
|
360
375
|
// rows keep their full surface inside the radius and the text stays 8 inside the group edge as before.
|
|
@@ -406,15 +421,15 @@ export const listRowRecipe = {
|
|
|
406
421
|
* the same negative inline margin, so pressed/selected fills keep 8 of room beyond the text.
|
|
407
422
|
*/
|
|
408
423
|
surfaceBleed: listRowSurfaceBleed,
|
|
409
|
-
gap:
|
|
410
|
-
leadingSize:
|
|
424
|
+
gap: listRowGap,
|
|
425
|
+
leadingSize: listRowLeadingSize,
|
|
411
426
|
/**
|
|
412
427
|
* Frame geometry for the leading slot. The size was already declared here but
|
|
413
428
|
* no renderer bound it, so every consumer re-derived the avatar box (radius,
|
|
414
429
|
* clipping, centering) in product styles.
|
|
415
430
|
*/
|
|
416
431
|
leadingShapes: { square: null, circle: "full" },
|
|
417
|
-
title: { color: semanticColors.content.body, textVariant: "bodyLarge", fontWeight: fontWeight
|
|
432
|
+
title: { color: semanticColors.content.body, textVariant: "bodyLarge", fontWeight: typography.title.fontWeight },
|
|
418
433
|
description: { color: semanticColors.content.secondary, textVariant: "body" },
|
|
419
434
|
trailing: {
|
|
420
435
|
textColor: semanticColors.content.secondary,
|
|
@@ -437,7 +452,7 @@ export const accordionRecipe = {
|
|
|
437
452
|
},
|
|
438
453
|
paddingHorizontal: spacing.xs,
|
|
439
454
|
gap: spacing.sm,
|
|
440
|
-
title: { color: semanticColors.content.body, textVariant: "bodyLarge", fontWeight: fontWeight
|
|
455
|
+
title: { color: semanticColors.content.body, textVariant: "bodyLarge", fontWeight: typography.title.fontWeight },
|
|
441
456
|
indicator: { color: semanticColors.content.secondary, glyph: "sm" },
|
|
442
457
|
panel: {
|
|
443
458
|
color: semanticColors.content.body,
|
|
@@ -577,7 +592,7 @@ export const selectRecipe = {
|
|
|
577
592
|
paddingVertical: spacing.xs,
|
|
578
593
|
},
|
|
579
594
|
optionLeading: { color: semanticColors.content.secondary, glyph: "sm" },
|
|
580
|
-
optionLabel: { fontWeight: fontWeight.
|
|
595
|
+
optionLabel: { fontWeight: fontWeight.medium, selectedFontWeight: fontWeight.semibold },
|
|
581
596
|
selectionIndicator: { color: semanticColors.border.focus, glyph: "sm" },
|
|
582
597
|
stateMessage: {
|
|
583
598
|
color: semanticColors.content.secondary,
|
|
@@ -648,6 +663,8 @@ export const comboboxRecipe = {
|
|
|
648
663
|
states: selectRecipe.states,
|
|
649
664
|
transition: selectRecipe.transition,
|
|
650
665
|
};
|
|
666
|
+
/** Block-side inset of the connected track: `container.padding` + `container.borderWidth`. */
|
|
667
|
+
const segmentedTrackInset = spacing.xxs + stroke.subtle;
|
|
651
668
|
export const segmentedControlRecipe = {
|
|
652
669
|
// Text navigation reuses radio selection, without cloning a product-only tab engine.
|
|
653
670
|
text: { gap: spacing.md, indicatorWidth: 16, indicatorHeight: 2, indicatorRadius: radius.full,
|
|
@@ -684,16 +701,25 @@ export const segmentedControlRecipe = {
|
|
|
684
701
|
padding: spacing.xxs,
|
|
685
702
|
gap: spacing.xxs,
|
|
686
703
|
},
|
|
704
|
+
/**
|
|
705
|
+
* `height` is the connected control's outer height (track border + padding included) and matches the Button /
|
|
706
|
+
* IconButton / Chip height of the same size step, so a segmented control and a chip in one row line up.
|
|
707
|
+
* `minHeight` is the option inside the track (height − 2 × (`container.padding` + `container.borderWidth`)) and `hitSlop` extends each
|
|
708
|
+
* option vertically to the 44 touch target. Before 2026-10-17 `minHeight` was the option itself, so the track
|
|
709
|
+
* drew 46/54 next to 36/44 chips and buttons (DiscoveryGallery sort row, user request "높이 맞춰").
|
|
710
|
+
*/
|
|
687
711
|
sizes: {
|
|
688
712
|
small: {
|
|
689
|
-
|
|
690
|
-
|
|
713
|
+
height: control.buttonHeight.small,
|
|
714
|
+
minHeight: control.buttonHeight.small - 2 * segmentedTrackInset,
|
|
715
|
+
hitSlop: (control.minTouchTarget - (control.buttonHeight.small - 2 * segmentedTrackInset)) / 2,
|
|
691
716
|
paddingHorizontal: spacing.sm,
|
|
692
717
|
textVariant: "label",
|
|
693
718
|
},
|
|
694
719
|
medium: {
|
|
695
|
-
|
|
696
|
-
|
|
720
|
+
height: control.buttonHeight.medium,
|
|
721
|
+
minHeight: control.buttonHeight.medium - 2 * segmentedTrackInset,
|
|
722
|
+
hitSlop: (control.minTouchTarget - (control.buttonHeight.medium - 2 * segmentedTrackInset)) / 2,
|
|
697
723
|
paddingHorizontal: spacing.md,
|
|
698
724
|
textVariant: "body",
|
|
699
725
|
},
|
|
@@ -702,7 +728,7 @@ export const segmentedControlRecipe = {
|
|
|
702
728
|
radius: "md",
|
|
703
729
|
gap: spacing.xxs,
|
|
704
730
|
idleContent: semanticColors.content.secondary,
|
|
705
|
-
fontWeight: fontWeight.
|
|
731
|
+
fontWeight: fontWeight.medium,
|
|
706
732
|
selectedBackground: semanticColors.canvas,
|
|
707
733
|
selectedContent: semanticColors.content.brand,
|
|
708
734
|
/**
|
|
@@ -712,7 +738,7 @@ export const segmentedControlRecipe = {
|
|
|
712
738
|
*/
|
|
713
739
|
selectedBorder: semanticColors.border.focus,
|
|
714
740
|
selectedBorderWidth: stroke.strong,
|
|
715
|
-
selectedFontWeight: fontWeight.
|
|
741
|
+
selectedFontWeight: fontWeight.semibold,
|
|
716
742
|
focusRing: semanticColors.border.focus,
|
|
717
743
|
pressedOpacity: opacity.pressed,
|
|
718
744
|
disabledOpacity: opacity.disabled,
|
|
@@ -773,11 +799,16 @@ export const switchRecipe = {
|
|
|
773
799
|
pressedOpacity: opacity.pressed,
|
|
774
800
|
},
|
|
775
801
|
rowMinHeight: control.minTouchTarget,
|
|
776
|
-
// A switch
|
|
777
|
-
//
|
|
778
|
-
//
|
|
779
|
-
//
|
|
780
|
-
|
|
802
|
+
// A described switch is a two-line row: the copy (body 20 + gap 4 + caption 16 = 40) with the
|
|
803
|
+
// comfortable list-row vertical padding (8) on both sides. The padding is drawn by the row itself
|
|
804
|
+
// so it survives larger text, and the minimum keeps neighbouring rows equal (a product author found
|
|
805
|
+
// content-only height gave them different heights). It used to borrow ListRow's 68, which is sized
|
|
806
|
+
// for a bodyLarge title + body description; on the smaller switch copy that left 14 above and below,
|
|
807
|
+
// and stacked rows read as widely spaced (2026-10-17 user report, notification settings: 84 pitch
|
|
808
|
+
// for 40 of copy, together with a Stack gap the rows must not have).
|
|
809
|
+
rowPaddingVertical: listRowRecipe.density.comfortable.paddingVertical,
|
|
810
|
+
rowTwoLineMinHeight: typography.body.lineHeight + spacing.xxs + typography.caption.lineHeight
|
|
811
|
+
+ 2 * listRowRecipe.density.comfortable.paddingVertical,
|
|
781
812
|
};
|
|
782
813
|
export const selectionControlRecipe = {
|
|
783
814
|
slots: [
|
|
@@ -853,8 +884,8 @@ export const selectionControlRecipe = {
|
|
|
853
884
|
},
|
|
854
885
|
label: {
|
|
855
886
|
color: semanticColors.content.body,
|
|
856
|
-
fontWeight: fontWeight.
|
|
857
|
-
checkedFontWeight: fontWeight.
|
|
887
|
+
fontWeight: fontWeight.medium,
|
|
888
|
+
checkedFontWeight: fontWeight.semibold,
|
|
858
889
|
},
|
|
859
890
|
leading: { size: "md", color: semanticColors.content.secondary },
|
|
860
891
|
description: { color: semanticColors.content.secondary },
|
|
@@ -1018,8 +1049,8 @@ export const bottomNavigationRecipe = {
|
|
|
1018
1049
|
},
|
|
1019
1050
|
},
|
|
1020
1051
|
label: {
|
|
1021
|
-
fontWeight: fontWeight.
|
|
1022
|
-
selectedFontWeight: fontWeight.
|
|
1052
|
+
fontWeight: fontWeight.medium,
|
|
1053
|
+
selectedFontWeight: fontWeight.semibold,
|
|
1023
1054
|
textAlign: "center",
|
|
1024
1055
|
wrap: true,
|
|
1025
1056
|
fixedLines: null,
|
|
@@ -1090,7 +1121,7 @@ export const tabsRecipe = {
|
|
|
1090
1121
|
},
|
|
1091
1122
|
gap: spacing.xs,
|
|
1092
1123
|
icon: { glyph: "xs" },
|
|
1093
|
-
label: { fontWeight: fontWeight.
|
|
1124
|
+
label: { fontWeight: fontWeight.medium, selectedFontWeight: fontWeight.semibold },
|
|
1094
1125
|
layouts: {
|
|
1095
1126
|
content: { fitted: false },
|
|
1096
1127
|
fitted: { fitted: true },
|
|
@@ -1129,21 +1160,30 @@ export const noticeRecipe = {
|
|
|
1129
1160
|
contentGap: spacing.xxs,
|
|
1130
1161
|
iconSize: "sm",
|
|
1131
1162
|
borderWidth: stroke.default,
|
|
1132
|
-
title: { textVariant: "body", fontWeight: fontWeight
|
|
1163
|
+
title: { textVariant: "body", fontWeight: typography.title.fontWeight },
|
|
1133
1164
|
description: { color: semanticColors.content.body, textVariant: "body" },
|
|
1134
1165
|
};
|
|
1135
1166
|
export const skeletonRecipe = {
|
|
1136
|
-
slots: ["root"],
|
|
1167
|
+
slots: ["root", "line"],
|
|
1137
1168
|
// animated는 0.9.12까지 false였다. 정지한 블록은 로딩이 아니라 깨진 화면으로
|
|
1138
1169
|
// 읽힌다. 전환 근거와 소비 측 migration은
|
|
1139
1170
|
// .changeset/skeleton-pulse-by-default.md에 있다.
|
|
1140
|
-
defaults: { shape: "block", animated: true },
|
|
1141
|
-
|
|
1171
|
+
defaults: { shape: "block", animated: true, lines: 1 },
|
|
1172
|
+
// 2026-10-17 사용자 요청: canvas 채움 + 1px 테두리는 흰 배경에서 거의 보이지 않아 로딩 모양을 알 수 없었다.
|
|
1173
|
+
// 2026-09-29 "넓은 회색 면은 canvas" 방향의 예외로, 자리표시는 채운 면이어야 모양이 읽힌다(skeleton.md 근거).
|
|
1174
|
+
background: semanticColors.surface.placeholder,
|
|
1175
|
+
// `aspectRatio`가 있으면 높이 대신 폭에 비례한다(media). `button`은 medium 버튼 높이와 Button 기본 모양의 모서리다.
|
|
1176
|
+
// 2026-10-17: 번뚝처럼 알약 버튼을 쓰는 제품은 자리표시도 알약이어야 하므로 모서리는 `buttonShape` 축
|
|
1177
|
+
// (buttonRecipe.shapes와 같은 이름·같은 기본값)으로 고르고, 이 값은 그 기본값에서 나온다.
|
|
1142
1178
|
shapes: {
|
|
1143
|
-
block: { radius: "md", defaultHeight: spacing.xxl },
|
|
1144
|
-
text: { radius: "sm", defaultHeight: spacing.md },
|
|
1145
|
-
circle: { radius: "full", defaultHeight: glyph.xxl },
|
|
1146
|
-
|
|
1179
|
+
block: { radius: "md", defaultHeight: spacing.xxl, aspectRatio: null },
|
|
1180
|
+
text: { radius: "sm", defaultHeight: spacing.md, aspectRatio: null },
|
|
1181
|
+
circle: { radius: "full", defaultHeight: glyph.xxl, aspectRatio: null },
|
|
1182
|
+
media: { radius: "md", defaultHeight: null, aspectRatio: 16 / 9 },
|
|
1183
|
+
button: { radius: buttonRecipe.shapes[buttonRecipe.defaults.shape], defaultHeight: control.buttonHeight.medium, aspectRatio: null },
|
|
1184
|
+
},
|
|
1185
|
+
// `lines` > 1 (text 전용): 줄 사이 간격과 짧게 끝나는 마지막 줄. 16 막대 + 8 간격 = 본문 큰 글자 줄 높이 24.
|
|
1186
|
+
lines: { gap: spacing.xs, lastLineWidthPercent: 60 },
|
|
1147
1187
|
animation: {
|
|
1148
1188
|
duration: motion.slow * 4,
|
|
1149
1189
|
easing: "standard",
|
|
@@ -1162,7 +1202,7 @@ export const emptyStateRecipe = {
|
|
|
1162
1202
|
paddingHorizontal: spacing.xl,
|
|
1163
1203
|
gap: spacing.xs,
|
|
1164
1204
|
icon: { size: "lg", color: semanticColors.content.decorative },
|
|
1165
|
-
title: { textVariant: "body", color: semanticColors.content.primary, fontWeight: fontWeight
|
|
1205
|
+
title: { textVariant: "body", color: semanticColors.content.primary, fontWeight: typography.title.fontWeight },
|
|
1166
1206
|
description: { textVariant: "label", color: semanticColors.content.secondary },
|
|
1167
1207
|
};
|
|
1168
1208
|
export const spinnerRecipe = {
|
|
@@ -1214,7 +1254,7 @@ export const loadMoreRecipe = {
|
|
|
1214
1254
|
radius: "md",
|
|
1215
1255
|
color: semanticColors.content.brand,
|
|
1216
1256
|
textVariant: "label",
|
|
1217
|
-
fontWeight: fontWeight.
|
|
1257
|
+
fontWeight: fontWeight.medium,
|
|
1218
1258
|
},
|
|
1219
1259
|
spinner: { size: "small", tone: "brand" },
|
|
1220
1260
|
states: {
|
|
@@ -1236,7 +1276,7 @@ export const avatarRecipe = {
|
|
|
1236
1276
|
background: semanticColors.canvas,
|
|
1237
1277
|
content: semanticColors.content.secondary,
|
|
1238
1278
|
border: semanticColors.border.default,
|
|
1239
|
-
/** Initials
|
|
1279
|
+
/** Initials use the strong emphasis step; their size follows the avatar (Web `.hjm-avatar[data-size]` steps). */
|
|
1240
1280
|
initialsWeight: "strong",
|
|
1241
1281
|
};
|
|
1242
1282
|
/**
|
|
@@ -1294,18 +1334,20 @@ export const statisticRecipe = {
|
|
|
1294
1334
|
},
|
|
1295
1335
|
label: {
|
|
1296
1336
|
color: semanticColors.content.secondary,
|
|
1297
|
-
fontWeight: fontWeight.
|
|
1337
|
+
fontWeight: fontWeight.medium,
|
|
1298
1338
|
},
|
|
1299
1339
|
value: {
|
|
1300
1340
|
color: semanticColors.content.primary,
|
|
1301
|
-
|
|
1341
|
+
// The key number keeps the semibold emphasis step (600, 2026-10-17 lighter scale) at the `heading` size.
|
|
1342
|
+
// It used to borrow the display heading weight, which was removed with the display tier the same day.
|
|
1343
|
+
fontWeight: fontWeight.semibold,
|
|
1302
1344
|
numericVariant: "tabular",
|
|
1303
1345
|
maxLines: null,
|
|
1304
1346
|
},
|
|
1305
1347
|
affix: {
|
|
1306
1348
|
color: semanticColors.content.body,
|
|
1307
1349
|
textVariant: "body",
|
|
1308
|
-
fontWeight: fontWeight.
|
|
1350
|
+
fontWeight: fontWeight.medium,
|
|
1309
1351
|
},
|
|
1310
1352
|
hint: {
|
|
1311
1353
|
color: semanticColors.content.secondary,
|
|
@@ -1313,7 +1355,7 @@ export const statisticRecipe = {
|
|
|
1313
1355
|
},
|
|
1314
1356
|
trend: {
|
|
1315
1357
|
textVariant: "caption",
|
|
1316
|
-
fontWeight: fontWeight.
|
|
1358
|
+
fontWeight: fontWeight.medium,
|
|
1317
1359
|
gap: spacing.xxs,
|
|
1318
1360
|
marks: {
|
|
1319
1361
|
up: "trendUp",
|
|
@@ -1378,12 +1420,8 @@ export const sheetRecipe = {
|
|
|
1378
1420
|
showWhen: "swipe-dismiss-enabled",
|
|
1379
1421
|
},
|
|
1380
1422
|
header: { minHeight: control.minTouchTarget, gap: spacing.sm },
|
|
1381
|
-
title:
|
|
1382
|
-
|
|
1383
|
-
textVariant: "title",
|
|
1384
|
-
fontWeight: fontWeight.bold,
|
|
1385
|
-
gap: spacing.xxs,
|
|
1386
|
-
},
|
|
1423
|
+
// No visual `title` region: sheets render the title only as the accessible name (2026-10-17 user decision).
|
|
1424
|
+
// The "title" slot stays because the title is still the dialog's name.
|
|
1387
1425
|
body: {
|
|
1388
1426
|
color: semanticColors.content.body,
|
|
1389
1427
|
textVariant: "body",
|
|
@@ -1467,7 +1505,7 @@ export const alertDialogRecipe = {
|
|
|
1467
1505
|
title: {
|
|
1468
1506
|
color: semanticColors.content.primary,
|
|
1469
1507
|
textVariant: "title",
|
|
1470
|
-
fontWeight: fontWeight
|
|
1508
|
+
fontWeight: typography.title.fontWeight,
|
|
1471
1509
|
},
|
|
1472
1510
|
description: {
|
|
1473
1511
|
color: semanticColors.content.secondary,
|
|
@@ -1586,7 +1624,7 @@ export const toastRecipe = {
|
|
|
1586
1624
|
title: {
|
|
1587
1625
|
color: semanticColors.content.primary,
|
|
1588
1626
|
textVariant: "body",
|
|
1589
|
-
fontWeight: fontWeight
|
|
1627
|
+
fontWeight: typography.title.fontWeight,
|
|
1590
1628
|
},
|
|
1591
1629
|
// Secondary copy so the title leads; body-on-body read as one grey block.
|
|
1592
1630
|
description: {
|
|
@@ -1594,7 +1632,7 @@ export const toastRecipe = {
|
|
|
1594
1632
|
textVariant: "body",
|
|
1595
1633
|
},
|
|
1596
1634
|
// Step dots of a running task: done and current are brand, upcoming is the divider colour; the current
|
|
1597
|
-
// label is
|
|
1635
|
+
// label is emphasized. Labels sit beside each dot so the row reads without colour alone (WCAG 1.4.1).
|
|
1598
1636
|
progress: {
|
|
1599
1637
|
gap: spacing.sm,
|
|
1600
1638
|
dotSize: 6,
|
|
@@ -1614,7 +1652,7 @@ export const toastRecipe = {
|
|
|
1614
1652
|
radius: "full",
|
|
1615
1653
|
align: "start",
|
|
1616
1654
|
textVariant: "body",
|
|
1617
|
-
fontWeight: fontWeight.
|
|
1655
|
+
fontWeight: fontWeight.medium,
|
|
1618
1656
|
minHeight: control.minTouchTarget,
|
|
1619
1657
|
paddingHorizontal: spacing.md,
|
|
1620
1658
|
},
|
|
@@ -1683,7 +1721,7 @@ export const topBarRecipe = {
|
|
|
1683
1721
|
paddingHorizontal: spacing.md,
|
|
1684
1722
|
gap: spacing.xs,
|
|
1685
1723
|
largeTextThreshold,
|
|
1686
|
-
title: { textVariant: "bodyLarge", color: semanticColors.content.primary, fontWeight: fontWeight
|
|
1724
|
+
title: { textVariant: "bodyLarge", color: semanticColors.content.primary, fontWeight: typography.title.fontWeight },
|
|
1687
1725
|
titleAction: {
|
|
1688
1726
|
minHeight: control.minTouchTarget,
|
|
1689
1727
|
minWidth: control.minTouchTarget,
|
|
@@ -1744,7 +1782,7 @@ export const sectionRecipe = {
|
|
|
1744
1782
|
gap: spacing.xs,
|
|
1745
1783
|
headerGap: spacing.sm,
|
|
1746
1784
|
copyGap: spacing.xxs,
|
|
1747
|
-
title: { textVariant: "title", color: semanticColors.content.body, fontWeight: fontWeight
|
|
1785
|
+
title: { textVariant: "title", color: semanticColors.content.body, fontWeight: typography.title.fontWeight },
|
|
1748
1786
|
description: { textVariant: "caption", color: semanticColors.content.secondary },
|
|
1749
1787
|
};
|
|
1750
1788
|
//# sourceMappingURL=component-recipes.js.map
|