file-tree.scss 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811
  1. :root {
  2. --file-tree-item-hover-bg: var(--bg-dark-secondary);
  3. --file-tree-item-selected-bg: var(--bg-accent-01);
  4. --file-tree-item-color: var(--content-primary-dark);
  5. --file-tree-bg: var(--bg-dark-tertiary);
  6. --file-tree-item-selected-color: var(--content-primary-dark);
  7. --file-tree-item-dragging-bg: #{rgb($bg-dark-secondary, 0.9)};
  8. --file-tree-item-dragging-color: var(--content-primary-dark);
  9. --file-tree-item-dragging-preview-bg: #{rgb($bg-accent-01, 0.6)};
  10. --file-tree-item-dragging-preview-colour: var(--content-primary-dark);
  11. --file-tree-line-height: 2.05;
  12. --file-tree-icon-colour: var(--content-disabled);
  13. }
  14. @include theme('light') {
  15. --file-tree-item-hover-bg: var(--bg-light-tertiary);
  16. --file-tree-item-color: var(--content-secondary);
  17. --file-tree-bg: var(--bg-light-primary);
  18. --file-tree-item-selected-color: var(--bg-light-primary);
  19. --file-tree-item-dragging-bg: #{rgb($bg-light-tertiary, 0.9)};
  20. --file-tree-item-dragging-color: var(--content-secondary);
  21. --file-tree-item-dragging-preview-colour: var(--bg-light-primary);
  22. .ide-redesign-main {
  23. --file-tree-item-hover-bg: var(--bg-light-secondary);
  24. --file-tree-item-selected-bg: var(--bg-accent-03);
  25. --file-tree-item-selected-color: var(--green-70);
  26. --file-tree-item-color: var(--content-primary);
  27. --file-tree-bg: var(--white);
  28. --file-tree-icon-colour: var(--content-primary);
  29. --file-tree-item-dragging-bg: #{rgb($bg-dark-primary, 0.9)};
  30. --file-tree-item-dragging-color: var(--white);
  31. --file-tree-item-dragging-preview-bg: #{rgb($bg-light-secondary, 0.6)};
  32. --file-tree-item-dragging-preview-colour: #{rgb($content-primary, 0.6)};
  33. --file-tree-expand-button-color: var(--content-primary);
  34. }
  35. }
  36. // TODO ide-redesign-cleanup: Replace the existing styling with these overrides.
  37. .ide-redesign-main {
  38. --file-tree-item-hover-bg: var(--bg-dark-secondary);
  39. --file-tree-item-selected-bg: var(--green-70);
  40. --file-tree-item-selected-color: var(--green-10);
  41. --file-tree-item-color: var(--content-primary-dark);
  42. --file-tree-bg: var(--bg-dark-primary);
  43. --file-tree-icon-colour: var(--content-primary-dark);
  44. --file-tree-item-dragging-bg: #{rgb($bg-light-primary, 0.9)};
  45. --file-tree-item-dragging-color: var(--content-secondary);
  46. --file-tree-item-dragging-preview-bg: var(--bg-light-primary);
  47. --file-tree-item-dragging-preview-colour: var(--bg-light-primary);
  48. --file-tree-expand-button-color: var(--content-primary-dark);
  49. .file-tree-outline-panel-group {
  50. background-color: var(--file-tree-bg);
  51. }
  52. .file-tree-toolbar {
  53. display: flex;
  54. justify-content: space-between;
  55. height: 28px;
  56. margin: var(--spacing-02);
  57. }
  58. .file-tree-panel {
  59. min-height: 36px;
  60. }
  61. .file-tree-panel-collapsed {
  62. max-height: 36px;
  63. }
  64. .file-tree-expand-collapse-button {
  65. border-radius: var(--border-radius-base);
  66. color: var(--file-tree-expand-button-color);
  67. display: flex;
  68. align-items: center;
  69. background-color: transparent;
  70. border: 0;
  71. padding: 0 var(--spacing-02);
  72. flex-grow: 1;
  73. overflow: hidden;
  74. &:hover {
  75. background-color: var(--file-tree-item-hover-bg);
  76. }
  77. h4 {
  78. color: var(--file-tree-expand-button-color);
  79. font-size: var(--font-size-02);
  80. margin: 0;
  81. font-weight: normal;
  82. overflow: hidden;
  83. text-overflow: ellipsis;
  84. white-space: nowrap;
  85. }
  86. }
  87. .file-tree-toolbar-action-buttons {
  88. display: flex;
  89. }
  90. .file-tree-toolbar-action-button {
  91. color: var(--file-tree-expand-button-color);
  92. padding: var(--spacing-02);
  93. border-radius: var(--border-radius-full);
  94. &:hover {
  95. background-color: var(--file-tree-item-hover-bg);
  96. }
  97. &:active {
  98. color: var(--file-tree-expand-button-color);
  99. }
  100. }
  101. .file-tree {
  102. background-color: var(--file-tree-bg);
  103. }
  104. .file-tree ul.file-tree-list {
  105. margin: var(--spacing-02);
  106. }
  107. .file-tree-folder-list {
  108. border-left: 1px solid
  109. color-mix(in srgb, var(--border-primary) 24%, transparent);
  110. margin-left: 14px !important;
  111. margin-top: 0;
  112. &.file-tree-list {
  113. border-left: none;
  114. margin-left: var(--spacing-02) !important;
  115. > .file-tree-folder-list-inner {
  116. margin-left: 0;
  117. }
  118. }
  119. }
  120. .file-tree-folder-list-inner {
  121. margin-left: 10px;
  122. display: flex;
  123. flex-direction: column;
  124. gap: var(--spacing-02);
  125. }
  126. .item-name-button,
  127. .folder-expand-collapse-button {
  128. display: flex;
  129. align-items: center;
  130. height: 20px !important;
  131. }
  132. .file-tree ul.file-tree-list li .material-symbols.file-tree-expand-icon {
  133. margin-left: 0;
  134. }
  135. .file-tree ul.file-tree-list li .material-symbols.file-tree-icon {
  136. margin-left: 0;
  137. margin-right: 0;
  138. }
  139. // TODO ide-redesign-cleanup: Remove the !important overrides once
  140. // we have replaced the default styling
  141. .linked-file-highlight {
  142. background-color: var(--file-tree-bg) !important;
  143. color: var(--file-tree-icon-colour) !important;
  144. left: 14px !important;
  145. }
  146. .entity-name {
  147. color: var(--file-tree-item-color);
  148. border-radius: var(--border-radius-base);
  149. padding: var(--spacing-02);
  150. // TODO ide-redesign-cleanup: This is here to override the fake-full-width-bg
  151. // mixin. We can just remove that mixin when we clean this up.
  152. &::before {
  153. content: none !important;
  154. }
  155. }
  156. .item-name-button {
  157. margin-left: var(--spacing-02);
  158. }
  159. .dnd-draggable-preview-item {
  160. border-radius: var(--border-radius-base);
  161. }
  162. }
  163. .ide-react-file-tree-panel {
  164. display: flex;
  165. flex-direction: column;
  166. // Prevent the file tree expanding beyond the boundary of the panel
  167. .file-tree {
  168. width: 100%;
  169. }
  170. }
  171. .context-menu {
  172. position: fixed;
  173. z-index: 100;
  174. }
  175. .editor-sidebar {
  176. background-color: var(--file-tree-bg);
  177. display: flex;
  178. flex-direction: column;
  179. }
  180. @mixin fake-full-width-bg($bg-color) {
  181. &::before {
  182. content: '\00a0';
  183. position: absolute;
  184. width: 9999px;
  185. left: -9999px;
  186. background-color: $bg-color;
  187. }
  188. }
  189. @include theme('default') {
  190. .file-tree {
  191. .toolbar {
  192. .toolbar-right,
  193. .toolbar-left {
  194. button {
  195. opacity: 0.8;
  196. &:hover,
  197. &:focus,
  198. &:active,
  199. &.active {
  200. background-color: rgba(125 125 125 / 20%);
  201. }
  202. &.active,
  203. &:active {
  204. background-color: rgba(125 125 125 / 40%);
  205. }
  206. }
  207. }
  208. }
  209. }
  210. }
  211. .file-tree {
  212. display: flex !important; // To work around jQuery layout's inline styles
  213. flex-direction: column;
  214. height: 100%;
  215. .file-tree-inner {
  216. position: relative;
  217. display: flex;
  218. flex-direction: column;
  219. flex-grow: 1;
  220. overflow-y: auto;
  221. width: inherit;
  222. height: inherit;
  223. font-size: var(--font-size-02);
  224. &.no-toolbar {
  225. top: 0;
  226. }
  227. }
  228. // TODO; Consolidate with "Project files" in Overleaf
  229. h3 {
  230. font-size: var(--font-size-03);
  231. border-bottom: 1px solid var(--border-primary);
  232. padding-bottom: var(--spacing-02);
  233. margin: var(--spacing-05);
  234. }
  235. .toolbar {
  236. .toolbar-right,
  237. .toolbar-left {
  238. button {
  239. display: inline-flex;
  240. align-items: center;
  241. justify-content: center;
  242. width: 24px;
  243. height: 24px;
  244. padding: 0;
  245. box-shadow: none;
  246. border-radius: var(--border-radius-base);
  247. border: none;
  248. &:hover,
  249. &:focus,
  250. &:active,
  251. &.active {
  252. background-color: rgb(125 125 125 / 10%);
  253. color: var(--toolbar-btn-color) !important;
  254. }
  255. &.active,
  256. &:active {
  257. background-color: rgb(125 125 125 / 20%);
  258. }
  259. }
  260. }
  261. }
  262. ul.file-tree-list {
  263. margin: 0;
  264. overflow: hidden auto;
  265. height: 100%;
  266. flex-grow: 1;
  267. position: relative;
  268. .entity > ul,
  269. ul[role='tree'] {
  270. margin-left: var(--spacing-08);
  271. }
  272. &::after {
  273. content: '';
  274. display: block;
  275. min-height: var(--spacing-08);
  276. }
  277. li {
  278. line-height: var(--file-tree-line-height);
  279. position: relative;
  280. .entity {
  281. user-select: none;
  282. }
  283. .entity > .entity-name {
  284. display: flex;
  285. align-items: center;
  286. & > button {
  287. background-color: transparent;
  288. border: 0;
  289. padding: 0;
  290. &.item-name-button {
  291. color: inherit;
  292. width: 100%;
  293. overflow: hidden;
  294. text-overflow: ellipsis;
  295. text-align: left;
  296. padding-right: var(--spacing-09);
  297. white-space: pre;
  298. }
  299. }
  300. }
  301. .entity-name {
  302. color: var(--file-tree-item-color);
  303. cursor: pointer;
  304. white-space: nowrap;
  305. overflow: hidden;
  306. text-overflow: ellipsis;
  307. &.entity-name-react {
  308. text-overflow: clip;
  309. }
  310. background-color: transparent;
  311. @include fake-full-width-bg(transparent);
  312. &:hover {
  313. background-color: var(--file-tree-item-hover-bg);
  314. // When the entity is a subfolder, the DOM element is "indented" via margin-left. This makes the
  315. // element not fill the entire file-tree width (as it's spaced from the left-hand side via margin)
  316. // and, in consequence, the background gets clipped. The ::before pseudo-selector is used to fill
  317. // the empty space.
  318. @include fake-full-width-bg(var(--file-tree-item-hover-bg));
  319. }
  320. input {
  321. line-height: 1.6;
  322. }
  323. .entity-menu-toggle > .material-symbols {
  324. color: var(--content-primary-dark);
  325. vertical-align: middle;
  326. }
  327. }
  328. .material-symbols {
  329. color: var(--file-tree-icon-colour);
  330. &.file-tree-icon {
  331. margin-right: var(--spacing-02);
  332. margin-left: var(--spacing-04);
  333. vertical-align: sub;
  334. &.linked-file-icon {
  335. position: relative;
  336. left: -2px;
  337. + .linked-file-highlight {
  338. color: var(--file-tree-bg);
  339. background-color: var(--content-disabled);
  340. position: absolute;
  341. top: 14px;
  342. left: 20px;
  343. font-size: var(--font-size-01);
  344. border-radius: var(--spacing-01);
  345. }
  346. }
  347. }
  348. &.file-tree-folder-icon {
  349. margin-right: var(--spacing-02);
  350. vertical-align: sub;
  351. }
  352. &.file-tree-expand-icon {
  353. margin-left: var(--spacing-04);
  354. vertical-align: sub;
  355. }
  356. }
  357. .material-symbols.toggle {
  358. width: 24px;
  359. padding: var(--spacing-03);
  360. font-size: var(--font-size-03);
  361. color: var(--file-tree-icon-colour);
  362. }
  363. .file-tree-dropdown-toggle {
  364. display: flex;
  365. align-items: center;
  366. color: var(--content-primary-dark);
  367. line-height: 1.6;
  368. font-size: var(--font-size-05);
  369. padding: 0 var(--font-size-02) 0 var(--font-size-04);
  370. &:hover,
  371. &:focus {
  372. text-decoration: none;
  373. }
  374. &::before {
  375. content: '\00B7\00B7\00B7';
  376. transform: rotate(90deg);
  377. letter-spacing: 0.5px;
  378. }
  379. }
  380. &.multi-selected {
  381. > .entity {
  382. > .entity-name {
  383. > div > .material-symbols,
  384. > button > .material-symbols,
  385. > .material-symbols,
  386. .entity-menu-toggle .material-symbols {
  387. color: var(--content-primary-dark);
  388. }
  389. > .material-symbols.linked-file-highlight {
  390. background-color: var(--bg-info-01);
  391. }
  392. @include fake-full-width-bg(var(--bg-info-01));
  393. color: var(--content-primary-dark);
  394. font-weight: bold;
  395. background-color: var(--bg-info-01);
  396. &:hover {
  397. background-color: var(--bg-info-02);
  398. @include fake-full-width-bg(var(--bg-info-02));
  399. }
  400. }
  401. }
  402. }
  403. .menu-button {
  404. position: absolute;
  405. right: 0;
  406. }
  407. .rename-input {
  408. display: block;
  409. position: absolute;
  410. top: 1px;
  411. left: 32px;
  412. right: 32px;
  413. color: var(--content-primary);
  414. input {
  415. width: 100%;
  416. }
  417. }
  418. > .entity > .entity-name {
  419. .entity-menu-toggle {
  420. display: none;
  421. }
  422. }
  423. .entity-limit-hit {
  424. line-height: var(--file-tree-line-height);
  425. color: var(--file-tree-item-color);
  426. margin-left: var(--spacing-05);
  427. white-space: nowrap;
  428. overflow: hidden;
  429. text-overflow: ellipsis;
  430. }
  431. .entity-limit-hit-message {
  432. font-style: italic;
  433. }
  434. .material-symbols .entity-limit-hit-tooltip-trigger {
  435. margin-left: var(spacing-03);
  436. cursor: pointer;
  437. }
  438. }
  439. }
  440. &:not(.multi-selected) {
  441. ul.file-tree-list li.selected {
  442. > .entity {
  443. > .entity-name {
  444. background-color: var(--file-tree-item-selected-bg);
  445. color: var(--file-tree-item-selected-color);
  446. > div > .material-symbols,
  447. > button > .material-symbols,
  448. > .material-symbols,
  449. .entity-menu-toggle .material-symbols {
  450. color: var(--file-tree-item-selected-color);
  451. }
  452. > .material-symbols.linked-file-highlight {
  453. background-color: var(--bg-info-01);
  454. }
  455. @include fake-full-width-bg(var(--file-tree-item-selected-bg));
  456. font-weight: bold;
  457. padding-right: var(--spacing-09);
  458. button {
  459. font-weight: inherit;
  460. }
  461. .entity-menu-toggle {
  462. display: inline-block;
  463. background-color: transparent;
  464. box-shadow: none;
  465. border: 0;
  466. padding-right: var(--spacing-02);
  467. padding-left: var(--spacing-02);
  468. }
  469. }
  470. }
  471. }
  472. }
  473. // while dragging, the previously selected item gets no highlight
  474. ul.file-tree-list.file-tree-dragging li.selected .entity .entity-name {
  475. @include fake-full-width-bg(transparent);
  476. font-weight: normal;
  477. background-color: transparent;
  478. color: var(--file-tree-item-color);
  479. .material-symbols {
  480. color: var(--content-disabled) !important;
  481. }
  482. }
  483. // the items being dragged get the full "hover" colour
  484. ul.file-tree-list.file-tree-dragging
  485. li
  486. .entity.file-tree-entity-dragging
  487. .entity-name {
  488. background-color: var(--file-tree-item-dragging-bg);
  489. @include fake-full-width-bg(var(--file-tree-item-dragging-bg));
  490. color: var(--file-tree-item-dragging-color);
  491. .material-symbols {
  492. color: var(--content-disabled) !important;
  493. }
  494. }
  495. // the drop target gets the "selected" colour
  496. ul.file-tree-list.file-tree-dragging
  497. li.dnd-droppable-hover
  498. .entity
  499. .entity-name {
  500. background-color: var(--file-tree-item-selected-bg);
  501. @include fake-full-width-bg(var(--file-tree-item-selected-bg));
  502. color: var(--file-tree-item-selected-color);
  503. .material-symbols {
  504. color: var(--file-tree-item-selected-color) !important;
  505. }
  506. }
  507. .dnd-draggable-preview-layer {
  508. position: absolute;
  509. pointer-events: none;
  510. z-index: 100;
  511. width: 100%;
  512. height: 100%;
  513. overflow: hidden;
  514. &.dnd-droppable-hover {
  515. border: 3px solid var(--file-tree-item-selected-bg);
  516. }
  517. }
  518. .dnd-draggable-preview-item {
  519. color: var(--file-tree-item-dragging-preview-colour);
  520. background-color: var(--file-tree-item-dragging-preview-bg);
  521. width: 75%;
  522. padding-left: var(--spacing-08);
  523. line-height: 2.05;
  524. overflow: hidden;
  525. text-overflow: ellipsis;
  526. white-space: nowrap;
  527. }
  528. .disconnected-overlay {
  529. background-color: var(--file-tree-bg);
  530. position: absolute;
  531. top: 0;
  532. left: 0;
  533. width: 100%;
  534. height: 100%;
  535. z-index: 10;
  536. opacity: 0.5;
  537. cursor: wait;
  538. }
  539. }
  540. .modal-new-file {
  541. padding: 0;
  542. table {
  543. width: 100%;
  544. table-layout: fixed;
  545. td {
  546. vertical-align: top;
  547. }
  548. }
  549. .toggle-file-type-button {
  550. font-size: var(--font-size-02);
  551. margin-top: calc(var(--spacing-05) * -1);
  552. .btn {
  553. display: inline-block;
  554. padding: 0;
  555. vertical-align: baseline;
  556. font-size: inherit;
  557. }
  558. .btn:focus-within {
  559. outline: none;
  560. text-decoration: none;
  561. }
  562. }
  563. }
  564. .modal-new-file-list {
  565. background-color: var(--bg-light-secondary);
  566. width: 220px;
  567. ul {
  568. li {
  569. /* old modal (a) */
  570. a {
  571. color: var(--content-secondary);
  572. padding: var(--spacing-03);
  573. display: block;
  574. text-decoration: none;
  575. }
  576. /* new modal (button) */
  577. .btn {
  578. color: var(--content-secondary);
  579. padding: var(--spacing-03);
  580. }
  581. .btn:hover {
  582. text-decoration: none;
  583. }
  584. .btn:focus {
  585. outline: none;
  586. text-decoration: none;
  587. background-color: white;
  588. }
  589. }
  590. li.active {
  591. background-color: white;
  592. /* old modal (a) */
  593. a {
  594. color: var(--link-ui);
  595. }
  596. /* new modal (button) */
  597. .btn {
  598. color: var(--link-ui);
  599. text-decoration: none;
  600. }
  601. }
  602. li:hover {
  603. background-color: white;
  604. }
  605. }
  606. }
  607. .file-tree-error {
  608. text-align: center;
  609. color: var(--content-secondary-dark);
  610. padding: 20px;
  611. }
  612. .file-tree-modal-alert {
  613. margin-top: var(--spacing-06);
  614. }
  615. .btn.modal-new-file-mode {
  616. justify-content: left;
  617. text-align: left;
  618. text-decoration: none;
  619. width: 100%;
  620. }
  621. .modal-new-file-body {
  622. padding: 20px;
  623. padding-top: var(--spacing-03);
  624. }
  625. .modal-new-file-body-upload {
  626. padding-top: 20px;
  627. }
  628. .modal-new-file-body-conflict {
  629. background-color: var(--bg-danger-03);
  630. border: 1px dashed var(--border-danger);
  631. min-height: 400px;
  632. border-radius: 3px;
  633. color: var(--content-primary);
  634. display: flex;
  635. flex-direction: column;
  636. justify-content: center;
  637. padding: var(--spacing-05);
  638. }
  639. .modal-footer {
  640. .approaching-file-limit {
  641. font-weight: bold;
  642. }
  643. .at-file-limit {
  644. text-align: left;
  645. }
  646. }
  647. /* stylelint-disable selector-class-pattern */
  648. .modal-new-file-body-upload .uppy-Root {
  649. font-family: inherit;
  650. }
  651. .modal-new-file-body-upload .uppy-Dashboard {
  652. .uppy-Dashboard-inner {
  653. border: none;
  654. }
  655. .uppy-Dashboard-dropFilesHereHint {
  656. inset: 0;
  657. }
  658. .uppy-Dashboard-AddFiles {
  659. margin: 0;
  660. border: 1px dashed var(--border-primary);
  661. height: 100%;
  662. .uppy-Dashboard-AddFiles-title {
  663. font-size: inherit;
  664. }
  665. }
  666. .uppy-Dashboard-AddFiles-title {
  667. width: 26em; // sized to create a wrap between the sentences
  668. max-width: 100%;
  669. }
  670. .uppy-Informer p {
  671. background-color: var(--bg-info-03);
  672. border: 1px solid var(--blue-20);
  673. border-radius: var(--border-radius-base);
  674. color: var(--content-primary);
  675. font-size: var(--font-size-03);
  676. }
  677. }