@deriv-com/dds-marketing 1.1.3 → 1.2.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.
Files changed (295) hide show
  1. package/.llm/components/accordion.md +6 -0
  2. package/.llm/components/accordionitem.md +6 -0
  3. package/.llm/components/aspectratio.md +6 -0
  4. package/.llm/components/awards.md +6 -0
  5. package/.llm/components/background.md +49 -10
  6. package/.llm/components/badge.md +6 -0
  7. package/.llm/components/bottomsheet.md +6 -0
  8. package/.llm/components/breadcrumb.md +6 -0
  9. package/.llm/components/breadcrumbitem.md +6 -0
  10. package/.llm/components/button.md +9 -3
  11. package/.llm/components/buttonicon.md +7 -1
  12. package/.llm/components/card.md +6 -0
  13. package/.llm/components/cardbody.md +7 -1
  14. package/.llm/components/cardbutton.md +6 -0
  15. package/.llm/components/checkbox.md +6 -0
  16. package/.llm/components/comparisoncards.md +9 -3
  17. package/.llm/components/comparisontable.md +6 -0
  18. package/.llm/components/ctabanner.md +6 -0
  19. package/.llm/components/ctabannerslider.md +6 -0
  20. package/.llm/components/datatable.md +6 -0
  21. package/.llm/components/divider.md +6 -0
  22. package/.llm/components/documentlink.md +237 -0
  23. package/.llm/components/documents.md +268 -0
  24. package/.llm/components/downloadbanner.md +7 -1
  25. package/.llm/components/dropdownmenu.md +6 -0
  26. package/.llm/components/estimator.md +6 -0
  27. package/.llm/components/faqaccordion.md +6 -0
  28. package/.llm/components/featurebullets.md +6 -0
  29. package/.llm/components/featurecards.md +42 -2
  30. package/.llm/components/featurecardscarousel.md +7 -1
  31. package/.llm/components/featurescroll.md +6 -0
  32. package/.llm/components/featuresplit.md +6 -0
  33. package/.llm/components/featurestack.md +6 -0
  34. package/.llm/components/featuretabs.md +369 -0
  35. package/.llm/components/filterchip.md +6 -0
  36. package/.llm/components/footer.md +6 -0
  37. package/.llm/components/footergroup.md +6 -0
  38. package/.llm/components/grid.md +30 -1
  39. package/.llm/components/icon.md +6 -0
  40. package/.llm/components/illustrationcard.md +52 -2
  41. package/.llm/components/illustrationcheck.md +193 -0
  42. package/.llm/components/illustrationchoice.md +187 -0
  43. package/.llm/components/illustrationcode.md +192 -0
  44. package/.llm/components/illustrationlist.md +175 -0
  45. package/.llm/components/illustrationscene.md +29 -3
  46. package/.llm/components/imagebanner.md +30 -5
  47. package/.llm/components/landinghero.md +6 -0
  48. package/.llm/components/link.md +7 -1
  49. package/.llm/components/logocolumns.md +7 -1
  50. package/.llm/components/logorows.md +42 -2
  51. package/.llm/components/menuitem.md +6 -0
  52. package/.llm/components/navbar.md +6 -0
  53. package/.llm/components/navbaritem.md +6 -0
  54. package/.llm/components/navbarmenu.md +6 -0
  55. package/.llm/components/navbarmenugroup.md +6 -0
  56. package/.llm/components/navbarpanel.md +6 -0
  57. package/.llm/components/navbarswitcher.md +6 -0
  58. package/.llm/components/navbarswitcheroption.md +6 -0
  59. package/.llm/components/option.md +6 -0
  60. package/.llm/components/pageheader.md +6 -0
  61. package/.llm/components/pagination.md +6 -0
  62. package/.llm/components/paginationdots.md +6 -0
  63. package/.llm/components/producthero.md +29 -4
  64. package/.llm/components/progressbar.md +305 -0
  65. package/.llm/components/removablechip.md +6 -0
  66. package/.llm/components/resourcebanner.md +6 -0
  67. package/.llm/components/row.md +6 -0
  68. package/.llm/components/scenescroll.md +38 -24
  69. package/.llm/components/scenescrollword.md +267 -0
  70. package/.llm/components/scroller.md +6 -0
  71. package/.llm/components/searchinput.md +6 -0
  72. package/.llm/components/segmentedcontrol.md +28 -1
  73. package/.llm/components/segmentedcontrolitem.md +6 -0
  74. package/.llm/components/select.md +6 -0
  75. package/.llm/components/selectchip.md +6 -0
  76. package/.llm/components/spinner.md +6 -0
  77. package/.llm/components/stack.md +6 -0
  78. package/.llm/components/stats.md +46 -1
  79. package/.llm/components/statscarousel.md +227 -0
  80. package/.llm/components/statusdot.md +41 -1
  81. package/.llm/components/steps.md +6 -0
  82. package/.llm/components/stickycards.md +6 -0
  83. package/.llm/components/subdomainnavbar.md +6 -0
  84. package/.llm/components/tab.md +6 -0
  85. package/.llm/components/table.md +6 -0
  86. package/.llm/components/tablebody.md +6 -0
  87. package/.llm/components/tablecell.md +6 -0
  88. package/.llm/components/tablehead.md +6 -0
  89. package/.llm/components/tableheadercell.md +6 -0
  90. package/.llm/components/tablerow.md +6 -0
  91. package/.llm/components/tablist.md +6 -0
  92. package/.llm/components/teamgrid.md +6 -0
  93. package/.llm/components/testimonialrow.md +43 -3
  94. package/.llm/components/testimonialslider.md +8 -2
  95. package/.llm/components/textarea.md +6 -0
  96. package/.llm/components/textinput.md +6 -0
  97. package/.llm/components/textscroll.md +6 -0
  98. package/.llm/components/tiers.md +13 -7
  99. package/.llm/components/tooltip.md +6 -0
  100. package/.llm/components/typography.md +63 -1
  101. package/.llm/digest/background.md +14 -6
  102. package/.llm/digest/button.md +1 -1
  103. package/.llm/digest/buttonicon.md +1 -1
  104. package/.llm/digest/documentlink.md +52 -0
  105. package/.llm/digest/documents.md +51 -0
  106. package/.llm/digest/downloadbanner.md +1 -1
  107. package/.llm/digest/featurecards.md +7 -0
  108. package/.llm/digest/featuretabs.md +50 -0
  109. package/.llm/digest/grid.md +1 -0
  110. package/.llm/digest/illustrationcard.md +6 -1
  111. package/.llm/digest/illustrationcheck.md +42 -0
  112. package/.llm/digest/illustrationchoice.md +43 -0
  113. package/.llm/digest/illustrationcode.md +41 -0
  114. package/.llm/digest/illustrationlist.md +38 -0
  115. package/.llm/digest/illustrationscene.md +4 -2
  116. package/.llm/digest/imagebanner.md +9 -3
  117. package/.llm/digest/logocolumns.md +1 -1
  118. package/.llm/digest/logorows.md +8 -1
  119. package/.llm/digest/producthero.md +8 -2
  120. package/.llm/digest/progressbar.md +56 -0
  121. package/.llm/digest/scenescroll.md +6 -5
  122. package/.llm/digest/scenescrollword.md +56 -0
  123. package/.llm/digest/segmentedcontrol.md +3 -0
  124. package/.llm/digest/stats.md +8 -0
  125. package/.llm/digest/statscarousel.md +48 -0
  126. package/.llm/digest/statusdot.md +7 -0
  127. package/.llm/digest/testimonialrow.md +8 -1
  128. package/.llm/digest/testimonialslider.md +1 -1
  129. package/.llm/digest/typography.md +18 -0
  130. package/.llm/index.md +14 -4
  131. package/.llm/rules.md +10 -0
  132. package/.llm/tokens.md +12 -3
  133. package/AGENTS.md +13 -2
  134. package/dist/components/arrival.d.ts +32 -0
  135. package/dist/components/arrival.js +140 -0
  136. package/dist/components/arrives.d.ts +17 -0
  137. package/dist/components/arrives.js +14 -0
  138. package/dist/components/blocks/awards/Awards.js +2 -27
  139. package/dist/components/blocks/block-pattern.css +23 -0
  140. package/dist/components/blocks/comparison-cards/comparison-cards-impl.css +29 -0
  141. package/dist/components/blocks/documents/Documents.css +90 -0
  142. package/dist/components/blocks/documents/Documents.d.ts +22 -0
  143. package/dist/components/blocks/documents/Documents.js +30 -0
  144. package/dist/components/blocks/documents/Documents.types.d.ts +37 -0
  145. package/dist/components/blocks/documents/Documents.types.js +14 -0
  146. package/dist/components/blocks/documents/documents-impl.css +103 -0
  147. package/dist/components/blocks/download-banner/DownloadBanner.css +1 -1
  148. package/dist/components/blocks/download-banner/DownloadBanner.types.d.ts +1 -1
  149. package/dist/components/blocks/feature-cards/FeatureCards.d.ts +2 -1
  150. package/dist/components/blocks/feature-cards/FeatureCards.js +10 -7
  151. package/dist/components/blocks/feature-cards/FeatureCards.types.d.ts +9 -1
  152. package/dist/components/blocks/feature-cards/feature-cards-impl.css +15 -3
  153. package/dist/components/blocks/feature-cards-carousel/FeatureCardsCarousel.types.d.ts +1 -1
  154. package/dist/components/blocks/feature-cards-carousel/feature-cards-carousel-impl.css +12 -0
  155. package/dist/components/blocks/feature-tabs/FeatureTabs.css +100 -0
  156. package/dist/components/blocks/feature-tabs/FeatureTabs.d.ts +23 -0
  157. package/dist/components/blocks/feature-tabs/FeatureTabs.js +38 -0
  158. package/dist/components/blocks/feature-tabs/FeatureTabs.types.d.ts +35 -0
  159. package/dist/components/blocks/feature-tabs/FeatureTabs.types.js +14 -0
  160. package/dist/components/blocks/feature-tabs/feature-tabs-impl.css +53 -0
  161. package/dist/components/blocks/image-banner/ImageBanner.css +1 -1
  162. package/dist/components/blocks/image-banner/ImageBanner.d.ts +1 -1
  163. package/dist/components/blocks/image-banner/ImageBanner.js +2 -2
  164. package/dist/components/blocks/image-banner/ImageBanner.types.d.ts +9 -7
  165. package/dist/components/blocks/image-banner/ImageBanner.types.js +1 -1
  166. package/dist/components/blocks/image-banner/image-banner-impl.css +77 -26
  167. package/dist/components/blocks/laurel.d.ts +16 -0
  168. package/dist/components/blocks/laurel.js +28 -0
  169. package/dist/components/blocks/logo-columns/LogoColumns.css +1 -1
  170. package/dist/components/blocks/logo-columns/LogoColumns.types.d.ts +1 -1
  171. package/dist/components/blocks/logo-rows/LogoRows.css +1 -1
  172. package/dist/components/blocks/logo-rows/LogoRows.d.ts +2 -1
  173. package/dist/components/blocks/logo-rows/LogoRows.js +7 -4
  174. package/dist/components/blocks/logo-rows/LogoRows.types.d.ts +9 -1
  175. package/dist/components/blocks/pattern-tone.d.ts +11 -0
  176. package/dist/components/blocks/pattern-tone.js +7 -0
  177. package/dist/components/blocks/product-hero/ProductHero.d.ts +1 -1
  178. package/dist/components/blocks/product-hero/ProductHero.js +2 -2
  179. package/dist/components/blocks/product-hero/ProductHero.types.d.ts +8 -3
  180. package/dist/components/blocks/product-hero/ProductHero.types.js +1 -1
  181. package/dist/components/blocks/product-hero/product-hero-impl.css +54 -0
  182. package/dist/components/blocks/resource-banner/ResourceBanner.css +1 -1
  183. package/dist/components/blocks/scene-scroll/SceneScroll.css +1 -1
  184. package/dist/components/blocks/scene-scroll/SceneScroll.d.ts +6 -5
  185. package/dist/components/blocks/scene-scroll/SceneScroll.js +8 -7
  186. package/dist/components/blocks/scene-scroll/SceneScroll.types.d.ts +5 -5
  187. package/dist/components/blocks/scene-scroll/SceneScroll.types.js +1 -1
  188. package/dist/components/blocks/scene-scroll/scene-scroll-impl.css +61 -44
  189. package/dist/components/blocks/scene-scroll-word/SceneScrollWord.css +105 -0
  190. package/dist/components/blocks/scene-scroll-word/SceneScrollWord.d.ts +31 -0
  191. package/dist/components/blocks/scene-scroll-word/SceneScrollWord.js +67 -0
  192. package/dist/components/blocks/scene-scroll-word/SceneScrollWord.types.d.ts +39 -0
  193. package/dist/components/blocks/scene-scroll-word/SceneScrollWord.types.js +18 -0
  194. package/dist/components/blocks/scene-scroll-word/scene-scroll-word-impl.css +370 -0
  195. package/dist/components/blocks/stats/Stats.d.ts +2 -1
  196. package/dist/components/blocks/stats/Stats.js +17 -14
  197. package/dist/components/blocks/stats/Stats.types.d.ts +8 -0
  198. package/dist/components/blocks/stats/stats-impl.css +4 -1
  199. package/dist/components/blocks/stats/use-wheel.d.ts +1 -1
  200. package/dist/components/blocks/stats/use-wheel.js +8 -4
  201. package/dist/components/blocks/stats-carousel/StatsCarousel.css +209 -0
  202. package/dist/components/blocks/stats-carousel/StatsCarousel.d.ts +20 -0
  203. package/dist/components/blocks/stats-carousel/StatsCarousel.js +48 -0
  204. package/dist/components/blocks/stats-carousel/StatsCarousel.types.d.ts +43 -0
  205. package/dist/components/blocks/stats-carousel/StatsCarousel.types.js +23 -0
  206. package/dist/components/blocks/stats-carousel/stats-carousel-impl.css +233 -0
  207. package/dist/components/blocks/sticky-cards/sticky-cards-impl.css +8 -0
  208. package/dist/components/blocks/testimonial-row/TestimonialRow.css +1 -1
  209. package/dist/components/blocks/testimonial-row/TestimonialRow.d.ts +2 -1
  210. package/dist/components/blocks/testimonial-row/TestimonialRow.js +16 -13
  211. package/dist/components/blocks/testimonial-row/TestimonialRow.types.d.ts +9 -1
  212. package/dist/components/blocks/testimonial-slider/TestimonialSlider.css +1 -1
  213. package/dist/components/blocks/testimonial-slider/TestimonialSlider.types.d.ts +1 -1
  214. package/dist/components/blocks/tiers/Tiers.types.d.ts +1 -1
  215. package/dist/components/core/background/Background.css +19 -0
  216. package/dist/components/core/background/Background.types.d.ts +2 -1
  217. package/dist/components/core/background/background-impl.css +47 -15
  218. package/dist/components/core/background/halftone.js +1 -1
  219. package/dist/components/core/button/Button.css +5 -5
  220. package/dist/components/core/button-icon/ButtonIcon.types.d.ts +1 -1
  221. package/dist/components/core/card-body/CardBody.css +5 -0
  222. package/dist/components/core/card-body/CardBody.types.d.ts +1 -1
  223. package/dist/components/core/document-link/DocumentLink.css +59 -0
  224. package/dist/components/core/document-link/DocumentLink.d.ts +19 -0
  225. package/dist/components/core/document-link/DocumentLink.js +21 -0
  226. package/dist/components/core/document-link/DocumentLink.types.d.ts +41 -0
  227. package/dist/components/core/document-link/DocumentLink.types.js +11 -0
  228. package/dist/components/core/document-link/document-link-impl.css +23 -0
  229. package/dist/components/core/illustration-card/IllustrationCard.css +7 -0
  230. package/dist/components/core/illustration-card/IllustrationCard.d.ts +5 -1
  231. package/dist/components/core/illustration-card/IllustrationCard.js +34 -8
  232. package/dist/components/core/illustration-card/IllustrationCard.types.d.ts +8 -1
  233. package/dist/components/core/illustration-card/IllustrationCard.types.js +1 -0
  234. package/dist/components/core/illustration-card/illustration-card-impl.css +113 -0
  235. package/dist/components/core/illustration-check/IllustrationCheck.css +25 -0
  236. package/dist/components/core/illustration-check/IllustrationCheck.d.ts +16 -0
  237. package/dist/components/core/illustration-check/IllustrationCheck.js +22 -0
  238. package/dist/components/core/illustration-check/IllustrationCheck.types.d.ts +25 -0
  239. package/dist/components/core/illustration-check/IllustrationCheck.types.js +9 -0
  240. package/dist/components/core/illustration-check/illustration-check-impl.css +76 -0
  241. package/dist/components/core/illustration-choice/IllustrationChoice.css +62 -0
  242. package/dist/components/core/illustration-choice/IllustrationChoice.d.ts +16 -0
  243. package/dist/components/core/illustration-choice/IllustrationChoice.js +31 -0
  244. package/dist/components/core/illustration-choice/IllustrationChoice.types.d.ts +25 -0
  245. package/dist/components/core/illustration-choice/IllustrationChoice.types.js +11 -0
  246. package/dist/components/core/illustration-choice/illustration-choice-impl.css +103 -0
  247. package/dist/components/core/illustration-code/IllustrationCode.css +25 -0
  248. package/dist/components/core/illustration-code/IllustrationCode.d.ts +12 -0
  249. package/dist/components/core/illustration-code/IllustrationCode.js +20 -0
  250. package/dist/components/core/illustration-code/IllustrationCode.types.d.ts +23 -0
  251. package/dist/components/core/illustration-code/IllustrationCode.types.js +8 -0
  252. package/dist/components/core/illustration-code/illustration-code-impl.css +42 -0
  253. package/dist/components/core/illustration-list/IllustrationList.css +19 -0
  254. package/dist/components/core/illustration-list/IllustrationList.d.ts +16 -0
  255. package/dist/components/core/illustration-list/IllustrationList.js +18 -0
  256. package/dist/components/core/illustration-list/IllustrationList.types.d.ts +15 -0
  257. package/dist/components/core/illustration-list/IllustrationList.types.js +6 -0
  258. package/dist/components/core/illustration-list/illustration-list-impl.css +52 -0
  259. package/dist/components/core/illustration-scene/IllustrationScene.css +6 -0
  260. package/dist/components/core/illustration-scene/IllustrationScene.d.ts +3 -2
  261. package/dist/components/core/illustration-scene/IllustrationScene.js +4 -3
  262. package/dist/components/core/illustration-scene/IllustrationScene.types.d.ts +5 -1
  263. package/dist/components/core/illustration-scene/IllustrationScene.types.js +2 -1
  264. package/dist/components/core/illustration-scene/illustration-scene-impl.css +65 -0
  265. package/dist/components/core/link/link-impl.css +5 -19
  266. package/dist/components/core/progress-bar/ProgressBar.css +101 -0
  267. package/dist/components/core/progress-bar/ProgressBar.d.ts +5 -0
  268. package/dist/components/core/progress-bar/ProgressBar.js +34 -0
  269. package/dist/components/core/progress-bar/ProgressBar.types.d.ts +52 -0
  270. package/dist/components/core/progress-bar/ProgressBar.types.js +12 -0
  271. package/dist/components/core/progress-bar/progress-bar-impl.css +45 -0
  272. package/dist/components/core/segmented-control/SegmentedControl.d.ts +1 -1
  273. package/dist/components/core/segmented-control/SegmentedControl.js +13 -5
  274. package/dist/components/core/segmented-control/SegmentedControl.types.d.ts +5 -1
  275. package/dist/components/core/segmented-control/segmented-control-impl.css +35 -0
  276. package/dist/components/core/status-dot/StatusDot.d.ts +1 -1
  277. package/dist/components/core/status-dot/StatusDot.js +7 -4
  278. package/dist/components/core/status-dot/StatusDot.types.d.ts +9 -1
  279. package/dist/components/core/status-dot/status-dot-impl.css +101 -0
  280. package/dist/components/core/typography/Typography.d.ts +3 -283
  281. package/dist/components/core/typography/Typography.js +9 -1
  282. package/dist/components/core/typography/Typography.types.d.ts +9 -15
  283. package/dist/components/core/typography/TypographyMotion.d.ts +28 -0
  284. package/dist/components/core/typography/TypographyMotion.js +43 -0
  285. package/dist/components/core/typography/typography-impl.css +106 -0
  286. package/dist/components/illustration-data.d.ts +15 -0
  287. package/dist/components/illustration-data.js +7 -0
  288. package/dist/components/index.d.ts +22 -1
  289. package/dist/components/index.js +20 -0
  290. package/dist/components/layout/grid/Grid.css +5 -0
  291. package/dist/components/layout/grid/Grid.types.d.ts +2 -1
  292. package/dist/components/scene-scroll-data.d.ts +35 -0
  293. package/dist/components/tiers-data.d.ts +3 -2
  294. package/dist/marketing.css +24 -6
  295. package/package.json +1 -1
