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