@deriv-com/dds-marketing 0.2.0 → 1.0.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.
Files changed (281) hide show
  1. package/.llm/components/accordion.md +9 -1
  2. package/.llm/components/accordionitem.md +9 -1
  3. package/.llm/components/aspectratio.md +9 -1
  4. package/.llm/components/badge.md +9 -1
  5. package/.llm/components/bottomsheet.md +9 -1
  6. package/.llm/components/breadcrumb.md +9 -1
  7. package/.llm/components/breadcrumbitem.md +9 -1
  8. package/.llm/components/button.md +55 -27
  9. package/.llm/components/buttonicon.md +16 -8
  10. package/.llm/components/card.md +16 -2
  11. package/.llm/components/cardbody.md +29 -3
  12. package/.llm/components/cardbutton.md +16 -2
  13. package/.llm/components/checkbox.md +9 -1
  14. package/.llm/components/ctabanner.md +186 -0
  15. package/.llm/components/ctabannerslider.md +204 -0
  16. package/.llm/components/divider.md +9 -1
  17. package/.llm/components/dropdownmenu.md +15 -7
  18. package/.llm/components/faqaccordion.md +217 -0
  19. package/.llm/components/featurebullets.md +254 -0
  20. package/.llm/components/featurecards.md +313 -0
  21. package/.llm/components/featurescroll.md +284 -0
  22. package/.llm/components/featuresplit.md +249 -0
  23. package/.llm/components/filterchip.md +9 -1
  24. package/.llm/components/footer.md +9 -1
  25. package/.llm/components/footergroup.md +9 -1
  26. package/.llm/components/grid.md +9 -1
  27. package/.llm/components/icon.md +21 -3
  28. package/.llm/components/landinghero.md +254 -0
  29. package/.llm/components/link.md +13 -5
  30. package/.llm/components/logocolumns.md +235 -0
  31. package/.llm/components/logorows.md +212 -0
  32. package/.llm/components/menuitem.md +9 -1
  33. package/.llm/components/navbar.md +80 -16
  34. package/.llm/components/navbaritem.md +10 -2
  35. package/.llm/components/navbarmenu.md +9 -1
  36. package/.llm/components/navbarmenugroup.md +9 -1
  37. package/.llm/components/navbarpanel.md +10 -2
  38. package/.llm/components/navbarswitcher.md +10 -2
  39. package/.llm/components/navbarswitcheroption.md +9 -1
  40. package/.llm/components/option.md +9 -1
  41. package/.llm/components/pageheader.md +231 -0
  42. package/.llm/components/pagination.md +27 -90
  43. package/.llm/components/paginationdots.md +215 -0
  44. package/.llm/components/producthero.md +248 -0
  45. package/.llm/components/removablechip.md +9 -1
  46. package/.llm/components/row.md +9 -1
  47. package/.llm/components/scroller.md +9 -1
  48. package/.llm/components/searchinput.md +9 -1
  49. package/.llm/components/segmentedcontrol.md +9 -1
  50. package/.llm/components/segmentedcontrolitem.md +9 -1
  51. package/.llm/components/select.md +9 -1
  52. package/.llm/components/selectchip.md +57 -16
  53. package/.llm/components/spinner.md +9 -1
  54. package/.llm/components/stack.md +9 -1
  55. package/.llm/components/statusdot.md +9 -1
  56. package/.llm/components/subdomainnavbar.md +9 -1
  57. package/.llm/components/tab.md +11 -3
  58. package/.llm/components/table.md +9 -1
  59. package/.llm/components/tablebody.md +9 -1
  60. package/.llm/components/tablecell.md +9 -1
  61. package/.llm/components/tablehead.md +9 -1
  62. package/.llm/components/tableheadercell.md +9 -1
  63. package/.llm/components/tablerow.md +9 -1
  64. package/.llm/components/tablist.md +9 -1
  65. package/.llm/components/testimonialrow.md +235 -0
  66. package/.llm/components/testimonialslider.md +254 -0
  67. package/.llm/components/textarea.md +9 -1
  68. package/.llm/components/textinput.md +9 -1
  69. package/.llm/components/tooltip.md +9 -1
  70. package/.llm/components/typography.md +9 -1
  71. package/.llm/digest/button.md +11 -6
  72. package/.llm/digest/buttonicon.md +2 -2
  73. package/.llm/digest/card.md +1 -0
  74. package/.llm/digest/cardbody.md +3 -1
  75. package/.llm/digest/cardbutton.md +1 -0
  76. package/.llm/digest/ctabanner.md +44 -0
  77. package/.llm/digest/ctabannerslider.md +45 -0
  78. package/.llm/digest/dropdownmenu.md +1 -1
  79. package/.llm/digest/faqaccordion.md +43 -0
  80. package/.llm/digest/featurebullets.md +52 -0
  81. package/.llm/digest/featurecards.md +49 -0
  82. package/.llm/digest/featurescroll.md +52 -0
  83. package/.llm/digest/featuresplit.md +54 -0
  84. package/.llm/digest/landinghero.md +53 -0
  85. package/.llm/digest/logocolumns.md +55 -0
  86. package/.llm/digest/logorows.md +48 -0
  87. package/.llm/digest/navbar.md +18 -3
  88. package/.llm/digest/pageheader.md +49 -0
  89. package/.llm/digest/pagination.md +6 -17
  90. package/.llm/digest/paginationdots.md +43 -0
  91. package/.llm/digest/producthero.md +53 -0
  92. package/.llm/digest/selectchip.md +6 -1
  93. package/.llm/digest/testimonialrow.md +51 -0
  94. package/.llm/digest/testimonialslider.md +51 -0
  95. package/.llm/index.md +24 -3
  96. package/.llm/rules.md +43 -9
  97. package/.llm/tokens.md +56 -12
  98. package/AGENTS.md +32 -8
  99. package/README.md +41 -21
  100. package/dist/components/banner-data.d.ts +38 -0
  101. package/dist/components/banner-data.js +15 -0
  102. package/dist/components/blocks/block-reveal.css +90 -0
  103. package/dist/components/blocks/cta-banner/CtaBanner.css +66 -0
  104. package/dist/components/blocks/cta-banner/CtaBanner.d.ts +22 -0
  105. package/dist/components/blocks/cta-banner/CtaBanner.js +31 -0
  106. package/dist/components/blocks/cta-banner/CtaBanner.types.d.ts +29 -0
  107. package/dist/components/blocks/cta-banner/CtaBanner.types.js +13 -0
  108. package/dist/components/blocks/cta-banner/cta-banner-impl.css +29 -0
  109. package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.css +90 -0
  110. package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.d.ts +39 -0
  111. package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.js +60 -0
  112. package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.types.d.ts +41 -0
  113. package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.types.js +15 -0
  114. package/dist/components/blocks/cta-banner-slider/cta-banner-slider-impl.css +73 -0
  115. package/dist/components/blocks/faq-accordion/FaqAccordion.css +54 -0
  116. package/dist/components/blocks/faq-accordion/FaqAccordion.d.ts +20 -0
  117. package/dist/components/blocks/faq-accordion/FaqAccordion.js +28 -0
  118. package/dist/components/blocks/faq-accordion/FaqAccordion.types.d.ts +25 -0
  119. package/dist/components/blocks/faq-accordion/FaqAccordion.types.js +10 -0
  120. package/dist/components/blocks/faq-accordion/faq-accordion-impl.css +54 -0
  121. package/dist/components/blocks/feature-bullets/FeatureBullets.css +139 -0
  122. package/dist/components/blocks/feature-bullets/FeatureBullets.d.ts +31 -0
  123. package/dist/components/blocks/feature-bullets/FeatureBullets.js +55 -0
  124. package/dist/components/blocks/feature-bullets/FeatureBullets.types.d.ts +39 -0
  125. package/dist/components/blocks/feature-bullets/FeatureBullets.types.js +16 -0
  126. package/dist/components/blocks/feature-bullets/feature-bullets-impl.css +104 -0
  127. package/dist/components/blocks/feature-cards/FeatureCards.css +84 -0
  128. package/dist/components/blocks/feature-cards/FeatureCards.d.ts +24 -0
  129. package/dist/components/blocks/feature-cards/FeatureCards.js +66 -0
  130. package/dist/components/blocks/feature-cards/FeatureCards.types.d.ts +33 -0
  131. package/dist/components/blocks/feature-cards/FeatureCards.types.js +14 -0
  132. package/dist/components/blocks/feature-cards/feature-cards-impl.css +245 -0
  133. package/dist/components/blocks/feature-scroll/FeatureScroll.css +137 -0
  134. package/dist/components/blocks/feature-scroll/FeatureScroll.d.ts +39 -0
  135. package/dist/components/blocks/feature-scroll/FeatureScroll.js +167 -0
  136. package/dist/components/blocks/feature-scroll/FeatureScroll.types.d.ts +40 -0
  137. package/dist/components/blocks/feature-scroll/FeatureScroll.types.js +17 -0
  138. package/dist/components/blocks/feature-scroll/feature-scroll-impl.css +292 -0
  139. package/dist/components/blocks/feature-split/FeatureSplit.css +95 -0
  140. package/dist/components/blocks/feature-split/FeatureSplit.d.ts +30 -0
  141. package/dist/components/blocks/feature-split/FeatureSplit.js +38 -0
  142. package/dist/components/blocks/feature-split/FeatureSplit.types.d.ts +39 -0
  143. package/dist/components/blocks/feature-split/FeatureSplit.types.js +14 -0
  144. package/dist/components/blocks/feature-split/feature-split-impl.css +83 -0
  145. package/dist/components/blocks/landing-hero/LandingHero.css +85 -0
  146. package/dist/components/blocks/landing-hero/LandingHero.d.ts +41 -0
  147. package/dist/components/blocks/landing-hero/LandingHero.js +54 -0
  148. package/dist/components/blocks/landing-hero/LandingHero.types.d.ts +37 -0
  149. package/dist/components/blocks/landing-hero/LandingHero.types.js +15 -0
  150. package/dist/components/blocks/landing-hero/landing-hero-impl.css +355 -0
  151. package/dist/components/blocks/logo-columns/LogoColumns.css +161 -0
  152. package/dist/components/blocks/logo-columns/LogoColumns.d.ts +23 -0
  153. package/dist/components/blocks/logo-columns/LogoColumns.js +46 -0
  154. package/dist/components/blocks/logo-columns/LogoColumns.types.d.ts +46 -0
  155. package/dist/components/blocks/logo-columns/LogoColumns.types.js +18 -0
  156. package/dist/components/blocks/logo-columns/logo-columns-impl.css +188 -0
  157. package/dist/components/blocks/logo-rows/LogoRows.css +122 -0
  158. package/dist/components/blocks/logo-rows/LogoRows.d.ts +20 -0
  159. package/dist/components/blocks/logo-rows/LogoRows.js +43 -0
  160. package/dist/components/blocks/logo-rows/LogoRows.types.d.ts +36 -0
  161. package/dist/components/blocks/logo-rows/LogoRows.types.js +16 -0
  162. package/dist/components/blocks/logo-rows/logo-rows-impl.css +179 -0
  163. package/dist/components/blocks/page-header/PageHeader.css +79 -0
  164. package/dist/components/blocks/page-header/PageHeader.d.ts +34 -0
  165. package/dist/components/blocks/page-header/PageHeader.js +43 -0
  166. package/dist/components/blocks/page-header/PageHeader.types.d.ts +32 -0
  167. package/dist/components/blocks/page-header/PageHeader.types.js +14 -0
  168. package/dist/components/blocks/page-header/page-header-impl.css +176 -0
  169. package/dist/components/blocks/product-hero/ProductHero.css +86 -0
  170. package/dist/components/blocks/product-hero/ProductHero.d.ts +35 -0
  171. package/dist/components/blocks/product-hero/ProductHero.js +48 -0
  172. package/dist/components/blocks/product-hero/ProductHero.types.d.ts +37 -0
  173. package/dist/components/blocks/product-hero/ProductHero.types.js +15 -0
  174. package/dist/components/blocks/product-hero/product-hero-impl.css +354 -0
  175. package/dist/components/blocks/testimonial-row/TestimonialRow.css +245 -0
  176. package/dist/components/blocks/testimonial-row/TestimonialRow.d.ts +20 -0
  177. package/dist/components/blocks/testimonial-row/TestimonialRow.js +128 -0
  178. package/dist/components/blocks/testimonial-row/TestimonialRow.types.d.ts +54 -0
  179. package/dist/components/blocks/testimonial-row/TestimonialRow.types.js +26 -0
  180. package/dist/components/blocks/testimonial-row/testimonial-row-impl.css +195 -0
  181. package/dist/components/blocks/testimonial-slider/TestimonialSlider.css +181 -0
  182. package/dist/components/blocks/testimonial-slider/TestimonialSlider.d.ts +22 -0
  183. package/dist/components/blocks/testimonial-slider/TestimonialSlider.js +36 -0
  184. package/dist/components/blocks/testimonial-slider/TestimonialSlider.types.d.ts +49 -0
  185. package/dist/components/blocks/testimonial-slider/TestimonialSlider.types.js +21 -0
  186. package/dist/components/blocks/testimonial-slider/testimonial-slider-impl.css +202 -0
  187. package/dist/components/blocks/use-reveal.d.ts +46 -0
  188. package/dist/components/blocks/use-reveal.js +120 -0
  189. package/dist/components/blocks/use-rotation.d.ts +62 -0
  190. package/dist/components/blocks/use-rotation.js +176 -0
  191. package/dist/components/core/accordion-item/AccordionItem.css +6 -5
  192. package/dist/components/core/bottom-sheet/BottomSheet.css +1 -1
  193. package/dist/components/core/button/Button.css +63 -16
  194. package/dist/components/core/button/Button.d.ts +14 -12
  195. package/dist/components/core/button/Button.js +43 -14
  196. package/dist/components/core/button/Button.types.d.ts +9 -14
  197. package/dist/components/core/button/button-impl.css +25 -0
  198. package/dist/components/core/button-icon/ButtonIcon.css +31 -15
  199. package/dist/components/core/button-icon/ButtonIcon.d.ts +2 -2
  200. package/dist/components/core/button-icon/ButtonIcon.js +2 -2
  201. package/dist/components/core/button-icon/ButtonIcon.types.d.ts +4 -4
  202. package/dist/components/core/card/Card.css +13 -4
  203. package/dist/components/core/card/Card.types.d.ts +2 -1
  204. package/dist/components/core/card-body/CardBody.css +11 -6
  205. package/dist/components/core/card-body/CardBody.d.ts +1 -1
  206. package/dist/components/core/card-body/CardBody.js +2 -2
  207. package/dist/components/core/card-body/CardBody.types.d.ts +4 -1
  208. package/dist/components/core/card-body/CardBody.types.js +1 -0
  209. package/dist/components/core/card-button/CardButton.css +13 -4
  210. package/dist/components/core/card-button/CardButton.types.d.ts +2 -1
  211. package/dist/components/core/checkbox/Checkbox.css +8 -1
  212. package/dist/components/core/dropdown-menu/DropdownMenu.css +13 -12
  213. package/dist/components/core/dropdown-menu/DropdownMenu.d.ts +5 -3
  214. package/dist/components/core/dropdown-menu/DropdownMenu.js +5 -3
  215. package/dist/components/core/filter-chip/FilterChip.css +2 -1
  216. package/dist/components/core/footer/footer-impl.css +1 -1
  217. package/dist/components/core/footer-group/FooterGroup.css +8 -7
  218. package/dist/components/core/icon/Icon.css +1 -1
  219. package/dist/components/core/link/Link.css +1 -1
  220. package/dist/components/core/link/Link.js +5 -5
  221. package/dist/components/core/menu-item/MenuItem.css +1 -1
  222. package/dist/components/core/navbar/Navbar.css +7 -8
  223. package/dist/components/core/navbar/Navbar.d.ts +17 -1
  224. package/dist/components/core/navbar/Navbar.js +139 -12
  225. package/dist/components/core/navbar/Navbar.types.d.ts +23 -4
  226. package/dist/components/core/navbar/Navbar.types.js +1 -1
  227. package/dist/components/core/navbar/navbar-impl.css +10 -3
  228. package/dist/components/core/navbar/navbar-material.css +96 -0
  229. package/dist/components/core/navbar-item/NavbarItem.css +4 -4
  230. package/dist/components/core/navbar-menu/NavbarMenu.css +7 -5
  231. package/dist/components/core/navbar-menu/NavbarMenu.d.ts +1 -0
  232. package/dist/components/core/navbar-menu/NavbarMenu.js +1 -0
  233. package/dist/components/core/navbar-menu/navbar-menu-impl.css +7 -7
  234. package/dist/components/core/navbar-switcher/NavbarSwitcher.css +6 -5
  235. package/dist/components/core/navbar-switcher/NavbarSwitcher.d.ts +1 -0
  236. package/dist/components/core/navbar-switcher/NavbarSwitcher.js +2 -1
  237. package/dist/components/core/option/Option.css +1 -1
  238. package/dist/components/core/pagination/Pagination.css +1 -75
  239. package/dist/components/core/pagination/Pagination.d.ts +4 -4
  240. package/dist/components/core/pagination/Pagination.js +11 -51
  241. package/dist/components/core/pagination/Pagination.types.d.ts +5 -17
  242. package/dist/components/core/pagination/Pagination.types.js +1 -3
  243. package/dist/components/core/pagination-dots/PaginationDots.css +60 -0
  244. package/dist/components/core/pagination-dots/PaginationDots.d.ts +25 -0
  245. package/dist/components/core/pagination-dots/PaginationDots.js +104 -0
  246. package/dist/components/core/pagination-dots/PaginationDots.types.d.ts +38 -0
  247. package/dist/components/core/pagination-dots/PaginationDots.types.js +9 -0
  248. package/dist/components/core/removable-chip/RemovableChip.css +3 -3
  249. package/dist/components/core/search-input/SearchInput.css +1 -1
  250. package/dist/components/core/segmented-control/SegmentedControl.css +1 -1
  251. package/dist/components/core/segmented-control-item/SegmentedControlItem.css +1 -1
  252. package/dist/components/core/select/Select.css +2 -1
  253. package/dist/components/core/select-chip/SelectChip.css +14 -7
  254. package/dist/components/core/select-chip/SelectChip.d.ts +1 -1
  255. package/dist/components/core/select-chip/SelectChip.js +7 -4
  256. package/dist/components/core/select-chip/SelectChip.types.d.ts +7 -1
  257. package/dist/components/core/select-chip/SelectChip.types.js +1 -1
  258. package/dist/components/core/select-chip/select-chip-impl.css +14 -3
  259. package/dist/components/core/status-dot/StatusDot.css +1 -1
  260. package/dist/components/core/subdomain-navbar/SubdomainNavbar.css +3 -3
  261. package/dist/components/core/tab/Tab.css +1 -1
  262. package/dist/components/core/tab/Tab.types.d.ts +1 -1
  263. package/dist/components/core/tab-list/TabList.css +1 -1
  264. package/dist/components/core/table/table-impl.css +36 -14
  265. package/dist/components/core/table-header-cell/TableHeaderCell.css +5 -5
  266. package/dist/components/core/text-area/TextArea.css +1 -1
  267. package/dist/components/core/text-input/TextInput.css +1 -1
  268. package/dist/components/core/tooltip/Tooltip.css +1 -1
  269. package/dist/components/core/typography/Typography.css +5 -5
  270. package/dist/components/index.d.ts +35 -0
  271. package/dist/components/index.js +30 -0
  272. package/dist/components/logo-data.d.ts +24 -0
  273. package/dist/components/logo-data.js +11 -0
  274. package/dist/components/scroll-data.d.ts +64 -0
  275. package/dist/components/scroll-data.js +17 -0
  276. package/dist/components/testimonial-row-data.d.ts +51 -0
  277. package/dist/components/testimonial-row-data.js +11 -0
  278. package/dist/components/testimonial-slider-data.d.ts +26 -0
  279. package/dist/components/testimonial-slider-data.js +10 -0
  280. package/dist/marketing.css +385 -14
  281. package/package.json +1 -6
