@riverbankcms/sdk 0.109.0 → 0.111.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 (186) hide show
  1. package/dist/{PreviewEditorSidebar-DWqwfy3_.mjs → PreviewEditorSidebar-CTR6LUhN.mjs} +178 -117
  2. package/dist/{PreviewEditorUI-B7OL4sfR.mjs → PreviewEditorUI-DZg15Zip.mjs} +3 -4
  3. package/dist/{PreviewQueryProvider-D0y2l8JN.mjs → PreviewQueryProvider-kkmjklLG.mjs} +1 -1
  4. package/dist/{SdkPreviewModeRuntime-D8Gt9Gbe.mjs → SdkPreviewModeRuntime-DeOTAFvR.mjs} +229 -219
  5. package/dist/{SiteChromeCustomizeContext-DUpalEdL.mjs → SiteChromeCustomizeContext-DOSDLCiJ.mjs} +1695 -2169
  6. package/dist/_dts/ai/src/contracts/proposals.d.ts +1716 -76
  7. package/dist/_dts/api/src/commercePortalEndpoints.d.ts +5 -5
  8. package/dist/_dts/api/src/contentRuntime.d.ts +4 -1
  9. package/dist/_dts/api/src/courses.d.ts +30 -15
  10. package/dist/_dts/api/src/endpoints.d.ts +14 -4
  11. package/dist/_dts/api/src/index.d.ts +2 -2
  12. package/dist/_dts/api/src/sdkContracts.d.ts +23 -11
  13. package/dist/_dts/api/src/siteManagementEndpoints.d.ts +5 -1
  14. package/dist/_dts/api/src/siteOperations.d.ts +11 -19
  15. package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +6 -6
  16. package/dist/_dts/api/src/webhooks.d.ts +98 -1
  17. package/dist/_dts/billing/src/site-arrangements.d.ts +3 -0
  18. package/dist/_dts/blocks/src/client/course-registration.d.ts +4 -1
  19. package/dist/_dts/blocks/src/client.d.ts +4 -1
  20. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +4 -4
  21. package/dist/_dts/blocks/src/index.d.ts +3 -1
  22. package/dist/_dts/blocks/src/system/blocks/course-registration.d.ts +2 -1
  23. package/dist/_dts/blocks/src/system/blocks/courses/shared/types.d.ts +2 -1
  24. package/dist/_dts/blocks/src/system/blocks/cta-full.d.ts +2 -4
  25. package/dist/_dts/blocks/src/system/blocks/event-registration.d.ts +2 -1
  26. package/dist/_dts/blocks/src/system/blocks/events/event-listing.d.ts +2 -1
  27. package/dist/_dts/blocks/src/system/blocks/events/event-spotlight.d.ts +2 -1
  28. package/dist/_dts/blocks/src/system/blocks/events/recurring-schedule.d.ts +3 -2
  29. package/dist/_dts/blocks/src/system/blocks/events/shared/types.d.ts +2 -1
  30. package/dist/_dts/blocks/src/system/blocks/file-download.d.ts +2 -1
  31. package/dist/_dts/blocks/src/system/blocks/newsletter-signup.d.ts +2 -1
  32. package/dist/_dts/blocks/src/system/blocks/shop.d.ts +2 -1
  33. package/dist/_dts/blocks/src/system/blocks/single-button.d.ts +2 -1
  34. package/dist/_dts/blocks/src/system/constants/buttonRoles.d.ts +35 -0
  35. package/dist/_dts/blocks/src/system/fields/button.d.ts +10 -21
  36. package/dist/_dts/blocks/src/system/fields/ctas.d.ts +2 -1
  37. package/dist/_dts/blocks/src/system/fragments/library/heroCtaRow.d.ts +9 -5
  38. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +18 -18
  39. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +9 -9
  40. package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessWholeSeriesRegistrationFlow.d.ts +29 -0
  41. package/dist/_dts/blocks/src/system/runtime/nodes/buttonAffordance.d.ts +1 -1
  42. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/ErrorStep.d.ts +2 -1
  43. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/PaymentFailedStep.d.ts +2 -1
  44. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/VerifyingTimeoutStep.d.ts +2 -1
  45. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/types.d.ts +21 -0
  46. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationWizard.d.ts +4 -4
  47. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/whole-series-registration.headless.contract.d.ts +326 -0
  48. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/whole-series-registration.headless.planning.d.ts +27 -0
  49. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration.interactive.d.ts +5 -4
  50. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.contract.d.ts +3 -2
  51. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +2 -1
  52. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.interactive.d.ts +5 -4
  53. package/dist/_dts/blocks/src/system/runtime/nodes/file-download.d.ts +2 -3
  54. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.types.d.ts +2 -1
  55. package/dist/_dts/blocks/src/system/runtime/nodes/shared/contract-schemas.d.ts +6 -3
  56. package/dist/_dts/blocks/src/system/runtime/nodes/shop.interactive.d.ts +7 -6
  57. package/dist/_dts/blocks/src/system/runtime/nodes/shop.types.d.ts +2 -1
  58. package/dist/_dts/blocks/src/system/runtime/shared/types.d.ts +2 -1
  59. package/dist/_dts/content-editor/src/FooterComposerPanel.d.ts +4 -2
  60. package/dist/_dts/content-editor/src/index.d.ts +12 -12
  61. package/dist/_dts/content-editor/src/ui/editorUiStore.d.ts +17 -2
  62. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +221 -53
  63. package/dist/_dts/editor-blocks/src/widgets/button/context.d.ts +3 -2
  64. package/dist/_dts/preview-next/src/client/index.d.ts +3 -2
  65. package/dist/_dts/preview-next/src/client/preview/ButtonStylePicker.d.ts +16 -0
  66. package/dist/_dts/preview-next/src/client/preview/PageBlockEditorPanel.d.ts +2 -3
  67. package/dist/_dts/preview-next/src/client/preview/PreviewDesignOpenRequestContext.d.ts +7 -0
  68. package/dist/_dts/preview-next/src/client/preview/PreviewEditorSidebar.d.ts +5 -11
  69. package/dist/_dts/preview-next/src/client/preview/PreviewShell.d.ts +5 -6
  70. package/dist/_dts/preview-next/src/client/preview/PreviewShellLayout.d.ts +6 -7
  71. package/dist/_dts/preview-next/src/client/preview/SiteChromeCustomizeContext.d.ts +7 -9
  72. package/dist/_dts/preview-next/src/client/preview/StyleConfigurator.d.ts +4 -11
  73. package/dist/_dts/preview-next/src/client/preview/StyleConfigurator.state.d.ts +7 -7
  74. package/dist/_dts/preview-next/src/client/preview/sidebarTabPreference.d.ts +0 -8
  75. package/dist/_dts/preview-next/src/client/preview/siteChromeLookRows.d.ts +1 -11
  76. package/dist/_dts/preview-next/src/client/preview/siteChromeQuickControlHistoryState.d.ts +1 -5
  77. package/dist/_dts/preview-next/src/client/preview/siteChromeSavePlan.d.ts +2 -3
  78. package/dist/_dts/preview-next/src/client/preview/siteStylePreviewPlanner.d.ts +3 -4
  79. package/dist/_dts/preview-next/src/client/preview/styleConfiguratorSnapshot.d.ts +3 -5
  80. package/dist/_dts/sdk/src/bookings/index.d.ts +5 -4
  81. package/dist/_dts/sdk/src/bookings/types.d.ts +3 -3
  82. package/dist/_dts/sdk/src/cli/commands/style.d.ts +3 -2
  83. package/dist/_dts/sdk/src/client/management/types.d.ts +2 -1
  84. package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +12 -15
  85. package/dist/_dts/sdk/src/public-api/contracts.d.ts +1 -1
  86. package/dist/_dts/sdk/src/version.d.ts +1 -1
  87. package/dist/_dts/sdk/src/webhooks/index.d.ts +1 -1
  88. package/dist/_dts/sdk/src/webhooks/verify.d.ts +3 -3
  89. package/dist/_dts/site-commands/src/commands.d.ts +129 -6
  90. package/dist/_dts/theme-core/src/buttons/index.d.ts +1 -1
  91. package/dist/_dts/theme-core/src/buttons/styles/domain.d.ts +80 -0
  92. package/dist/_dts/theme-core/src/buttons/styles/index.d.ts +3 -0
  93. package/dist/_dts/theme-core/src/buttons/styles/recipes/defineStaticButtonStyleRecipe.d.ts +49 -0
  94. package/dist/_dts/theme-core/src/buttons/styles/recipes/quietArrow.d.ts +67 -0
  95. package/dist/_dts/theme-core/src/buttons/styles/recipes/staticRecipes.d.ts +649 -0
  96. package/dist/_dts/theme-core/src/buttons/styles/registry.d.ts +753 -0
  97. package/dist/_dts/theme-core/src/buttons/styles/selection.d.ts +69 -0
  98. package/dist/_dts/theme-core/src/site-styles/curatedSiteStyles.d.ts +26 -24
  99. package/dist/_dts/theme-core/src/site-styles/footerLooks.d.ts +19 -153
  100. package/dist/_dts/theme-core/src/site-styles/headerCtaVariants.d.ts +3 -1
  101. package/dist/_dts/theme-core/src/site-styles/previewCompiler.d.ts +8 -9
  102. package/dist/_dts/theme-core/src/site-styles/runtimeCompiler.d.ts +4 -4
  103. package/dist/_dts/ui/src/palette/hex.d.ts +3 -3
  104. package/dist/cli/index.mjs +1760 -1914
  105. package/dist/cli/init-docs/content/workflow-isr-revalidation.md +1 -1
  106. package/dist/client/{DiscountCodeDisclosure-DU1ygxU2.mjs → DiscountCodeDisclosure-C4xvTBux.mjs} +1 -1
  107. package/dist/client/{EventCombined.client-DB5zagCo.mjs → EventCombined.client-Cr7G131j.mjs} +2 -3
  108. package/dist/client/{EventListing.client-CTX9JHBL.mjs → EventListing.client-CAjbseNy.mjs} +2 -2
  109. package/dist/client/{LeafletStaticMap-BYImhgiB.mjs → LeafletStaticMap-BMlWfwz3.mjs} +1 -1
  110. package/dist/client/{MagicLinkForm-CRkw_M3l.mjs → MagicLinkForm-ChdFz96y.mjs} +1 -2
  111. package/dist/client/{StepIndicator-BnmVBJJh.mjs → StepIndicator-7D3GaBeM.mjs} +2 -2
  112. package/dist/client/{accordion-CeGreumd.mjs → accordion-D8JTs2Si.mjs} +1 -1
  113. package/dist/client/{bookingForm-CSzFNrpN.mjs → bookingForm-H3DCRBHs.mjs} +6 -7
  114. package/dist/client/bookings.mjs +3069 -1447
  115. package/dist/client/{carousel-B2jDtogf.mjs → carousel-DMr_QWlz.mjs} +1 -1
  116. package/dist/client/{cart-D-jZ-vaY.mjs → cart-DWMbfBdR.mjs} +3 -3
  117. package/dist/client/{checkout-Dza-LA7N.mjs → checkout-zmfdkXLx.mjs} +3 -3
  118. package/dist/client/client.mjs +1732 -1913
  119. package/dist/client/{colorStyles-CrgzoXsm.mjs → colorStyles-gcTh5yZT.mjs} +2 -12
  120. package/dist/client/{colorTokenParts-CMugwvX_.mjs → colorTokenParts-FSS3al6l.mjs} +31 -1
  121. package/dist/client/{courseRegistration-TYkNychb.mjs → courseRegistration-Z_mn18jy.mjs} +100 -37
  122. package/dist/client/{eventCalendar-BI_90SsT.mjs → eventCalendar-CYp0YJGF.mjs} +4 -5
  123. package/dist/client/{eventCombined-mNrpryE9.mjs → eventCombined-rKyYZUa9.mjs} +2 -2
  124. package/dist/client/{eventDetails-D4GVlCIY.mjs → eventDetails-X0ZaUuMj.mjs} +3 -3
  125. package/dist/client/{eventListing-YhKN018y.mjs → eventListing-W1SuL7EP.mjs} +2 -2
  126. package/dist/client/{eventRegistration-CdHGtilr.mjs → eventRegistration-ClWricui.mjs} +6 -7
  127. package/dist/client/{form-AcAL45rA.mjs → form--eKPwAAD.mjs} +1 -2
  128. package/dist/client/{headerSection-uEC52ueD.mjs → headerSection-BSeGr-FS.mjs} +2 -3
  129. package/dist/client/hooks.mjs +1554 -1871
  130. package/dist/client/{locationMap-_wJDSUYe.mjs → locationMap-BpOrtNYn.mjs} +8 -5
  131. package/dist/client/{media-BK0O3b-U.mjs → media-DoF0dcVx.mjs} +2 -2
  132. package/dist/client/{newsletterForm-DrArsb2B.mjs → newsletterForm-Bt7it7Dy.mjs} +1 -2
  133. package/dist/client/{pricing-BSYVghwo.mjs → pricing-BTjSDDr4.mjs} +1 -1
  134. package/dist/client/{productDetail-Dyk90sMs.mjs → productDetail-ICnVTcCg.mjs} +3 -3
  135. package/dist/client/{productList-BCKThwAI.mjs → productList-ZHr6D604.mjs} +3 -3
  136. package/dist/client/{propsDecoder-CkXxkdSR.mjs → propsDecoder-wWN0tBDF.mjs} +2351 -129
  137. package/dist/client/rendering/client.mjs +1664 -1824
  138. package/dist/client/rendering/islands.mjs +20 -20
  139. package/dist/client/rendering.mjs +1697 -1909
  140. package/dist/client/{shop-DeltVH10.mjs → shop-C1u_BUn0.mjs} +5 -6
  141. package/dist/client/{shop-commerce-BD9Jsm2Z.mjs → shop-commerce-CleZdRha.mjs} +5 -6
  142. package/dist/client/{shop-commerce-store-CmXD6FDS.mjs → shop-commerce-store-ycnoB2Ce.mjs} +1 -1
  143. package/dist/client/{shopShared-B8v-lH_F.mjs → shopShared-CPhByt2a.mjs} +3 -3
  144. package/dist/client/{useDiscountCodeUi-DbWJN8ld.mjs → useDiscountCodeUi-cStSQI6C.mjs} +1 -1
  145. package/dist/client/{useEventFilters-EJIMUnqT.mjs → useEventFilters-DKPN7hSY.mjs} +26 -27
  146. package/dist/client/{usePolling-Cmh14fc7.mjs → usePolling-BKAd6pkZ.mjs} +2 -2
  147. package/dist/preview-next/before-render.mjs +37 -6
  148. package/dist/preview-next/client/runtime.mjs +4 -4
  149. package/dist/preview-next/middleware.mjs +37 -6
  150. package/dist/{previewAuthStore-CTO7CRPk.mjs → previewAuthStore-BkT1D06A.mjs} +37 -6
  151. package/dist/{sdk-runtime-Dou0GAav.mjs → sdk-runtime-hu3wr3ng.mjs} +2 -2
  152. package/dist/{separator-CI5wZNXT.mjs → separator-Bln8izQ9.mjs} +1 -1
  153. package/dist/server/components.mjs +1472 -1788
  154. package/dist/server/config-validation.mjs +1559 -1876
  155. package/dist/server/config.mjs +1559 -1876
  156. package/dist/server/data.mjs +1554 -1871
  157. package/dist/server/index.mjs +38 -7
  158. package/dist/server/next/revalidate.mjs +53 -1
  159. package/dist/server/next.mjs +1584 -1869
  160. package/dist/server/page-converter.mjs +1543 -1860
  161. package/dist/server/prebuild.mjs +1 -1
  162. package/dist/server/rendering/server.mjs +1472 -1788
  163. package/dist/server/rendering.mjs +1472 -1788
  164. package/dist/server/routing.mjs +1600 -1891
  165. package/dist/server/server.mjs +1574 -1860
  166. package/dist/server/theme-bridge.mjs +1436 -1619
  167. package/dist/server/theme.mjs +1345 -1241
  168. package/dist/server/webhooks.mjs +54 -2
  169. package/package.json +1 -1
  170. package/dist/_dts/theme-core/src/buttons/personalities/brushed-wash.d.ts +0 -16
  171. package/dist/_dts/theme-core/src/buttons/personalities/confident-chip.d.ts +0 -16
  172. package/dist/_dts/theme-core/src/buttons/personalities/earth-pill.d.ts +0 -16
  173. package/dist/_dts/theme-core/src/buttons/personalities/editorial-link.d.ts +0 -16
  174. package/dist/_dts/theme-core/src/buttons/personalities/flat-ink.d.ts +0 -20
  175. package/dist/_dts/theme-core/src/buttons/personalities/index.d.ts +0 -172
  176. package/dist/_dts/theme-core/src/buttons/personalities/ink-stamp.d.ts +0 -16
  177. package/dist/_dts/theme-core/src/buttons/personalities/joy-stamp.d.ts +0 -22
  178. package/dist/_dts/theme-core/src/buttons/personalities/ornate-ritual.d.ts +0 -16
  179. package/dist/_dts/theme-core/src/buttons/personalities/pebble.d.ts +0 -16
  180. package/dist/_dts/theme-core/src/buttons/personalities/quiet-arrow.d.ts +0 -17
  181. package/dist/_dts/theme-core/src/buttons/personalities/showtime-pill.d.ts +0 -17
  182. package/dist/_dts/theme-core/src/buttons/personalities/soft-pill.d.ts +0 -16
  183. package/dist/_dts/theme-core/src/buttons/personalities/two-tone-pill.d.ts +0 -17
  184. package/dist/_dts/theme-core/src/buttons/personalities/types.d.ts +0 -285
  185. package/dist/client/buttons-DoFV7KDL.mjs +0 -2115
  186. package/dist/client/foregroundContract-xICPq59x.mjs +0 -31