@@ -15,18 +15,22 @@ export interface IllustrationSceneOwnProps {
15
15
  src: string;
16
16
  /** Empty by default, because the card's `label` describes the whole picture and the photograph is decoration. Write one only where the photograph says something the label does not */
17
17
  alt?: string;
18
+ /** The photograph is bright where the card sits — a sunny sky, a white wall — so the glass would come out mid-grey and the card's small lines would fall below AA. A shade under the card only, following the card's placement, so the rest of the photograph keeps its light. */
19
+ shade?: boolean;
18
20
  /** Allowed: IllustrationCard */
19
21
  children: ReactNode;
20
22
  }
21
- export type IllustrationSceneProps = IllustrationSceneOwnProps & Omit<HTMLAttributes<HTMLDivElement>, 'className' | 'ratio' | 'placement' | 'src' | 'alt'>;
23
+ export type IllustrationSceneProps = IllustrationSceneOwnProps & Omit<HTMLAttributes<HTMLDivElement>, 'className' | 'ratio' | 'placement' | 'src' | 'alt' | 'shade'>;
22
24
  /** The class each part carries. Apply these — do not retype them. */
23
25
  export declare const illustrationSceneParts: {
24
26
  readonly root: "dds-illustrationscene";
25
27
  readonly image: "dds-illustrationscene__image";
28
+ readonly shade: "dds-illustrationscene__shade";
26
29
  };
