file-tree.scss 19 KB

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