@@ -0,0 +1,49 @@
1
+ import type { TestimonialSliderQuote } from '../../testimonial-slider-data.js';
2
+ export interface TestimonialSliderOwnProps {
3
+ /**
4
+ * `page` — The default, and the page's own white. The card is the recessed gray that sets it off
5
+ * `subtle` — The grey band, the reference design's ground for this section. The card turns white on it. Painted as the band's tint laid over the page's own ground, so it is the same grey whatever is behind the section
6
+ * `strong` — `color.bg.brand-strong`, the dark band, for a section a reader should arrive at. The heading and the quote turn white and the card takes color.bg.surface-card-strong — gray.900 in both themes, the colour a page card takes in dark mode, and TestimonialRow's card on the same band — so the band reads as a dark-mode section in either theme. The coral dots sit on it
7
+ */
8
+ ground?: 'page' | 'subtle' | 'strong';
9
+ /** Always. Whose words these are, in a few — "What our partners say", "What our customers say". */
10
+ title: string;
11
+ /** Always. The quotes, in the order they rotate — two to five, each a few sentences, each with the name of who said it. An empty list draws nothing; one quote is drawn still, with no dots. */
12
+ quotes: TestimonialSliderQuote[];
13
+ /** A decorative picture, laid over the card's top start corner — a photograph, a product screen, any small piece of art, usually a PNG — as a path or a URL. It is drawn as it is, with rounded corners and no frame, so a transparent ground shows the card through it. Drawn square and cropped to fill its square, so a picture whose subject sits in its middle crops best. It runs up behind the card's top edge, so the edge cuts straight across it, set in from the side, stays put while the quotes rotate, and drifts down by motion.distance.drift as the section passes through the view. The one shown on a phone, where it moves to the top end corner above the quote and drifts half as far, so more of it shows. Decorative: it takes an empty alt and is hidden from assistive technology. */
14
+ imageStart?: string;
15
+ /** A decorative picture at the card's bottom end corner, the pair to imageStart: drawn the same way behind the card's bottom edge, and drifting up as the other drifts down, so the two read as depth. Drawn from the fold only: a phone has room for one, and it is the opening one. Decorative, as imageStart is. */
16
+ imageEnd?: string;
17
+ /** Whether it advances on its own, holding each slide for motion.duration.dwell. Off by default, so a slider nobody configured stays still. On, it holds while the pointer is over it or focus is inside it, never moves for a reader who asked for less motion, and stops for good once the reader presses anything in it — a slide, its action, a dot — or swipes it. A press stops it for good — the WAI carousel pattern's rule that a reader who has interacted is reading, not watching. That gives a reader a way to stop the rotation, which WCAG 2.2.2 asks for, but not a visible one: nothing says a press will stop it, so a page that needs 2.2.2 met plainly should still offer its own pause, or leave autoplay off. */
18
+ autoplay?: boolean;
19
+ /** The name the dots are announced by. Its own name rather than the section's, so a screen reader moving into the dots hears what they are. Translate it with the page. */
20
+ controlsLabel?: string;
21
+ /** The word each dot is announced by, before its number — 'Slide 2'. Translate it with the page, as controlsLabel is; a page that translates only the group's name still has every dot announced in English. */
22
+ slideLabel?: string;
23
+ }
24
+ export type TestimonialSliderProps = TestimonialSliderOwnProps;
25
+ /** The class each part carries. Apply these — do not retype them. */
26
+ export declare const testimonialSliderParts: {
27
+ readonly root: "dds-testimonialslider";
28
+ readonly inner: "dds-testimonialslider__inner";
29
+ readonly title: "dds-testimonialslider__title";
30
+ readonly carousel: "dds-testimonialslider__carousel";
31
+ readonly track: "dds-testimonialslider__track";
32
+ readonly item: "dds-testimonialslider__item";
33
+ readonly 'image-start': "dds-testimonialslider__image-start";
34
+ readonly 'image-end': "dds-testimonialslider__image-end";
35
+ readonly image: "dds-testimonialslider__image";
36
+ readonly quote: "dds-testimonialslider__quote";
37
+ readonly author: "dds-testimonialslider__author";
38
+ readonly avatar: "dds-testimonialslider__avatar";
39
+ readonly name: "dds-testimonialslider__name";
40
+ readonly detail: "dds-testimonialslider__detail";
41
+ readonly controls: "dds-testimonialslider__controls";
42
+ };
43
+ /** Generated so defaults cannot drift from the contract. */
44
+ export declare const testimonialSliderDefaults: {
45
+ readonly ground: "page";
46
+ readonly autoplay: false;
47
+ readonly controlsLabel: "Testimonials";
48
+ readonly slideLabel: "Slide";
49
+ };
@@ -0,0 +1,21 @@
1
+ // GENERATED from testimonial-slider.contract.json. Do not edit.
2
+ /** The class each part carries. Apply these — do not retype them. */
3
+ export const testimonialSliderParts = {
4
+ root: 'dds-testimonialslider',
5
+ inner: 'dds-testimonialslider__inner',
6
+ title: 'dds-testimonialslider__title',
7
+ carousel: 'dds-testimonialslider__carousel',
8
+ track: 'dds-testimonialslider__track',
9
+ item: 'dds-testimonialslider__item',
10
+ 'image-start': 'dds-testimonialslider__image-start',
11
+ 'image-end': 'dds-testimonialslider__image-end',
12
+ image: 'dds-testimonialslider__image',
13
+ quote: 'dds-testimonialslider__quote',
14
+ author: 'dds-testimonialslider__author',
15
+ avatar: 'dds-testimonialslider__avatar',
16
+ name: 'dds-testimonialslider__name',
17
+ detail: 'dds-testimonialslider__detail',
18
+ controls: 'dds-testimonialslider__controls',
19
+ };
20
+ /** Generated so defaults cannot drift from the contract. */
21
+ export const testimonialSliderDefaults = { ground: 'page', autoplay: false, controlsLabel: 'Testimonials', slideLabel: 'Slide' };
@@ -0,0 +1,202 @@
1
+ /*
2
+ * Scoped to this package, like the generated sheet beside it.
3
+ */
4
+
5
+ /*
6
+ * One cell for every quote, so a change of quote is a change in place.
7
+ *
8
+ * CtaBannerSlider's arrangement: the section takes the height of its longest quote whichever is
9
+ * showing, and nothing under it moves. The quote in view is drawn; the others wait in the same cell
10
+ * at opacity.hidden, and `visibility` takes them out of hit-testing as well as sight, beside the
11
+ * `inert` the component gives them. The fade borrows the track's timing through `inherit`, so the
12
+ * fade and the dots move on one beat.
13
+ */
14
+ :where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__item {
15
+ grid-area: 1 / 1;
16
+ transition-property: opacity, visibility;
17
+ transition-duration: inherit;
18
+ transition-timing-function: inherit;
19
+ }
20
+
21
+ :where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__item[aria-hidden='true'] {
22
+ opacity: var(--opacity-hidden);
23
+ visibility: hidden;
24
+ }
25
+
26
+ @media (prefers-reduced-motion: reduce) {
27
+ :where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__item {
28
+ transition-property: none;
29
+ }
30
+ }
31
+
32
+ /* The track owns horizontal gestures and leaves vertical ones to the page — see CtaBannerSlider. */
33
+ :where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__track {
34
+ touch-action: pan-y;
35
+ }
36
+
37
+ /*
38
+ * The card is ranged to the start on a phone and centred from the fold, as the reference design sets it.
39
+ *
40
+ * The heading, the quote and the person under it centre together. `margin-inline: auto` on the
41
+ * heading and the quote centres their measured boxes rather than their words inside a box left at
42
+ * the start edge.
43
+ */
44
+ @container (min-width: 48rem) {
45
+ /* The heading centres with the card, the way every other block's heading does from the fold. */
46
+ :where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__title {
47
+ margin-inline: auto;
48
+ text-align: center;
49
+ }
50
+
51
+ :where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__item {
52
+ align-items: center;
53
+ padding-inline: var(--space-inset-4xl);
54
+ text-align: center;
55
+ }
56
+
57
+ :where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__quote {
58
+ margin-inline: auto;
59
+ }
60
+
61
+ /* And the dots follow the quote: at the start edge on a phone, under the centre once it centres. */
62
+ :where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__controls {
63
+ justify-content: center;
64
+ }
65
+ }
66
+
67
+ /*
68
+ * How far the pictures drift, and so how far each is tucked behind its edge to keep its corners
69
+ * hidden while it does. Half of motion.distance.drift on a phone, where the one picture is set
70
+ * above the quote and every pixel tucked away is a pixel of it not shown; the whole of it from the
71
+ * fold, where the card is wide enough for the movement to read.
72
+ */
73
+ :where([data-dds-context="marketing"]) .dds-testimonialslider {
74
+ --dds-testimonialslider-drift: calc(var(--motion-distance-drift) * 0.5);
75
+ }
76
+
77
+ @container (min-width: 48rem) {
78
+ :where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__track {
79
+ --dds-testimonialslider-drift: var(--motion-distance-drift);
80
+ }
81
+ }
82
+
83
+ /*
84
+ * The corner pictures, tucked behind the card's own edges.
85
+ *
86
+ * The opening one runs up behind the card's top edge and the closing one down behind its bottom
87
+ * edge, each set in from its side by the card's inset — so the pair runs from edge to edge of the
88
+ * card diagonally, as though passing behind it. Each is tucked by its own corner radius and the
89
+ * whole of its drift, so the corners on that side are behind the edge at every point of the
90
+ * scroll: the card's edge is a straight cut across the picture, and only the corners facing the
91
+ * quote show rounded. Their
92
+ * offsets are here rather than in bindings because a contract has no vocabulary for one: a
93
+ * position is a fact about this card's corners, which no other component shares.
94
+ *
95
+ * On a phone only the opening one is drawn, at full size, in the top end corner above the quote — the quote starts at the other edge, so the picture takes the side the words leave
96
+ * empty; from the fold both are, at full size, in opposite corners.
97
+ */
98
+ :where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__image-start {
99
+ inline-size: var(--size-testimonial-art);
100
+ inset-block-start: calc(-1 * (var(--radius-container-item) + var(--dds-testimonialslider-drift)));
101
+ inset-inline-end: var(--space-inset-lg);
102
+ }
103
+
104
+ :where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__image-end {
105
+ inset-block-end: calc(-1 * (var(--radius-container-item) + var(--dds-testimonialslider-drift)));
106
+ inset-inline-end: var(--space-inset-xl);
107
+ }
108
+
109
+ /*
110
+ * Room is made on the card for whichever is drawn, so a picture never sits over the words, and
111
+ * `:has()` asks the track whether one is there, so a card with none keeps its own padding.
112
+ *
113
+ * Above the quote on a phone: as much of the picture as ever comes out from behind the top edge —
114
+ * its size less its corner, the drift and the tuck cancelling — and two insets between it and
115
+ * the words.
116
+ */
117
+ :where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__track:has(> .dds-testimonialslider__image-start) .dds-testimonialslider__item {
118
+ padding-block-start: calc(var(--size-testimonial-art) - var(--radius-container-item) + 2 * var(--space-inset-lg));
119
+ }
120
+
121
+ @container (min-width: 48rem) {
122
+ :where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__image-start {
123
+ inline-size: var(--size-testimonial-art);
124
+ inset-block-start: calc(-1 * (var(--radius-container-item) + var(--dds-testimonialslider-drift)));
125
+ inset-inline-end: auto;
126
+ inset-inline-start: var(--space-inset-xl);
127
+ }
128
+
129
+ :where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__image-end {
130
+ display: block;
131
+ }
132
+
133
+ /* At the sides from the fold: each picture, with an inset either side of it. Tall enough to hold
134
+ a picture and its insets, so neither runs off the top or the bottom of a short card. */
135
+ :where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__track:is(:has(> .dds-testimonialslider__image-start), :has(> .dds-testimonialslider__image-end)) .dds-testimonialslider__item {
136
+ justify-content: center;
137
+ min-block-size: calc(var(--size-testimonial-art) + 2 * var(--space-inset-3xl));
138
+ padding-block-start: var(--space-inset-3xl);
139
+ padding-inline: calc(var(--size-testimonial-art) + 2 * var(--space-inset-xl));
140
+ }
141
+ }
142
+
143
+ /*
144
+ * They drift against the scroll while the section passes through the view — half of
145
+ * motion.distance.drift on a phone, all of it from the fold: the opening one down and the closing one up, each from where it rests, so the two mirror
146
+ * each other at every point of the scroll and keep the same distance from their own edges.
147
+ *
148
+ * Scroll-driven, LandingHero's way: a view timeline measures the card against the viewport, so it
149
+ * moves as the reader scrolls and back again as they scroll back, and there is no timer and no
150
+ * script. A browser with no scroll timeline draws both still, which is the whole of the fallback.
151
+ */
152
+ @keyframes dds-testimonialslider-drift-down {
153
+ from {
154
+ translate: none;
155
+ }
156
+ to {
157
+ translate: 0 var(--dds-testimonialslider-drift);
158
+ }
159
+ }
160
+
161
+ @keyframes dds-testimonialslider-drift-up {
162
+ from {
163
+ translate: none;
164
+ }
165
+ to {
166
+ translate: 0 calc(-1 * var(--dds-testimonialslider-drift));
167
+ }
168
+ }
169
+
170
+ @supports (animation-timeline: view()) {
171
+ /* One timeline for the pair, the card's own pass through the view. Each picture measuring its own
172
+ would put the higher one further along at every point of the scroll, and the two would drift
173
+ by different distances.
174
+
175
+ It measures against the nearest scroll container, which is why the section and the track clip
176
+ with `overflow: clip` rather than `hidden`: `hidden` makes a box a scroll container even when
177
+ it never scrolls, and the timeline would then measure the card against a box that does not
178
+ move — the pictures would sit still at one point of the drift however far the page scrolled. */
179
+ :where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__track {
180
+ view-timeline: --dds-testimonialslider-card block;
181
+ }
182
+
183
+ :where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__image-start {
184
+ animation: dds-testimonialslider-drift-down linear both;
185
+ animation-range: cover;
186
+ animation-timeline: --dds-testimonialslider-card;
187
+ }
188
+
189
+ :where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__image-end {
190
+ animation: dds-testimonialslider-drift-up linear both;
191
+ animation-range: cover;
192
+ animation-timeline: --dds-testimonialslider-card;
193
+ }
194
+ }
195
+
196
+ /* A reader who asked for less movement gets none of it: the pictures hold still in their corners. */
197
+ @media (prefers-reduced-motion: reduce) {
198
+ :where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__image-start,
199
+ :where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__image-end {
200
+ animation: none;
201
+ }
202
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Whether a block has arrived on screen yet, so its stylesheet can bring it in.
3
+ *
4
+ * Every trigger CSS alone can offer is invisible somewhere, and both were tried here first. A
5
+ * timed animation fires when the element is created, so a block below the fold has finished
6
+ * arriving before a reader scrolls to it. A scroll-driven one — `animation-timeline: view()` —
7
+ * fires as the element enters the viewport, so a block that is *already* in view at the first
8
+ * frame is past the range before anything is painted, and an opening band never moves at all.
9
+ *
10
+ * What is wanted is "when it comes into view, counting already being there as coming into view",
11
+ * and that is the one thing a view timeline cannot say. An observer can, which is the whole reason
12
+ * this file exists.
13
+ *
14
+ * It answers `true` before it knows anything, and that is deliberate. A block hidden until
15
+ * JavaScript says otherwise is content behind a script — a reader with none, or one whose bundle
16
+ * failed, gets a blank band. So the resting answer is visible, and hiding is something this only
17
+ * does once it is running and has somewhere to put the block back.
18
+ *
19
+ * `useLayoutEffect` so the hiding lands before the browser paints. In an effect it would run after
20
+ * the first frame, and every block would show itself, hide, and come back — a flash on every
21
+ * section of the page.
22
+ *
23
+ * It fires once. A section that re-arrived every time a reader scrolled back up would be a page
24
+ * that will not settle, and the observer is disconnected rather than left listening.
25
+ */
26
+ export declare function useReveal<T extends HTMLElement>(): [
27
+ ref: (held: T | null) => void,
28
+ revealed: boolean
29
+ ];
30
+ /**
31
+ * One part's place in the order its block arrives in.
32
+ *
33
+ * Spread onto each part that moves: `<p {...arriving(1)} …>`. Two spellings of one number, because
34
+ * CSS needs both and can do neither job with the other's — an attribute is what a selector can
35
+ * match, and a custom property is what `calc()` can multiply into a delay.
36
+ *
37
+ * The number is the reading order rather than the DOM order, and they are not always the same: a
38
+ * hero's picture sits before its words in the markup, because a band paints its ground before it
39
+ * sets type on it, and a reader still meets the claim first.
40
+ */
41
+ export declare function arriving(at: number): {
42
+ 'data-reveal-at': number;
43
+ style: {
44
+ [key: string]: string | number;
45
+ };
46
+ };
@@ -0,0 +1,120 @@
1
+ 'use client';
2
+ import { useLayoutEffect, useRef, useState } from 'react';
3
+ /**
4
+ * Whether a block has arrived on screen yet, so its stylesheet can bring it in.
5
+ *
6
+ * Every trigger CSS alone can offer is invisible somewhere, and both were tried here first. A
7
+ * timed animation fires when the element is created, so a block below the fold has finished
8
+ * arriving before a reader scrolls to it. A scroll-driven one — `animation-timeline: view()` —
9
+ * fires as the element enters the viewport, so a block that is *already* in view at the first
10
+ * frame is past the range before anything is painted, and an opening band never moves at all.
11
+ *
12
+ * What is wanted is "when it comes into view, counting already being there as coming into view",
13
+ * and that is the one thing a view timeline cannot say. An observer can, which is the whole reason
14
+ * this file exists.
15
+ *
16
+ * It answers `true` before it knows anything, and that is deliberate. A block hidden until
17
+ * JavaScript says otherwise is content behind a script — a reader with none, or one whose bundle
18
+ * failed, gets a blank band. So the resting answer is visible, and hiding is something this only
19
+ * does once it is running and has somewhere to put the block back.
20
+ *
21
+ * `useLayoutEffect` so the hiding lands before the browser paints. In an effect it would run after
22
+ * the first frame, and every block would show itself, hide, and come back — a flash on every
23
+ * section of the page.
24
+ *
25
+ * It fires once. A section that re-arrived every time a reader scrolled back up would be a page
26
+ * that will not settle, and the observer is disconnected rather than left listening.
27
+ */
28
+ export function useReveal() {
29
+ const held = useRef(null);
30
+ const [revealed, setRevealed] = useState(true);
31
+ useLayoutEffect(() => {
32
+ const element = held.current;
33
+ if (element === null)
34
+ return;
35
+ // A reader who asked for less movement is not hidden and then shown; they are simply shown.
36
+ // The stylesheet drops the transition as well, so this is the half that matters: without it
37
+ // the block would still be hidden for a frame before appearing, which is the flicker that
38
+ // preference exists to remove.
39
+ //
40
+ // Asked defensively, like the observer below. A renderer with no `matchMedia` cannot be
41
+ // asked what the reader prefers, and the honest answer to a question that cannot be asked
42
+ // is the one that hides nothing.
43
+ const asked = typeof window.matchMedia === 'function';
44
+ if (asked && window.matchMedia('(prefers-reduced-motion: reduce)').matches)
45
+ return;
46
+ // Anything the browser cannot observe arrives already arrived, which is the same answer this
47
+ // hook starts on: seen rather than waiting.
48
+ if (typeof IntersectionObserver === 'undefined')
49
+ return;
50
+ /**
51
+ * A box that does not exist cannot come into view, so it is never hidden.
52
+ *
53
+ * `display: contents` is the case, and it cost a section its words: FeatureScroll's text column
54
+ * gives up its box on a phone so the picture can sit between the title and the line under it,
55
+ * an observer watching it was never going to report anything, and the copy stayed waiting for
56
+ * an arrival that could not happen. Permanently invisible content is the worst failure this
57
+ * hook has available to it, so it checks.
58
+ *
59
+ * A caller that wants motion for such a group watches something inside it that does have a box
60
+ * and marks the group — the ref and the attribute need not sit on the same element. This is the
61
+ * floor under that, not a substitute for it.
62
+ */
63
+ if (element.getClientRects().length === 0)
64
+ return;
65
+ setRevealed(false);
66
+ /**
67
+ * The arrival is put off to the next frame, and that one frame is the whole of it.
68
+ *
69
+ * A transition needs a painted starting state. For a block already on screen the observer's
70
+ * first callback is delivered in the rendering steps of the frame the block was laid out in —
71
+ * so flipping there applies the landed state before the waiting one has ever been painted, and
72
+ * the browser has nothing to move between. It goes straight to the end, which looks exactly
73
+ * like no animation at all.
74
+ *
75
+ * That was the bug, and it hid itself well: a block below the fold worked, because the
76
+ * observer does not fire until a reader scrolls and by then the waiting state has been on
77
+ * screen for many frames. Everything a reader sees first — the heading, the first block, any
78
+ * band shown on its own — did not.
79
+ */
80
+ let frame = 0;
81
+ const watching = new IntersectionObserver((entries) => {
82
+ if (!entries.some((entry) => entry.isIntersecting))
83
+ return;
84
+ watching.disconnect();
85
+ frame = window.requestAnimationFrame(() => {
86
+ frame = 0;
87
+ setRevealed(true);
88
+ });
89
+ },
90
+ // A tenth of the block, so a band a screen tall is not held back until a reader has scrolled
91
+ // most of it into view, and a short one is not brought in by a sliver at the edge.
92
+ { threshold: 0.1 });
93
+ watching.observe(element);
94
+ return () => {
95
+ watching.disconnect();
96
+ if (frame !== 0)
97
+ window.cancelAnimationFrame(frame);
98
+ };
99
+ }, []);
100
+ return [
101
+ (element) => {
102
+ held.current = element;
103
+ },
104
+ revealed,
105
+ ];
106
+ }
107
+ /**
108
+ * One part's place in the order its block arrives in.
109
+ *
110
+ * Spread onto each part that moves: `<p {...arriving(1)} …>`. Two spellings of one number, because
111
+ * CSS needs both and can do neither job with the other's — an attribute is what a selector can
112
+ * match, and a custom property is what `calc()` can multiply into a delay.
113
+ *
114
+ * The number is the reading order rather than the DOM order, and they are not always the same: a
115
+ * hero's picture sits before its words in the markup, because a band paints its ground before it
116
+ * sets type on it, and a reader still meets the claim first.
117
+ */
118
+ export function arriving(at) {
119
+ return { 'data-reveal-at': at, style: { '--dds-reveal-at': at } };
120
+ }
@@ -0,0 +1,62 @@
1
+ import { type FocusEvent, type MouseEvent, type PointerEvent } from 'react';
2
+ /**
3
+ * One block rotating between a few things in place — which one is in view, and every way a reader
4
+ * moves it, holds it or stops it.
5
+ *
6
+ * Shared because two blocks rotate, CtaBannerSlider and TestimonialSlider, and a carousel is the
7
+ * kind of thing that drifts: one stops on a press and the other does not, one swallows the click a swipe
8
+ * ends in and the other follows the link. The rules are stated once here and each block spreads
9
+ * what this hands back onto its own parts.
10
+ *
11
+ * The clock is not here. PaginationDots holds the timer and the reduced-motion stillness, and this
12
+ * tells it when to wait — so there is one clock per block, and it is the one a reader can see.
13
+ *
14
+ * What it hands back:
15
+ * - `root`, the ref for the block's own element, which the swipe threshold and the reading
16
+ * direction are read off;
17
+ * - `region`, spread on that element: the carousel's role description and the hold and stop
18
+ * handlers;
19
+ * - `track`, spread on the element holding the items: the swipe and what is announced;
20
+ * - `item(at)`, spread on each item: its group role, its "2 / 3" name and its inert state;
21
+ * - `dots`, spread on PaginationDots alongside the block's own label.
22
+ *
23
+ * Fewer than two items is a set with nothing to move to, drawn still rather than broken: every
24
+ * attribute that says "carousel" is left off and the dots are the block's to omit.
25
+ */
26
+ export declare function useRotation(count: number, autoplay: boolean): {
27
+ current: number;
28
+ rotating: boolean;
29
+ root: import("react").RefObject<HTMLElement | null>;
30
+ region: {
31
+ 'aria-roledescription': string | undefined;
32
+ onPointerEnter: (event: PointerEvent<HTMLElement>) => void;
33
+ onPointerLeave: (event: PointerEvent<HTMLElement>) => void;
34
+ onFocus: () => void;
35
+ onPointerDownCapture: (event: PointerEvent<HTMLElement>) => void;
36
+ onBlur: (event: FocusEvent<HTMLElement>) => void;
37
+ };
38
+ track: {
39
+ 'aria-live': "polite" | "off";
40
+ onPointerDown: (event: PointerEvent<HTMLElement>) => void;
41
+ onPointerUp: (event: PointerEvent<HTMLElement>) => void;
42
+ onPointerCancel: () => void;
43
+ onPointerLeave: () => void;
44
+ onClickCapture: (event: MouseEvent<HTMLElement>) => void;
45
+ };
46
+ /** Whether an item is out of view: inert, hidden, and waiting rather than arrived. */
47
+ away: (at: number) => boolean;
48
+ item: (at: number) => {
49
+ role: string | undefined;
50
+ 'aria-roledescription': string | undefined;
51
+ 'aria-label': string | undefined;
52
+ 'aria-hidden': true | undefined;
53
+ inert: true | undefined;
54
+ };
55
+ dots: {
56
+ page: number;
57
+ totalPages: number;
58
+ onPageChange: (page: number) => void;
59
+ autoplay: boolean;
60
+ paused: boolean;
61
+ };
62
+ };