27
30
  /** Generated so defaults cannot drift from the contract. */
28
31
  export declare const illustrationSceneDefaults: {
29
32
  readonly ratio: "square";
30
33
  readonly placement: "center";
31
34
  readonly alt: "";
35
+ readonly shade: false;
32
36
  };
@@ -3,6 +3,7 @@
3
3
  export const illustrationSceneParts = {
4
4
  root: 'dds-illustrationscene',
5
5
  image: 'dds-illustrationscene__image',
6
+ shade: 'dds-illustrationscene__shade',
6
7
  };
7
8
  /** Generated so defaults cannot drift from the contract. */
8
- export const illustrationSceneDefaults = { ratio: 'square', placement: 'center', alt: '' };
9
+ export const illustrationSceneDefaults = { ratio: 'square', placement: 'center', alt: '', shade: false };
@@ -59,3 +59,68 @@
59
59
  justify-self: stretch;
60
60
  margin-block-end: var(--space-inset-card);
61
61
  }
62
+
63
+ /*
64
+ * At the foot, the strip is held to two fifths of the frame and its UI scaled into it.
65
+ *
66
+ * A strip is as tall as what it holds, and what it holds keeps its full type sizes however small the
67
+ * scene is drawn — so on a narrow column the strip outgrew its share and, at a tablet's width, its
68
+ * photograph. Capped, the pane has a height smaller than its UI, and IllustrationCard's fit scales
69
+ * the UI down into it as it does for a centred card. Two fifths is about the share the strip takes
70
+ * on a desktop, where nothing needs scaling, so the composition holds at every width rather than
71
+ * changing with it. A proportion of the frame, like every share here.
72
+ */
73
+ :where([data-dds-context="marketing"]) .dds-illustrationscene[data-placement='bottom'] > .dds-illustrationcard {
74
+ max-block-size: 40%;
75
+ }
76
+
77
+ /*
78
+ * The shade, between the photograph and the card.
79
+ *
80
+ * It fills the frame's one cell like the photograph and draws only where the card is: up from the
81
+ * foot at full strength to just above a strip at the foot, then clear by two thirds of the way up,
82
+ * so the subject above keeps its light; or an oval behind a centred card, full strength under the
83
+ * card's words and fading from there, so it never stands round the card as a dark ring, and clear at
84
+ * the frame's edges. color.bg.overlay, which takes a white photograph to a grey that the card's glass and its
85
+ * small type clear at AA.
86
+ */
87
+ :where([data-dds-context="marketing"]) .dds-illustrationscene[data-placement='bottom'] .dds-illustrationscene__shade {
88
+ background-image: linear-gradient(to top, var(--color-bg-overlay), var(--color-bg-overlay) 45%, transparent 70%);
89
+ }
90
+
91
+ :where([data-dds-context="marketing"]) .dds-illustrationscene[data-placement='center'] .dds-illustrationscene__shade {
92
+ background-image: radial-gradient(closest-side, var(--color-bg-overlay), var(--color-bg-overlay) 45%, transparent);
93
+ }
94
+
95
+ /*
96
+ * The card arrives after its photograph.
97
+ *
98
+ * Inside a block's arrival — block-reveal.css — whatever holds the scene comes up at its step, and
99
+ * the scene with it. The card then waits three steps of motion.duration.stagger more and rises onto
100
+ * the photograph, so the place lands and then the product does. The holder's step is read from
101
+ * `--dds-reveal-at`, which the block sets on the part and which the card inherits, so this follows
102
+ * whatever number the block gives its media rather than guessing past it; with none it counts from
103
+ * the block's first step. The same distance, duration and curve as every other part's arrival.
104
+ *
105
+ * Only inside a reveal — a scene with no `data-revealed` above it is simply drawn — and never for a
106
+ * reader who asked for less movement, as every arrival. Written a class deeper than block-reveal's
107
+ * own rule, so a page that marked the card with a step of its own is overruled by this one.
108
+ */
109
+ :where([data-dds-context="marketing"]) [data-revealed='false'] .dds-illustrationscene > .dds-illustrationcard {
110
+ opacity: var(--opacity-hidden);
111
+ transition: none;
112
+ translate: var(--motion-translate-reveal);
113
+ }
114
+
115
+ :where([data-dds-context="marketing"]) [data-revealed='true'] .dds-illustrationscene > .dds-illustrationcard {
116
+ transition-delay: calc((var(--dds-reveal-at, 0) + 3) * var(--motion-duration-stagger));
117
+ transition-duration: var(--motion-duration-reveal);
118
+ transition-property: opacity, translate;
119
+ transition-timing-function: var(--motion-easing-reveal);
120
+ }
121
+
122
+ @media (prefers-reduced-motion: reduce) {
123
+ :where([data-dds-context="marketing"]) [data-revealed] .dds-illustrationscene > .dds-illustrationcard {
124
+ transition: none;
125
+ }
126
+ }
@@ -56,27 +56,13 @@
56
56
  }
