Skip to content

Commit

Permalink
feat(cxl-ui): add cxl-search-filters and related components
Browse files Browse the repository at this point in the history
  • Loading branch information
freudFlintstone committed Jul 28, 2023
1 parent 8fa92d6 commit d1b7a38
Show file tree
Hide file tree
Showing 17 changed files with 585 additions and 1 deletion.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"@commitlint/cli": "^12.0.1",
"@commitlint/config-conventional": "^12.0.1",
"@commitlint/config-lerna-scopes": "^12.1.4",
"@lit-labs/observers": "^2.0.0",
"@open-wc/testing-helpers": "^0.9.5",
"@size-limit/file": "^6.0.3",
"@webcomponents/webcomponentsjs": "^2.2.10",
Expand Down
1 change: 1 addition & 0 deletions packages/cxl-lumo-styles/src/icons.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion packages/cxl-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"directory": "packages/cxl-ui"
},
"dependencies": {
"@conversionxl/cxl-lumo-styles": "^1.6.4"
"@conversionxl/cxl-lumo-styles": "^1.6.4",
"@lit-labs/observers": "^2.0.0"
},
"devDependencies": {
"@conversionxl/normalize-wheel": "^1.0.1",
Expand Down
29 changes: 29 additions & 0 deletions packages/cxl-ui/scss/cxl-filter-header-item.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
:host {
font-weight: 400;

vaadin-button {
background-color: transparent;
border-radius: var(--lumo-border-radius-s) var(--lumo-border-radius-s) 0 0 ;
margin-bottom: 0;

&::part(label) {
color: var(--lumo-shade);
}
}

.label {
font-weight: 600;
}
}

:host(.checked) {
color: var(--lumo-contrast);

vaadin-button, vaadin-button {
background-color: var(--lumo-primary-color);

&::part(label) {
color: var(--lumo-base-color);
}
}
}
114 changes: 114 additions & 0 deletions packages/cxl-ui/scss/cxl-filter-header.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
@use "~@conversionxl/cxl-lumo-styles/scss/mq";

:host {
display: block;
font-weight: 400;

.container {
width: 100%;
}

.tabs {
display: flex;
position: relative;
width: 100%;

.scroll-control {
position: absolute;

&:first-child {
left: -2px;
background: linear-gradient(to left, rgba(255, 255, 255, 0), var(--lumo-base-color));
z-index: 1;
}

&:last-child {
right: -2px;
background: linear-gradient(to right, rgba(255, 255, 255, 0), var(--lumo-base-color));
z-index: 1;
}
}
}

.filters {
display: flex;
border-bottom: 1px solid var(--lumo-shade-20pct);
max-width: 100%;
overflow-x: scroll;
scroll-snap-type: x mandatory;
-webkit-overflow-scrolling: touch;
scroll-behavior: smooth;

&::-webkit-scrollbar {
display: none;
}

/* This seems more future-proof than \`overflow: -moz-scrollbars-none\` which is marked obsolete
and is no longer guaranteed to work:
https://developer.mozilla.org/en-US/docs/Web/CSS/overflow#Mozilla_Extensions
*/
@-moz-document url-prefix() {
overflow: hidden;
}

::slotted(*) {
scroll-snap-align: start;
scroll-snap-stop: always;
}

}

.controls {
display: flex;
flex-direction: row-reverse;
flex-wrap: wrap-reverse;
justify-content: stretch;
padding-top: var(--lumo-space-l);
gap: var(--lumo-space-m);

.flex-group {
display: flex;
flex-direction: row-reverse;
justify-content: stretch;
width: 100%;
gap: var(--lumo-space-m);

> ::slotted(*) {
flex: 1;
width: auto !important;
}

#show-filters {
--lumo-button-size: var(--lumo-size-l);
display: block;
margin: 0;
text-align: start;
flex-basis: 50%;
}
}

::slotted([slot="search"]) {
width: 100%;
line-height: var(--lumo-size-l);
}
}

@media #{mq.$small} {
.controls {
flex-direction: row;
flex-wrap: nowrap;

.flex-group {
width: auto;

#show-filters {
display: none;
}
}

.search {
line-height: normal;
}
}
}
}
24 changes: 24 additions & 0 deletions packages/cxl-ui/scss/cxl-search-filters-item.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
:host {
display: flex;
justify-content: space-between;
font-size: var(--lumo-font-size-s);
gap: var(--lumo-space-s);

.count {
color: var(--lumo-shade-60pct);
}

vaadin-checkbox {
font-size: var(--lumo-font-size-s);
--vaadin-checkbox-size: var(--lumo-font-size-s);

// Checkbox style can't be matched with current design tokens
&::part(checkbox) {
// border-radius: calc(var(--lumo-border-radius-s) / 2);
// background-color: transparent;
// border: 1px solid var(--lumo-shade-60pct);
margin-right: var(--lumo-space-s);
}
}

}
23 changes: 23 additions & 0 deletions packages/cxl-ui/scss/cxl-search-filters-panel.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@

