file-tree.scss 18 KB

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