57
57
 
58
58
  /*
59
- * A link whose ink belongs to the ground gets its underline back under the pointer.
59
+ * A link that inherits its ink, with no mark, gets an underline under the pointer.
60
60
  *
61
- * A standalone link at `tone: inherit` — one on a brand card, a dark band, a scrim. It takes
62
- * the colour around it, so the colour cannot change under the pointer, and
63
- * `text-decoration-thickness` thickens a line that is not there. Without this it had no hover
64
- * affordance at all.
65
- *
66
- * The list variant had the same hole and answers it differently, below: it has a mark to
67
- * bring in, and a column of rows that underline one at a time reads as a table of contents
68
- * being corrected.
69
- *
70
- * Product reaches the same conclusion from the other end: its standalone drops the underline
71
- * except at `tone: inherit`, "because the link is the same colour as the text around it and
72
- * the rule is the only thing left saying it is a link". It keeps the line at all times. These
73
- * designs have no line at rest — a footer of fifty underlined rows is a wall — so it arrives
74
- * with the pointer instead, which is the same argument applied to a denser page.
75
- *
76
- * Here rather than in the contract because `structure` carries no state: it says what a
77
- * variant looks like, not what it looks like while a pointer is over it.
61
+ * At `tone: inherit` the colour is the ground's and cannot change, so what answers the pointer is
62
+ * the mark moving, below — the brand link's behaviour, with no line. A link given `showIcon={false}`
63
+ * has no mark to move, and without this nothing about it would answer the pointer at all.
78
64
  */
