Skip to content

Commit

Permalink
GH-203 - Browse improvements
Browse files Browse the repository at this point in the history
1. Closing action bar resets state including rename input field.
2. Long operations should show status and prevent user interaction.
3. Add modified date to list view
4. Improve rename UX polish
5. Create ability to copy & paste in same folder by appending `-copy` to the item
6. Do no redundantly list breadcrumb path in search item list

1. Make renaming large items faster and more reliable.
2. Make copying large items faster more reliable.
3. Make deleting large items faster more reliable.

Resolves: GH-203
  • Loading branch information
auniverseaway committed Sep 8, 2024
1 parent e3ce5f1 commit 384a3ad
Show file tree
Hide file tree
Showing 26 changed files with 1,527 additions and 1,100 deletions.
4 changes: 4 additions & 0 deletions blocks/browse/browse.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
body {
background: rgb(245 245 245);
}

main {
position: relative;
}
61 changes: 61 additions & 0 deletions blocks/browse/da-actionbar/da-actionbar.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
button {
font-family: var(--body-font-family);
}

.da-action-bar {
bottom: 12px;
position: fixed;
background: #BC1C74;
min-height: 48px;
border-radius: 6px;
width: var(--grid-container-width);
z-index: 400;
filter: drop-shadow(rgb(0 0 0 / 15%) 0 1px 4px);
display: flex;
justify-content: space-between;
align-items: center;
padding: 4px;
box-sizing: border-box;
color: #FFF;
font-size: 14px;
}

.da-action-bar button {
background: none;
height: 32px;
color: #FFF;
border: none;
border-radius: 4px;
display: flex;
align-items: center;
gap: 12px;
padding: 0 12px;
}

.da-action-bar button:hover {
background-color: rgb(255 255 255 / 25%);
}

.da-action-bar button img {
display: block;
width: 18px;
height: 18px;
}

.da-action-bar-left-rail {
margin-left: 14px;
display: flex;
align-items: center;
gap: 12px;
}

.da-action-bar-right-rail {
margin: 0 3px;
display: flex;
gap: 8px;
}

.da-action-bar.hide,
.da-action-bar .hide {
display: none;
}
106 changes: 106 additions & 0 deletions blocks/browse/da-actionbar/da-actionbar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { LitElement, html } from '../../../deps/lit/lit-core.min.js';
import { getNx } from '../../../scripts/utils.js';

// Styles
const { default: getStyle } = await import(`${getNx()}/utils/styles.js`);
const STYLE = await getStyle(import.meta.url);

export default class DaActionBar extends LitElement {
static properties = {
items: { attribute: false },
_canPaste: { state: true },
};

constructor() {
super();
this.items = [];
}

connectedCallback() {
super.connectedCallback();
this.shadowRoot.adoptedStyleSheets = [STYLE];
}

async update(props) {
if (props.has('items')) {
// Reset state when items go empty
if (this.items.length === 0) {
this._canPaste = false;
}
}

super.update(props);
}

handleClear() {
this._canPaste = false;
const opts = { detail: true, bubbles: true, composed: true };
const event = new CustomEvent('clearselection', opts);
this.dispatchEvent(event);
}

handleRename() {
const opts = { detail: true, bubbles: true, composed: true };
const event = new CustomEvent('rename', opts);
this.dispatchEvent(event);
}

handleCopy() {
this._canPaste = true;
}

handlePaste() {
const opts = { bubbles: true, composed: true };
const event = new CustomEvent('onpaste', opts);
this.dispatchEvent(event);
}

handleDelete() {
const opts = { bubbles: true, composed: true };
const event = new CustomEvent('ondelete', opts);
this.dispatchEvent(event);
}

render() {
return html`
<div class="da-action-bar">
<div class="da-action-bar-left-rail">
<button
class="close-circle"
@click=${this.handleClear}
aria-label="Unselect items">
<img src="/blocks/browse/da-browse/img/CrossSize200.svg" />
</button>
<span>${this.items.length} selected</span>
</div>
<div class="da-action-bar-right-rail">
<button
@click=${this.handleRename}
class="rename-button ${this.items.length === 1 ? '' : 'hide'} ${this._canPaste ? 'hide' : ''}">
<img src="/blocks/browse/da-browse/img/Smock_TextEdit_18_N.svg" />
<span>Rename</span>
</button>
<button
@click=${this.handleCopy}
class="copy-button ${this._canPaste ? 'hide' : ''}">
<img src="/blocks/browse/da-browse/img/Smock_Copy_18_N.svg" />
<span>Copy</span>
</button>
<button
@click=${this.handlePaste}
class="copy-button ${this._canPaste ? '' : 'hide'}">
<img src="/blocks/browse/da-browse/img/Smock_Copy_18_N.svg" />
<span>Paste</span>
</button>
<button
@click=${this.handleDelete}
class="delete-button">
<img src="/blocks/browse/da-browse/img/Smock_Delete_18_N.svg" />
<span>Delete</span>
</button>
</div>
</div>`;
}
}