@@ -138,39 +138,6 @@ function parseThemeColorToken(value) {
138
138
  }
139
139
  const themeColorTokenSchema = z$1.string().min(1).refine((value) => Boolean(isThemeColorToken(value)), "Expected a known Theme V2 color token");
140
140
  //#endregion
141
- //#region ../theme-core/src/site-styles/styleTags.ts
142
- /**
143
- * Descriptive style-axis metadata for button personalities and palette
144
- * variants. Site Style picker shape is curated explicitly; these tags remain
145
- * for catalog audit, docs, and future discovery tooling.
146
- */
147
- const STYLE_AXIS_VALUES = {
148
- tone: [
149
- "minimal",
150
- "classic",
151
- "bold"
152
- ],
153
- energy: ["calm", "vibrant"],
154
- motion: [
155
- "subtle",
156
- "standard",
157
- "expressive"
158
- ],
159
- era: [
160
- "editorial",
161
- "modern",
162
- "organic",
163
- "technical",
164
- "retro"
165
- ]
166
- };
167
- const styleTagsSchema = z$1.object({
168
- tone: z$1.enum(STYLE_AXIS_VALUES.tone).optional(),
169
- energy: z$1.enum(STYLE_AXIS_VALUES.energy).optional(),
170
- motion: z$1.enum(STYLE_AXIS_VALUES.motion).optional(),
171
- era: z$1.enum(STYLE_AXIS_VALUES.era).optional()
172
- });
173
- //#endregion
174
141
  //#region ../theme-core/src/lib/media.ts