79
- :where([data-dds-context="marketing"]) .dds-link[data-variant='standalone'][data-tone='inherit']:hover {
65
+ :where([data-dds-context="marketing"]) .dds-link[data-variant='standalone'][data-tone='inherit']:not(:has(.dds-link__icon-trailing)):hover {
80
66
  text-decoration-line: underline;
81
67
  }
82
68
 
@@ -0,0 +1,101 @@
1
+ /* GENERATED from progressbar.contract.json. Do not edit. */
2
+
3
+ :where([data-dds-context="marketing"]) .dds-progressbar {
4
+ display: flex;
5
+ flex-direction: column;
6
+ gap: var(--space-gap-xs);
7
+ }
8
+
9
+ :where([data-dds-context="marketing"]) .dds-progressbar .dds-progressbar__track {
10
+ overflow: hidden;
11
+ position: relative;
12
+ background-color: var(--color-bg-track);
13
+ border-radius: var(--radius-pill);
14
+ }
15
+
16
+ :where([data-dds-context="marketing"]) .dds-progressbar .dds-progressbar__value-label {
17
+ font-variant-numeric: tabular-nums;
18
+ color: var(--color-fg-muted);
19
+ }
20
+
21
+ :where([data-dds-context="marketing"]) .dds-progressbar .dds-progressbar__description-text {
22
+ color: var(--color-fg-muted);
23
+ font-family: var(--font-body-sm-family);
24
+ font-size: var(--font-body-sm-size);
25
+ font-weight: var(--font-body-sm-weight);
26
+ line-height: var(--font-body-sm-line-height);
27
+ }
28
+
29
+ :where([data-dds-context="marketing"]) .dds-progressbar .dds-progressbar__fill {
30
+ border-radius: var(--radius-pill);
31
+ transition-duration: var(--motion-duration-normal);
32
+ transition-timing-function: var(--motion-easing-standard);
33
+ }
34
+
35
+ :where([data-dds-context="marketing"]) .dds-progressbar .dds-progressbar__label {
36
+ color: var(--color-fg-default);
37
+ }
38
+
39
+ :where([data-dds-context="marketing"]) .dds-progressbar[data-size="md"] .dds-progressbar__label {
40
+ font-family: var(--font-label-md-family);
41
+ font-size: var(--font-label-md-size);
42
+ font-weight: var(--font-label-md-weight);
43
+ line-height: var(--font-label-md-line-height);
44
+ }
45
+
46
+ :where([data-dds-context="marketing"]) .dds-progressbar[data-size="md"] .dds-progressbar__track {
47
+ height: var(--size-progressbar-track-md);
48
+ }
49
+
50
+ :where([data-dds-context="marketing"]) .dds-progressbar[data-size="md"] .dds-progressbar__value-label {
51
+ font-family: var(--font-label-md-family);
52
+ font-size: var(--font-label-md-size);
53
+ line-height: var(--font-label-md-line-height);
54
+ }
55
+
56
+ :where([data-dds-context="marketing"]) .dds-progressbar[data-size="sm"] .dds-progressbar__label {
57
+ font-family: var(--font-label-sm-family);
58
+ font-size: var(--font-label-sm-size);
59
+ font-weight: var(--font-label-sm-weight);
60
+ line-height: var(--font-label-sm-line-height);
61
+ }
62
+
63
+ :where([data-dds-context="marketing"]) .dds-progressbar[data-size="sm"] .dds-progressbar__track {
64
+ height: var(--size-progressbar-track-sm);
65
+ }
66
+
67
+ :where([data-dds-context="marketing"]) .dds-progressbar[data-size="sm"] .dds-progressbar__value-label {
68
+ font-family: var(--font-label-sm-family);
69
+ font-size: var(--font-label-sm-size);
70
+ line-height: var(--font-label-sm-line-height);
71
+ }
72
+
73
+ :where([data-dds-context="marketing"]) .dds-progressbar[data-variant="accent"] .dds-progressbar__fill {
74
+ background-color: var(--color-bg-brand);
75
+ }
76
+
77
+ :where([data-dds-context="marketing"]) .dds-progressbar[data-variant="default"] .dds-progressbar__fill {
78
+ background-color: var(--color-bg-strong);
79
+ }
80
+
81
+ :where([data-dds-context="marketing"]) .dds-progressbar[data-variant="error"] .dds-progressbar__fill {
82
+ background-color: var(--color-bg-danger);
83
+ }
84
+
85
+ :where([data-dds-context="marketing"]) .dds-progressbar[data-variant="info"] .dds-progressbar__fill {
86
+ background-color: var(--color-bg-info);
87
+ }
88
+
89
+ :where([data-dds-context="marketing"]) .dds-progressbar[data-variant="success"] .dds-progressbar__fill {
90
+ background-color: var(--color-bg-success);
91
+ }
92
+
93
+ :where([data-dds-context="marketing"]) .dds-progressbar[data-variant="warning"] .dds-progressbar__fill {
94
+ background-color: var(--color-bg-warning);
95
+ }
96
+
97
+ @media (prefers-reduced-motion: reduce) {
98
+ :where([data-dds-context="marketing"]) .dds-progressbar,
99
+ :where([data-dds-context="marketing"]) .dds-progressbar * { transition: none !important; }
100
+ }
101
+
@@ -0,0 +1,5 @@
1
+ import './ProgressBar.css';
2
+ import './progress-bar-impl.css';
3
+ import { type ProgressBarProps } from './ProgressBar.types.js';
4
+ export type { ProgressBarProps };
5
+ export declare function ProgressBar({ size, variant, value, max, label, showLabel, showValueLabel, description, motion, ...rest }: ProgressBarProps): import("react").JSX.Element;
@@ -0,0 +1,34 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import './ProgressBar.css';
3
+ import { visuallyHidden } from '../../visually-hidden.js';
4
+ import './progress-bar-impl.css';
5
+ import { given } from '../../given.js';
6
+ import { Arrives } from '../../arrives.js';
7
+ import { progressBarDefaults, progressBarParts } from './ProgressBar.types.js';
8
+ export function ProgressBar({ size = progressBarDefaults.size, variant = progressBarDefaults.variant, value = progressBarDefaults.value, max = progressBarDefaults.max, label, showLabel = progressBarDefaults.showLabel, showValueLabel = progressBarDefaults.showValueLabel, description, motion, ...rest }) {
9
+ /**
10
+ * How far along, as a percentage of max.
11
+ *
12
+ * Three lines shorter than it was, and none of what went was doing any work of its own.
13
+ * `value` and `max` were declared as strings because the contract had no number to
14
+ * declare, so this converted them, guarded the NaN a conversion can produce, and kept a
15
+ * second copy of max's default for when the conversion failed. All three existed to undo
16
+ * a declaration rather than to describe a progress bar.
17
+ *
18
+ * What stays is the one clamp that is a real decision: a value above max reads as full
19
+ * rather than overflowing its own track. It is applied to the number rather than to the
20
+ * percentage now, because it was only ever applied to the width — so a bar given 150 of 100
21
+ * was drawn full and announced as "150 of 100", the eye and the ear disagreeing about a
22
+ * control whose whole job is to report one number. A value below nought was worse: `width:
23
+ * -10%` is not a width, so the fill kept whatever the track gave it and the reading went out
24
+ * as -10.
25
+ *
26
+ * A max of nought or less has no percentage to state — nothing can be a fraction of nothing —
27
+ * and it read as complete, which is the one answer that is certainly wrong.
28
+ */
29
+ const bounded = Math.min(Math.max(value, 0), Math.max(max, 0));
30
+ const percent = max > 0 ? (bounded / max) * 100 : 0;
31
+ const bar = (_jsxs("div", { className: progressBarParts.root, role: "progressbar", "aria-label": given(label) ? label : undefined, "aria-valuenow": bounded, "aria-valuemin": 0, "aria-valuemax": max, "data-size": size, "data-variant": variant, "data-motion": motion, ...rest, children: [given(label) || showValueLabel ? (_jsxs("div", { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }, children: [given(label) ? (_jsx("span", { className: progressBarParts.label, style: showLabel ? undefined : visuallyHidden, children: label })) : null, showValueLabel ? (_jsx("span", { className: progressBarParts['value-label'], children: `${Math.round(percent)}%` })) : null] })) : null, _jsx("div", { className: progressBarParts.track, children: _jsx("div", { className: progressBarParts.fill, style: { height: '100%', width: `${percent}%` } }) }), given(description) ? (_jsx("p", { className: progressBarParts['description-text'], children: description })) : null] }));
32
+ // A bar that fills on arrival moves once, so only then does it take a script.
33
+ return motion === undefined ? bar : _jsx(Arrives, { children: bar });
34
+ }
@@ -0,0 +1,52 @@
1
+ import type { HTMLAttributes } from 'react';
2
+ export interface ProgressBarOwnProps {
3
+ /**
4
+ * `sm` — Dense layouts or inline indicators where vertical space is limited
5
+ * `md` — Default for standalone progress indicators in forms or dialogs
6
+ */
7
+ size?: 'sm' | 'md';
8
+ /**
9
+ * `default` — The default, and neutral: no status and no brand. Most progress is merely progress — a step count filling as a form is completed, a bar moving while a file uploads — and the fact that work is moving is all the colour has to say. StepperItem is named and defaults the same way, and the two draw the same neutral, so a stepper and a bar reporting one task agree.
10
+ * `accent` — Brand-coloured, and asked for rather than arrived at. Reach for it where the page is drawing attention to this progress — the one thing on screen a reader is waiting on. It carries no status: what it adds over the neutral is prominence, not meaning, so a page reaching for it everywhere has spent the emphasis it buys.
11
+ * `success` — Indicating completion or a successful process
12
+ * `warning` — Progress that needs attention, such as approaching a limit
13
+ * `error` — Progress of a process that has encountered a problem
14
+ * `info` — Informational progress such as downloads, syncing, or data loading
15
+ */
16
+ variant?: 'default' | 'accent' | 'success' | 'warning' | 'error' | 'info';
17
+ /** The amount of work completed — a number between 0 and max. Defaults to 0, which is the honest rendering of nothing started */
18
+ value?: number;
19
+ /** The total amount of work differs from the default of 100 */
20
+ max?: number;
21
+ /** Naming what is in progress, when the bar is not already named by what surrounds it. Omit it for a bar that is part of a labelled flow — an onboarding stepper under its own heading — and name the bar with aria-labelledby instead */
22
+ label?: string;
23
+ /** The label is visible. When false, the label is visually hidden but remains accessible to screen readers */
24
+ showLabel?: boolean;
25
+ /** The numeric progress value is visible alongside the bar */
26
+ showValueLabel?: boolean;
27
+ /** Freeform context below the bar, such as a step count, status message, or time remaining */
28
+ description?: string;
29
+ /**
30
+ * `fill` — The bar fills from empty to its value once, on arrival, over motion.duration.dramatic — an account set-up three steps in, shown in a pane
31
+ */
32
+ motion?: 'fill';
33
+ }
34
+ export type ProgressBarProps = ProgressBarOwnProps & Omit<HTMLAttributes<HTMLDivElement>, 'className' | 'size' | 'variant' | 'value' | 'max' | 'label' | 'showLabel' | 'showValueLabel' | 'description' | 'motion'>;
35
+ /** The class each part carries. Apply these — do not retype them. */
36
+ export declare const progressBarParts: {
37
+ readonly root: "dds-progressbar";
38
+ readonly track: "dds-progressbar__track";
39
+ readonly fill: "dds-progressbar__fill";
40
+ readonly label: "dds-progressbar__label";
41
+ readonly 'value-label': "dds-progressbar__value-label";
42
+ readonly 'description-text': "dds-progressbar__description-text";
43
+ };
44
+ /** Generated so defaults cannot drift from the contract. */
45
+ export declare const progressBarDefaults: {
46
+ readonly size: "md";
47
+ readonly variant: "default";
48
+ readonly value: 0;
49
+ readonly max: 100;
50
+ readonly showLabel: true;
51
+ readonly showValueLabel: true;
52
+ };
@@ -0,0 +1,12 @@
1
+ // GENERATED from progress-bar.contract.json. Do not edit.
2
+ /** The class each part carries. Apply these — do not retype them. */
3
+ export const progressBarParts = {
4
+ root: 'dds-progressbar',
5
+ track: 'dds-progressbar__track',
6
+ fill: 'dds-progressbar__fill',
7
+ label: 'dds-progressbar__label',
8
+ 'value-label': 'dds-progressbar__value-label',
9
+ 'description-text': 'dds-progressbar__description-text',
10
+ };
11
+ /** Generated so defaults cannot drift from the contract. */
12
+ export const progressBarDefaults = { size: 'md', variant: 'default', value: 0, max: 100, showLabel: true, showValueLabel: true };
@@ -0,0 +1,45 @@
1
+ /*
2
+ * Scoped to this package, like the generated sheet beside it.
3
+ *
4
+ * `:where([data-dds-context="marketing"])` confines these rules without contributing
5
+ * specificity, so every override below still ties or beats exactly what it did
6
+ * before — several here are written a class deeper than they look in order to
7
+ * match generated CSS, and a scope that carried weight would break all of them.
8
+ */
9
+
10
+ /* Implementation CSS that the contract's staticCss cannot express. */
11
+
12
+ :where([data-dds-context="marketing"]) .dds-progressbar {
13
+ width: 100%;
14
+ }
15
+
16
+ :where([data-dds-context="marketing"]) .dds-progressbar__description-text {
17
+ margin: 0;
18
+ }
19
+
20
+ /*
21
+ * `motion="fill"`: the bar fills from empty to where the task has got to, once, on arrival — over
22
+ * motion.duration.dramatic, a step of motion.duration.fast after the bar has landed. `data-arrival`
23
+ * is the bar's own answer from useArrival (arrival.ts): `waiting` holds it empty, `playing` fills
24
+ * it, and no attribute — a server, a reader who asked for less movement — is the bar at its value.
25
+ * The value itself, and what is read out, never moves.
26
+ */
27
+ @keyframes dds-progressbar-fill {
28
+ from {
29
+ width: 0;
30
+ }
31
+ }
32
+
33
+ :where([data-dds-context="marketing"]) .dds-progressbar[data-motion='fill'][data-arrival] .dds-progressbar__fill {
34
+ animation: dds-progressbar-fill var(--motion-duration-dramatic) var(--motion-easing-reveal) var(--motion-duration-fast) both;
35
+ }
36
+
37
+ :where([data-dds-context="marketing"]) .dds-progressbar[data-motion='fill'][data-arrival='waiting'] .dds-progressbar__fill {
38
+ animation-play-state: paused !important;
39
+ }
40
+
41
+ @media (prefers-reduced-motion: reduce) {
42
+ :where([data-dds-context="marketing"]) .dds-progressbar[data-motion='fill'][data-arrival] .dds-progressbar__fill {
43
+ animation: none;
44
+ }
45
+ }
@@ -34,4 +34,4 @@ export type { SegmentedControlProps };
34
34
  * the reader a value is in force that the page never set, and hide whatever caused the
