radio-group.css 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. [data-component="radio-group"] {
  2. --radio-group-height: 28px;
  3. --radio-group-gap: 4px;
  4. --radio-group-padding: 2px;
  5. display: inline-flex;
  6. [data-slot="radio-group-wrapper"] {
  7. all: unset;
  8. background-color: var(--surface-inset-base);
  9. border-radius: var(--radius-sm);
  10. box-shadow: var(--shadow-xxs-border);
  11. display: inline-flex;
  12. height: var(--radio-group-height);
  13. margin: 0;
  14. overflow: visible;
  15. padding: 0;
  16. position: relative;
  17. width: fit-content;
  18. }
  19. &[data-fill] [data-slot="radio-group-wrapper"] {
  20. width: 100%;
  21. }
  22. [data-slot="radio-group-items"] {
  23. display: inline-flex;
  24. flex-direction: row;
  25. gap: var(--radio-group-gap);
  26. height: 100%;
  27. list-style: none;
  28. position: relative;
  29. z-index: 1;
  30. }
  31. &[data-fill] [data-slot="radio-group-items"] {
  32. width: 100%;
  33. }
  34. [data-slot="radio-group-indicator"] {
  35. background: var(--button-secondary-base);
  36. border-radius: var(--radius-sm);
  37. box-shadow: var(--shadow-xs-border-base);
  38. content: "";
  39. opacity: var(--indicator-opacity, 1);
  40. pointer-events: none;
  41. position: absolute;
  42. transition:
  43. opacity 200ms ease-out,
  44. box-shadow 100ms ease-in-out,
  45. width 200ms cubic-bezier(0.22, 1.2, 0.36, 1),
  46. height 200ms cubic-bezier(0.22, 1.2, 0.36, 1),
  47. transform 300ms cubic-bezier(0.22, 1.2, 0.36, 1);
  48. will-change: transform;
  49. z-index: 0;
  50. }
  51. [data-slot="radio-group-item"] {
  52. display: flex;
  53. height: 100%;
  54. min-width: 0;
  55. position: relative;
  56. }
  57. &[data-fill] [data-slot="radio-group-item"] {
  58. flex: 1;
  59. }
  60. [data-slot="radio-group-item-input"] {
  61. border-width: 0;
  62. clip: rect(0 0 0 0);
  63. height: 1px;
  64. margin: -1px;
  65. overflow: hidden;
  66. padding: 0;
  67. position: absolute;
  68. white-space: nowrap;
  69. width: 1px;
  70. }
  71. [data-slot="radio-group-item-label"] {
  72. color: var(--text-weak);
  73. cursor: default;
  74. display: flex;
  75. align-items: center;
  76. justify-content: center;
  77. font-family: var(--font-family-sans);
  78. font-size: var(--font-size-small);
  79. font-weight: var(--font-weight-medium);
  80. flex: 1;
  81. height: 100%;
  82. line-height: 1;
  83. padding: var(--radio-group-padding);
  84. position: relative;
  85. transition:
  86. color 200ms ease-out,
  87. opacity 200ms ease-out;
  88. user-select: none;
  89. }
  90. [data-slot="radio-group-item-control"] {
  91. align-items: center;
  92. border-radius: var(--radius-xs);
  93. display: inline-flex;
  94. height: 100%;
  95. justify-content: center;
  96. min-width: 0;
  97. padding: var(--radio-group-control-padding, 0 10px);
  98. transition: background-color 200ms ease-out;
  99. width: 100%;
  100. }
  101. &[data-pad="none"] {
  102. --radio-group-control-padding: 0;
  103. }
  104. &[data-pad="normal"] {
  105. --radio-group-control-padding: 0 10px;
  106. }
  107. /* Checked state */
  108. [data-slot="radio-group-item-input"][data-checked] + [data-slot="radio-group-item-label"] {
  109. color: var(--text-strong);
  110. }
  111. /* Hover state: match the inset background (adds subtle density) */
  112. [data-slot="radio-group-item-input"]:not([data-checked], [data-disabled])
  113. + [data-slot="radio-group-item-label"]:hover
  114. [data-slot="radio-group-item-control"] {
  115. background-color: var(--surface-inset-base);
  116. }
  117. /* Do not overlay hover on the active segment */
  118. [data-slot="radio-group-item-input"][data-checked]
  119. + [data-slot="radio-group-item-label"]:hover
  120. [data-slot="radio-group-item-control"] {
  121. background-color: transparent;
  122. }
  123. /* Disabled state */
  124. [data-slot="radio-group-item-input"][data-disabled] + [data-slot="radio-group-item-label"] {
  125. cursor: not-allowed;
  126. opacity: 0.5;
  127. }
  128. /* Focus state */
  129. [data-slot="radio-group-wrapper"]:has([data-slot="radio-group-item-input"]:focus-visible)
  130. [data-slot="radio-group-indicator"] {
  131. box-shadow: var(--shadow-xs-border-focus);
  132. }
  133. /* Hide indicator when nothing is checked */
  134. [data-slot="radio-group-wrapper"]:not(:has([data-slot="radio-group-item-input"][data-checked]))
  135. [data-slot="radio-group-indicator"] {
  136. --indicator-opacity: 0;
  137. }
  138. /* Vertical orientation */
  139. &[aria-orientation="vertical"] [data-slot="radio-group-items"] {
  140. flex-direction: column;
  141. }
  142. /* Small size variant */
  143. &[data-size="small"] {
  144. --radio-group-height: 24px;
  145. --radio-group-gap: 3px;
  146. --radio-group-padding: 2px;
  147. [data-slot="radio-group-item-label"] {
  148. font-size: 12px;
  149. }
  150. [data-slot="radio-group-item-control"] {
  151. padding: var(--radio-group-control-padding, 0 8px);
  152. }
  153. }
  154. &[data-size="small"][data-pad="normal"] {
  155. --radio-group-control-padding: 0 8px;
  156. }
  157. /* Disabled root state */
  158. &[data-disabled] {
  159. opacity: 0.5;
  160. cursor: not-allowed;
  161. }
  162. }