diff options
| author | Nikhil M Warrier <nikhilmwarrier@disroot.org> | 2026-09-05 21:22:09 +0530 |
|---|---|---|
| committer | Nikhil M Warrier <nikhilmwarrier@disroot.org> | 2026-09-05 21:36:20 +0530 |
| commit | 0de50f40eb826c2a127bb4b12b4d3c11f0c90f15 (patch) | |
| tree | fb188110c709c3c26a6c30c8895bd5311631c7ee | |
| parent | 7538b6a88405c5903e14f7fa7832c560f39c7fe5 (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.css | 308 | ||||
| -rw-r--r-- | assets/index.html | 96 | ||||
| -rw-r--r-- | assets/index.js | 44 |
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> |