35
35
  * mismatch — a stale piece of state, a segment that has not loaded yet.
36
36
  */
37
- export declare function SegmentedControl({ layout, size, disabled, label, value, onChange, children, ...rest }: SegmentedControlProps): import("react").JSX.Element;
37
+ export declare function SegmentedControl({ layout, size, disabled, label, value, onChange, motion, children, ...rest }: SegmentedControlProps): import("react").JSX.Element;
@@ -1,8 +1,9 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { Children, cloneElement, isValidElement, useCallback, useEffect, useLayoutEffect, useRef, useState, } from "react";
3
+ import { Children, cloneElement, isValidElement, useCallback, useEffect, useLayoutEffect, useState, } from "react";
4
4
  import "./SegmentedControl.css";
5
5
  import "./segmented-control-impl.css";
6
+ import { useArrival } from "../../arrival.js";
6
7
  import { segmentedControlItemParts } from "../segmented-control-item/SegmentedControlItem.types.js";
7
8
  import { segmentedControlDefaults, segmentedControlParts, } from "./SegmentedControl.types.js";
8
9
  /**
@@ -70,8 +71,9 @@ function chain(theirs, ours) {
70
71
  export function SegmentedControl({ layout = segmentedControlDefaults.layout, size = segmentedControlDefaults.size, disabled = segmentedControlDefaults.disabled,
71
72
  // No fallback, because there is no default to fall back to. The contract requires it:
72
73
  // the question the segments are answers to is the one thing nothing else can supply.
73
- label, value, onChange, children, ...rest }) {
74
- const rootRef = useRef(null);
74
+ label, value, onChange, motion, children, ...rest }) {
75
+ // The row's own element, and — under `motion="slide"` — where its arrival has got to.
76
+ const [rootRef, arrival] = useArrival(motion === "slide");
75
77
  const segments = Children.toArray(children).filter((isValidElement));
76
78
  /**
77
79
  * Whether the consumer owns which value is in force.
@@ -154,11 +156,15 @@ label, value, onChange, children, ...rest }) {
154
156
  on, and every segment's pill landed one row-width minus a segment to the right of it.
155
157
  */
