tabs.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. export const settingsTabs = {
  2. tabs: {
  3. // Container
  4. 'u-controls-tabs-container': 'w-full flex-col ',
  5. // Atoms: scrollable tab list (single header row)
  6. 'u-controls-tabs-header':
  7. 'relative flex flex-1 flex-row flex-nowrap overflow-x-auto bg-background overflow-y-hidden web:scrollbar-none ',
  8. // Shared structural class for scrollbar hiding (molecules variant rows include this)
  9. 'u-controls-tabs-header-row':
  10. 'relative flex flex-1 flex-row flex-nowrap overflow-x-auto bg-transparent overflow-y-hidden web:scrollbar-none',
  11. // Header item base (shared)
  12. 'u-controls-tabs-header-item':
  13. 'inline-flex flex-auto justify-center items-center whitespace-nowrap font-medium truncate web:cursor-pointer web:disabled:pointer-events-none web:disabled:opacity-50 ',
  14. // Atoms TabsTrigger: static active surface (no animated pill)
  15. 'u-controls-tabs-header-item-active':
  16. ' bg-popover web:shadow-sm web:duration-300 ',
  17. 'u-controls-tabs-header-item-inactive':
  18. ' group web:hover:bg-muted web:duration-500',
  19. // Header item text
  20. 'u-controls-tabs-header-item-text':
  21. 'native:text-secondary-foreground font-medium ',
  22. 'u-controls-tabs-header-item-text-active':
  23. 'text-foreground font-medium ',
  24. // Tab content
  25. 'u-controls-tabs-tab-content': 'w-full',
  26. 'u-controls-tabs-tab-content-animated':
  27. 'web:animate-[tabContentFadeIn_0.2s_ease-out]',
  28. // Animated selection layer (molecules) — duration/easing from tabs-selection-constants (native + web)
  29. 'u-controls-tabs-selection-layer':
  30. 'absolute pointer-events-none',
  31. },
  32. /**
  33. * Tab bar styles, picked with `<Tabs variant="…">`. Each entry:
  34. * indicator 'pill' (sliding surface behind the active tab) or 'line' (underline).
  35. * Missing: 'pill' when `pill` is set, else 'line' when `line` is set.
  36. * track surface behind the whole row (absolute, fills the bar)
  37. * row the tab list row
  38. * trigger_active / trigger_inactive each tab (hover washes go on inactive)
  39. * pill / line the selection indicator
  40. * text / text_active optional label classes; replace `u-controls-tabs-header-item-text*` when set
  41. */
  42. tabs_variants: {
  43. // Flat segmented control: a translucent muted rail (it takes on tinted
  44. // backgrounds) with NeoButton `bordered` pill colours. The pill is lighter
  45. // than the rail in both schemes (white in light, button-hover in dark,
  46. // where the 60% rail sits darker than solid muted).
  47. default: {
  48. indicator: 'pill',
  49. track:
  50. 'absolute inset-0 z-0 bg-muted/60 pointer-events-none',
  51. row: '',
  52. trigger_active: '',
  53. trigger_inactive:
  54. ' group text-secondary-foreground web:hover:text-foreground web:hover:bg-button-hover/60 web:duration-200 ',
  55. pill: 'bg-popover dark:bg-button-hover shadow-sm',
  56. line: '',
  57. },
  58. // Glass segmented control: NeoButton `glass` (`theme.neo_button.styles.glass`).
  59. // Track = the glass button at rest, pill = a lighter lens with the pressed shadow.
  60. glass: {
  61. indicator: 'pill',
  62. track:
  63. 'absolute inset-0 z-0 web:backdrop-blur-md bg-popover/50 shadow-btn-glass dark:shadow-btn-glass-deep pointer-events-none',
  64. row: '',
  65. trigger_active: '',
  66. trigger_inactive:
  67. ' group web:hover:bg-muted/50 web:duration-200 ',
  68. pill: 'bg-popover shadow-btn-glass-pressed dark:bg-foreground/15 dark:shadow-btn-glass-pressed-deep',
  69. line: '',
  70. text: 'font-medium text-card-foreground',
  71. text_active: 'font-medium text-foreground',
  72. },
  73. secondary: {
  74. indicator: 'line',
  75. track:
  76. 'absolute inset-0 z-0 bg-transparent pointer-events-none',
  77. row: '',
  78. trigger_active: ' ',
  79. trigger_inactive:
  80. ' group text-secondary-foreground web:hover:text-foreground web:hover:bg-muted/50 web:duration-200',
  81. pill: '',
  82. line: 'bg-ring',
  83. },
  84. },
  85. // Sizes: layout + corner radii (track / row / pill). Use `rounded` prop on Tabs for rounded-full.
  86. tabs_sizes: {
  87. default_size: 'md',
  88. sm: {
  89. header: ' p-1 gap-1 ',
  90. /** px — matches horizontal list padding; scroll-into-view uses this so tabs don’t sit flush on the viewport edge */
  91. scroll_inset: 4,
  92. gap_px: 4,
  93. track: 'rounded-xl',
  94. row: 'rounded-xl',
  95. item: ' h-9 px-2 text-sm web:focus-visible:outline-2 ',
  96. pill: 'rounded-lg overflow-hidden',
  97. indicator_pad: ' px-2 ',
  98. indicator_inner: 'rounded-full h-0.5 mt-1 ',
  99. text: ' text-sm whitespace-nowrap ',
  100. text_active: ' text-sm whitespace-nowrap ',
  101. },
  102. md: {
  103. header: ' p-1.5 gap-1',
  104. scroll_inset: 6,
  105. gap_px: 4,
  106. track: 'rounded-xl',
  107. row: 'rounded-xl',
  108. item: ' h-10 px-3 text-base web:focus-visible:outline-2 ',
  109. pill: 'rounded-lg overflow-hidden',
  110. indicator_pad: ' px-3 ',
  111. indicator_inner: 'rounded-full h-[3px] mt-1.5 ',
  112. text: ' text-base ',
  113. text_active: ' text-base ',
  114. },
  115. lg: {
  116. header: ' p-2 gap-1 ',
  117. scroll_inset: 8,
  118. gap_px: 4,
  119. track: 'rounded-2xl',
  120. row: 'rounded-2xl',
  121. item: ' h-12 px-4 text-lg web:focus-visible:outline-2',
  122. pill: 'rounded-xl overflow-hidden',
  123. indicator_pad: ' px-4 ',
  124. indicator_inner: 'rounded-full h-1 mt-2',
  125. text: ' text-lg ',
  126. text_active: ' text-lg ',
  127. },
  128. },
  129. }