customElements.define('da-actionbar', DaActionBar);
99 changes: 99 additions & 0 deletions blocks/browse/da-breadcrumbs/da-breadcrumbs.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
:host > svg {
display: none;
}

button {
font-family: var(--body-font-family);
}

.da-breadcrumb {
margin-bottom: 12px;
}

.da-breadcrumb-list {
margin: 0 0 12px;
padding: 0 24px 0 0;
display: flex;
flex-wrap: wrap;
list-style: none;
gap: 12px 24px;
}

.da-breadcrumb-list-item {
position: relative;
display: block;
font-size: 16px;
font-weight: 700;
cursor: pointer;
}

.da-breadcrumb-list-item-link-wrapper {
padding: 0 10px;
background: #dcdcdc;
border-radius: 6px;
line-height: 32px;
display: flex;
overflow: hidden;
}

.da-breadcrumb-list-item a {
text-decoration: none;
color: rgb(44 44 44);
}

.da-breadcrumb-list-item-config {
overflow: hidden;
text-indent: -1000px;
width: 32px;
padding-right: 2px;
margin: 0 -10px 0 2px;
display: flex;
justify-content: center;
align-items: center;
color: rgb(44 44 44);
}

.da-breadcrumb-list-item-config:hover {
background-color: #147af3;
color: #FFF;
}

.da-breadcrumb-list-item-icon {
display: block;
width: 18px;
height: 18px;
}

.da-breadcrumb-list-item:last-child {
cursor: unset;
}

.da-breadcrumb-list-item::after {
position: absolute;
right: -24px;
top: 0;
display: block;
content: "";
width: 24px;
opacity: 0.5;
background: url('/blocks/browse/img/Smock_ChevronRight_18_N.svg') center center / 24px 24px no-repeat;
height: 32px;
}

@media (width >= 600px) {
.da-breadcrumb-list {
margin: 0;
}

.da-breadcrumb:has(da-search) .da-breadcrumb-list {
margin-bottom: 12px;
}
}

@media (min-width: 900px) {
.da-breadcrumb {
margin-bottom: 12px;
display: flex;
gap: 24px;
}
}
66 changes: 66 additions & 0 deletions blocks/browse/da-breadcrumbs/da-breadcrumbs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { LitElement, html } from '../../../deps/lit/lit-core.min.js';
import { getNx } from '../../../scripts/utils.js';

// Styles & Icons
const { default: getStyle } = await import(`${getNx()}/utils/styles.js`);
const { default: getSvg } = await import(`${getNx()}/utils/svg.js`);
const STYLE = await getStyle(import.meta.url);
const ICONS = ['/blocks/browse/da-browse/img/Smock_Settings_18_N.svg'];

export default class DaBreadcrumbs extends LitElement {
static properties = {
fullpath: { type: String },
depth: { type: Number },
_breadcrumbs: { state: true },
};

connectedCallback() {
super.connectedCallback();
this.shadowRoot.adoptedStyleSheets = [STYLE];
getSvg({ parent: this.shadowRoot, paths: ICONS });
}

update(props) {
this._breadcrumbs = this.getBreadcrumbs();
super.update(props);
}

getBreadcrumbs() {
const pathSplit = this.fullpath.split('/').filter((part) => part !== '');
return pathSplit.map((part, idx) => ({
name: part,
path: `#/${pathSplit.slice(0, idx + 1).join('/')}`,
}));
}

renderConfig(length, crumb, idx) {
if (this.depth <= 2 && idx + 1 === length) {
return html`
<a class="da-breadcrumb-list-item-config"
href="/config${crumb.path}/"
aria-label="Config">
<svg class="da-breadcrumb-list-item-icon"><use href="#spectrum-settings"/></svg>
</a>`;
}
return null;
}

render() {
return html`
<div class="da-breadcrumb">
<ul class="da-breadcrumb-list">
${this._breadcrumbs.map((crumb, idx) => html`
<li class="da-breadcrumb-list-item">
<div class=da-breadcrumb-list-item-link-wrapper>
<a href="${crumb.path}">${crumb.name}</a>
${this.renderConfig(this._breadcrumbs.length, crumb, idx)}
</a>
</li>
`)}
</ul>
</div>
`;
}
}

customElements.define('da-breadcrumbs', DaBreadcrumbs);
Loading

0 comments on commit 384a3ad

Please sign in to comment.