156
158
  const rtl = getComputedStyle(root).direction === "rtl";
159
+ const at = (each) => rtl ? each.offsetLeft + each.offsetWidth - root.clientWidth : each.offsetLeft;
160
+ const first = root.querySelector(`:scope > .${segmentedControlItemParts.root}`) ?? box;
157
161
  setPill({
158
- x: rtl ? box.offsetLeft + box.offsetWidth - root.clientWidth : box.offsetLeft,
162
+ x: at(box),
159
163
  y: box.offsetTop,
160
164
  w: box.offsetWidth,
161
165
  h: box.offsetHeight,
166
+ fromX: at(first),
167
+ fromW: first.offsetWidth,
162
168
  });
163
169
  }, [active]);
164
170
  // Layout rather than a plain effect: between the two the pill would be painted at its
@@ -244,12 +250,14 @@ label, value, onChange, children, ...rest }) {
244
250
  target?.focus();
245
251
  target?.click();
246
252
  };
247
- return (_jsxs("div", { ...rest, ref: rootRef, className: segmentedControlParts.root, role: "radiogroup", "aria-label": label, "aria-disabled": disabled ? true : undefined, "data-layout": layout, "data-size": size, "data-disabled": String(disabled), onKeyDown: onKeyDown, children: [_jsx("span", { className: segmentedControlParts.indicator, hidden: pill === null, style: pill === null
253
+ return (_jsxs("div", { ...rest, ref: rootRef, className: segmentedControlParts.root, role: "radiogroup", "aria-label": label, "aria-disabled": disabled ? true : undefined, "data-layout": layout, "data-size": size, "data-disabled": String(disabled), "data-motion": motion, "data-arrival": arrival === "still" ? undefined : arrival, onKeyDown: onKeyDown, children: [_jsx("span", { className: segmentedControlParts.indicator, hidden: pill === null, style: pill === null
248
254
  ? undefined
249
255
  : {
250
256
  blockSize: `${pill.h}px`,
251
257
  inlineSize: `${pill.w}px`,
252
258
  translate: `${pill.x}px ${pill.y}px`,
259
+ ["--dds-segmentedcontrol-from"]: `${pill.fromX}px ${pill.y}px`,
260
+ ["--dds-segmentedcontrol-from-size"]: `${pill.fromW}px`,
253
261
  } }), segments.map((segment, index) => cloneElement(segment, {
254
262
  // Both are the row's to decide, and both overwrite whatever the segment was
255
263
  // given: one chosen value, one height. Availability is the segment's own — the
@@ -21,10 +21,14 @@ export interface SegmentedControlOwnProps {
21
21
  value?: string;
22
22
  /** Whenever value is — together they are how a page holds the choice. It is called with the chosen segment's value after that segment's own onSelect, so a segment that reports its own presses keeps doing so inside a row */
23
23
  onChange?: (value: string) => void;
24
+ /**
25
+ * `slide` — The pill starts on the first segment and slides to the chosen one once, on arrival — a trade ticket set to Sell showing it was Buy first. It holds for motion.duration.hold, then slides over motion.duration.shift
26
+ */
27
+ motion?: 'slide';
24
28
  /** Allowed: SegmentedControlItem */
25
29
  children: ReactNode;
26
30
  }
27
- export type SegmentedControlProps = SegmentedControlOwnProps & Omit<HTMLAttributes<HTMLDivElement>, 'className' | 'layout' | 'size' | 'disabled' | 'label' | 'value' | 'onChange'>;
31
+ export type SegmentedControlProps = SegmentedControlOwnProps & Omit<HTMLAttributes<HTMLDivElement>, 'className' | 'layout' | 'size' | 'disabled' | 'label' | 'value' | 'onChange' | 'motion'>;
28
32
  /** The class each part carries. Apply these — do not retype them. */
29
33
  export declare const segmentedControlParts: {
30
34
  readonly root: "dds-segmentedcontrol";
@@ -55,3 +55,38 @@
55
55
  .dds-segmentedcontrol__indicator {
56
56
  transition-property: translate, inline-size, block-size;
57
57
  }
58
+
59
+ /*
60
+ * `motion="slide"`: the pill starts on the first segment and slides to the chosen one once, on
61
+ * arrival — Buy to Sell — over motion.duration.shift on its easing, after holding where it started
62
+ * for motion.duration.hold. Where it starts is measured with where it lands (the first segment's
63
+ * place and width, set on the pill as custom properties), so the slide is the stylesheet's.
64
+ * `data-arrival` is the row's own answer from useArrival (arrival.ts): `waiting` holds the pill on
65
+ * the first segment, `playing` slides it, and no attribute is the pill where it belongs.
66
+ */
67
+ @keyframes dds-segmentedcontrol-slide {
68
+ from {
69
+ inline-size: var(--dds-segmentedcontrol-from-size);
70
+ translate: var(--dds-segmentedcontrol-from);
71
+ }
72
+ }
73
+
74
+ :where([data-dds-context="marketing"])
75
+ .dds-segmentedcontrol[data-motion='slide'][data-arrival]
76
+ .dds-segmentedcontrol__indicator {
77
+ animation: dds-segmentedcontrol-slide var(--motion-duration-shift) var(--motion-easing-shift) var(--motion-duration-hold) both;
78
+ }
79
+
80
+ :where([data-dds-context="marketing"])
81
+ .dds-segmentedcontrol[data-motion='slide'][data-arrival='waiting']
82
+ .dds-segmentedcontrol__indicator {
83
+ animation-play-state: paused !important;
84
+ }
85
+
86
+ @media (prefers-reduced-motion: reduce) {
87
+ :where([data-dds-context="marketing"])
88
+ .dds-segmentedcontrol[data-motion='slide'][data-arrival]
89
+ .dds-segmentedcontrol__indicator {
90
+ animation: none;
91
+ }
92
+ }
@@ -32,4 +32,4 @@ export type { StatusDotProps };
32
32
  * carrying a tooltip must have — a tooltip makes it a tab stop, and a focusable thing
33
33
  * with no name is announced as nothing at all.
34
34
  */
35
- export declare function StatusDot({ variant, pulse, label, tooltip, ...rest }: StatusDotProps): import("react").JSX.Element;
35
+ export declare function StatusDot({ variant, pulse, from, label, tooltip, ...rest }: StatusDotProps): import("react").JSX.Element;
@@ -2,6 +2,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import './StatusDot.css';
3
3
  import './status-dot-impl.css';
4
4
  import { TooltipAnchor } from '../tooltip/TooltipAnchor.js';
5
+ import { Arrives } from '../../arrives.js';
5
6
  import { given } from '../../given.js';
6
7
  import { statusDotDefaults, statusDotParts } from './StatusDot.types.js';
7
8
  /**
@@ -34,13 +35,15 @@ import { statusDotDefaults, statusDotParts } from './StatusDot.types.js';
34
35
  * carrying a tooltip must have — a tooltip makes it a tab stop, and a focusable thing
35
36
  * with no name is announced as nothing at all.
36
37
  */
37
- export function StatusDot({ variant = statusDotDefaults.variant, pulse = statusDotDefaults.pulse, label, tooltip, ...rest }) {
38
+ export function StatusDot({ variant = statusDotDefaults.variant, pulse = statusDotDefaults.pulse, from, label, tooltip, ...rest }) {
38
39
  const described = given(tooltip);
39
- const dot = (_jsx("span", { className: statusDotParts.root, "aria-label": label, "aria-hidden": label === undefined || undefined, "data-variant": variant, "data-pulse": pulse || undefined, tabIndex: described ? 0 : undefined, ...rest }));
40
+ const dot = (_jsx("span", { className: statusDotParts.root, "aria-label": label, "aria-hidden": label === undefined || undefined, "data-variant": variant, "data-pulse": pulse || undefined, "data-from": from, tabIndex: described ? 0 : undefined, ...rest }));
41
+ // A dot that starts as another state moves once on arrival, so only then does it take a script.
42
+ const drawn = from === undefined ? dot : _jsx(Arrives, { children: dot });
40
43
  if (!described)
41
- return dot;
44
+ return drawn;
42
45
  // The anchor clones the dot to attach its handlers and the aria-describedby, so the
43
46
  // description belongs to the element carrying the role — not to the wrapper, which
44
47
  // no assistive technology has any reason to visit.
45
- return _jsx(TooltipAnchor, { content: tooltip, children: dot });
48
+ return _jsx(TooltipAnchor, { content: tooltip, children: drawn });
46
49
  }
@@ -10,8 +10,16 @@ export interface StatusDotOwnProps {
10
10
  variant?: 'accent' | 'success' | 'warning' | 'error' | 'info';
11
11
  /** The status is live or actively changing — draws attention to an ongoing state */
12
12
  pulse?: boolean;
13
+ /**
14
+ * `accent` — Starts as accent before becoming its own state.
15
+ * `success` — Starts as success before becoming its own state.
16
+ * `warning` — Starts as warning before becoming its own state.
17
+ * `error` — Starts as error before becoming its own state.
18
+ * `info` — Starts as info before becoming its own state.
19
+ */
20
+ from?: 'accent' | 'success' | 'warning' | 'error' | 'info';
13
21
  }
14
- export type StatusDotProps = StatusDotOwnProps & Omit<HTMLAttributes<HTMLSpanElement>, 'className' | 'variant' | 'pulse' | 'label' | 'tooltip'> & ({
22
+ export type StatusDotProps = StatusDotOwnProps & Omit<HTMLAttributes<HTMLSpanElement>, 'className' | 'variant' | 'pulse' | 'label' | 'tooltip' | 'from'> & ({
15
23
  tooltip?: string;
16
24
  label: string;
17
25
  } | {