CodeBlock.module.css 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. /* Visual baseline: deepsuite `@deepseek/md` code-block.css. Highlight colors
  2. stay on the existing shiki `--shiki-*` sheet (not Prism highlight.css). */
  3. .block {
  4. --dsl-code-block-banner-background-color: var(--dsw-alias-markdown-code-block-banner);
  5. --dsl-code-block-border-radius: 12px;
  6. /* Local 11/18 instead of the shared --dsw-font-xs-13: the banner scales
  7. with the markdown 0.875 ladder without shrinking every other xs-13 use. */
  8. --dsl-code-block-banner-font: 11px/18px var(--dsw-font-family);
  9. --dsl-code-block-banner-height: 36px;
  10. --dsl-code-block-content-font: var(--dsw-font-markdown-code-block);
  11. --dsl-code-block-background: var(--dsw-alias-markdown-code-block);
  12. position: relative;
  13. width: 100%;
  14. max-width: 100%;
  15. margin: 16px 0;
  16. color: var(--dsw-alias-label-primary);
  17. background: var(--dsl-code-block-background);
  18. border-radius: var(--dsl-code-block-border-radius);
  19. }
  20. .block:not(:last-child) {
  21. margin-bottom: 11px;
  22. }
  23. .bannerWrap {
  24. position: sticky;
  25. top: 0;
  26. z-index: 6;
  27. background-color: var(--dsw-alias-bg-base);
  28. border-top-left-radius: var(--dsl-code-block-border-radius);
  29. border-top-right-radius: var(--dsl-code-block-border-radius);
  30. transition: opacity 160ms ease;
  31. }
  32. .block[data-preview] .bannerWrap {
  33. opacity: 0;
  34. }
  35. .block[data-preview]:hover .bannerWrap,
  36. .block[data-preview]:has(:focus-visible) .bannerWrap {
  37. opacity: 1;
  38. }
  39. .banner {
  40. background: var(--dsl-code-block-banner-background-color);
  41. padding: 4px 10px 4px 14px;
  42. display: flex;
  43. justify-content: space-between;
  44. align-items: center;
  45. gap: 12px;
  46. font: var(--dsl-code-block-banner-font);
  47. border-top-left-radius: var(--dsl-code-block-border-radius);
  48. border-top-right-radius: var(--dsl-code-block-border-radius);
  49. }
  50. .infostring {
  51. color: var(--dsw-alias-label-primary);
  52. font-family: var(--ds-font-family-code);
  53. font-size: 11px;
  54. line-height: 18px;
  55. min-width: 0;
  56. overflow: hidden;
  57. text-overflow: ellipsis;
  58. white-space: nowrap;
  59. }
  60. .action {
  61. min-height: 28px;
  62. display: flex;
  63. align-items: center;
  64. flex-shrink: 0;
  65. gap: 2px;
  66. }
  67. /* Match the sidebar pane controls: a 28px circle around a 15px glyph. */
  68. .iconButton {
  69. display: inline-flex;
  70. flex: none;
  71. align-items: center;
  72. justify-content: center;
  73. box-sizing: border-box;
  74. width: 28px;
  75. height: 28px;
  76. padding: 6px;
  77. color: var(--dsw-alias-label-secondary);
  78. line-height: 1;
  79. background: transparent;
  80. border: none;
  81. border-radius: 28px;
  82. cursor: pointer;
  83. }
  84. .iconButton svg {
  85. width: 15px;
  86. height: 15px;
  87. }
  88. .iconButton:hover:not(:disabled) {
  89. background: var(--dsw-alias-interactive-bg-hover);
  90. }
  91. .iconButton[aria-pressed='true'] {
  92. background: var(--dsw-alias-interactive-bg-hover);
  93. color: var(--dsw-alias-label-primary);
  94. }
  95. .iconButton:disabled {
  96. color: var(--dsw-alias-label-tertiary);
  97. cursor: default;
  98. }
  99. .previewActionSlot,
  100. .iconSlot {
  101. display: inline-flex;
  102. }
  103. .segments {
  104. position: relative;
  105. display: grid;
  106. grid-auto-flow: column;
  107. grid-auto-columns: 1fr;
  108. padding: 2px;
  109. margin-left: 4px;
  110. border-radius: 8px;
  111. background: var(--dsw-alias-interactive-bg-hover);
  112. isolation: isolate;
  113. }
  114. .selection {
  115. position: absolute;
  116. inset: 2px;
  117. width: calc((100% - 4px) / 2);
  118. border-radius: 6px;
  119. background: var(--dsw-alias-bg-base);
  120. transition: transform 160ms ease;
  121. z-index: -1;
  122. }
  123. .segments[data-preview-selected] .selection {
  124. transform: translateX(100%);
  125. }
  126. .segments:has(.sourceOnly) .selection {
  127. width: calc(100% - 4px);
  128. }
  129. .segments button,
  130. .sourceOnly {
  131. border: 0;
  132. background: transparent;
  133. color: inherit;
  134. padding: 2px 8px;
  135. font: inherit;
  136. white-space: nowrap;
  137. text-align: center;
  138. }
  139. .segments button {
  140. cursor: pointer;
  141. }
  142. .segments button[aria-pressed='false'] {
  143. color: var(--dsw-alias-label-secondary);
  144. }
  145. .body {
  146. min-height: 0;
  147. }
  148. .previewActionSlot[hidden] {
  149. display: none;
  150. }
  151. .sourceHidden {
  152. visibility: hidden;
  153. pointer-events: none;
  154. }
  155. @media (prefers-reduced-motion: reduce) {
  156. .selection { transition: none; }
  157. .bannerWrap { transition: none; }
  158. }
  159. @media (hover: none) {
  160. .block[data-preview] .bannerWrap { opacity: 1; }
  161. }
  162. .block :where(pre) {
  163. font: var(--dsl-code-block-content-font);
  164. padding: 16px;
  165. margin: 0 !important;
  166. overflow-x: auto;
  167. white-space: pre-wrap;
  168. word-break: break-all;
  169. background: var(--dsl-code-block-background);
  170. /* Bottom radii live on <pre>: overflow:hidden on .block would kill the
  171. sticky banner, and this opaque fill otherwise squares off the wrapper. */
  172. border-bottom-left-radius: var(--dsl-code-block-border-radius);
  173. border-bottom-right-radius: var(--dsl-code-block-border-radius);
  174. }
  175. /* Shiki inlines its theme background var; route it to the repo token. */
  176. .block :where(pre.shiki) {
  177. background: var(--dsl-code-block-background) !important;
  178. }
  179. .block :where(pre) code {
  180. font: inherit;
  181. background: none;
  182. padding: 0;
  183. }
  184. .plain {
  185. color: var(--dsw-alias-label-primary);
  186. }
  187. .previewLayer {
  188. display: grid;
  189. overflow: auto;
  190. background: var(--dsl-code-block-background);
  191. border-bottom-right-radius: var(--dsl-code-block-border-radius);
  192. border-bottom-left-radius: var(--dsl-code-block-border-radius);
  193. }
  194. /* The retained image sizes both views without laying out hidden source. */
  195. .previewLayer[hidden] {
  196. display: grid;
  197. visibility: hidden;
  198. pointer-events: none;
  199. }
  200. .previewable > .body {
  201. position: absolute;
  202. inset: 0;
  203. overflow: auto;
  204. border-radius: inherit;
  205. }
  206. .previewable[data-code-block-header] > .body {
  207. inset-block-start: var(--dsl-code-block-banner-height);
  208. }
  209. .numbered :where(pre) code {
  210. display: block;
  211. counter-reset: source-line;
  212. white-space: normal;
  213. }
  214. .numbered :where(pre) code > :global(.line) {
  215. position: relative;
  216. display: block;
  217. min-height: 1lh;
  218. padding-inline-start: calc(var(--dsl-code-block-line-number-width) + 12px);
  219. counter-increment: source-line;
  220. white-space: var(--dsl-code-block-line-white-space, pre-wrap);
  221. }
  222. .numbered :where(pre) code > :global(.line)::before {
  223. position: absolute;
  224. inset-inline-start: 0;
  225. width: var(--dsl-code-block-line-number-width);
  226. color: var(--dsw-alias-label-tertiary);
  227. text-align: end;
  228. content: counter(source-line);
  229. user-select: none;
  230. }
  231. @media (max-width: 480px) {
  232. .banner {
  233. gap: 4px;
  234. padding-inline: 8px;
  235. }
  236. .segments {
  237. margin-left: 0;
  238. }
  239. .segments button,
  240. .sourceOnly {
  241. padding-inline: 4px;
  242. }
  243. }