TerminalBlock.module.css 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /* Geometry mirrors CodeBlock (12px radius, code-block surface + banner rows,
  2. markdown code-block font) so a terminal card and a fenced code block read as
  3. one family. The one deliberate divergence: output keeps `white-space: pre`
  4. and scrolls horizontally, because folding a column-aligned command's output
  5. destroys its alignment. */
  6. .block {
  7. --dsl-terminal-radius: 12px;
  8. --dsl-terminal-line-height: 22px;
  9. /* The card's own left inset, holding the run-state dot in a column of its own
  10. so it never competes with the commands for horizontal space. */
  11. --dsl-terminal-gutter: 30px;
  12. position: relative;
  13. margin: 16px 0;
  14. /* The gutter is the card's OWN padding, not a margin: every consumer rewrites
  15. `margin` wholesale (each render site sets its own indent), which silently
  16. cancelled the reservation and let the dot fall outside the card into a
  17. container that clips it. Owning the reservation here keeps the invariant
  18. with the component that depends on it. */
  19. padding-left: var(--dsl-terminal-gutter);
  20. color: var(--dsw-alias-label-primary);
  21. background: var(--dsw-alias-markdown-code-block);
  22. border-radius: var(--dsl-terminal-radius);
  23. }
  24. /* Top-aligned: the status pill and copy control stay on the first prompt row
  25. however many command lines the card carries. */
  26. .header {
  27. display: flex;
  28. align-items: flex-start;
  29. gap: 12px;
  30. /* Pulled back across the card's gutter padding so the banner background and
  31. its top-left radius span the FULL surface, then re-inset by the same amount
  32. so the prompt text and the dot keep their positions. A plain block child
  33. only reaches the content box, which left the gutter column painted in the
  34. body color and drew the card's top-left corner in it — invisible in the
  35. light theme, where banner and body share a token, and visible in the dark
  36. one, where they do not. */
  37. margin-left: calc(-1 * var(--dsl-terminal-gutter));
  38. padding: 9px 14px 9px var(--dsl-terminal-gutter);
  39. background: var(--dsw-alias-markdown-code-block-banner);
  40. border-top-left-radius: var(--dsl-terminal-radius);
  41. border-top-right-radius: var(--dsl-terminal-radius);
  42. }
  43. /* One row per command line. The prompt column is the only element allowed to
  44. shrink; the status pill and the copy control keep their intrinsic width. */
  45. .prompt {
  46. display: flex;
  47. flex-direction: column;
  48. min-width: 0;
  49. flex: 1;
  50. font: var(--dsw-font-markdown-code-block);
  51. }
  52. .promptLine {
  53. position: relative;
  54. display: flex;
  55. align-items: baseline;
  56. gap: 8px;
  57. min-width: 0;
  58. line-height: var(--dsl-terminal-line-height);
  59. }
  60. /* Out of flow inside the card's own gutter padding, so the reservation and the
  61. dot move together and no consumer margin can pull them apart; the dot neither
  62. indents its command nor depends on the command's text metrics to line up.
  63. Centered against the row's line box, not the code font's baseline. */
  64. .runState {
  65. position: absolute;
  66. left: calc(-1 * var(--dsl-terminal-gutter) + 8px);
  67. top: 50%;
  68. transform: translateY(-50%);
  69. }
  70. /* The dot is aria-hidden; this is its text label for assistive technology. */
  71. .runStateLabel {
  72. position: absolute;
  73. width: 1px;
  74. height: 1px;
  75. overflow: hidden;
  76. clip-path: inset(50%);
  77. white-space: nowrap;
  78. }
  79. .cwd {
  80. flex: none;
  81. color: var(--dsw-alias-label-tertiary);
  82. }
  83. /* `pre`, not `nowrap`: the prompt row renders the command verbatim, and
  84. `nowrap` collapses the repeated spaces, tabs, and alignment of an indented
  85. continuation. Both hold the single row and the ellipsis. */
  86. .command {
  87. min-width: 0;
  88. color: var(--dsw-alias-label-primary);
  89. overflow: hidden;
  90. text-overflow: ellipsis;
  91. white-space: pre;
  92. }
  93. .status {
  94. flex: none;
  95. color: var(--dsw-alias-state-error-primary);
  96. }
  97. .copyButton {
  98. flex: none;
  99. background-color: transparent;
  100. border: none;
  101. padding: 0;
  102. margin: 0;
  103. color: var(--dsw-alias-label-secondary);
  104. cursor: pointer;
  105. font: var(--dsw-font-xs-13);
  106. }
  107. .output {
  108. padding: 12px 14px 12px 0;
  109. font: var(--dsw-font-markdown-code-block);
  110. overflow-x: auto;
  111. overflow-y: hidden;
  112. }
  113. /* No wrapping, no word-break: alignment is the payload of terminal output. */
  114. .line {
  115. min-height: var(--dsl-terminal-line-height);
  116. white-space: pre;
  117. }
  118. .expand {
  119. display: block;
  120. width: 100%;
  121. padding: 0;
  122. border: none;
  123. background-color: transparent;
  124. color: var(--dsw-alias-label-tertiary);
  125. cursor: pointer;
  126. font: inherit;
  127. text-align: left;
  128. }
  129. .expand:hover {
  130. color: var(--dsw-alias-label-secondary);
  131. }
  132. .empty {
  133. padding: 12px 14px 12px 0;
  134. font: var(--dsw-font-markdown-code-block);
  135. color: var(--dsw-alias-label-tertiary);
  136. }