aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNikhil M Warrier <nikhilmwarrier@disroot.org>2026-09-05 21:22:09 +0530
committerNikhil M Warrier <nikhilmwarrier@disroot.org>2026-09-05 21:36:20 +0530
commit0de50f40eb826c2a127bb4b12b4d3c11f0c90f15 (patch)
treefb188110c709c3c26a6c30c8895bd5311631c7ee
parent7538b6a88405c5903e14f7fa7832c560f39c7fe5 (diff)
Reskin file manager UI with Linear-style polish
- Refresh design tokens and dark/light palette (accent #5e6ad2, #0a0a0a dark) - Glass sticky header, targeted hover/transition, focus rings, reduced-motion support - Swap all icons to Lucide stroke icons (CSS drives color via vars) - Animate menu/more popovers closed; enforce only one open at a time - Right-align desktop header toolbar; even icon spacing - Single shared subgrid for table header + rows so columns align exactly
-rw-r--r--assets/index.css308
-rw-r--r--assets/index.html96
-rw-r--r--assets/index.js44
3 files changed, 338 insertions, 110 deletions
diff --git a/assets/index.css b/assets/index.css
index 181e333..601e274 100644
--- a/assets/index.css
+++ b/assets/index.css
@@ -1,5 +1,7 @@
* {
- box-sizing: border-box;
+ box-sizing: border-box;
+ scrollbar-width: thin;
+ scrollbar-color: var(--border-secondary) transparent;
}
:root {
@@ -7,16 +9,20 @@
--bg-primary: #fff;
--bg-secondary: #fafafa;
--bg-tertiary: #fff;
- --bg-hover: #fafafa;
- --text-primary: #24292e;
- --text-secondary: #5c5c5c;
- --text-tertiary: #586069;
- --text-accent: #0366d6;
- --svg-primary: #24292e;
- --svg-secondary: rgba(3, 47, 98, 0.5);
- --svg-tertiary: #24292e;
- --border-primary: #ddd;
- --border-secondary: #ced4da;
+ --bg-hover: #f5f5f5;
+ --text-primary: #0a0a0a;
+ --text-secondary: #606060;
+ --text-tertiary: #8a8a8a;
+ --text-accent: #111;
+ --svg-primary: #0a0a0a;
+ --svg-secondary: #666;
+ --svg-tertiary: #666;
+ --border-primary: rgba(0, 0, 0, 0.09);
+ --border-secondary: #e5e5e5;
+ --accent: #5e6ad2;
+ --shadow-pop: 0 8px 24px rgba(0, 0, 0, 0.08);
+ --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
+ --duration-fast: 120ms;
}
html {
@@ -31,7 +37,12 @@ body {
}
svg {
- fill: var(--svg-primary);
+ fill: none;
+ stroke: var(--svg-primary);
+ stroke-width: 2;
+ stroke-linecap: round;
+ stroke-linejoin: round;
+ transition: stroke var(--duration-fast) ease;
}
.hidden {
@@ -48,21 +59,36 @@ svg {
position: sticky;
top: 0;
background-color: var(--bg-tertiary);
+ border-bottom: 1px solid var(--border-primary);
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
+}
+
+@supports ((backdrop-filter: blur(0px)) or (-webkit-backdrop-filter: blur(0px))) {
+ .head {
+ background-color: color-mix(in srgb, var(--bg-tertiary) 85%, transparent);
+ -webkit-backdrop-filter: blur(12px) saturate(180%);
+ backdrop-filter: blur(12px) saturate(180%);
+ }
}
.breadcrumb {
font-size: 1.25em;
padding-right: 0.6em;
word-break: break-all;
+ font-weight: 600;
+ letter-spacing: -0.01em;
}
.breadcrumb>a {
color: var(--text-accent);
text-decoration: none;
+ text-decoration-color: transparent;
+ text-underline-offset: 3px;
}
.breadcrumb>a:hover {
text-decoration: underline;
+ text-decoration-color: currentColor;
}
/* final breadcrumb */
@@ -77,7 +103,7 @@ svg {
.breadcrumb svg {
height: 100%;
- fill: var(--svg-secondary);
+ stroke: var(--svg-secondary);
}
.toolbox {
@@ -110,13 +136,18 @@ svg {
justify-content: center;
flex-wrap: nowrap;
background-color: var(--bg-secondary);
- transition: all .15s;
+ transition: border-color var(--duration-fast) var(--ease-out), box-shadow var(--duration-fast) var(--ease-out);
border: 1px var(--border-primary) solid;
border-radius: 15px;
margin-bottom: 2px;
padding-left: 0.5rem;
}
+.searchbar:focus-within {
+ border-color: var(--accent);
+ box-shadow: 0 0 0 3px rgba(94, 106, 210, 0.18);
+}
+
.searchbar #search {
box-sizing: border-box;
width: 100%;
@@ -138,15 +169,18 @@ svg {
}
.searchbar svg {
- fill: var(--svg-tertiary);
+ stroke: var(--svg-tertiary);
}
.main {
- padding: 0 1em;
+ padding: 0;
}
.empty-folder {
- font-style: italic;
+ color: var(--text-tertiary);
+ text-align: center;
+ padding: 3rem 1rem;
+ animation: fade-in 200ms ease-out;
}
.uploaders-table th {
@@ -169,29 +203,71 @@ svg {
display: inline-block;
}
-.paths-header-row,
+@media (min-width: 768px) {
+ .paths-table {
+ display: grid;
+ grid-template-columns: 24px minmax(0, 1fr) 120px 70px 130px;
+ column-gap: 1.5em;
+ align-items: center;
+ }
+
+ .paths-header,
+ .paths-body {
+ display: contents;
+ }
+
+ .paths-header-row,
+ .path-item {
+ display: grid;
+ grid-column: 1 / -1;
+ grid-template-columns: subgrid;
+ align-items: center;
+ }
+}
+
.path-item {
- display: grid;
- grid-template-columns: 24px minmax(0, 1fr) 120px 70px 130px;
- align-items: center;
- column-gap: 1.5em;
- padding: 0.4em 0;
+ padding: 0.4em;
+ border-radius: 6px;
+ transition: background-color var(--duration-fast) ease;
}
-.path-item:hover {
- background-color: var(--bg-hover);
+@media (hover: hover) and (pointer: fine) {
+ .path-item:hover {
+ background-color: var(--bg-hover);
+ }
+
+ .path-item .cell-actions {
+ opacity: 0.4;
+ transition: opacity var(--duration-fast) ease;
+ }
+
+ .path-item:hover .cell-actions {
+ opacity: 1;
+ }
}
.paths-header-row {
+ padding: 0.4em 1em;
color: var(--text-secondary);
font-weight: unset;
border-bottom: 1px solid var(--border-primary);
+ font-size: 0.9em;
+ letter-spacing: 0.02em;
}
.paths-header-row .h-sort {
color: unset;
text-decoration: none;
white-space: nowrap;
+ transition: color var(--duration-fast) ease;
+}
+
+.paths-header-row .h-sort:hover {
+ color: var(--text-primary);
+}
+
+.paths-header-row .h-sort.active {
+ color: var(--accent);
}
.paths-header-row .h-sort>span {
@@ -211,6 +287,7 @@ svg {
.path-item .cell-actions {
display: flex;
align-items: center;
+ justify-content: flex-start;
}
.path-item .cell-more {
@@ -221,7 +298,7 @@ svg {
.path svg,
.path-item .cell-icon svg {
height: 16px;
- fill: var(--svg-secondary);
+ stroke: var(--svg-secondary);
vertical-align: text-top;
}
@@ -236,15 +313,30 @@ svg {
overflow: hidden;
display: block;
text-decoration: none;
+ text-decoration-color: transparent;
+ text-underline-offset: 2px;
+ font-weight: 500;
}
.path-item .cell-name a:hover {
text-decoration: underline;
+ text-decoration-color: currentColor;
}
.action-btn {
padding-right: 0.3em;
cursor: pointer;
+ transition: transform 100ms ease-out, opacity var(--duration-fast) ease;
+}
+
+.action-btn:active {
+ transform: scale(0.9);
+}
+
+@media (hover: hover) and (pointer: fine) {
+ .action-btn:hover svg {
+ stroke: var(--accent);
+ }
}
.uploaders-table {
@@ -263,6 +355,25 @@ svg {
color: var(--text-primary);
outline: none;
padding: 5px;
+ transition: border-color var(--duration-fast) ease, box-shadow var(--duration-fast) ease;
+}
+
+.editor:focus {
+ border-color: var(--accent);
+ box-shadow: 0 0 0 3px rgba(94, 106, 210, 0.18);
+}
+
+a:focus-visible,
+.control:focus-visible,
+.login-btn:focus-visible,
+.logout-btn:focus-visible,
+.save-btn:focus-visible,
+.action-btn:focus-visible,
+.menu-btn:focus-visible,
+.more-btn:focus-visible
+{
+ outline: 2px solid var(--accent);
+ outline-offset: 2px;
}
.toolbox-right {
@@ -287,7 +398,9 @@ svg {
}
.user-name {
- padding-left: 3px;
+ padding-left: 0.5em;
+ font-size: 0.9rem;
+ color: var(--text-secondary);
}
.not-editable {
@@ -299,6 +412,10 @@ svg {
}
@media (min-width: 768px) {
+ .cell-icon {
+ margin-right: -1.75em;
+ }
+
.menu,
.menu-content {
display: contents;
@@ -308,6 +425,49 @@ svg {
.menu-btn {
display: none;
}
+
+ .toolbox {
+ margin-left: auto;
+ gap: 1em;
+ }
+
+ .toolbox .control {
+ padding-left: 0;
+ }
+
+ .searchbar {
+ margin-right: 10px;
+ }
+
+ .toolbox-right {
+ margin-left: 0;
+ margin-right: 0;
+ }
+
+ .toolbox .control,
+ .toolbox-right>div,
+ .toolbox>a {
+ transition: transform 100ms ease-out, background-color var(--duration-fast) ease;
+ border-radius: 6px;
+ }
+
+ .toolbox .control:hover,
+ .toolbox-right>div:hover,
+ .toolbox>a:hover {
+ background-color: var(--bg-hover);
+ }
+
+ .toolbox .control:hover svg,
+ .toolbox-right>div:hover svg,
+ .toolbox>a:hover svg {
+ stroke: var(--accent);
+ }
+
+ .toolbox .control:active,
+ .toolbox-right>div:active,
+ .toolbox>a:active {
+ transform: scale(0.9);
+ }
}
@media (max-width: 767.98px) {
@@ -330,22 +490,32 @@ svg {
}
.menu-content {
- display: none;
position: absolute;
right: 0;
top: calc(100% + 6px);
z-index: 100;
+ display: flex;
flex-direction: column;
min-width: 250px;
padding: 0.4em;
background-color: var(--bg-tertiary);
border: 1px solid var(--border-primary);
border-radius: 10px;
- box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
+ box-shadow: var(--shadow-pop);
+ opacity: 0;
+ visibility: hidden;
+ transform: translateY(-4px) scale(0.96);
+ transform-origin: top right;
+ pointer-events: none;
+ transition: opacity 150ms var(--ease-out), transform 150ms var(--ease-out), visibility 0s linear 150ms;
}
.menu-toggle:checked ~ .menu-content {
- display: flex;
+ opacity: 1;
+ visibility: visible;
+ transform: translateY(0) scale(1);
+ pointer-events: auto;
+ transition-delay: 0s;
}
.menu-content .searchbar {
@@ -459,24 +629,34 @@ svg {
}
.more-panel {
- display: none;
position: absolute;
right: 0;
top: 100%;
z-index: 100;
+ display: flex;
flex-direction: column;
gap: 0.5em;
padding: 0.6em;
background-color: var(--bg-tertiary);
border: 1px solid var(--border-primary);
- border-radius: 6px;
- box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
+ border-radius: 8px;
+ box-shadow: var(--shadow-pop);
min-width: 180px;
white-space: nowrap;
+ opacity: 0;
+ visibility: hidden;
+ transform: translateY(-4px) scale(0.96);
+ transform-origin: top right;
+ pointer-events: none;
+ transition: opacity 150ms var(--ease-out), transform 150ms var(--ease-out), visibility 0s linear 150ms;
}
.more-toggle:checked ~ .more-panel {
- display: flex;
+ opacity: 1;
+ visibility: visible;
+ transform: translateY(0) scale(1);
+ pointer-events: auto;
+ transition-delay: 0s;
}
.more-row {
@@ -508,18 +688,54 @@ svg {
@media (prefers-color-scheme: dark) {
:root {
color-scheme: dark;
- --bg-primary: #000;
+ --bg-primary: #0a0a0a;
--bg-secondary: #111;
- --bg-tertiary: #111;
- --bg-hover: #1a1a1a;
- --text-primary: #fff;
- --text-secondary: #ccc;
- --text-tertiary: #586069; /*Unchanged in both color schemes*/
- --text-accent: #3191ff;
- --svg-primary: #fff;
- --svg-secondary: #fff;
- --svg-tertiary: #fff6;
- --border-primary: #fff6;
- --border-secondary: #ced4da; /*Unchanged in both color schemes*/
+ --bg-tertiary: #0f0f10;
+ --bg-hover: #161617;
+ --text-primary: #ededed;
+ --text-secondary: #9a9a9a;
+ --text-tertiary: #71717a;
+ --text-accent: #ededed;
+ --svg-primary: #ededed;
+ --svg-secondary: #a1a1aa;
+ --svg-tertiary: #a1a1aa;
+ --border-primary: rgba(255, 255, 255, 0.12);
+ --border-secondary: #2a2a2b;
+ --shadow-pop: 0 8px 24px rgba(0, 0, 0, 0.5);
+ }
+}
+
+@keyframes fade-in {
+ from {
+ opacity: 0;
+ transform: translateY(2px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+.status-swap {
+ animation: fade-in 200ms ease-out;
+}
+
+.cell-icon {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.path-basename {
+ font-weight: 500;
+}
+
+@media (prefers-reduced-motion: reduce) {
+ *,
+ *::before,
+ *::after {
+ animation-duration: 0.01ms !important;
+ animation-iteration-count: 1 !important;
+ transition-duration: 0.01ms !important;
}
}
diff --git a/assets/index.html b/assets/index.html
index 79487e3..280101b 100644
--- a/assets/index.html
+++ b/assets/index.html
@@ -17,69 +17,71 @@
<div class="menu">
<input type="checkbox" id="menu-toggle" class="menu-toggle">
<label for="menu-toggle" class="menu-btn" title="Menu">
- <svg width="22" height="22" viewBox="0 0 16 16">
- <path fill-rule="evenodd"
- d="M2.5 12a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5z" />
+ <svg width="22" height="22" viewBox="0 0 24 24" fill="none">
+ <line x1="4" x2="20" y1="6" y2="6" />
+ <line x1="4" x2="20" y1="12" y2="12" />
+ <line x1="4" x2="20" y1="18" y2="18" />
</svg>
</label>
<div class="menu-content">
<div class="toolbox">
<a href="" class="control download hidden" title="Download file" download="">
- <svg width="16" height="16" viewBox="0 0 16 16">
- <path
- d="M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5z" />
- <path
- d="M7.646 11.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V1.5a.5.5 0 0 0-1 0v8.793L5.354 8.146a.5.5 0 1 0-.708.708l3 3z" />
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none">
+ <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
+ <polyline points="7 10 12 15 17 10" />
+ <line x1="12" x2="12" y1="15" y2="3" />
</svg>
</a>
<div class="control move-file hidden" title="Move & Rename">
- <svg class="icon-move" width="16" height="16" viewBox="0 0 16 16">
- <path fill-rule="evenodd"
- d="M1.5 1.5A.5.5 0 0 0 1 2v4.8a2.5 2.5 0 0 0 2.5 2.5h9.793l-3.347 3.346a.5.5 0 0 0 .708.708l4.2-4.2a.5.5 0 0 0 0-.708l-4-4a.5.5 0 0 0-.708.708L13.293 8.3H3.5A1.5 1.5 0 0 1 2 6.8V2a.5.5 0 0 0-.5-.5z">
- </path>
+ <svg class="icon-move" width="16" height="16" viewBox="0 0 24 24" fill="none">
+ <path d="M12 2v20" />
+ <path d="m15 19-3 3-3-3" />
+ <path d="m19 9 3 3-3 3" />
+ <path d="M2 12h20" />
+ <path d="m5 9-3 3 3 3" />
+ <path d="m9 5 3-3 3 3" />
</svg>
</div>
<div class="control delete-file hidden" title="Delete">
- <svg class="icon-delete" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
- <path
- d="M6.854 7.146a.5.5 0 1 0-.708.708L7.293 9l-1.147 1.146a.5.5 0 0 0 .708.708L8 9.707l1.146 1.147a.5.5 0 0 0 .708-.708L8.707 9l1.147-1.146a.5.5 0 0 0-.708-.708L8 8.293 6.854 7.146z" />
- <path
- d="M14 14V4.5L9.5 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2zM9.5 3A1.5 1.5 0 0 0 11 4.5h2V14a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h5.5v2z" />
+ <svg class="icon-delete" width="16" height="16" viewBox="0 0 24 24" fill="none">
+ <path d="M3 6h18" />
+ <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" />
+ <path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" />
+ <line x1="10" x2="10" y1="11" y2="17" />
+ <line x1="14" x2="14" y1="11" y2="17" />
</svg>
</div>
<div class="control upload-file hidden" title="Upload files/folders">
<label for="file">
- <svg width="16" height="16" viewBox="0 0 16 16">
- <path
- d="M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5z" />
- <path
- d="M7.646 1.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1-.708.708L8.5 2.707V11.5a.5.5 0 0 1-1 0V2.707L5.354 4.854a.5.5 0 1 1-.708-.708l3-3z" />
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none">
+ <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
+ <polyline points="17 8 12 3 7 8" />
+ <line x1="12" x2="12" y1="3" y2="15" />
</svg>
</label>
<input type="file" id="file" title="Upload files/folders" name="file" multiple>
</div>
<div class="control new-folder hidden" title="New folder">
- <svg width="16" height="16" viewBox="0 0 16 16">
- <path
- d="m.5 3 .04.87a1.99 1.99 0 0 0-.342 1.311l.637 7A2 2 0 0 0 2.826 14H9v-1H2.826a1 1 0 0 1-.995-.91l-.637-7A1 1 0 0 1 2.19 4h11.62a1 1 0 0 1 .996 1.09L14.54 8h1.005l.256-2.819A2 2 0 0 0 13.81 3H9.828a2 2 0 0 1-1.414-.586l-.828-.828A2 2 0 0 0 6.172 1H2.5a2 2 0 0 0-2 2zm5.672-1a1 1 0 0 1 .707.293L7.586 3H2.19c-.24 0-.47.042-.683.12L1.5 2.98a1 1 0 0 1 1-.98h3.672z" />
- <path
- d="M13.5 10a.5.5 0 0 1 .5.5V12h1.5a.5.5 0 1 1 0 1H14v1.5a.5.5 0 1 1-1 0V13h-1.5a.5.5 0 0 1 0-1H13v-1.5a.5.5 0 0 1 .5-.5z" />
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none">
+ <path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z" />
+ <line x1="12" x2="12" y1="11" y2="17" />
+ <line x1="9" x2="15" y1="14" y2="14" />
</svg>
</div>
<div class="control new-file hidden" title="New File">
- <svg width="16" height="16" viewBox="0 0 16 16">
- <path
- d="M8 6.5a.5.5 0 0 1 .5.5v1.5H10a.5.5 0 0 1 0 1H8.5V11a.5.5 0 0 1-1 0V9.5H6a.5.5 0 0 1 0-1h1.5V7a.5.5 0 0 1 .5-.5z" />
- <path
- d="M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5L14 4.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5h-2z" />
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none">
+ <path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" />
+ <path d="M14 2v4a2 2 0 0 0 2 2h4" />
+ <path d="M9 15h6" />
+ <path d="M12 12v6" />
</svg>
</div>
</div>
<form class="searchbar hidden">
<div class="icon">
- <svg width="16" height="16" viewBox="0 0 16 16">
- <path
- d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z" />
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none">
+ <circle cx="11" cy="11" r="8" />
+ <path d="m21 21-4.3-4.3" />
</svg>
</div>
<input id="search" title="Searching for folders or files" name="q" type="text" maxlength="128" autocomplete="off"
@@ -88,25 +90,25 @@
</form>
<div class="toolbox-right">
<div class="login-btn hidden" title="Login">
- <svg width="16" height="16" viewBox="0 0 16 16">
- <path fill-rule="evenodd"
- d="M6 3.5a.5.5 0 0 1 .5-.5h8a.5.5 0 0 1 .5.5v9a.5.5 0 0 1-.5.5h-8a.5.5 0 0 1-.5-.5v-2a.5.5 0 0 0-1 0v2A1.5 1.5 0 0 0 6.5 14h8a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 14.5 2h-8A1.5 1.5 0 0 0 5 3.5v2a.5.5 0 0 0 1 0v-2z" />
- <path fill-rule="evenodd"
- d="M11.854 8.354a.5.5 0 0 0 0-.708l-3-3a.5.5 0 1 0-.708.708L10.293 7.5H1.5a.5.5 0 0 0 0 1h8.793l-2.147 2.146a.5.5 0 0 0 .708.708l3-3z" />
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none">
+ <path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4" />
+ <polyline points="10 17 15 12 10 7" />
+ <line x1="15" x2="3" y1="12" y2="12" />
</svg>
</div>
<div class="logout-btn hidden" title="Logout">
- <svg width="16" height="16" viewBox="0 0 16 16">
- <path fill-rule="evenodd" d="M10 3.5a.5.5 0 0 0-.5-.5h-8a.5.5 0 0 0-.5.5v9a.5.5 0 0 0 .5.5h8a.5.5 0 0 0 .5-.5v-2a.5.5 0 0 1 1 0v2A1.5 1.5 0 0 1 9.5 14h-8A1.5 1.5 0 0 1 0 12.5v-9A1.5 1.5 0 0 1 1.5 2h8A1.5 1.5 0 0 1 11 3.5v2a.5.5 0 0 1-1 0z"/>
- <path fill-rule="evenodd" d="M4.146 8.354a.5.5 0 0 1 0-.708l3-3a.5.5 0 1 1 .708.708L5.707 7.5H14.5a.5.5 0 0 1 0 1H5.707l2.147 2.146a.5.5 0 0 1-.708.708z"/>
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none">
+ <path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" />
+ <polyline points="16 17 21 12 16 7" />
+ <line x1="21" x2="9" y1="12" y2="12" />
</svg>
<span class="user-name"></span>
</div>
<div class="save-btn hidden" title="Save file">
- <svg viewBox="0 0 1024 1024" width="24" height="24">
- <path
- d="M426.666667 682.666667v42.666666h170.666666v-42.666666h-170.666666z m-42.666667-85.333334h298.666667v128h42.666666V418.133333L605.866667 298.666667H298.666667v426.666666h42.666666v-128h42.666667z m260.266667-384L810.666667 379.733333V810.666667H213.333333V213.333333h430.933334zM341.333333 341.333333h85.333334v170.666667H341.333333V341.333333z"
- p-id="8311"></path>
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none">
+ <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" />
+ <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" />
+ <path d="M7 3v4a1 1 0 0 0 1 1h7" />
</svg>
</div>
</div>
diff --git a/assets/index.js b/assets/index.js
index f95bd6e..f15ce9c 100644
--- a/assets/index.js
+++ b/assets/index.js
@@ -53,15 +53,15 @@ const IFRAME_FORMATS = [
const MAX_SUBPATHS_COUNT = 1000;
const ICONS = {
- dir: `<svg height="16" viewBox="0 0 14 16" width="14"><path fill-rule="evenodd" d="M13 4H7V3c0-.66-.31-1-1-1H1c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1V5c0-.55-.45-1-1-1zM6 4H1V3h5v1z"></path></svg>`,
- symlinkFile: `<svg height="16" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M8.5 1H1c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h10c.55 0 1-.45 1-1V4.5L8.5 1zM11 14H1V2h7l3 3v9zM6 4.5l4 3-4 3v-2c-.98-.02-1.84.22-2.55.7-.71.48-1.19 1.25-1.45 2.3.02-1.64.39-2.88 1.13-3.73.73-.84 1.69-1.27 2.88-1.27v-2H6z"></path></svg>`,
- symlinkDir: `<svg height="16" viewBox="0 0 14 16" width="14"><path fill-rule="evenodd" d="M13 4H7V3c0-.66-.31-1-1-1H1c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1V5c0-.55-.45-1-1-1zM1 3h5v1H1V3zm6 9v-2c-.98-.02-1.84.22-2.55.7-.71.48-1.19 1.25-1.45 2.3.02-1.64.39-2.88 1.13-3.73C4.86 8.43 5.82 8 7.01 8V6l4 3-4 3H7z"></path></svg>`,
- file: `<svg height="16" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M6 5H2V4h4v1zM2 8h7V7H2v1zm0 2h7V9H2v1zm0 2h7v-1H2v1zm10-7.5V14c0 .55-.45 1-1 1H1c-.55 0-1-.45-1-1V2c0-.55.45-1 1-1h7.5L12 4.5zM11 5L8 2H1v12h10V5z"></path></svg>`,
- download: `<svg width="16" height="16" viewBox="0 0 16 16"><path d="M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5z"/><path d="M7.646 11.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V1.5a.5.5 0 0 0-1 0v8.793L5.354 8.146a.5.5 0 1 0-.708.708l3 3z"/></svg>`,
- move: `<svg width="16" height="16" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M1.5 1.5A.5.5 0 0 0 1 2v4.8a2.5 2.5 0 0 0 2.5 2.5h9.793l-3.347 3.346a.5.5 0 0 0 .708.708l4.2-4.2a.5.5 0 0 0 0-.708l-4-4a.5.5 0 0 0-.708.708L13.293 8.3H3.5A1.5 1.5 0 0 1 2 6.8V2a.5.5 0 0 0-.5-.5z"/></svg>`,
- edit: `<svg width="16" height="16" viewBox="0 0 16 16"><path d="M12.146.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1 0 .708l-10 10a.5.5 0 0 1-.168.11l-5 2a.5.5 0 0 1-.65-.65l2-5a.5.5 0 0 1 .11-.168l10-10zM11.207 2.5 13.5 4.793 14.793 3.5 12.5 1.207 11.207 2.5zm1.586 3L10.5 3.207 4 9.707V10h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.293l6.5-6.5zm-9.761 5.175-.106.106-1.528 3.821 3.821-1.528.106-.106A.5.5 0 0 1 5 12.5V12h-.5a.5.5 0 0 1-.5-.5V11h-.5a.5.5 0 0 1-.468-.325z"/></svg>`,
- delete: `<svg width="16" height="16" viewBox="0 0 16 16"><path d="M6.854 7.146a.5.5 0 1 0-.708.708L7.293 9l-1.147 1.146a.5.5 0 0 0 .708.708L8 9.707l1.146 1.147a.5.5 0 0 0 .708-.708L8.707 9l1.147-1.146a.5.5 0 0 0-.708-.708L8 8.293 6.854 7.146z"/><path d="M14 14V4.5L9.5 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2zM9.5 3A1.5 1.5 0 0 0 11 4.5h2V14a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h5.5v2z"/></svg>`,
- view: `<svg width="16" height="16" viewBox="0 0 16 16"><path d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8zM1.173 8a13.133 13.133 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.133 13.133 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5c-2.12 0-3.879-1.168-5.168-2.457A13.134 13.134 0 0 1 1.172 8z"/><path d="M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5zM4.5 8a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0z"/></svg>`,
+ dir: `<svg width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"/></svg>`,
+ symlinkFile: `<svg width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="M4 11V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.706.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h7"/><path d="M14 2v5a1 1 0 0 0 1 1h5"/><path d="m10 18 3-3-3-3"/></svg>`,
+ symlinkDir: `<svg width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="M2 9.35V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h7"/><path d="m8 16 3-3-3-3"/></svg>`,
+ file: `<svg width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/></svg>`,
+ download: `<svg width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" x2="12" y1="15" y2="3"/></svg>`,
+ move: `<svg width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="M12 2v20"/><path d="m15 19-3 3-3-3"/><path d="m19 9 3 3-3 3"/><path d="M2 12h20"/><path d="m5 9-3 3 3 3"/><path d="m9 5 3-3 3 3"/></svg>`,
+ edit: `<svg width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z"/><path d="m15 5 4 4"/></svg>`,
+ delete: `<svg width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="M3 6h18"/><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/><line x1="10" x2="10" y1="11" y2="17"/><line x1="14" x2="14" y1="11" y2="17"/></svg>`,
+ view: `<svg width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0"/><circle cx="12" cy="12" r="3"/></svg>`,
}
/**
@@ -147,6 +147,15 @@ async function ready() {
document.querySelectorAll('.menu-toggle, .more-toggle').forEach(cb => cb.checked = false);
});
+ document.addEventListener('change', e => {
+ const t = e.target;
+ if (t.matches('.menu-toggle, .more-toggle') && t.checked) {
+ document.querySelectorAll('.menu-toggle, .more-toggle').forEach(cb => {
+ if (cb !== t) cb.checked = false;
+ });
+ }
+ });
+
addBreadcrumb(DATA.href, DATA.uri_prefix);
if (DATA.kind === "Index") {
@@ -279,7 +288,7 @@ class Uploader {
complete() {
const $uploadStatusNew = this.$uploadStatus.cloneNode(true);
- $uploadStatusNew.innerHTML = `✓`;
+ $uploadStatusNew.innerHTML = `<span class="status-swap">✓</span>`;
this.$uploadStatus.parentNode.replaceChild($uploadStatusNew, this.$uploadStatus);
this.$uploadStatus = null;
failUploaders.delete(this.idx);
@@ -288,7 +297,7 @@ class Uploader {
}
fail(reason = "") {
- this.$uploadStatus.innerHTML = `<span style="width: 20px;" title="${reason}">✗</span><span class="retry-btn" id="retry${this.idx}" title="Retry">↻</span>`;
+ this.$uploadStatus.innerHTML = `<span class="status-swap" style="width: 20px;" title="${reason}">✗</span><span class="retry-btn" id="retry${this.idx}" title="Retry">↻</span>`;
failUploaders.set(this.idx, this);
Uploader.runnings--;
Uploader.runQueue();
@@ -348,9 +357,9 @@ function addBreadcrumb(href, uri_prefix) {
}
const encodedName = encodedStr(name);
if (i === 0) {
- $breadcrumb.insertAdjacentHTML("beforeend", `<a href="${path}" title="Root"><svg width="16" height="16" viewBox="0 0 16 16"><path d="M6.5 14.5v-3.505c0-.245.25-.495.5-.495h2c.25 0 .5.25.5.5v3.5a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.146-.354L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.354 1.146a.5.5 0 0 0-.708 0l-6 6A.5.5 0 0 0 1.5 7.5v7a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5z"/></svg></a>`);
+ $breadcrumb.insertAdjacentHTML("beforeend", `<a href="${path}" title="Root"><svg width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg></a>`);
} else if (i === len - 1) {
- $breadcrumb.insertAdjacentHTML("beforeend", `<b>${encodedName}</b>`);
+ $breadcrumb.insertAdjacentHTML("beforeend", `<span class="path-basename">${encodedName}</span>`);
} else {
$breadcrumb.insertAdjacentHTML("beforeend", `<a href="${path}">${encodedName}</a>`);
}
@@ -417,19 +426,20 @@ function renderPathsTableHead() {
<div class="paths-header-row">
<span class="h-icon"></span>
${headerItems.map(item => {
- let svg = `<svg width="12" height="12" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M11.5 15a.5.5 0 0 0 .5-.5V2.707l3.146 3.147a.5.5 0 0 0 .708-.708l-4-4a.5.5 0 0 0-.708 0l-4 4a.5.5 0 1 0 .708.708L11 2.707V14.5a.5.5 0 0 0 .5.5zm-7-14a.5.5 0 0 1 .5.5v11.793l3.146-3.147a.5.5 0 0 1 .708.708l-4 4a.5.5 0 0 1-.708 0l-4-4a.5.5 0 0 1 .708-.708L4 13.293V1.5a.5.5 0 0 1 .5-.5z"/></svg>`;
+ let svg = `<svg width="12" height="12" viewBox="0 0 24 24" fill="none"><path d="m7 15 5 5 5-5"/><path d="m7 9 5-5 5 5"/></svg>`;
let order = "desc";
if (PARAMS.sort === item.name) {
if (PARAMS.order === "desc") {
order = "asc";
- svg = `<svg width="12" height="12" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8 1a.5.5 0 0 1 .5.5v11.793l3.146-3.147a.5.5 0 0 1 .708.708l-4 4a.5.5 0 0 1-.708 0l-4-4a.5.5 0 0 1 .708-.708L7.5 13.293V1.5A.5.5 0 0 1 8 1z"/></svg>`
+ svg = `<svg width="12" height="12" viewBox="0 0 24 24" fill="none"><path d="m18 15-6-6-6 6"/></svg>`
} else {
- svg = `<svg width="12" height="12" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8 15a.5.5 0 0 0 .5-.5V2.707l3.146 3.147a.5.5 0 0 0 .708-.708l-4-4a.5.5 0 0 0-.708 0l-4 4a.5.5 0 1 0 .708.708L7.5 2.707V14.5a.5.5 0 0 0 .5.5z"/></svg>`
+ svg = `<svg width="12" height="12" viewBox="0 0 24 24" fill="none"><path d="m6 9 6 6 6-6"/></svg>`
}
}
const qs = new URLSearchParams({ ...PARAMS, order, sort: item.name }).toString();
const icon = `<span>${svg}</span>`
- return `<a class="h-sort ${item.cls}" href="?${qs}">${item.text}${icon}</a>`
+ const active = PARAMS.sort === item.name ? " active" : "";
+ return `<a class="h-sort ${item.cls}${active}" href="?${qs}">${item.text}${icon}</a>`
}).join("\n")}
<span class="h-actions">Actions</span>
</div>