buttons.js 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614
  1. export const settingsButtons = {
  2. button_sizes: {
  3. default_size: 'base',
  4. default_variant: 'default',
  5. xs: {
  6. rounded: 'rounded-md',
  7. container: 'px-2 gap-1 h-7 min-w-7 ',
  8. container_icon_only: 'h-7 w-7 items-center justify-center',
  9. text: 'text-xs ',
  10. icon_size: 14,
  11. hitSlop: 8,
  12. },
  13. sm: {
  14. rounded: 'rounded-lg ',
  15. container: 'px-2.5 gap-1 h-9 min-w-9 ',
  16. container_icon_only: 'h-9 w-9',
  17. text: 'text-sm leading-5',
  18. icon_size: 16,
  19. hitSlop: 4,
  20. },
  21. base: {
  22. rounded: 'rounded-lg',
  23. container: 'px-3 gap-2 min-h-11 min-w-11',
  24. container_icon_only: 'min-h-11 min-w-11',
  25. title_container: ' leading-11 text-base',
  26. icon_size: 20,
  27. hitSlop: 0,
  28. },
  29. lg: {
  30. rounded: 'rounded-xl',
  31. container: 'px-4 gap-2 min-h-13 min-w-13',
  32. container_icon_only: 'min-h-13 min-w-13',
  33. title_container: ' leading-13 text-base',
  34. icon_size: 24,
  35. hitSlop: 0,
  36. },
  37. xl: {
  38. rounded: 'rounded-xl',
  39. container: 'px-4 gap-2 min-h-16 min-w-16',
  40. container_icon_only: 'min-h-16 min-w-16',
  41. title_container: ' leading-16 text-base',
  42. icon_size: 28,
  43. hitSlop: 0,
  44. },
  45. },
  46. button_styles: {
  47. motion:{
  48. springTransition: { type: 'spring', damping: 24, stiffness: 360 },
  49. highlightBackgroundlight: 'rgba(255,255,255,0.5)',
  50. highlightBackgrounddark: 'rgba(0,0,0,0.5)',
  51. scale: 0.95,
  52. },
  53. group:{
  54. container: ' border items-center border-border overflow-hidden ',
  55. separator: ' bg-border/60 w-px h-full',
  56. },
  57. primary:{
  58. container:{
  59. base:'backdrop-blur',
  60. default:' bg-primary ',
  61. active:' bg-primary-hover ',
  62. pressed:' bg-primary ',
  63. hovered:' bg-primary-hover ',
  64. focused:' bg-primary ',
  65. disabled:' bg-primary/50 ',
  66. },
  67. text:{
  68. base:'font-medium',
  69. default:'text-primary-foreground',
  70. hovered:'text-primary-foreground',
  71. focused:'text-primary-foreground',
  72. active:'text-primary-foreground',
  73. pressed:'text-primary-foreground',
  74. disabled:'text-primary-foreground/50',
  75. }
  76. },
  77. default:{
  78. container:{
  79. base:' border border-border/60 ',
  80. default:' bg-popover/60 shadow-btn-outline dark:shadow-btn-outline-deep ',
  81. active:' bg-muted/50 shadow-sm ',
  82. pressed:' bg-muted/50 shadow-sm ',
  83. hovered:' bg-popover shadow-btn-outline dark:shadow-btn-outline-deep ',
  84. focused:' bg-popover shadow-btn-outline dark:shadow-btn-outline-deep ',
  85. disabled:' bg-popover shadow-btn-outline dark:shadow-btn-outline-deep opacity-50 ',
  86. },
  87. text:{
  88. base:'font-medium',
  89. default:'text-foreground',
  90. hovered:'text-foreground',
  91. focused:'text-foreground',
  92. active:'text-foreground',
  93. pressed:'text-foreground',
  94. disabled:'text-card-foreground/50',
  95. }
  96. },
  97. accent:{
  98. container:{
  99. base:' ',
  100. default:'bg-accent/60 ',
  101. active:'web:ring-2 web:ring-accent web:ring-offset-2 web:outline-none',
  102. pressed:'bg-accent/60',
  103. hovered:'bg-accent/90',
  104. focused:'',
  105. disabled:'',
  106. },
  107. text:{
  108. base:'font-medium ',
  109. default:'font-medium text-accent-foreground',
  110. hovered:'font-medium text-accent-foreground',
  111. focused:'font-medium text-accent-foreground',
  112. active:'font-medium text-accent-foreground',
  113. pressed:'font-medium text-accent-foreground',
  114. disabled:'font-medium text-accent-foreground/50',
  115. }
  116. },
  117. secondary:{
  118. container:{
  119. base:'',
  120. default:'bg-muted/50 ',
  121. active:' bg-muted ',
  122. pressed:' bg-muted ',
  123. hovered:' bg-muted ',
  124. focused:' bg-muted ',
  125. disabled:' bg-muted/50',
  126. },
  127. text:{
  128. base:'font-semibold',
  129. default:'text-card-foreground',
  130. hovered:'text-foreground',
  131. focused:'text-foreground',
  132. active:'text-foreground',
  133. pressed:'text-foreground',
  134. disabled:'text-muted-foreground',
  135. },
  136. },
  137. danger:{
  138. container:{
  139. base:'bg-destructive',
  140. default:'',
  141. active:'bg-red-600/90 ',
  142. pressed:'bg-red-600/90 ',
  143. hovered:'bg-red-500 shadow',
  144. focused:'',
  145. disabled:'',
  146. },
  147. text:{
  148. base:'font-medium ',
  149. default:'text-destructive-foreground',
  150. hovered:'',
  151. focused:'',
  152. active:'',
  153. pressed:'',
  154. disabled:'',
  155. }
  156. },
  157. text:{
  158. container:{
  159. base:'',
  160. default:'',
  161. active:' bg-muted ',
  162. pressed:' bg-accent/60 ',
  163. hovered:' bg-muted/50 ',
  164. focused:' bg-muted/50 ',
  165. disabled:'opacity-50',
  166. },
  167. text:{
  168. base:'font-medium ',
  169. default:'text-secondary-foreground',
  170. hovered:'text-foreground',
  171. focused:'text-foreground',
  172. active:'text-foreground',
  173. pressed:'text-accent-foreground',
  174. disabled:'text-secondary-foreground',
  175. }
  176. },
  177. ghost:{
  178. container:{
  179. base:'',
  180. default:'',
  181. active:' ',
  182. pressed:'',
  183. hovered:'',
  184. focused:'',
  185. disabled:'',
  186. },
  187. text:{
  188. base:'font-medium',
  189. default:' text-secondary-foreground',
  190. hovered:'text-foreground',
  191. focused:'text-foreground',
  192. active:'text-foreground',
  193. pressed:'text-foreground',
  194. disabled:'text-muted-foreground',
  195. }
  196. },
  197. link:{
  198. container:{
  199. base:'',
  200. default:'',
  201. active:' ',
  202. pressed:'',
  203. hovered:'',
  204. focused:'',
  205. disabled:'',
  206. },
  207. text:{
  208. base:'font-medium',
  209. default:'text-secondary-foreground',
  210. hovered:'text-foreground underline',
  211. focused:'text-accent-foreground',
  212. active:'text-accent-foreground',
  213. pressed:'text-accent-foreground',
  214. disabled:'text-accent-foreground/50',
  215. }
  216. },
  217. outline:{
  218. container:{
  219. base:'border ',
  220. default:'border-border/60',
  221. active:'bg-muted/50 ',
  222. pressed:'bg-muted/50',
  223. hovered:'bg-muted/50',
  224. focused:'bg-muted/50',
  225. disabled:'opacity-50',
  226. },
  227. text:{
  228. base:'font-medium ',
  229. default:'text-secondary-foreground',
  230. hovered:'text-foreground',
  231. focused:'text-foreground',
  232. active:'text-foreground',
  233. pressed:'text-foreground',
  234. disabled:'text-secondary-foreground/50',
  235. }
  236. }
  237. },
  238. /*
  239. * NeoButton theme — single tree, SwiftUI-aligned API.
  240. *
  241. * Mirrors SwiftUI's Button axes:
  242. * role → Button(role:) (default | cancel | close | confirm | destructive)
  243. * style → .buttonStyle() (plain | bordered | borderedProminent
  244. * | borderless | link | glass | glassProminent)
  245. * controlSize → .controlSize() (mini | small | regular | large | xlarge)
  246. * borderShape → .buttonBorderShape() (capsule | rectangle | roundedRectangle | circle)
  247. * tint → .tint() (CSS color)
  248. *
  249. * Any leaf can be a scope-keyed object resolved at runtime by
  250. * `useResolvedNeoButton`. Supported scope keys (most-specific wins):
  251. * default · light/dark · web/ios/android/native · touch/mouse · sm/md/lg/xl/2xl
  252. * plus controlSize keys (mini/small/regular/large/xlarge) inside per-size slots
  253. * such as `borderShapes.roundedRectangle`.
  254. *
  255. * The legacy `neo_button_sizes` / `neo_button_styles` keys are gone — the
  256. * only consumer was `NeoButton` itself, which now reads `neo_button`.
  257. */
  258. neo_button: {
  259. defaults: {
  260. // Used when no `style` prop, no `<NeoButtonStyleProvider>` parent,
  261. // and no role.defaultStyle apply. See `resolveStyle()` in the
  262. // resolver for the full precedence chain.
  263. style: 'bordered',
  264. controlSize: 'regular',
  265. borderShape: 'roundedRectangle',
  266. role: 'default',
  267. imagePlacement: 'leading',
  268. align: 'center',
  269. width: 'auto',
  270. focusRing: { default: 'never', web: 'auto' },
  271. pressAnimation: true,
  272. // Same `FeedbackHaptics` types as tabs (`Select` / `Medium` / …).
  273. // `haptics={false}` on a button opts out.
  274. haptics: 'Medium',
  275. // How `glass` / `glassProminent` render on web:
  276. // 'standard' — flat surface: theme fill + `shadow-btn-glass*` tokens.
  277. // 'realistic' — layered glass: conic rim, light sweep, blurred
  278. // ground shadow, tilt on press (`.neo-glass*` in
  279. // `design/styles/global.css`). Fills come from
  280. // `styles.<glass>.realistic`, merged over the style.
  281. // Web only: Expo UI draws real liquid glass on iOS, and the native
  282. // JS fallback has no mask / backdrop-filter to build it with.
  283. // Per button: `<NeoButton glassEffect="standard" />`.
  284. glassEffect: { default: 'standard', web: 'standard' },
  285. // Behavioral flags. The resolver gates event handlers on these so
  286. // web-only hover code does not run on native, etc.
  287. behaviors: {
  288. hover: { default: false, mouse: true },
  289. focusRing: { default: false, web: true },
  290. pressAnimation: { default: true },
  291. longPress: { default: true },
  292. },
  293. },
  294. // Scale: mini 28 / small 36 / regular 44 / large 52 / xlarge 64 (same heights as legacy xs/sm/base/lg/xl).
  295. // hitSlop is derived: max(0, ceil((44 − height) / 2)) → mini 8, small 4, regular+ 0 (resolver `hitSlopForHeight`).
  296. // Add an explicit `hitSlop` only to deviate; the resolver warns in dev if height + 2·hitSlop < 44.
  297. controlSizes: {
  298. mini: { height: 28, paddingX: 10, font: 'text-xs ', icon: 16, labelGap: 4, contentInsets: { mediaLeading: { left: 2 } } },
  299. small: { height: 36, paddingX: 12, font: 'text-sm ', icon: 20, labelGap: 6, contentInsets: { mediaLeading: { left: 4 } } },
  300. regular: {
  301. default: { height: 44, paddingX: 16, font: 'text-base leading-11', icon: 24, labelGap: 8, contentInsets: { mediaLeading: { left: 4 } } },
  302. // web: { height: 44, paddingX: 12 },
  303. // mouse: { height: 44, paddingX: 12, font: 'text-sm', icon: 20, hitSlop: 0, labelGap: 8, contentInsets: { mediaLeading: { left: 4 } } },
  304. },
  305. large: { height: 52, paddingX: 24, font: 'text-base leading-13', icon: 24, labelGap: 10, contentInsets: { mediaLeading: { left: 6 } } },
  306. xlarge: { height: 64, paddingX: 32, font: 'text-lg leading-16', icon: 28, labelGap: 12, contentInsets: { mediaLeading: { left: 8 } } },
  307. },
  308. // borderShape → rounding strategy. roundedRectangle scales with
  309. // controlSize; the others are fixed.
  310. //
  311. // `iconOnlyPadded` keeps the normal horizontal padding on an icon-only
  312. // button instead of collapsing it to `px-0`. Without it a capsule
  313. // icon-only button is indistinguishable from `circle`: `px-0` plus a
  314. // min-width equal to the height lands exactly on a square, which
  315. // `rounded-full` then renders as a circle. With it, the pill keeps the
  316. // proportions of a labelled button — the iOS Messages send-button look.
  317. // `circle` deliberately omits the flag: it must stay a true circle.
  318. borderShapes: {
  319. capsule: { rounded: 'rounded-full', iconOnlyPadded: true },
  320. rectangle: { rounded: 'rounded-none' },
  321. roundedRectangle: {
  322. rounded: {
  323. default: 'rounded-xl',
  324. mini: 'rounded-md',
  325. small: 'rounded-lg',
  326. regular: 'rounded-xl',
  327. large: 'rounded-xl',
  328. xlarge: 'rounded-2xl',
  329. },
  330. },
  331. circle: { rounded: 'rounded-full', aspectSquare: true },
  332. },
  333. // Segmented group (`NeoButtonGroup`, `ButtonsGroupMenu`). Rounding comes
  334. // from the group's controlSize (`roundedRectangle`). No `overflow-hidden`:
  335. // it would clip the segments' focus rings.
  336. group: {
  337. container: 'flex-row items-stretch border border-border',
  338. separator: 'w-px self-stretch bg-border/60',
  339. },
  340. // SwiftUI roles. `defaultStyle` is used when no `style` prop is
  341. // passed and no parent provider sets one (e.g. `role="confirm"` →
  342. // borderedProminent). `defaultImage` is used when no `image` is
  343. // passed (e.g. role="close" → 'X').
  344. roles: {
  345. default: {},
  346. cancel: { textClass: 'text-secondary-foreground' },
  347. close: { textClass: 'text-secondary-foreground', defaultImage: 'X' },
  348. confirm: { defaultStyle: 'borderedProminent' },
  349. destructive: {
  350. tint: 'rgb(var(--destructive))',
  351. // Prominent styles paint the tint as the fill, so their label stays on the foreground.
  352. textClass: { default: 'text-destructive', borderedProminent: 'text-destructive-foreground', glassProminent: 'text-destructive-foreground' },
  353. },
  354. },
  355. // Per-style visual recipes. Same slot/state shape as before
  356. // (container/text + base/default/hovered/focused/pressed/active/
  357. // pressedToggle/disabled), now scoped under `styles[name]`.
  358. styles: {
  359. // SwiftUI .plain — label only; no fill, hover wash, or press tint.
  360. plain: {
  361. container: {
  362. default: '',
  363. hovered: '',
  364. focused: '',
  365. pressed: '',
  366. active: '',
  367. pressedToggle: '',
  368. disabled: 'opacity-50',
  369. },
  370. text: {
  371. base: 'font-medium',
  372. default: 'text-card-foreground',
  373. hovered: 'text-card-foreground',
  374. focused: 'text-card-foreground',
  375. pressed: 'text-card-foreground',
  376. active: 'text-card-foreground',
  377. pressedToggle: 'text-card-foreground',
  378. disabled: 'text-muted-foreground',
  379. },
  380. },
  381. // SwiftUI .bordered — neutral fill, no shadow.
  382. // Definition is just the background colour — keeps the surface
  383. // perfectly flat (the inset/border-via-shadow stack is reserved
  384. // for the glass family).
  385. bordered: {
  386. container: {
  387. base: ' ',
  388. default: 'bg-button ',
  389. hovered: 'bg-button-hover ',
  390. focused: 'bg-button-hover ',
  391. pressed: 'bg-button-hover ',
  392. active: 'bg-button-hover ',
  393. // Selected must differ from hover; matches the native expo_ui bordered toggle.
  394. pressedToggle: 'bg-accent',
  395. // A cast like or reaction (selectedState="voted").
  396. voted: 'bg-accent/60',
  397. disabled: 'bg-button/50 ',
  398. },
  399. text: {
  400. base: 'font-medium tracking-tight',
  401. default: 'text-button-foreground',
  402. hovered: 'text-button-foreground',
  403. focused: 'text-button-foreground',
  404. pressed: 'text-button-foreground',
  405. active: 'text-button-foreground',
  406. pressedToggle: 'text-accent-foreground',
  407. voted: 'text-accent-foreground',
  408. disabled: 'text-muted-foreground',
  409. },
  410. },
  411. // SwiftUI .borderedProminent — primary action, flat fill.
  412. // No shadow — the only signal is the primary background colour
  413. // and the press background swap.
  414. borderedProminent: {
  415. container: {
  416. default: 'bg-primary',
  417. hovered: 'bg-primary-hover',
  418. focused: 'bg-primary',
  419. pressed: 'bg-primary',
  420. active: 'bg-primary-hover',
  421. pressedToggle: 'bg-primary-hover',
  422. disabled: 'bg-primary opacity-50',
  423. },
  424. text: {
  425. base: 'font-medium tracking-tight',
  426. default: 'text-primary-foreground',
  427. hovered: 'text-primary-foreground',
  428. focused: 'text-primary-foreground',
  429. pressed: 'text-primary-foreground',
  430. active: 'text-primary-foreground',
  431. pressedToggle: 'text-primary-foreground',
  432. disabled: 'text-primary-foreground',
  433. },
  434. },
  435. // SwiftUI .borderless — text-like with hover wash on web.
  436. borderless: {
  437. container: {
  438. default: '',
  439. hovered: 'bg-muted/50',
  440. focused: 'bg-muted/50',
  441. pressed: 'bg-accent/80 web:hover:bg-accent',
  442. active: 'bg-muted/50 ',
  443. pressedToggle: 'bg-muted',
  444. // A cast like or reaction (selectedState="voted" in objects/likes, reactions).
  445. voted: 'bg-accent/60',
  446. disabled: 'opacity-50',
  447. },
  448. text: {
  449. base: 'font-semibold tracking-tight',
  450. default: 'text-card-foreground',
  451. hovered: 'text-foreground',
  452. focused: 'text-foreground',
  453. pressed: 'text-accent-foreground',
  454. active: 'text-foreground',
  455. pressedToggle: 'text-accent-foreground',
  456. voted: 'text-accent-foreground',
  457. disabled: 'text-secondary-foreground',
  458. },
  459. },
  460. // SwiftUI has no link style; we provide one that matches a web
  461. // text link (no fill, hover-underline on web).
  462. link: {
  463. container: { default: '',
  464. hovered: 'bg-muted/50',
  465. focused: 'bg-muted/50',
  466. pressed: 'bg-muted/50',
  467. active: 'bg-muted/50',
  468. pressedToggle: 'bg-muted/50',
  469. disabled: 'opacity-50' },
  470. text: {
  471. base: 'font-medium tracking-tight text-accent-foreground',
  472. default: ' ',
  473. hovered: ' ',
  474. focused: ' ',
  475. pressed: '',
  476. active: '',
  477. pressedToggle: 'underline',
  478. disabled: 'opacity-50',
  479. },
  480. },
  481. // SwiftUI .glass (iOS 26+). Web fallback uses backdrop-blur.
  482. // shadow-btn-glass carries border + inner highlight + wide soft
  483. // ambient drop. shadow-btn-glass-pressed shrinks the drop.
  484. glass: {
  485. container: {
  486. base: 'web:backdrop-blur-md shadow-btn-glass dark:shadow-btn-glass-deep',
  487. default: ' bg-popover/50 ',
  488. hovered: ' bg-muted/50 ',
  489. focused: ' bg-popover/50',
  490. pressed: 'bg-muted shadow-btn-glass-pressed dark:shadow-btn-glass-pressed-deep',
  491. active: 'bg-muted/50 shadow-btn-glass-pressed dark:shadow-btn-glass-pressed-deep',
  492. pressedToggle: 'bg-accent shadow-btn-glass-pressed dark:shadow-btn-glass-pressed-deep',
  493. disabled: 'bg-muted/50',
  494. },
  495. text: {
  496. base: 'font-medium',
  497. default: 'text-card-foreground',
  498. hovered: 'text-foreground',
  499. focused: 'text-foreground',
  500. pressed: 'text-foreground',
  501. active: 'text-foreground',
  502. pressedToggle: 'text-accent-foreground',
  503. disabled: 'text-muted-foreground',
  504. },
  505. // `defaults.glassEffect: 'realistic'` — the CSS layers own
  506. // shadow, blur and highlights, so only a thin fill is left here.
  507. // Dark needs more fill: popover is close to the page there.
  508. realistic: {
  509. container: {
  510. base: '',
  511. default: 'bg-popover/20 dark:bg-popover/50',
  512. hovered: 'bg-popover/30 dark:bg-popover/60',
  513. focused: 'bg-popover/20 dark:bg-popover/50',
  514. pressed: 'bg-popover/40 dark:bg-popover/70',
  515. active: 'bg-popover/30 dark:bg-popover/60',
  516. pressedToggle: 'bg-accent/70',
  517. disabled: 'bg-muted/30',
  518. },
  519. },
  520. },
  521. // SwiftUI .glassProminent — primary action colour with glass lift.
  522. glassProminent: {
  523. container: {
  524. base: 'web:backdrop-blur-md shadow-btn-glass-prominent dark:shadow-btn-glass-prominent-deep',
  525. default: 'bg-primary',
  526. hovered: 'bg-primary-hover',
  527. focused: 'bg-primary-hover',
  528. pressed: 'bg-primary-hover shadow-btn-glass-prominent-pressed dark:shadow-btn-glass-prominent-pressed-deep',
  529. active: 'bg-primary-hover',
  530. pressedToggle: 'bg-primary-hover shadow-btn-glass-prominent-pressed dark:shadow-btn-glass-prominent-pressed-deep',
  531. disabled: 'bg-primary opacity-50',
  532. },
  533. text: {
  534. base: 'font-medium tracking-tight',
  535. default: 'text-primary-foreground',
  536. hovered: 'text-primary-foreground',
  537. focused: 'text-primary-foreground',
  538. pressed: 'text-primary-foreground',
  539. active: 'text-primary-foreground',
  540. pressedToggle: 'text-primary-foreground',
  541. disabled: 'text-primary-foreground',
  542. },
  543. // Opaque: any see-through lets the page wash the tint out.
  544. realistic: {
  545. container: {
  546. base: '',
  547. default: 'bg-primary',
  548. hovered: 'bg-primary-hover',
  549. focused: 'bg-primary',
  550. pressed: 'bg-primary-hover',
  551. active: 'bg-primary-hover',
  552. pressedToggle: 'bg-primary-hover',
  553. disabled: 'bg-primary opacity-50',
  554. },
  555. },
  556. },
  557. },
  558. // Per-style transitions. Each style picks one of:
  559. // { type: 'scale', from, to, spring } — CSS transform on web, MotionView on native
  560. // { type: 'shadow' } — no wrapper; press class swap only
  561. // { type: 'opacity', duration } — CSS opacity on web, MotionView on native
  562. // false / null — no transition at all
  563. // `default` is the fallback for any style that does not declare its own.
  564. transitions: {
  565. default: {
  566. press: {
  567. type: 'scale',
  568. from: 1,
  569. to: { default: 1.1, mouse: 0.98, touch: 1.1 },
  570. spring: { damping: 24, stiffness: 360 },
  571. },
  572. hover: { type: 'opacity', duration: 120 },
  573. appear: null,
  574. },
  575. glass: { press: { type: 'scale', from: 1, to: { default: 1.1, mouse: 0.98, touch: 1.1 }, spring: { damping: 24, stiffness: 360 } }, hover: { type: 'opacity', duration: 200 } },
  576. glassProminent: { press: { type: 'scale', from: 1, to: { default: 1.1, mouse: 0.98, touch: 1.1 }, spring: { damping: 24, stiffness: 360 } }, hover: { type: 'opacity', duration: 200 } },
  577. plain: { press: false, hover: false },
  578. link: { press: false, hover: { type: 'opacity', duration: 120 } },
  579. borderless: { press: { type: 'scale', from: 1, to: 0.98, spring: { damping: 28, stiffness: 380 } }, hover: { type: 'opacity', duration: 120 } },
  580. },
  581. // Highlight overlay used for press feedback inside the container.
  582. // Matches the pre-rebuild MotionView highlight behaviour.
  583. motion: {
  584. highlightBackgroundlight: 'rgba(255,255,255,0.5)',
  585. highlightBackgrounddark: 'rgba(0,0,0,0.5)',
  586. },
  587. },
  588. }