175
142
  const hotspotSchema = z.object({
176
143
  x: z.number().min(0).max(1),
@@ -511,7 +478,7 @@ const gradientDirectionSchema$1 = z$1.enum([
511
478
  "to-br",
512
479
  "to-bl"
513
480
  ]);
514
- const buttonBackgroundSchema = z$1.discriminatedUnion("type", [
481
+ const buttonColourTreatmentSchema = z$1.discriminatedUnion("type", [
515
482
  z$1.object({
516
483
  type: z$1.literal("solid"),
517
484
  colorToken: opaqueButtonColourTokenSchema
@@ -535,6 +502,7 @@ const buttonBackgroundSchema = z$1.discriminatedUnion("type", [
535
502
  role: z$1.literal("link")
536
503
  })
537
504
  ]);
505
+ const buttonBackgroundSchema = buttonColourTreatmentSchema;
538
506
  const effectApplicationSchema$1 = z$1.object({
539
507
  effectId: z$1.string(),
540
508
  options: z$1.record(z$1.string(), z$1.json()).optional()
@@ -747,265 +715,429 @@ function isUnknownArray(value) {
747
715
  }
748
716
  buttonSizeNameSchema.options;
749
717
  //#endregion
750
- //#region ../theme-core/src/buttons/personalities/types.ts
751
- function asButtonPersonalityId(value) {
752
- if (value.length === 0) throw new Error("ButtonPersonalityId must be a non-empty string");
753
- return value;
718
+ //#region ../theme-core/src/buttons/styles/domain.ts
719
+ const PUBLIC_BUTTON_ROLES = [
720
+ "primary",
721
+ "secondary",
722
+ "outline",
723
+ "ghost",
724
+ "accent"
725
+ ];
726
+ function defineButtonStyleRecipe(recipe) {
727
+ return recipe;
754
728
  }
755
- const buttonPersonalityIdSchema = z$1.string().min(1).transform((value) => asButtonPersonalityId(value));
756
- z$1.object({
757
- id: buttonPersonalityIdSchema,
758
- name: z$1.string().min(1),
759
- description: z$1.string().min(1),
760
- tags: styleTagsSchema,
761
- buttonSystem: buttonSystemSchema
762
- });
763
- /**
764
- * Helper for personality file modules to keep the call site short and
765
- * type-safe. `as const satisfies ...` would also work but produces wider
766
- * types at use sites.
767
- */
768
- function defineButtonPersonality(input) {
729
+ function materializeButtonRoles(definitions) {
730
+ const primary = materializeCompleteRole("primary", definitions.primary.appearance);
731
+ const secondary = materializeCompleteRole("secondary", definitions.secondary.appearance);
732
+ const completeRoles = {
733
+ primary,
734
+ secondary
735
+ };
769
736
  return {
770
- id: asButtonPersonalityId(input.id),
771
- name: input.name,
772
- description: input.description,
773
- tags: input.tags,
774
- buttonSystem: buttonSystemSchema.parse(input.buttonSystem)
737
+ primary,
738
+ secondary,
739
+ outline: materializeSupportingRole("outline", definitions.outline, completeRoles),
740
+ ghost: materializeSupportingRole("ghost", definitions.ghost, completeRoles),
741
+ accent: materializeSupportingRole("accent", definitions.accent, completeRoles)
742
+ };
743
+ }
744
+ function resolveButtonStyleRecipe(recipe, parameters) {
745
+ const parsedParameters = recipe.parameterSchema.safeParse(parameters);
746
+ if (!parsedParameters.success) return {
747
+ kind: "error",
748
+ error: {
749
+ kind: "invalid-parameters",
750
+ styleId: recipe.id,
751
+ issues: parsedParameters.error.issues.map((issue) => issue.message)
752
+ }
753
+ };
754
+ const definition = recipe.defineSystem(parsedParameters.data);
755
+ const roles = materializeButtonRoles(definition.roles);
756
+ const buttonSystem = {
757
+ global: definition.global,
758
+ variants: PUBLIC_BUTTON_ROLES.map((role) => roles[role]),
759
+ ...definition.sizes ? { sizes: definition.sizes } : {}
760
+ };
761
+ const parsedButtonSystem = buttonSystemSchema.safeParse(buttonSystem);
762
+ if (!parsedButtonSystem.success) return {
763
+ kind: "error",
764
+ error: {
765
+ kind: "invalid-button-system",
766
+ styleId: recipe.id,
767
+ issues: parsedButtonSystem.error.issues.map((issue) => issue.message)
768
+ }
769
+ };
770
+ return {
771
+ kind: "resolved",
772
+ buttonSystem: parsedButtonSystem.data
773
+ };
774
+ }
775
+ function materializeSupportingRole(role, definition, completeRoles) {
776
+ if (definition.kind === "complete") return materializeCompleteRole(role, definition.appearance);
777
+ return {
778
+ ...completeRoles[definition.from],
779
+ ...definition.overrides,
780
+ id: role,
781
+ name: roleName(role),
782
+ enabled: true,
783
+ priority: 3
775
784
  };
776
785
  }
786
+ function materializeCompleteRole(role, appearance) {
787
+ return {
788
+ ...appearance,
789
+ id: role,
790
+ name: roleName(role),
791
+ enabled: true,
792
+ priority: rolePriority(role)
793
+ };
794
+ }
795
+ function roleName(role) {
796
+ return role.charAt(0).toUpperCase() + role.slice(1);
797
+ }
798
+ function rolePriority(role) {
799
+ if (role === "primary") return 1;
800
+ if (role === "secondary") return 2;
801
+ return 3;
802
+ }
777
803
  //#endregion
778
- //#region ../theme-core/src/buttons/personalities/brushed-wash.ts
779
- /**
780
- * Brushed Wash — gradient backgrounds that read as watercolour washes.
781
- * Generous padding, soft shadows; pairs with vibrant organic brands.
782
- */
783
- const brushedWash = defineButtonPersonality({
784
- id: "brushed-wash",
785
- name: "Brushed Wash",
786
- description: "Watercolour-gradient buttons with soft shadows and generous padding.",
804
+ //#region ../theme-core/src/buttons/styles/selection.ts
805
+ const BUTTON_STYLE_IDS = [
806
+ "soft-pill",
807
+ "earth-pill",
808
+ "confident-chip",
809
+ "editorial-link",
810
+ "pebble",
811
+ "ink-stamp",
812
+ "flat-ink",
813
+ "brushed-wash",
814
+ "showtime-pill",
815
+ "joy-stamp",
816
+ "ornate-ritual",
817
+ "quiet-arrow"
818
+ ];
819
+ const quietArrowParametersSchema = z$1.object({ secondaryTreatment: z$1.enum(["outlined", "solid-accent"]) }).strict();
820
+ const emptyParametersSchema$1 = z$1.object({}).strict();
821
+ function selectionBranch(styleId, parameters) {
822
+ return z$1.object({
823
+ styleId: z$1.literal(styleId),
824
+ parameters
825
+ }).strict();
826
+ }
827
+ z$1.discriminatedUnion("styleId", [
828
+ selectionBranch("soft-pill", emptyParametersSchema$1),
829
+ selectionBranch("earth-pill", emptyParametersSchema$1),
830
+ selectionBranch("confident-chip", emptyParametersSchema$1),
831
+ selectionBranch("editorial-link", emptyParametersSchema$1),
832
+ selectionBranch("pebble", emptyParametersSchema$1),
833
+ selectionBranch("ink-stamp", emptyParametersSchema$1),
834
+ selectionBranch("flat-ink", emptyParametersSchema$1),
835
+ selectionBranch("brushed-wash", emptyParametersSchema$1),
836
+ selectionBranch("showtime-pill", emptyParametersSchema$1),
837
+ selectionBranch("joy-stamp", emptyParametersSchema$1),
838
+ selectionBranch("ornate-ritual", emptyParametersSchema$1),
839
+ selectionBranch("quiet-arrow", quietArrowParametersSchema)
840
+ ]);
841
+ //#endregion
842
+ //#region ../theme-core/src/buttons/styles/recipes/quietArrow.ts
843
+ const quietArrowRecipe = defineButtonStyleRecipe({
844
+ id: "quiet-arrow",
845
+ accessibilityLabel: "Wide uppercase buttons with trailing arrows",
787
846
  tags: {
788
847
  tone: "classic",
789
- energy: "vibrant",
790
- motion: "standard",
791
- era: "organic"
848
+ energy: "calm",
849
+ motion: "subtle",
850
+ era: "editorial"
792
851
  },
793
- buttonSystem: {
852
+ parameterSchema: quietArrowParametersSchema,
853
+ defaultParameters: { secondaryTreatment: "outlined" },
854
+ controls: [{
855
+ kind: "choice",
856
+ parameter: "secondaryTreatment",
857
+ label: "Secondary button treatment",
858
+ options: [{
859
+ value: "outlined",
860
+ label: "Outlined"
861
+ }, {
862
+ value: "solid-accent",
863
+ label: "Solid accent"
864
+ }]
865
+ }],
866
+ defineSystem: (parameters) => ({
794
867
  global: {
795
868
  cornerStyle: "rounded",
796
- shadow: "low",
797
- textTransform: "none",
869
+ textTransform: "uppercase",
798
870
  fontWeight: 500,
799
871
  borderWidth: 1,
872
+ typography: "body",
873
+ fontSize: "text-sm",
874
+ letterSpacing: "loose",
800
875
  hoverTransform: "none",
801
876
  hoverColor: "none"
802
877
  },
803
878
  sizes: {
804
879
  sm: {
805
- padding: "0.75rem 2rem",
880
+ padding: "0.625rem 1.25rem",
881
+ fontSize: "text-xs"
882
+ },
883
+ md: {
884
+ padding: "0.8125rem 1.75rem",
806
885
  fontSize: "text-sm"
807
886
  },
808
- md: { padding: "1rem 2.5rem" },
809
887
  lg: {
810
- padding: "1.25rem 3rem",
811
- fontSize: "text-lg"
888
+ padding: "0.9375rem 2.125rem",
889
+ fontSize: "text-sm"
812
890
  },
813
891
  xl: {
814
- padding: "1.625rem 3.75rem",
815
- fontSize: "text-xl"
892
+ padding: "1.0625rem 2.5rem",
893
+ fontSize: "text-base"
816
894
  }
817
895
  },
818
- variants: [
819
- {
820
- id: "primary",
821
- name: "Primary",
822
- enabled: true,
823
- priority: 1,
824
- background: {
825
- type: "gradient",
826
- stops: ["primary", "accent"],
827
- direction: "to-r",
828
- foregroundToken: "primaryForeground"
829
- },
830
- borderRadius: "rounded-lg",
831
- shadow: {
832
- elevation: "low",
833
- softness: "soft",
834
- position: "bottom"
896
+ roles: {
897
+ primary: {
898
+ kind: "complete",
899
+ appearance: {
900
+ background: {
901
+ type: "solid",
902
+ colorToken: unsafeAsOpaqueButtonColourToken("primary")
903
+ },
904
+ borderRadius: "rounded-xl",
905
+ affordance: { iconId: "ArrowRight" },
906
+ effects: { hover: [{
907
+ effectId: "darken-background",
908
+ options: { amount: 100 }
909
+ }] }
910
+ }
911
+ },
912
+ secondary: {
913
+ kind: "complete",
914
+ appearance: parameters.secondaryTreatment === "solid-accent" ? {
915
+ background: {
916
+ type: "solid",
917
+ colorToken: unsafeAsOpaqueButtonColourToken("accent")
918
+ },
919
+ borderRadius: "rounded-xl",
920
+ affordance: { iconId: "ArrowRight" },
921
+ effects: { hover: [{
922
+ effectId: "darken-background",
923
+ options: { amount: 100 }
924
+ }] }
925
+ } : {
926
+ background: {
927
+ type: "surface",
928
+ role: "link"
929
+ },
930
+ borderRadius: "rounded-xl",
931
+ border: { widthClass: "border" },
932
+ affordance: { iconId: "ArrowRight" },
933
+ effects: { hover: [{
934
+ effectId: "background-on-hover",
935
+ options: { colorToken: "surfaceAlt" }
936
+ }] }
835
937
  }
836
938
  },
837
- {
838
- id: "secondary",
839
- name: "Secondary",
840
- enabled: true,
841
- priority: 2,
842
- background: {
843
- type: "gradient",
844
- stops: ["secondary", "accent"],
845
- direction: "to-br",
846
- foregroundToken: "primaryForeground"
847
- },
848
- borderRadius: "rounded-lg",
849
- shadow: {
850
- elevation: "low",
851
- softness: "soft",
852
- position: "bottom"
939
+ outline: {
940
+ kind: "complete",
941
+ appearance: {
942
+ background: {
943
+ type: "surface",
944
+ role: "link"
945
+ },
946
+ borderRadius: "rounded-xl",
947
+ border: { widthClass: "border" }
853
948
  }
854
949
  },
855
- {
856
- id: "outline",
857
- name: "Outline",
858
- enabled: true,
859
- priority: 3,
860
- background: {
861
- type: "surface",
862
- role: "link"
863
- },
864
- borderRadius: "rounded-lg",
865
- border: { widthClass: "border" },
866
- effects: { hover: [{
867
- effectId: "background-on-hover",
868
- options: { colorToken: "surface" }
869
- }] }
950
+ ghost: {
951
+ kind: "complete",
952
+ appearance: {
953
+ background: {
954
+ type: "surface",
955
+ role: "link"
956
+ },
957
+ borderRadius: "rounded-xl"
958
+ }
870
959
  },
871
- {
872
- id: "ghost",
873
- name: "Ghost",
874
- enabled: true,
875
- priority: 3,
876
- background: {
877
- type: "surface",
878
- role: "link"
879
- },
880
- borderRadius: "rounded-lg",
881
- effects: { hover: [{
882
- effectId: "background-on-hover",
883
- options: { colorToken: "surface" }
884
- }] }
960
+ accent: {
961
+ kind: "derive",
962
+ from: "primary",
963
+ overrides: { background: {
964
+ type: "solid",
965
+ colorToken: unsafeAsOpaqueButtonColourToken("accent")
966
+ } }
885
967
  }
886
- ]
887
- }
968
+ }
969
+ })
888
970
  });
889
971
  //#endregion
890
- //#region ../theme-core/src/buttons/personalities/confident-chip.ts
891
- /**
892
- * Confident Chip — moderate-radius solid buttons that read as competent and
893
- * direct. Default for Clear Professional; works for any modern brand voice.
894
- */
895
- const confidentChip = defineButtonPersonality({
896
- id: "confident-chip",
897
- name: "Confident Chip",
898
- description: "Mid-radius solid buttons with a crisp hover.",
972
+ //#region ../theme-core/src/buttons/styles/recipes/defineStaticButtonStyleRecipe.ts
973
+ const emptyParametersSchema = z$1.object({}).strict();
974
+ function defineStaticButtonStyleRecipe(input) {
975
+ const system = normalizeSystem(input.system);
976
+ return defineButtonStyleRecipe({
977
+ id: input.id,
978
+ accessibilityLabel: input.accessibilityLabel,
979
+ tags: input.tags,
980
+ parameterSchema: emptyParametersSchema,
981
+ defaultParameters: {},
982
+ controls: [],
983
+ defineSystem: () => system
984
+ });
985
+ }
986
+ function normalizeSystem(input) {
987
+ return {
988
+ global: buttonGlobalSettingsSchema.parse(input.global),
989
+ ...input.sizes ? { sizes: input.sizes } : {},
990
+ roles: {
991
+ primary: normalizeCompleteRole(input.roles.primary),
992
+ secondary: normalizeCompleteRole(input.roles.secondary),
993
+ outline: normalizeSupportingRole(input.roles.outline),
994
+ ghost: normalizeSupportingRole(input.roles.ghost),
995
+ accent: normalizeSupportingRole(input.roles.accent)
996
+ }
997
+ };
998
+ }
999
+ function normalizeCompleteRole(role) {
1000
+ return {
1001
+ kind: "complete",
1002
+ appearance: normalizeAppearance(role.appearance)
1003
+ };
1004
+ }
1005
+ function normalizeSupportingRole(role) {
1006
+ if (role.kind === "complete") return normalizeCompleteRole(role);
1007
+ return {
1008
+ kind: "derive",
1009
+ from: role.from,
1010
+ ...role.overrides ? { overrides: normalizeAppearanceOverrides(role.overrides) } : {}
1011
+ };
1012
+ }
1013
+ function normalizeAppearance(appearance) {
1014
+ const { background, hoverBackgroundToken, ...rest } = appearance;
1015
+ return {
1016
+ ...rest,
1017
+ background: buttonColourTreatmentSchema.parse(background),
1018
+ ...hoverBackgroundToken ? { hoverBackgroundToken: opaqueButtonColourTokenSchema.parse(hoverBackgroundToken) } : {}
1019
+ };
1020
+ }
1021
+ function normalizeAppearanceOverrides(overrides) {
1022
+ const { background, hoverBackgroundToken, ...rest } = overrides;
1023
+ return {
1024
+ ...rest,
1025
+ ...background ? { background: buttonColourTreatmentSchema.parse(background) } : {},
1026
+ ...hoverBackgroundToken ? { hoverBackgroundToken: opaqueButtonColourTokenSchema.parse(hoverBackgroundToken) } : {}
1027
+ };
1028
+ }
1029
+ //#endregion
1030
+ //#region ../theme-core/src/buttons/styles/recipes/staticRecipes.ts
1031
+ const softPillRecipe = defineStaticButtonStyleRecipe({
1032
+ id: "soft-pill",
1033
+ accessibilityLabel: "Rounded pill buttons with a gentle hover lift",
899
1034
  tags: {
900
1035
  tone: "classic",
901
1036
  energy: "calm",
902
- motion: "standard",
903
- era: "modern"
1037
+ motion: "subtle",
1038
+ era: "organic"
904
1039
  },
905
- buttonSystem: {
1040
+ system: {
906
1041
  global: {
907
- cornerStyle: "rounded",
908
- shadow: "medium",
1042
+ cornerStyle: "pill",
1043
+ shadow: "low",
909
1044
  textTransform: "none",
910
- fontWeight: 600,
911
- borderWidth: 1,
912
- hoverTransform: "none",
1045
+ fontWeight: 500,
1046
+ borderWidth: 2,
1047
+ hoverTransform: "lift",
913
1048
  hoverColor: "none"
914
1049
  },
915
- variants: [
916
- {
917
- id: "primary",
918
- name: "Primary",
919
- enabled: true,
920
- priority: 1,
921
- background: {
922
- type: "solid",
923
- colorToken: "primary"
924
- },
925
- borderRadius: "rounded-md",
926
- shadow: {
927
- elevation: "medium",
928
- softness: "soft",
929
- position: "bottom"
930
- },
931
- effects: {
932
- hover: [{
933
- effectId: "darken-background",
934
- options: { amount: 100 }
935
- }],
936
- active: [{
937
- effectId: "scale-down",
938
- options: { scale: "0.97" }
939
- }]
1050
+ roles: {
1051
+ primary: {
1052
+ kind: "complete",
1053
+ appearance: {
1054
+ background: {
1055
+ type: "solid",
1056
+ colorToken: "primary"
1057
+ },
1058
+ borderRadius: "rounded-full",
1059
+ shadow: {
1060
+ elevation: "low",
1061
+ softness: "soft",
1062
+ position: "bottom"
1063
+ },
1064
+ effects: {
1065
+ hover: [{
1066
+ effectId: "lift",
1067
+ options: { translateY: "-1px" }
1068
+ }],
1069
+ active: [{
1070
+ effectId: "scale-down",
1071
+ options: { scale: "0.98" }
1072
+ }]
1073
+ }
940
1074
  }
941
1075
  },
942
- {
943
- id: "secondary",
944
- name: "Secondary",
945
- enabled: true,
946
- priority: 2,
947
- background: {
948
- type: "solid",
949
- colorToken: "surface"
950
- },
951
- borderRadius: "rounded-md",
952
- border: { widthClass: "border" },
953
- effects: { hover: [{
954
- effectId: "background-on-hover",
955
- options: { colorToken: "background" }
956
- }] }
1076
+ secondary: {
1077
+ kind: "complete",
1078
+ appearance: {
1079
+ background: {
1080
+ type: "surface",
1081
+ role: "link"
1082
+ },
1083
+ borderRadius: "rounded-full",
1084
+ border: { widthClass: "border-2" },
1085
+ effects: { hover: [{
1086
+ effectId: "background-on-hover",
1087
+ options: { colorToken: "surface" }
1088
+ }] }
1089
+ }
1090
+ },
1091
+ outline: {
1092
+ kind: "complete",
1093
+ appearance: {
1094
+ background: {
1095
+ type: "surface",
1096
+ role: "link"
1097
+ },
1098
+ borderRadius: "rounded-full",
1099
+ border: { widthClass: "border" },
1100
+ effects: { hover: [{
1101
+ effectId: "background-on-hover",
1102
+ options: { colorToken: "surface" }
1103
+ }] }
1104
+ }
957
1105
  },
958
- {
959
- id: "outline",
960
- name: "Outline",
961
- enabled: true,
962
- priority: 3,
963
- background: {
964
- type: "surface",
965
- role: "link"
966
- },
967
- borderRadius: "rounded-md",
968
- border: { widthClass: "border" },
969
- effects: { hover: [{
970
- effectId: "background-on-hover",
971
- options: { colorToken: "surface" }
972
- }] }
1106
+ ghost: {
1107
+ kind: "complete",
1108
+ appearance: {
1109
+ background: {
1110
+ type: "surface",
1111
+ role: "link"
1112
+ },
1113
+ borderRadius: "rounded-full",
1114
+ effects: { hover: [{
1115
+ effectId: "background-on-hover",
1116
+ options: { colorToken: "surface" }
1117
+ }] }
1118
+ }
973
1119
  },
974
- {
975
- id: "ghost",
976
- name: "Ghost",
977
- enabled: true,
978
- priority: 3,
979
- background: {
980
- type: "surface",
981
- role: "link"
982
- },
983
- borderRadius: "rounded-md",
984
- effects: { hover: [{
985
- effectId: "background-on-hover",
986
- options: { colorToken: "surface" }
987
- }] }
1120
+ accent: {
1121
+ kind: "derive",
1122
+ from: "primary",
1123
+ overrides: { background: {
1124
+ type: "solid",
1125
+ colorToken: "accent"
1126
+ } }
988
1127
  }
989
- ]
1128
+ }
990
1129
  }
991
1130
  });
992
- //#endregion
993
- //#region ../theme-core/src/buttons/personalities/earth-pill.ts
994
- /**
995
- * Earth Pill - warm studio pills with compact, primary-coloured ghost CTAs.
996
- * Built for grounded editorial wellness styles such as Soft Earth.
997
- */
998
- const earthPill = defineButtonPersonality({
1131
+ const earthPillRecipe = defineStaticButtonStyleRecipe({
999
1132
  id: "earth-pill",
1000
- name: "Earth Pill",
1001
- description: "Compact terracotta pills with quiet primary-coloured ghost CTAs.",
1133
+ accessibilityLabel: "Compact rounded buttons with a quiet hover lift",
1002
1134
  tags: {
1003
1135
  tone: "classic",
1004
1136
  energy: "calm",
1005
1137
  motion: "subtle",
1006
1138
  era: "organic"
1007
1139
  },
1008
- buttonSystem: {
1140
+ system: {
1009
1141
  global: {
1010
1142
  cornerStyle: "pill",
1011
1143
  shadow: "low",
@@ -1032,119 +1164,222 @@ const earthPill = defineButtonPersonality({
1032
1164
  fontSize: "text-xl"
1033
1165
  }
1034
1166
  },
1035
- variants: [
1036
- {
1037
- id: "primary",
1038
- name: "Primary",
1039
- enabled: true,
1040
- priority: 1,
1041
- background: {
1042
- type: "solid",
1043
- colorToken: "primary"
1044
- },
1045
- borderRadius: "rounded-full",
1046
- shadow: {
1047
- elevation: "low",
1048
- softness: "soft",
1049
- position: "bottom"
1050
- },
1051
- effects: {
1052
- hover: [{
1053
- effectId: "lift",
1054
- options: { translateY: "-1px" }
1055
- }, {
1167
+ roles: {
1168
+ primary: {
1169
+ kind: "complete",
1170
+ appearance: {
1171
+ background: {
1172
+ type: "solid",
1173
+ colorToken: "primary"
1174
+ },
1175
+ borderRadius: "rounded-full",
1176
+ shadow: {
1177
+ elevation: "low",
1178
+ softness: "soft",
1179
+ position: "bottom"
1180
+ },
1181
+ effects: {
1182
+ hover: [{
1183
+ effectId: "lift",
1184
+ options: { translateY: "-1px" }
1185
+ }, {
1186
+ effectId: "background-on-hover",
1187
+ options: { colorToken: "accent" }
1188
+ }],
1189
+ active: [{
1190
+ effectId: "scale-down",
1191
+ options: { scale: "0.98" }
1192
+ }]
1193
+ }
1194
+ }
1195
+ },
1196
+ secondary: {
1197
+ kind: "complete",
1198
+ appearance: {
1199
+ background: {
1200
+ type: "surface",
1201
+ role: "link"
1202
+ },
1203
+ borderRadius: "rounded-full",
1204
+ border: { widthClass: "border" },
1205
+ effects: { hover: [{
1056
1206
  effectId: "background-on-hover",
1057
- options: { colorToken: "accent" }
1058
- }],
1059
- active: [{
1060
- effectId: "scale-down",
1061
- options: { scale: "0.98" }
1062
- }]
1207
+ options: { colorToken: "muted" }
1208
+ }] }
1063
1209
  }
1064
1210
  },
1065
- {
1066
- id: "secondary",
1067
- name: "Secondary",
1068
- enabled: true,
1069
- priority: 2,
1070
- background: {
1071
- type: "surface",
1072
- role: "link"
1073
- },
1074
- borderRadius: "rounded-full",
1075
- border: { widthClass: "border" },
1076
- effects: { hover: [{
1077
- effectId: "background-on-hover",
1078
- options: { colorToken: "muted" }
1079
- }] }
1211
+ outline: {
1212
+ kind: "complete",
1213
+ appearance: {
1214
+ background: {
1215
+ type: "surface",
1216
+ role: "link"
1217
+ },
1218
+ borderRadius: "rounded-full",
1219
+ border: { widthClass: "border" },
1220
+ effects: { hover: [{
1221
+ effectId: "background-on-hover",
1222
+ options: { colorToken: "surfaceAlt" }
1223
+ }] }
1224
+ }
1080
1225
  },
1081
- {
1082
- id: "outline",
1083
- name: "Outline",
1084
- enabled: true,
1085
- priority: 3,
1086
- background: {
1087
- type: "surface",
1088
- role: "link"
1089
- },
1090
- borderRadius: "rounded-full",
1091
- border: { widthClass: "border" },
1092
- effects: { hover: [{
1093
- effectId: "background-on-hover",
1094
- options: { colorToken: "surfaceAlt" }
1095
- }] }
1226
+ ghost: {
1227
+ kind: "complete",
1228
+ appearance: {
1229
+ background: {
1230
+ type: "surface",
1231
+ role: "link"
1232
+ },
1233
+ borderRadius: "rounded-full",
1234
+ shadow: {
1235
+ elevation: "none",
1236
+ softness: null,
1237
+ position: "bottom"
1238
+ },
1239
+ sizes: {
1240
+ sm: {
1241
+ padding: "0.25rem 0",
1242
+ fontSize: "text-sm"
1243
+ },
1244
+ md: { padding: "0.375rem 0" },
1245
+ lg: {
1246
+ padding: "0.5rem 0",
1247
+ fontSize: "text-lg"
1248
+ },
1249
+ xl: {
1250
+ padding: "0.625rem 0",
1251
+ fontSize: "text-xl"
1252
+ }
1253
+ }
1254
+ }
1096
1255
  },
1097
- {
1098
- id: "ghost",
1099
- name: "Ghost",
1100
- enabled: true,
1101
- priority: 3,
1102
- background: {
1103
- type: "surface",
1104
- role: "link"
1105
- },
1106
- borderRadius: "rounded-full",
1107
- shadow: {
1108
- elevation: "none",
1109
- softness: null,
1110
- position: "bottom"
1111
- },
1112
- sizes: {
1113
- sm: {
1114
- padding: "0.25rem 0",
1115
- fontSize: "text-sm"
1256
+ accent: {
1257
+ kind: "derive",
1258
+ from: "primary",
1259
+ overrides: { background: {
1260
+ type: "solid",
1261
+ colorToken: "accent"
1262
+ } }
1263
+ }
1264
+ }
1265
+ }
1266
+ });
1267
+ const confidentChipRecipe = defineStaticButtonStyleRecipe({
1268
+ id: "confident-chip",
1269
+ accessibilityLabel: "Moderately rounded solid buttons with a crisp hover",
1270
+ tags: {
1271
+ tone: "classic",
1272
+ energy: "calm",
1273
+ motion: "standard",
1274
+ era: "modern"
1275
+ },
1276
+ system: {
1277
+ global: {
1278
+ cornerStyle: "rounded",
1279
+ shadow: "medium",
1280
+ textTransform: "none",
1281
+ fontWeight: 600,
1282
+ borderWidth: 1,
1283
+ hoverTransform: "none",
1284
+ hoverColor: "none"
1285
+ },
1286
+ roles: {
1287
+ primary: {
1288
+ kind: "complete",
1289
+ appearance: {
1290
+ background: {
1291
+ type: "solid",
1292
+ colorToken: "primary"
1116
1293
  },
1117
- md: { padding: "0.375rem 0" },
1118
- lg: {
1119
- padding: "0.5rem 0",
1120
- fontSize: "text-lg"
1294
+ borderRadius: "rounded-md",
1295
+ shadow: {
1296
+ elevation: "medium",
1297
+ softness: "soft",
1298
+ position: "bottom"
1121
1299
  },
1122
- xl: {
1123
- padding: "0.625rem 0",
1124
- fontSize: "text-xl"
1300
+ effects: {
1301
+ hover: [{
1302
+ effectId: "darken-background",
1303
+ options: { amount: 100 }
1304
+ }],
1305
+ active: [{
1306
+ effectId: "scale-down",
1307
+ options: { scale: "0.97" }
1308
+ }]
1125
1309
  }
1126
1310
  }
1311
+ },
1312
+ secondary: {
1313
+ kind: "complete",
1314
+ appearance: {
1315
+ background: {
1316
+ type: "solid",
1317
+ colorToken: "surface"
1318
+ },
1319
+ borderRadius: "rounded-md",
1320
+ border: { widthClass: "border" },
1321
+ effects: { hover: [{
1322
+ effectId: "background-on-hover",
1323
+ options: { colorToken: "background" }
1324
+ }] }
1325
+ }
1326
+ },
1327
+ outline: {
1328
+ kind: "complete",
1329
+ appearance: {
1330
+ background: {
1331
+ type: "surface",
1332
+ role: "link"
1333
+ },
1334
+ borderRadius: "rounded-md",
1335
+ border: { widthClass: "border" },
1336
+ effects: { hover: [{
1337
+ effectId: "background-on-hover",
1338
+ options: { colorToken: "surface" }
1339
+ }] }
1340
+ }
1341
+ },
1342
+ ghost: {
1343
+ kind: "complete",
1344
+ appearance: {
1345
+ background: {
1346
+ type: "surface",
1347
+ role: "link"
1348
+ },
1349
+ borderRadius: "rounded-md",
1350
+ effects: { hover: [{
1351
+ effectId: "background-on-hover",
1352
+ options: { colorToken: "surface" }
1353
+ }] }
1354
+ }
1355
+ },
1356
+ accent: {
1357
+ kind: "derive",
1358
+ from: "primary",
1359
+ overrides: { background: {
1360
+ type: "solid",
1361
+ colorToken: "accent"
1362
+ } }
1127
1363
  }
1128
- ]
1364
+ }
1129
1365
  }
1130
1366
  });
1131
- //#endregion
1132
- //#region ../theme-core/src/buttons/personalities/editorial-link.ts
1133
- /**
1134
- * Editorial Link — all variants are link-style with a growing underline.
1135
- * Default for Warm Editorial and Quiet Luxury; reads as refined and quiet.
1136
- */
1137
- const editorialLink = defineButtonPersonality({
1367
+ const editorialSizes = {
1368
+ sm: { padding: "0.25rem 0" },
1369
+ md: { padding: "0.5rem 0" },
1370
+ lg: { padding: "0.625rem 0" },
1371
+ xl: { padding: "0.75rem 0" }
1372
+ };
1373
+ const editorialLinkRecipe = defineStaticButtonStyleRecipe({
1138
1374
  id: "editorial-link",
1139
- name: "Editorial Link",
1140
- description: "Link-style with a growing underline. Refined, typographic.",
1375
+ accessibilityLabel: "Flat typographic buttons with an underline treatment",
1141
1376
  tags: {
1142
1377
  tone: "minimal",
1143
1378
  energy: "calm",
1144
1379
  motion: "subtle",
1145
1380
  era: "editorial"
1146
1381
  },
1147
- buttonSystem: {
1382
+ system: {
1148
1383
  global: {
1149
1384
  cornerStyle: "square",
1150
1385
  textTransform: "none",
@@ -1153,455 +1388,323 @@ const editorialLink = defineButtonPersonality({
1153
1388
  hoverTransform: "none",
1154
1389
  hoverColor: "none"
1155
1390
  },
1156
- variants: [
1157
- {
1158
- id: "primary",
1159
- name: "Primary",
1160
- enabled: true,
1161
- priority: 1,
1162
- background: {
1163
- type: "surface",
1164
- role: "link"
1165
- },
1166
- borderRadius: "rounded-none",
1167
- sizes: {
1168
- sm: { padding: "0.25rem 0" },
1169
- md: { padding: "0.5rem 0" },
1170
- lg: { padding: "0.625rem 0" },
1171
- xl: { padding: "0.75rem 0" }
1172
- },
1173
- effects: { base: [{
1174
- effectId: "border-bottom-grow",
1175
- options: {
1176
- height: 2,
1177
- colorToken: "text",
1178
- origin: "left"
1179
- }
1180
- }] }
1391
+ roles: {
1392
+ primary: {
1393
+ kind: "complete",
1394
+ appearance: {
1395
+ background: {
1396
+ type: "surface",
1397
+ role: "link"
1398
+ },
1399
+ borderRadius: "rounded-none",
1400
+ sizes: editorialSizes,
1401
+ effects: { base: [{
1402
+ effectId: "border-bottom-grow",
1403
+ options: {
1404
+ height: 2,
1405
+ colorToken: "text",
1406
+ origin: "left"
1407
+ }
1408
+ }] }
1409
+ }
1181
1410
  },
1182
- {
1183
- id: "secondary",
1184
- name: "Secondary",
1185
- enabled: true,
1186
- priority: 2,
1187
- background: {
1188
- type: "surface",
1189
- role: "link"
1190
- },
1191
- borderRadius: "rounded-none",
1192
- sizes: {
1193
- sm: { padding: "0.25rem 0" },
1194
- md: { padding: "0.5rem 0" },
1195
- lg: { padding: "0.625rem 0" },
1196
- xl: { padding: "0.75rem 0" }
1197
- },
1198
- effects: { base: [{
1199
- effectId: "border-bottom-grow",
1200
- options: {
1201
- height: 1,
1202
- colorToken: "mutedText",
1203
- origin: "left"
1204
- }
1205
- }] }
1411
+ secondary: {
1412
+ kind: "complete",
1413
+ appearance: {
1414
+ background: {
1415
+ type: "surface",
1416
+ role: "link"
1417
+ },
1418
+ borderRadius: "rounded-none",
1419
+ sizes: editorialSizes,
1420
+ effects: { base: [{
1421
+ effectId: "border-bottom-grow",
1422
+ options: {
1423
+ height: 1,
1424
+ colorToken: "mutedText",
1425
+ origin: "left"
1426
+ }
1427
+ }] }
1428
+ }
1429
+ },
1430
+ outline: {
1431
+ kind: "complete",
1432
+ appearance: {
1433
+ background: {
1434
+ type: "surface",
1435
+ role: "link"
1436
+ },
1437
+ borderRadius: "rounded-none",
1438
+ sizes: editorialSizes,
1439
+ effects: { base: [{
1440
+ effectId: "border-bottom-grow",
1441
+ options: {
1442
+ height: 1,
1443
+ colorToken: "accent",
1444
+ origin: "left"
1445
+ }
1446
+ }] }
1447
+ }
1448
+ },
1449
+ ghost: {
1450
+ kind: "complete",
1451
+ appearance: {
1452
+ background: {
1453
+ type: "surface",
1454
+ role: "link"
1455
+ },
1456
+ borderRadius: "rounded-none",
1457
+ sizes: editorialSizes
1458
+ }
1206
1459
  },
1207
- {
1208
- id: "outline",
1209
- name: "Outline",
1210
- enabled: true,
1211
- priority: 3,
1212
- background: {
1213
- type: "surface",
1214
- role: "link"
1215
- },
1216
- borderRadius: "rounded-none",
1217
- sizes: {
1218
- sm: { padding: "0.25rem 0" },
1219
- md: { padding: "0.5rem 0" },
1220
- lg: { padding: "0.625rem 0" },
1221
- xl: { padding: "0.75rem 0" }
1222
- },
1223
- effects: { base: [{
1460
+ accent: {
1461
+ kind: "derive",
1462
+ from: "primary",
1463
+ overrides: { effects: { base: [{
1224
1464
  effectId: "border-bottom-grow",
1225
1465
  options: {
1226
- height: 1,
1466
+ height: 2,
1227
1467
  colorToken: "accent",
1228
1468
  origin: "left"
1229
1469
  }
1230
- }] }
1231
- },
1232
- {
1233
- id: "ghost",
1234
- name: "Ghost",
1235
- enabled: true,
1236
- priority: 3,
1237
- background: {
1238
- type: "surface",
1239
- role: "link"
1240
- },
1241
- borderRadius: "rounded-none",
1242
- sizes: {
1243
- sm: { padding: "0.25rem 0" },
1244
- md: { padding: "0.5rem 0" },
1245
- lg: { padding: "0.625rem 0" },
1246
- xl: { padding: "0.75rem 0" }
1247
- }
1470
+ }] } }
1248
1471
  }
1249
- ]
1472
+ }
1250
1473
  }
1251
1474
  });
1252
- //#endregion
1253
- //#region ../theme-core/src/buttons/personalities/flat-ink.ts
1254
- /**
1255
- * Flat Ink — a solid ink primary, a hairline ghost secondary, and a single
1256
- * amber accent climax, all completely flat (no drop shadow) with a modest
1257
- * radius. Reads as grounded, editorial and clinician-precise: the Fulcrum
1258
- * physiotherapy voice. The primary shifts to the secondary (moss) on hover and
1259
- * every variant lifts 2px; the amber accent is meant to be used sparingly as
1260
- * the page's one conversion climax.
1261
- */
1262
- const flatInk = defineButtonPersonality({
1263
- id: "flat-ink",
1264
- name: "Flat Ink",
1265
- description: "Flat solid-ink primary, hairline ghost secondary, and a single amber accent climax — modest radius, no shadow.",
1475
+ const pebbleRecipe = defineStaticButtonStyleRecipe({
1476
+ id: "pebble",
1477
+ accessibilityLabel: "Generously padded pill buttons",
1266
1478
  tags: {
1267
1479
  tone: "classic",
1268
1480
  energy: "calm",
1269
- motion: "subtle",
1270
- era: "editorial"
1481
+ motion: "standard",
1482
+ era: "organic"
1271
1483
  },
1272
- buttonSystem: {
1484
+ system: {
1273
1485
  global: {
1274
- cornerStyle: "rounded",
1486
+ cornerStyle: "pill",
1275
1487
  textTransform: "none",
1276
- fontWeight: 600,
1277
- borderWidth: 1,
1278
- typography: "body",
1279
- letterSpacing: "tight",
1280
- paddingPreset: "default",
1281
- hoverTransform: "lift",
1488
+ fontWeight: 500,
1489
+ borderWidth: 2,
1490
+ hoverTransform: "none",
1282
1491
  hoverColor: "none"
1283
1492
  },
1284
1493
  sizes: {
1285
1494
  sm: {
1286
- padding: "0.625rem 1.125rem",
1495
+ padding: "0.625rem 1.75rem",
1287
1496
  fontSize: "text-sm"
1288
1497
  },
1289
- md: { padding: "0.8125rem 1.375rem" },
1498
+ md: { padding: "0.875rem 2.25rem" },
1290
1499
  lg: {
1291
- padding: "0.9375rem 1.625rem",
1500
+ padding: "1.125rem 2.75rem",
1292
1501
  fontSize: "text-lg"
1293
1502
  },
1294
1503
  xl: {
1295
- padding: "1.0625rem 2rem",
1504
+ padding: "1.5rem 3.5rem",
1296
1505
  fontSize: "text-xl"
1297
1506
  }
1298
1507
  },
1299
- variants: [
1300
- {
1301
- id: "primary",
1302
- name: "Primary",
1303
- enabled: true,
1304
- priority: 1,
1305
- background: {
1306
- type: "solid",
1307
- colorToken: "primary"
1308
- },
1309
- borderRadius: "rounded-lg",
1310
- affordance: { iconId: "ArrowRight" },
1311
- effects: { hover: [{
1312
- effectId: "lift",
1313
- options: { translateY: "-2px" }
1314
- }, {
1315
- effectId: "background-on-hover",
1316
- options: { colorToken: "secondary" }
1317
- }] }
1508
+ roles: {
1509
+ primary: {
1510
+ kind: "complete",
1511
+ appearance: {
1512
+ background: {
1513
+ type: "solid",
1514
+ colorToken: "primary"
1515
+ },
1516
+ borderRadius: "rounded-full",
1517
+ effects: { hover: [{
1518
+ effectId: "darken-background",
1519
+ options: { amount: 100 }
1520
+ }] }
1521
+ }
1522
+ },
1523
+ secondary: {
1524
+ kind: "complete",
1525
+ appearance: {
1526
+ background: {
1527
+ type: "surface",
1528
+ role: "link"
1529
+ },
1530
+ borderRadius: "rounded-full",
1531
+ border: { widthClass: "border-2" },
1532
+ effects: { hover: [{
1533
+ effectId: "background-on-hover",
1534
+ options: { colorToken: "accent" }
1535
+ }] }
1536
+ }
1537
+ },
1538
+ outline: {
1539
+ kind: "complete",
1540
+ appearance: {
1541
+ background: {
1542
+ type: "surface",
1543
+ role: "link"
1544
+ },
1545
+ borderRadius: "rounded-full",
1546
+ border: { widthClass: "border" },
1547
+ effects: { hover: [{
1548
+ effectId: "background-on-hover",
1549
+ options: { colorToken: "surface" }
1550
+ }] }
1551
+ }
1318
1552
  },
1319
- {
1320
- id: "secondary",
1321
- name: "Secondary",
1322
- enabled: true,
1323
- priority: 2,
1324
- background: {
1325
- type: "surface",
1326
- role: "link"
1327
- },
1328
- borderRadius: "rounded-lg",
1329
- border: { widthClass: "border" },
1330
- effects: { hover: [{
1331
- effectId: "lift",
1332
- options: { translateY: "-2px" }
1333
- }, {
1334
- effectId: "background-on-hover",
1335
- options: { colorToken: "surfaceAlt" }
1336
- }] }
1553
+ ghost: {
1554
+ kind: "complete",
1555
+ appearance: {
1556
+ background: {
1557
+ type: "surface",
1558
+ role: "link"
1559
+ },
1560
+ borderRadius: "rounded-full",
1561
+ sizes: {
1562
+ sm: {
1563
+ padding: "0.375rem 0.875rem",
1564
+ fontSize: "text-sm"
1565
+ },
1566
+ md: { padding: "0.5rem 1rem" },
1567
+ lg: {
1568
+ padding: "0.625rem 1.25rem",
1569
+ fontSize: "text-lg"
1570
+ },
1571
+ xl: {
1572
+ padding: "0.75rem 1.5rem",
1573
+ fontSize: "text-xl"
1574
+ }
1575
+ }
1576
+ }
1337
1577
  },
1338
- {
1339
- id: "accent",
1340
- name: "Accent",
1341
- enabled: true,
1342
- priority: 3,
1343
- background: {
1578
+ accent: {
1579
+ kind: "derive",
1580
+ from: "primary",
1581
+ overrides: { background: {
1344
1582
  type: "solid",
1345
1583
  colorToken: "accent"
1346
- },
1347
- borderRadius: "rounded-lg",
1348
- affordance: { iconId: "ArrowRight" },
1349
- effects: { hover: [{
1350
- effectId: "lift",
1351
- options: { translateY: "-2px" }
1352
- }] }
1584
+ } }
1353
1585
  }
1354
- ]
1586
+ }
1355
1587
  }
1356
1588
  });
1357
- //#endregion
1358
- //#region ../theme-core/src/buttons/personalities/ink-stamp.ts
1359
- /**
1360
- * Ink Stamp — solid earthy fills with a bordered, hand-stamped block-print
1361
- * feel. Reads as bold and handmade; suits expressive craft brands.
1362
- */
1363
- const inkStamp = defineButtonPersonality({
1364
- id: "ink-stamp",
1365
- name: "Ink Stamp",
1366
- description: "Hand-stamped block-print buttons with a slight lift on hover.",
1589
+ const brushedWashRecipe = defineStaticButtonStyleRecipe({
1590
+ id: "brushed-wash",
1591
+ accessibilityLabel: "Generously padded gradient buttons with soft shadows",
1367
1592
  tags: {
1368
- tone: "bold",
1593
+ tone: "classic",
1369
1594
  energy: "vibrant",
1370
1595
  motion: "standard",
1371
1596
  era: "organic"
1372
1597
  },
1373
- buttonSystem: {
1598
+ system: {
1374
1599
  global: {
1375
1600
  cornerStyle: "rounded",
1376
- textTransform: "uppercase",
1377
- fontWeight: 600,
1601
+ shadow: "low",
1602
+ textTransform: "none",
1603
+ fontWeight: 500,
1378
1604
  borderWidth: 1,
1379
1605
  hoverTransform: "none",
1380
- hoverColor: "none",
1381
- letterSpacing: "loose"
1606
+ hoverColor: "none"
1382
1607
  },
1383
1608
  sizes: {
1384
1609
  sm: {
1385
- padding: "0.5rem 1.25rem",
1386
- fontSize: "text-xs"
1387
- },
1388
- md: {
1389
- padding: "0.75rem 1.75rem",
1610
+ padding: "0.75rem 2rem",
1390
1611
  fontSize: "text-sm"
1391
1612
  },
1613
+ md: { padding: "1rem 2.5rem" },
1392
1614
  lg: {
1393
- padding: "0.875rem 2.25rem",
1394
- fontSize: "text-base"
1615
+ padding: "1.25rem 3rem",
1616
+ fontSize: "text-lg"
1395
1617
  },
1396
1618
  xl: {
1397
- padding: "1.125rem 2.75rem",
1398
- fontSize: "text-lg"
1619
+ padding: "1.625rem 3.75rem",
1620
+ fontSize: "text-xl"
1399
1621
  }
1400
1622
  },
1401
- variants: [
1402
- {
1403
- id: "primary",
1404
- name: "Primary",
1405
- enabled: true,
1406
- priority: 1,
1407
- background: {
1408
- type: "solid",
1409
- colorToken: "primary"
1410
- },
1411
- borderRadius: "rounded-md",
1412
- effects: {
1413
- hover: [{
1414
- effectId: "drop-shadow",
1415
- options: { intensity: "medium" }
1416
- }, {
1417
- effectId: "scale-up",
1418
- options: { scale: "1.02" }
1419
- }],
1420
- active: [{
1421
- effectId: "scale-down",
1422
- options: { scale: "0.98" }
1423
- }]
1623
+ roles: {
1624
+ primary: {
1625
+ kind: "complete",
1626
+ appearance: {
1627
+ background: {
1628
+ type: "gradient",
1629
+ stops: ["primary", "accent"],
1630
+ direction: "to-r",
1631
+ foregroundToken: "primaryForeground"
1632
+ },
1633
+ borderRadius: "rounded-lg",
1634
+ shadow: {
1635
+ elevation: "low",
1636
+ softness: "soft",
1637
+ position: "bottom"
1638
+ }
1424
1639
  }
1425
1640
  },
1426
- {
1427
- id: "secondary",
1428
- name: "Secondary",
1429
- enabled: true,
1430
- priority: 2,
1431
- background: {
1432
- type: "surface",
1433
- role: "link"
1434
- },
1435
- borderRadius: "rounded-md",
1436
- border: { widthClass: "border-2" },
1437
- effects: { hover: [{
1438
- effectId: "background-on-hover",
1439
- options: { colorToken: "surface" }
1440
- }] }
1441
- },
1442
- {
1443
- id: "outline",
1444
- name: "Outline",
1445
- enabled: true,
1446
- priority: 3,
1447
- background: {
1448
- type: "surface",
1449
- role: "link"
1450
- },
1451
- borderRadius: "rounded-md",
1452
- border: { widthClass: "border-2" },
1453
- effects: { hover: [{
1454
- effectId: "background-on-hover",
1455
- options: { colorToken: "surface" }
1456
- }] }
1457
- },
1458
- {
1459
- id: "ghost",
1460
- name: "Ghost",
1461
- enabled: true,
1462
- priority: 3,
1463
- background: {
1464
- type: "surface",
1465
- role: "link"
1466
- },
1467
- borderRadius: "rounded-none",
1468
- sizes: {
1469
- sm: {
1470
- padding: "0.375rem 0",
1471
- fontSize: "text-xs"
1641
+ secondary: {
1642
+ kind: "complete",
1643
+ appearance: {
1644
+ background: {
1645
+ type: "gradient",
1646
+ stops: ["secondary", "accent"],
1647
+ direction: "to-br",
1648
+ foregroundToken: "primaryForeground"
1472
1649
  },
1473
- md: {
1474
- padding: "0.5rem 0",
1475
- fontSize: "text-sm"
1476
- },
1477
- lg: {
1478
- padding: "0.625rem 0",
1479
- fontSize: "text-base"
1480
- },
1481
- xl: {
1482
- padding: "0.75rem 0",
1483
- fontSize: "text-lg"
1484
- }
1485
- },
1486
- effects: { base: [{
1487
- effectId: "border-bottom-grow",
1488
- options: {
1489
- height: 1,
1490
- colorToken: "accent",
1491
- origin: "left"
1650
+ borderRadius: "rounded-lg",
1651
+ shadow: {
1652
+ elevation: "low",
1653
+ softness: "soft",
1654
+ position: "bottom"
1492
1655
  }
1493
- }] }
1494
- }
1495
- ]
1496
- }
1497
- });
1498
- //#endregion
1499
- //#region ../theme-core/src/buttons/personalities/joy-stamp.ts
1500
- /**
1501
- * Joy Stamp — neo-brutalist pills with a hard, brand-coloured offset shadow
1502
- * that collapses as the button presses into it on hover. Authored for the
1503
- * Original Joy site style: a cream "stamp" shadow under the solid primary, and
1504
- * a brown shadow under the cream outline. Reads as bold, warm, and handmade.
1505
- *
1506
- * The coloured offset shadow relies on the per-variant `shadow.colorToken`
1507
- * extension; the press is the shared `press-down` effect, which matches its
1508
- * translate to each variant's own shadow offset.
1509
- */
1510
- const joyStamp = defineButtonPersonality({
1511
- id: "joy-stamp",
1512
- name: "Joy Stamp",
1513
- description: "Pill buttons with a hard, brand-coloured offset shadow that presses in on hover.",
1514
- tags: {
1515
- tone: "bold",
1516
- energy: "vibrant",
1517
- motion: "expressive",
1518
- era: "organic"
1519
- },
1520
- buttonSystem: {
1521
- global: {
1522
- cornerStyle: "pill",
1523
- shadow: "high",
1524
- textTransform: "none",
1525
- typography: "heading",
1526
- fontWeight: 700,
1527
- fontSize: "text-lg",
1528
- borderWidth: 2,
1529
- hoverTransform: "none",
1530
- hoverColor: "none"
1531
- },
1532
- sizes: {
1533
- sm: {
1534
- padding: "0.625rem 1.25rem",
1535
- fontSize: "text-base"
1656
+ }
1536
1657
  },
1537
- md: {
1538
- padding: "0.875rem 1.75rem",
1539
- fontSize: "text-lg"
1658
+ outline: {
1659
+ kind: "complete",
1660
+ appearance: {
1661
+ background: {
1662
+ type: "surface",
1663
+ role: "link"
1664
+ },
1665
+ borderRadius: "rounded-lg",
1666
+ border: { widthClass: "border" },
1667
+ effects: { hover: [{
1668
+ effectId: "background-on-hover",
1669
+ options: { colorToken: "surface" }
1670
+ }] }
1671
+ }
1540
1672
  },
1541
- lg: {
1542
- padding: "1.125rem 2.25rem",
1543
- fontSize: "text-xl"
1673
+ ghost: {
1674
+ kind: "complete",
1675
+ appearance: {
1676
+ background: {
1677
+ type: "surface",
1678
+ role: "link"
1679
+ },
1680
+ borderRadius: "rounded-lg",
1681
+ effects: { hover: [{
1682
+ effectId: "background-on-hover",
1683
+ options: { colorToken: "surface" }
1684
+ }] }
1685
+ }
1544
1686
  },
1545
- xl: {
1546
- padding: "1.25rem 2.75rem",
1547
- fontSize: "text-2xl"
1687
+ accent: {
1688
+ kind: "derive",
1689
+ from: "primary",
1690
+ overrides: { background: {
1691
+ type: "solid",
1692
+ colorToken: "accent"
1693
+ } }
1548
1694
  }
1549
- },
1550
- variants: [{
1551
- id: "primary",
1552
- name: "Primary",
1553
- enabled: true,
1554
- priority: 1,
1555
- background: {
1556
- type: "solid",
1557
- colorToken: "primary"
1558
- },
1559
- borderRadius: "rounded-full",
1560
- shadow: {
1561
- elevation: "high",
1562
- softness: "hard",
1563
- position: "bottom-right",
1564
- colorToken: "text"
1565
- },
1566
- effects: { hover: [{ effectId: "press-down" }] }
1567
- }, {
1568
- id: "secondary",
1569
- name: "Secondary",
1570
- enabled: true,
1571
- priority: 2,
1572
- background: {
1573
- type: "surface",
1574
- role: "link"
1575
- },
1576
- borderRadius: "rounded-full",
1577
- border: { widthClass: "border-2" },
1578
- shadow: {
1579
- elevation: "high",
1580
- softness: "hard",
1581
- position: "bottom-right",
1582
- colorToken: "secondary"
1583
- },
1584
- effects: { hover: [{ effectId: "press-down" }] }
1585
- }]
1695
+ }
1586
1696
  }
1587
1697
  });
1588
- //#endregion
1589
- //#region ../theme-core/src/buttons/personalities/ornate-ritual.ts
1590
- /**
1591
- * Ornate Ritual — framed, ceremonial buttons with jewel-toned fills and
1592
- * deliberate spacing. Designed for music, ceremony, and soulful event sites.
1593
- */
1594
- const ornateRitual = defineButtonPersonality({
1595
- id: "ornate-ritual",
1596
- name: "Ornate Ritual",
1597
- description: "Ceremonial framed buttons with jewel-toned fills and quiet color-change hover states.",
1698
+ const inkStampRecipe = defineStaticButtonStyleRecipe({
1699
+ id: "ink-stamp",
1700
+ accessibilityLabel: "Uppercase block-print buttons with a playful hover",
1598
1701
  tags: {
1599
- tone: "classic",
1702
+ tone: "bold",
1600
1703
  energy: "vibrant",
1601
- motion: "subtle",
1704
+ motion: "standard",
1602
1705
  era: "organic"
1603
1706
  },
1604
- buttonSystem: {
1707
+ system: {
1605
1708
  global: {
1606
1709
  cornerStyle: "rounded",
1607
1710
  textTransform: "uppercase",
@@ -1613,655 +1716,656 @@ const ornateRitual = defineButtonPersonality({
1613
1716
  },
1614
1717
  sizes: {
1615
1718
  sm: {
1616
- padding: "0.5625rem 1.25rem",
1719
+ padding: "0.5rem 1.25rem",
1617
1720
  fontSize: "text-xs"
1618
1721
  },
1619
1722
  md: {
1620
1723
  padding: "0.75rem 1.75rem",
1621
- fontSize: "text-xs"
1724
+ fontSize: "text-sm"
1622
1725
  },
1623
1726
  lg: {
1624
1727
  padding: "0.875rem 2.25rem",
1625
- fontSize: "text-sm"
1728
+ fontSize: "text-base"
1626
1729
  },
1627
1730
  xl: {
1628
- padding: "1rem 2.75rem",
1629
- fontSize: "text-base"
1731
+ padding: "1.125rem 2.75rem",
1732
+ fontSize: "text-lg"
1630
1733
  }
1631
1734
  },
1632
- variants: [
1633
- {
1634
- id: "primary",
1635
- name: "Primary",
1636
- enabled: true,
1637
- priority: 1,
1638
- background: {
1639
- type: "solid",
1640
- colorToken: "primary"
1641
- },
1642
- borderRadius: "rounded-md",
1643
- border: { widthClass: "border" },
1644
- effects: {
1645
- hover: [{
1646
- effectId: "background-on-hover",
1647
- options: { colorToken: "primary-100" }
1648
- }],
1649
- active: [{
1650
- effectId: "scale-down",
1651
- options: { scale: "0.98" }
1652
- }]
1735
+ roles: {
1736
+ primary: {
1737
+ kind: "complete",
1738
+ appearance: {
1739
+ background: {
1740
+ type: "solid",
1741
+ colorToken: "primary"
1742
+ },
1743
+ borderRadius: "rounded-md",
1744
+ effects: {
1745
+ hover: [{
1746
+ effectId: "drop-shadow",
1747
+ options: { intensity: "medium" }
1748
+ }, {
1749
+ effectId: "scale-up",
1750
+ options: { scale: "1.02" }
1751
+ }],
1752
+ active: [{
1753
+ effectId: "scale-down",
1754
+ options: { scale: "0.98" }
1755
+ }]
1756
+ }
1653
1757
  }
1654
1758
  },
1655
- {
1656
- id: "secondary",
1657
- name: "Secondary",
1658
- enabled: true,
1659
- priority: 2,
1660
- background: {
1661
- type: "solid",
1662
- colorToken: "secondary"
1663
- },
1664
- borderRadius: "rounded-md",
1665
- border: { widthClass: "border" },
1666
- effects: { hover: [{
1667
- effectId: "background-on-hover",
1668
- options: { colorToken: "surface" }
1669
- }] }
1670
- },
1671
- {
1672
- id: "outline",
1673
- name: "Outline",
1674
- enabled: true,
1675
- priority: 3,
1676
- background: {
1677
- type: "surface",
1678
- role: "link"
1679
- },
1680
- borderRadius: "rounded-md",
1681
- border: { widthClass: "border" },
1682
- effects: { hover: [{
1683
- effectId: "background-on-hover",
1684
- options: { colorToken: "muted" }
1685
- }] }
1759
+ secondary: {
1760
+ kind: "complete",
1761
+ appearance: {
1762
+ background: {
1763
+ type: "surface",
1764
+ role: "link"
1765
+ },
1766
+ borderRadius: "rounded-md",
1767
+ border: { widthClass: "border-2" },
1768
+ effects: { hover: [{
1769
+ effectId: "background-on-hover",
1770
+ options: { colorToken: "surface" }
1771
+ }] }
1772
+ }
1686
1773
  },
1687
- {
1688
- id: "ghost",
1689
- name: "Ghost",
1690
- enabled: true,
1691
- priority: 3,
1692
- background: {
1693
- type: "surface",
1694
- role: "link"
1695
- },
1696
- borderRadius: "rounded-none",
1697
- sizes: {
1698
- sm: {
1699
- padding: "0.375rem 0",
1700
- fontSize: "text-xs"
1774
+ outline: {
1775
+ kind: "complete",
1776
+ appearance: {
1777
+ background: {
1778
+ type: "surface",
1779
+ role: "link"
1701
1780
  },
1702
- md: {
1703
- padding: "0.5rem 0",
1704
- fontSize: "text-sm"
1781
+ borderRadius: "rounded-md",
1782
+ border: { widthClass: "border-2" },
1783
+ effects: { hover: [{
1784
+ effectId: "background-on-hover",
1785
+ options: { colorToken: "surface" }
1786
+ }] }
1787
+ }
1788
+ },
1789
+ ghost: {
1790
+ kind: "complete",
1791
+ appearance: {
1792
+ background: {
1793
+ type: "surface",
1794
+ role: "link"
1705
1795
  },
1706
- lg: {
1707
- padding: "0.625rem 0",
1708
- fontSize: "text-base"
1796
+ borderRadius: "rounded-none",
1797
+ sizes: {
1798
+ sm: {
1799
+ padding: "0.375rem 0",
1800
+ fontSize: "text-xs"
1801
+ },
1802
+ md: {
1803
+ padding: "0.5rem 0",
1804
+ fontSize: "text-sm"
1805
+ },
1806
+ lg: {
1807
+ padding: "0.625rem 0",
1808
+ fontSize: "text-base"
1809
+ },
1810
+ xl: {
1811
+ padding: "0.75rem 0",
1812
+ fontSize: "text-lg"
1813
+ }
1709
1814
  },
1710
- xl: {
1711
- padding: "0.75rem 0",
1712
- fontSize: "text-lg"
1713
- }
1714
- },
1715
- effects: { base: [{
1716
- effectId: "border-bottom-grow",
1717
- options: {
1718
- height: 1,
1719
- colorToken: "accent",
1720
- origin: "left"
1721
- }
1722
- }] }
1815
+ effects: { base: [{
1816
+ effectId: "border-bottom-grow",
1817
+ options: {
1818
+ height: 1,
1819
+ colorToken: "accent",
1820
+ origin: "left"
1821
+ }
1822
+ }] }
1823
+ }
1824
+ },
1825
+ accent: {
1826
+ kind: "derive",
1827
+ from: "primary",
1828
+ overrides: { background: {
1829
+ type: "solid",
1830
+ colorToken: "accent"
1831
+ } }
1723
1832
  }
1724
- ]
1833
+ }
1725
1834
  }
1726
1835
  });
1727
- //#endregion
1728
- //#region ../theme-core/src/buttons/personalities/pebble.ts
1729
- /**
1730
- * Pebble — large pill primaries with generous padding. Reads as spa-luxurious
1731
- * and natural; pairs well with wellness/yoga/dance brands.
1732
- */
1733
- const pebble = defineButtonPersonality({
1734
- id: "pebble",
1735
- name: "Pebble",
1736
- description: "Generous pill buttons with a quiet colour-softening hover.",
1836
+ const flatInkRecipe = defineStaticButtonStyleRecipe({
1837
+ id: "flat-ink",
1838
+ accessibilityLabel: "Flat rounded buttons with arrow affordances",
1737
1839
  tags: {
1738
1840
  tone: "classic",
1739
1841
  energy: "calm",
1740
- motion: "standard",
1741
- era: "organic"
1842
+ motion: "subtle",
1843
+ era: "editorial"
1742
1844
  },
1743
- buttonSystem: {
1845
+ system: {
1744
1846
  global: {
1745
- cornerStyle: "pill",
1847
+ cornerStyle: "rounded",
1746
1848
  textTransform: "none",
1747
- fontWeight: 500,
1748
- borderWidth: 2,
1749
- hoverTransform: "none",
1849
+ fontWeight: 600,
1850
+ borderWidth: 1,
1851
+ typography: "body",
1852
+ letterSpacing: "tight",
1853
+ paddingPreset: "default",
1854
+ hoverTransform: "lift",
1750
1855
  hoverColor: "none"
1751
1856
  },
1752
1857
  sizes: {
1753
1858
  sm: {
1754
- padding: "0.625rem 1.75rem",
1859
+ padding: "0.625rem 1.125rem",
1755
1860
  fontSize: "text-sm"
1756
1861
  },
1757
- md: { padding: "0.875rem 2.25rem" },
1862
+ md: { padding: "0.8125rem 1.375rem" },
1758
1863
  lg: {
1759
- padding: "1.125rem 2.75rem",
1864
+ padding: "0.9375rem 1.625rem",
1760
1865
  fontSize: "text-lg"
1761
1866
  },
1762
1867
  xl: {
1763
- padding: "1.5rem 3.5rem",
1868
+ padding: "1.0625rem 2rem",
1764
1869
  fontSize: "text-xl"
1765
1870
  }
1766
1871
  },
1767
- variants: [
1768
- {
1769
- id: "primary",
1770
- name: "Primary",
1771
- enabled: true,
1772
- priority: 1,
1773
- background: {
1774
- type: "solid",
1775
- colorToken: "primary"
1776
- },
1777
- borderRadius: "rounded-full",
1778
- effects: { hover: [{
1779
- effectId: "darken-background",
1780
- options: { amount: 100 }
1781
- }] }
1872
+ roles: {
1873
+ primary: {
1874
+ kind: "complete",
1875
+ appearance: {
1876
+ background: {
1877
+ type: "solid",
1878
+ colorToken: "primary"
1879
+ },
1880
+ borderRadius: "rounded-lg",
1881
+ affordance: { iconId: "ArrowRight" },
1882
+ effects: { hover: [{
1883
+ effectId: "lift",
1884
+ options: { translateY: "-2px" }
1885
+ }, {
1886
+ effectId: "background-on-hover",
1887
+ options: { colorToken: "secondary" }
1888
+ }] }
1889
+ }
1782
1890
  },
1783
- {
1784
- id: "secondary",
1785
- name: "Secondary",
1786
- enabled: true,
1787
- priority: 2,
1788
- background: {
1789
- type: "surface",
1790
- role: "link"
1791
- },
1792
- borderRadius: "rounded-full",
1793
- border: { widthClass: "border-2" },
1794
- effects: { hover: [{
1795
- effectId: "background-on-hover",
1796
- options: { colorToken: "accent" }
1797
- }] }
1891
+ secondary: {
1892
+ kind: "complete",
1893
+ appearance: {
1894
+ background: {
1895
+ type: "surface",
1896
+ role: "link"
1897
+ },
1898
+ borderRadius: "rounded-lg",
1899
+ border: { widthClass: "border" },
1900
+ effects: { hover: [{
1901
+ effectId: "lift",
1902
+ options: { translateY: "-2px" }
1903
+ }, {
1904
+ effectId: "background-on-hover",
1905
+ options: { colorToken: "surfaceAlt" }
1906
+ }] }
1907
+ }
1798
1908
  },
1799
- {
1800
- id: "outline",
1801
- name: "Outline",
1802
- enabled: true,
1803
- priority: 3,
1804
- background: {
1805
- type: "surface",
1806
- role: "link"
1807
- },
1808
- borderRadius: "rounded-full",
1809
- border: { widthClass: "border" },
1810
- effects: { hover: [{
1811
- effectId: "background-on-hover",
1812
- options: { colorToken: "surface" }
1813
- }] }
1909
+ outline: {
1910
+ kind: "complete",
1911
+ appearance: {
1912
+ background: {
1913
+ type: "surface",
1914
+ role: "link"
1915
+ },
1916
+ borderRadius: "rounded-lg",
1917
+ border: { widthClass: "border" },
1918
+ effects: { hover: [{
1919
+ effectId: "lift",
1920
+ options: { translateY: "-2px" }
1921
+ }, {
1922
+ effectId: "background-on-hover",
1923
+ options: { colorToken: "surfaceAlt" }
1924
+ }] }
1925
+ }
1814
1926
  },
1815
- {
1816
- id: "ghost",
1817
- name: "Ghost",
1818
- enabled: true,
1819
- priority: 3,
1820
- background: {
1821
- type: "surface",
1822
- role: "link"
1823
- },
1824
- borderRadius: "rounded-full",
1825
- sizes: {
1826
- sm: {
1827
- padding: "0.375rem 0.875rem",
1828
- fontSize: "text-sm"
1927
+ ghost: {
1928
+ kind: "complete",
1929
+ appearance: {
1930
+ background: {
1931
+ type: "surface",
1932
+ role: "link"
1829
1933
  },
1830
- md: { padding: "0.5rem 1rem" },
1831
- lg: {
1832
- padding: "0.625rem 1.25rem",
1833
- fontSize: "text-lg"
1934
+ borderRadius: "rounded-lg",
1935
+ effects: { hover: [{
1936
+ effectId: "lift",
1937
+ options: { translateY: "-2px" }
1938
+ }] }
1939
+ }
1940
+ },
1941
+ accent: {
1942
+ kind: "complete",
1943
+ appearance: {
1944
+ background: {
1945
+ type: "solid",
1946
+ colorToken: "accent"
1834
1947
  },
1835
- xl: {
1836
- padding: "0.75rem 1.5rem",
1837
- fontSize: "text-xl"
1838
- }
1948
+ borderRadius: "rounded-lg",
1949
+ affordance: { iconId: "ArrowRight" },
1950
+ effects: { hover: [{
1951
+ effectId: "lift",
1952
+ options: { translateY: "-2px" }
1953
+ }] }
1839
1954
  }
1840
1955
  }
1841
- ]
1956
+ }
1842
1957
  }
1843
1958
  });
1844
- //#endregion
1845
- //#region ../theme-core/src/buttons/personalities/quiet-arrow.ts
1846
- /**
1847
- * Quiet Arrow — wide, flat editorial buttons for grounded service businesses.
1848
- * Primary and secondary keep stable semantic colours; surrounding surfaces are
1849
- * responsible for contrast rather than reversing the button roles.
1850
- */
1851
- const quietArrow = defineButtonPersonality({
1852
- id: "quiet-arrow",
1853
- name: "Quiet Arrow",
1854
- description: "Wide, flat arrow buttons with a solid primary and a primary-colour outlined secondary.",
1959
+ const showtimePillRecipe = defineStaticButtonStyleRecipe({
1960
+ id: "showtime-pill",
1961
+ accessibilityLabel: "Bold uppercase pill buttons with playful movement",
1855
1962
  tags: {
1856
- tone: "classic",
1857
- energy: "calm",
1858
- motion: "subtle",
1859
- era: "editorial"
1963
+ tone: "bold",
1964
+ energy: "vibrant",
1965
+ motion: "expressive",
1966
+ era: "modern"
1860
1967
  },
1861
- buttonSystem: {
1968
+ system: {
1862
1969
  global: {
1863
- cornerStyle: "rounded",
1970
+ cornerStyle: "pill",
1971
+ shadow: "low",
1864
1972
  textTransform: "uppercase",
1865
- fontWeight: 500,
1866
- borderWidth: 1,
1973
+ fontWeight: 700,
1974
+ borderWidth: 2,
1975
+ hoverTransform: "lift",
1976
+ hoverColor: "darken",
1867
1977
  typography: "body",
1868
- fontSize: "text-sm",
1869
- letterSpacing: "loose",
1870
- hoverTransform: "none",
1871
- hoverColor: "none"
1978
+ paddingPreset: "spacious",
1979
+ italic: false
1872
1980
  },
1873
1981
  sizes: {
1874
1982
  sm: {
1875
1983
  padding: "0.625rem 1.25rem",
1876
- fontSize: "text-xs"
1984
+ fontSize: "0.875rem"
1877
1985
  },
1878
1986
  md: {
1879
- padding: "0.8125rem 1.75rem",
1880
- fontSize: "text-sm"
1987
+ padding: "0.875rem 1.75rem",
1988
+ fontSize: "1rem"
1881
1989
  },
1882
1990
  lg: {
1883
- padding: "0.9375rem 2.125rem",
1884
- fontSize: "text-sm"
1991
+ padding: "1.125rem 2.25rem",
1992
+ fontSize: "1.125rem"
1885
1993
  },
1886
1994
  xl: {
1887
- padding: "1.0625rem 2.5rem",
1888
- fontSize: "text-base"
1995
+ padding: "1.125rem 2.25rem",
1996
+ fontSize: "1.125rem"
1889
1997
  }
1890
1998
  },
1891
- variants: [
1892
- {
1893
- id: "primary",
1894
- name: "Primary",
1895
- enabled: true,
1896
- priority: 1,
1897
- background: {
1898
- type: "solid",
1899
- colorToken: "primary"
1900
- },
1901
- borderRadius: "rounded-xl",
1902
- affordance: { iconId: "ArrowRight" },
1903
- effects: { hover: [{
1904
- effectId: "darken-background",
1905
- options: { amount: 100 }
1906
- }] }
1999
+ roles: {
2000
+ primary: {
2001
+ kind: "complete",
2002
+ appearance: {
2003
+ background: {
2004
+ type: "solid",
2005
+ colorToken: "primary"
2006
+ },
2007
+ borderRadius: "rounded-full",
2008
+ effects: { hover: [{ effectId: "pop" }] }
2009
+ }
2010
+ },
2011
+ secondary: {
2012
+ kind: "complete",
2013
+ appearance: {
2014
+ background: {
2015
+ type: "surface",
2016
+ role: "link"
2017
+ },
2018
+ borderRadius: "rounded-full",
2019
+ border: { widthClass: "border-2" },
2020
+ effects: { hover: [{ effectId: "pop" }] }
2021
+ }
1907
2022
  },
1908
- {
1909
- id: "secondary",
1910
- name: "Secondary",
1911
- enabled: true,
1912
- priority: 2,
1913
- background: {
1914
- type: "surface",
1915
- role: "link"
1916
- },
1917
- borderRadius: "rounded-xl",
1918
- border: { widthClass: "border" },
1919
- affordance: { iconId: "ArrowRight" },
1920
- effects: { hover: [{
1921
- effectId: "background-on-hover",
1922
- options: { colorToken: "surfaceAlt" }
1923
- }] }
2023
+ outline: {
2024
+ kind: "complete",
2025
+ appearance: {
2026
+ background: {
2027
+ type: "surface",
2028
+ role: "link"
2029
+ },
2030
+ borderRadius: "rounded-full",
2031
+ border: { widthClass: "border-2" },
2032
+ effects: { hover: [{
2033
+ effectId: "background-on-hover",
2034
+ options: { colorToken: "background" }
2035
+ }] }
2036
+ }
1924
2037
  },
1925
- {
1926
- id: "outline",
1927
- name: "Outline",
1928
- enabled: true,
1929
- priority: 3,
1930
- background: {
1931
- type: "surface",
1932
- role: "link"
1933
- },
1934
- borderRadius: "rounded-xl",
1935
- border: { widthClass: "border" }
2038
+ ghost: {
2039
+ kind: "complete",
2040
+ appearance: {
2041
+ background: {
2042
+ type: "surface",
2043
+ role: "link"
2044
+ },
2045
+ borderRadius: "rounded-full",
2046
+ effects: { hover: [{
2047
+ effectId: "background-on-hover",
2048
+ options: { colorToken: "surface" }
2049
+ }] }
2050
+ }
1936
2051
  },
1937
- {
1938
- id: "ghost",
1939
- name: "Ghost",
1940
- enabled: true,
1941
- priority: 3,
1942
- background: {
1943
- type: "surface",
1944
- role: "link"
1945
- },
1946
- borderRadius: "rounded-xl"
2052
+ accent: {
2053
+ kind: "complete",
2054
+ appearance: {
2055
+ background: {
2056
+ type: "solid",
2057
+ colorToken: "secondary"
2058
+ },
2059
+ borderRadius: "rounded-full",
2060
+ effects: { hover: [{ effectId: "pop" }] }
2061
+ }
1947
2062
  }
1948
- ]
2063
+ }
1949
2064
  }
1950
2065
  });
1951
- //#endregion
1952
- //#region ../theme-core/src/buttons/personalities/showtime-pill.ts
1953
- /**
1954
- * Showtime Pill — bold, spacious, fully rounded buttons with playful pop
1955
- * motion. Suits energetic schools, performers, festivals, and community brands
1956
- * that need calls to action to feel loud without becoming visually chaotic.
1957
- */
1958
- const showtimePill = defineButtonPersonality({
1959
- id: "showtime-pill",
1960
- name: "Showtime Pill",
1961
- description: "Bold pill buttons with uppercase labels, generous padding, and a playful pop.",
2066
+ const joyStampRecipe = defineStaticButtonStyleRecipe({
2067
+ id: "joy-stamp",
2068
+ accessibilityLabel: "Bold pill buttons with a hard offset shadow",
1962
2069
  tags: {
1963
2070
  tone: "bold",
1964
2071
  energy: "vibrant",
1965
2072
  motion: "expressive",
1966
- era: "modern"
2073
+ era: "organic"
1967
2074
  },
1968
- buttonSystem: {
2075
+ system: {
1969
2076
  global: {
1970
2077
  cornerStyle: "pill",
1971
- shadow: "low",
1972
- textTransform: "uppercase",
2078
+ shadow: "high",
2079
+ textTransform: "none",
2080
+ typography: "heading",
1973
2081
  fontWeight: 700,
2082
+ fontSize: "text-lg",
1974
2083
  borderWidth: 2,
1975
- hoverTransform: "lift",
1976
- hoverColor: "darken",
1977
- typography: "body",
1978
- paddingPreset: "spacious",
1979
- italic: false
2084
+ hoverTransform: "none",
2085
+ hoverColor: "none"
1980
2086
  },
1981
2087
  sizes: {
1982
2088
  sm: {
1983
2089
  padding: "0.625rem 1.25rem",
1984
- fontSize: "0.875rem"
2090
+ fontSize: "text-base"
1985
2091
  },
1986
2092
  md: {
1987
2093
  padding: "0.875rem 1.75rem",
1988
- fontSize: "1rem"
2094
+ fontSize: "text-lg"
1989
2095
  },
1990
2096
  lg: {
1991
2097
  padding: "1.125rem 2.25rem",
1992
- fontSize: "1.125rem"
2098
+ fontSize: "text-xl"
1993
2099
  },
1994
2100
  xl: {
1995
- padding: "1.125rem 2.25rem",
1996
- fontSize: "1.125rem"
2101
+ padding: "1.25rem 2.75rem",
2102
+ fontSize: "text-2xl"
1997
2103
  }
1998
2104
  },
1999
- variants: [
2000
- {
2001
- id: "primary",
2002
- name: "Primary",
2003
- enabled: true,
2004
- priority: 1,
2005
- background: {
2006
- type: "solid",
2007
- colorToken: "primary"
2008
- },
2009
- borderRadius: "rounded-full",
2010
- effects: { hover: [{ effectId: "pop" }] }
2011
- },
2012
- {
2013
- id: "secondary",
2014
- name: "Secondary",
2015
- enabled: true,
2016
- priority: 2,
2017
- background: {
2018
- type: "surface",
2019
- role: "link"
2020
- },
2021
- borderRadius: "rounded-full",
2022
- border: { widthClass: "border-2" },
2023
- effects: { hover: [{ effectId: "pop" }] }
2105
+ roles: {
2106
+ primary: {
2107
+ kind: "complete",
2108
+ appearance: {
2109
+ background: {
2110
+ type: "solid",
2111
+ colorToken: "primary"
2112
+ },
2113
+ borderRadius: "rounded-full",
2114
+ shadow: {
2115
+ elevation: "high",
2116
+ softness: "hard",
2117
+ position: "bottom-right",
2118
+ colorToken: "text"
2119
+ },
2120
+ effects: { hover: [{ effectId: "press-down" }] }
2121
+ }
2024
2122
  },
2025
- {
2026
- id: "hero",
2027
- name: "Hero",
2028
- enabled: true,
2029
- priority: 1,
2030
- background: {
2031
- type: "solid",
2032
- colorToken: "secondary"
2033
- },
2034
- borderRadius: "rounded-full",
2035
- effects: { hover: [{ effectId: "pop" }] }
2123
+ secondary: {
2124
+ kind: "complete",
2125
+ appearance: {
2126
+ background: {
2127
+ type: "surface",
2128
+ role: "link"
2129
+ },
2130
+ borderRadius: "rounded-full",
2131
+ border: { widthClass: "border-2" },
2132
+ shadow: {
2133
+ elevation: "high",
2134
+ softness: "hard",
2135
+ position: "bottom-right",
2136
+ colorToken: "secondary"
2137
+ },
2138
+ effects: { hover: [{ effectId: "press-down" }] }
2139
+ }
2036
2140
  },
2037
- {
2038
- id: "header",
2039
- name: "Header",
2040
- enabled: true,
2041
- priority: 2,
2042
- background: {
2043
- type: "solid",
2044
- colorToken: "background"
2045
- },
2046
- borderRadius: "rounded-full",
2047
- border: { widthClass: "border-2" },
2048
- effects: { hover: [{
2049
- effectId: "background-on-hover",
2050
- options: { colorToken: "surface" }
2051
- }] }
2141
+ outline: {
2142
+ kind: "derive",
2143
+ from: "secondary"
2052
2144
  },
2053
- {
2054
- id: "outline",
2055
- name: "Outline",
2056
- enabled: true,
2057
- priority: 3,
2058
- background: {
2059
- type: "surface",
2060
- role: "link"
2061
- },
2062
- borderRadius: "rounded-full",
2063
- border: { widthClass: "border-2" },
2064
- effects: { hover: [{
2065
- effectId: "background-on-hover",
2066
- options: { colorToken: "background" }
2067
- }] }
2145
+ ghost: {
2146
+ kind: "complete",
2147
+ appearance: {
2148
+ background: {
2149
+ type: "surface",
2150
+ role: "link"
2151
+ },
2152
+ borderRadius: "rounded-full",
2153
+ effects: { hover: [{ effectId: "press-down" }] }
2154
+ }
2068
2155
  },
2069
- {
2070
- id: "ghost",
2071
- name: "Ghost",
2072
- enabled: true,
2073
- priority: 3,
2074
- background: {
2075
- type: "surface",
2076
- role: "link"
2077
- },
2078
- borderRadius: "rounded-full",
2079
- effects: { hover: [{
2080
- effectId: "background-on-hover",
2081
- options: { colorToken: "surface" }
2082
- }] }
2156
+ accent: {
2157
+ kind: "derive",
2158
+ from: "primary",
2159
+ overrides: { background: {
2160
+ type: "solid",
2161
+ colorToken: "accent"
2162
+ } }
2083
2163
  }
2084
- ]
2164
+ }
2085
2165
  }
2086
2166
  });
2087
- //#endregion
2088
- //#region ../theme-core/src/buttons/personalities/soft-pill.ts
2089
- /**
2090
- * Soft Pill — rounded-full pill buttons with a hover lift. The default for
2091
- * Calm Studio and Modern Wellness; reads as quietly modern and welcoming.
2092
- */
2093
- const softPill = defineButtonPersonality({
2094
- id: "soft-pill",
2095
- name: "Soft Pill",
2096
- description: "Rounded pills with a gentle lift on hover. Quietly modern.",
2167
+ const ornateRitualRecipe = defineStaticButtonStyleRecipe({
2168
+ id: "ornate-ritual",
2169
+ accessibilityLabel: "Uppercase framed buttons with restrained movement",
2097
2170
  tags: {
2098
2171
  tone: "classic",
2099
- energy: "calm",
2172
+ energy: "vibrant",
2100
2173
  motion: "subtle",
2101
2174
  era: "organic"
2102
2175
  },
2103
- buttonSystem: {
2176
+ system: {
2104
2177
  global: {
2105
- cornerStyle: "pill",
2106
- shadow: "low",
2107
- textTransform: "none",
2108
- fontWeight: 500,
2109
- borderWidth: 2,
2110
- hoverTransform: "lift",
2111
- hoverColor: "none"
2178
+ cornerStyle: "rounded",
2179
+ textTransform: "uppercase",
2180
+ fontWeight: 600,
2181
+ borderWidth: 1,
2182
+ hoverTransform: "none",
2183
+ hoverColor: "none",
2184
+ letterSpacing: "loose"
2112
2185
  },
2113
- variants: [
2114
- {
2115
- id: "primary",
2116
- name: "Primary",
2117
- enabled: true,
2118
- priority: 1,
2119
- background: {
2120
- type: "solid",
2121
- colorToken: "primary"
2122
- },
2123
- borderRadius: "rounded-full",
2124
- shadow: {
2125
- elevation: "low",
2126
- softness: "soft",
2127
- position: "bottom"
2128
- },
2129
- effects: {
2130
- hover: [{
2131
- effectId: "lift",
2132
- options: { translateY: "-1px" }
2133
- }],
2134
- active: [{
2135
- effectId: "scale-down",
2136
- options: { scale: "0.98" }
2137
- }]
2186
+ sizes: {
2187
+ sm: {
2188
+ padding: "0.5625rem 1.25rem",
2189
+ fontSize: "text-xs"
2190
+ },
2191
+ md: {
2192
+ padding: "0.75rem 1.75rem",
2193
+ fontSize: "text-xs"
2194
+ },
2195
+ lg: {
2196
+ padding: "0.875rem 2.25rem",
2197
+ fontSize: "text-sm"
2198
+ },
2199
+ xl: {
2200
+ padding: "1rem 2.75rem",
2201
+ fontSize: "text-base"
2202
+ }
2203
+ },
2204
+ roles: {
2205
+ primary: {
2206
+ kind: "complete",
2207
+ appearance: {
2208
+ background: {
2209
+ type: "solid",
2210
+ colorToken: "primary"
2211
+ },
2212
+ borderRadius: "rounded-md",
2213
+ border: { widthClass: "border" },
2214
+ effects: {
2215
+ hover: [{
2216
+ effectId: "background-on-hover",
2217
+ options: { colorToken: "primary-100" }
2218
+ }],
2219
+ active: [{
2220
+ effectId: "scale-down",
2221
+ options: { scale: "0.98" }
2222
+ }]
2223
+ }
2138
2224
  }
2139
2225
  },
2140
- {
2141
- id: "secondary",
2142
- name: "Secondary",
2143
- enabled: true,
2144
- priority: 2,
2145
- background: {
2146
- type: "surface",
2147
- role: "link"
2148
- },
2149
- borderRadius: "rounded-full",
2150
- border: { widthClass: "border-2" },
2151
- effects: { hover: [{
2152
- effectId: "background-on-hover",
2153
- options: { colorToken: "surface" }
2154
- }] }
2226
+ secondary: {
2227
+ kind: "complete",
2228
+ appearance: {
2229
+ background: {
2230
+ type: "solid",
2231
+ colorToken: "secondary"
2232
+ },
2233
+ borderRadius: "rounded-md",
2234
+ border: { widthClass: "border" },
2235
+ effects: { hover: [{
2236
+ effectId: "background-on-hover",
2237
+ options: { colorToken: "surface" }
2238
+ }] }
2239
+ }
2155
2240
  },
2156
- {
2157
- id: "outline",
2158
- name: "Outline",
2159
- enabled: true,
2160
- priority: 3,
2161
- background: {
2162
- type: "surface",
2163
- role: "link"
2164
- },
2165
- borderRadius: "rounded-full",
2166
- border: { widthClass: "border" },
2167
- effects: { hover: [{
2168
- effectId: "background-on-hover",
2169
- options: { colorToken: "surface" }
2170
- }] }
2241
+ outline: {
2242
+ kind: "complete",
2243
+ appearance: {
2244
+ background: {
2245
+ type: "surface",
2246
+ role: "link"
2247
+ },
2248
+ borderRadius: "rounded-md",
2249
+ border: { widthClass: "border" },
2250
+ effects: { hover: [{
2251
+ effectId: "background-on-hover",
2252
+ options: { colorToken: "muted" }
2253
+ }] }
2254
+ }
2171
2255
  },
2172
- {
2173
- id: "ghost",
2174
- name: "Ghost",
2175
- enabled: true,
2176
- priority: 3,
2177
- background: {
2178
- type: "surface",
2179
- role: "link"
2180
- },
2181
- borderRadius: "rounded-full",
2182
- effects: { hover: [{
2183
- effectId: "background-on-hover",
2184
- options: { colorToken: "surface" }
2185
- }] }
2256
+ ghost: {
2257
+ kind: "complete",
2258
+ appearance: {
2259
+ background: {
2260
+ type: "surface",
2261
+ role: "link"
2262
+ },
2263
+ borderRadius: "rounded-none",
2264
+ sizes: {
2265
+ sm: {
2266
+ padding: "0.375rem 0",
2267
+ fontSize: "text-xs"
2268
+ },
2269
+ md: {
2270
+ padding: "0.5rem 0",
2271
+ fontSize: "text-sm"
2272
+ },
2273
+ lg: {
2274
+ padding: "0.625rem 0",
2275
+ fontSize: "text-base"
2276
+ },
2277
+ xl: {
2278
+ padding: "0.75rem 0",
2279
+ fontSize: "text-lg"
2280
+ }
2281
+ },
2282
+ effects: { base: [{
2283
+ effectId: "border-bottom-grow",
2284
+ options: {
2285
+ height: 1,
2286
+ colorToken: "accent",
2287
+ origin: "left"
2288
+ }
2289
+ }] }
2290
+ }
2291
+ },
2292
+ accent: {
2293
+ kind: "derive",
2294
+ from: "primary",
2295
+ overrides: { background: {
2296
+ type: "solid",
2297
+ colorToken: "accent"
2298
+ } }
2186
2299
  }
2187
- ]
2300
+ }
2188
2301
  }
2189
2302
  });
2190
2303
  //#endregion
2191
- //#region ../theme-core/src/buttons/personalities/two-tone-pill.ts
2192
- const solidSecondary = {
2193
- id: "secondary",
2194
- name: "Secondary",
2195
- enabled: true,
2196
- priority: 2,
2197
- background: {
2198
- type: "solid",
2199
- colorToken: unsafeAsOpaqueButtonColourToken("secondary")
2200
- },
2201
- borderRadius: "rounded-full",
2202
- shadow: {
2203
- elevation: "none",
2204
- softness: null,
2205
- position: "bottom"
2206
- },
2207
- effects: {
2208
- hover: [{
2209
- effectId: "background-on-hover-alpha",
2210
- options: {
2211
- colorToken: "secondary",
2212
- opacity: 88
2213
- }
2214
- }],
2215
- active: [{
2216
- effectId: "scale-down",
2217
- options: { scale: "0.98" }
2218
- }]
2219
- }
2220
- };
2221
- //#endregion
2222
- //#region ../theme-core/src/buttons/personalities/index.ts
2223
- const buttonPersonalities = [
2224
- softPill,
2225
- defineButtonPersonality({
2226
- id: "two-tone-pill",
2227
- name: "Two-tone Pill",
2228
- description: "Rounded pills with distinct solid primary and secondary brand colours.",
2229
- tags: softPill.tags,
2230
- buttonSystem: {
2231
- ...softPill.buttonSystem,
2232
- variants: softPill.buttonSystem.variants.map((variant) => variant.id === "secondary" ? solidSecondary : variant)
2233
- }
2234
- }),
2235
- earthPill,
2236
- confidentChip,
2237
- editorialLink,
2238
- pebble,
2239
- inkStamp,
2240
- flatInk,
2241
- brushedWash,
2242
- showtimePill,
2243
- joyStamp,
2244
- ornateRitual,
2245
- quietArrow
2304
+ //#region ../theme-core/src/buttons/styles/registry.ts
2305
+ const buttonStyleRecipes = [
2306
+ softPillRecipe,
2307
+ earthPillRecipe,
2308
+ confidentChipRecipe,
2309
+ editorialLinkRecipe,
2310
+ pebbleRecipe,
2311
+ inkStampRecipe,
2312
+ flatInkRecipe,
2313
+ brushedWashRecipe,
2314
+ showtimePillRecipe,
2315
+ joyStampRecipe,
2316
+ ornateRitualRecipe,
2317
+ quietArrowRecipe
2246
2318
  ];
2247
- new Map(buttonPersonalities.map((p) => [p.id, p]));
2248
- buttonPersonalities.map((personality) => ({
2249
- id: personality.id,
2250
- name: personality.name,
2251
- description: personality.description,
2252
- category: presetCategory(personality),
2253
- buttonSystem: personality.buttonSystem,
2254
- compatibility: {
2255
- ...personality.tags.tone ? { tones: [personality.tags.tone] } : {},
2256
- ...personality.tags.energy ? { energies: [personality.tags.energy] } : {}
2319
+ const recipesById = new Map(buttonStyleRecipes.map((recipe) => [recipe.id, recipe]));
2320
+ function findButtonStyleRecipe(id) {
2321
+ const recipe = recipesById.get(id);
2322
+ if (recipe === void 0) throw new Error(`Button style registry is missing known style ${id}`);
2323
+ return recipe;
2324
+ }
2325
+ function resolveButtonStyleSelection(selection) {
2326
+ switch (selection.styleId) {
2327
+ case "soft-pill": return resolveButtonStyleRecipe(softPillRecipe, selection.parameters);
2328
+ case "earth-pill": return resolveButtonStyleRecipe(earthPillRecipe, selection.parameters);
2329
+ case "confident-chip": return resolveButtonStyleRecipe(confidentChipRecipe, selection.parameters);
2330
+ case "editorial-link": return resolveButtonStyleRecipe(editorialLinkRecipe, selection.parameters);
2331
+ case "pebble": return resolveButtonStyleRecipe(pebbleRecipe, selection.parameters);
2332
+ case "ink-stamp": return resolveButtonStyleRecipe(inkStampRecipe, selection.parameters);
2333
+ case "flat-ink": return resolveButtonStyleRecipe(flatInkRecipe, selection.parameters);
2334
+ case "brushed-wash": return resolveButtonStyleRecipe(brushedWashRecipe, selection.parameters);
2335
+ case "showtime-pill": return resolveButtonStyleRecipe(showtimePillRecipe, selection.parameters);
2336
+ case "joy-stamp": return resolveButtonStyleRecipe(joyStampRecipe, selection.parameters);
2337
+ case "ornate-ritual": return resolveButtonStyleRecipe(ornateRitualRecipe, selection.parameters);
2338
+ case "quiet-arrow": return resolveButtonStyleRecipe(quietArrowRecipe, selection.parameters);
2257
2339
  }
2258
- }));
2259
- function presetCategory(personality) {
2260
- switch (personality.tags.era) {
2340
+ }
2341
+ function defaultButtonStyleSelectionFor(styleId) {
2342
+ return {
2343
+ styleId,
2344
+ parameters: findButtonStyleRecipe(styleId).defaultParameters
2345
+ };
2346
+ }
2347
+ if (buttonStyleRecipes.map((recipe) => recipe.id).length !== BUTTON_STYLE_IDS.length || BUTTON_STYLE_IDS.some((id) => !recipesById.has(id))) throw new Error("Button style registry and ButtonStyleId catalog are out of sync");
2348
+ buttonStyleRecipes.map((recipe) => {
2349
+ const resolved = resolveButtonStyleSelection(defaultButtonStyleSelectionFor(recipe.id));
2350
+ if (resolved.kind === "error") throw new Error(`Invalid registered button style ${recipe.id}: ${resolved.error.issues.join(", ")}`);
2351
+ return {
2352
+ id: recipe.id,
2353
+ name: recipe.accessibilityLabel,
2354
+ description: recipe.accessibilityLabel,
2355
+ category: presetCategory(recipe),
2356
+ buttonSystem: resolved.buttonSystem,
2357
+ compatibility: {
2358
+ ...recipe.tags.tone ? { tones: [recipe.tags.tone] } : {},
2359
+ ...recipe.tags.energy ? { energies: [recipe.tags.energy] } : {}
2360
+ }
2361
+ };
2362
+ });
2363
+ function presetCategory(recipe) {
2364
+ switch (recipe.tags.era) {
2261
2365
  case "retro": return "retro";
2262
2366
  case "editorial": return "minimal";
2263
2367
  case "organic": return "artistic";
2264
- case "modern": return personality.tags.tone === "bold" ? "modern" : "technical";
2368
+ case "modern": return recipe.tags.tone === "bold" ? "modern" : "technical";
2265
2369
  case "technical": return "technical";
2266
2370
  case void 0: return "modern";
2267
2371
  }