:host {
display: block;
min-width: 240px;

.content {
display: flex;
flex-direction: column;
}
vaadin-accordion-panel {
font-size: var(--lumo-font-size-s);

&::part(summary-content) {
font-weight: 600;
color: var(--lumo-contrast);
font-size: var(--lumo-font-size-s);
}

&::part(toggle) {
background-color: unset;
}
}
}
13 changes: 13 additions & 0 deletions packages/cxl-ui/scss/cxl-search-filters.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
:host {
display: flex;
flex-direction: column;
align-items: start;
gap: var(--lumo-space-m);

header {
color: var(--lumo-shade-60pct);
font-size: var(--lumo-font-size-s);
font-weight: 300;
text-transform: uppercase;
}
}
29 changes: 29 additions & 0 deletions packages/cxl-ui/src/components/cxl-filter-header-item.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/* eslint-disable import/no-extraneous-dependencies */
import { LitElement, html } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import '@vaadin/button';
import cxlFilterHeaderItemStyles from '../styles/cxl-filter-header-item-css.js';

@customElement('cxl-filter-header-item')
export class CXLFilterHeaderItemElement extends LitElement {
static get styles() {
return [cxlFilterHeaderItemStyles];
}

@property({ type: String }) label = '';
@property({ type: String }) value = '';

@property({ type: Number }) count = 0;

@property({ type: Boolean, reflect: true }) checked = false;

render () {
return html`
<vaadin-button>
<span class="label">${this.label}</span>
<span class="count">(${this.count})</span>
</vaadin-button>
`
}
}
95 changes: 95 additions & 0 deletions packages/cxl-ui/src/components/cxl-filter-header.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/* eslint-disable import/no-extraneous-dependencies */
import { LitElement, html } from 'lit';
import { ResizeController } from '@lit-labs/observers/resize-controller.js';
import { customElement, state, query } from 'lit/decorators.js';
import './cxl-vaadin-accordion';
import '@vaadin/button'
import cxlDashboardFilterHeaderStyles from '../styles/cxl-filter-header-css.js';

const supportsScrollEndEvent = 'onscrollend' in window
const isFirefox = document.scrollingElement.scrollLeftMax !== undefined

@customElement('cxl-filter-header')
export class CXLFilterHeaderElement extends LitElement {
static get styles() {
return [cxlDashboardFilterHeaderStyles];
}

@state() tabsWidth = 0

@state() tabsNumber = 1

@query('.filters') filtersContainer = null

@query('#filters-slot') filtersSlot = null

isOverflowing = new ResizeController(this, {
callback: (entries) => {
const entry = entries[0];
this.showScrollers = entry && entry.borderBoxSize[0].inlineSize < this.tabsWidth;
return this.showScrollers
}
});

_checkTabsMaxWidth () {
if (!this.filtersSlot) return 0
const tabs = this.filtersSlot.assignedElements()
const fullWidth = tabs.map(tab => tab.clientWidth).reduce((total, w) => total + w, 0);
this.tabsWidth = fullWidth
this.tabsNumber = tabs.length
return this.tabsWidth
}

_scrollForwards () {
// `behavior: 'smooth'` option not being used due to firefox bug
this.filtersContainer.scrollBy({ left: (this.filtersContainer.scrollWidth - this.filtersContainer.clientWidth), behavior: isFirefox ? 'instant' : 'smooth' })
// Workaround for browsers that don't support scrollend event to update rendering
if (!supportsScrollEndEvent) {
setTimeout(() => { this.requestUpdate() }, 100)
}
}

_scrollBackwards () {
// `behavior: 'smooth'` option not being used due to firefox bug
this.filtersContainer.scrollBy({ left: -(this.filtersContainer.scrollWidth - this.filtersContainer.clientWidth), behavior: isFirefox ? 'instant' : 'smooth' })
// Workaround for browsers that don't support scrollend event to update rendering
if (!supportsScrollEndEvent) {
setTimeout(() => { this.requestUpdate() }, 100)
}
}

get showBackwardScroller () {
return this.isOverflowing.value && this.filtersContainer.scrollLeft > 0
}

get showForwardScroller () {
return this.isOverflowing.value && this.filtersContainer.scrollLeft < (this.filtersContainer.scrollWidth - this.filtersContainer.clientWidth)
}


render () {
return html`
<div class="container">
<div class="tabs">
<vaadin-button ?hidden=${!this.showBackwardScroller} class="scroll-control backwards" theme="icon tertiary" @click=${this._scrollBackwards}><vaadin-icon icon="lumo:angle-left"></vaadin-icon></vaadin-button>
<div class="filters" @scrollend=${() => { this.requestUpdate() }}>
<slot id="filters-slot" @slotchange=${this._checkTabsMaxWidth}></slot>
</div>
<vaadin-button ?hidden=${!this.showForwardScroller} class="scroll-control forwards" theme="icon tertiary" @click=${this._scrollForwards}><vaadin-icon icon="lumo:angle-right"></vaadin-icon></vaadin-button>
</div>
<div class="controls">
<!-- search -->
<slot name="search"></slot>
<div class="flex-group">
<!-- sort -->
<slot name="sort"></slot>
<vaadin-button id="show-filters">
<vaadin-icon icon="vaadin:filter" slot="prefix"></vaadin-icon>
<span>Filters</span>
</vaadin-button>
</div>
</div>
</div>
`
}
}
Loading

0 comments on commit d1b7a38

Please sign in to comment.