Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add basic dashboard section structure #7685

Merged
merged 8 commits into from
Aug 23, 2024
Merged
17 changes: 10 additions & 7 deletions dev/dashboard-layout.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<script type="module">
import '@vaadin/dashboard/vaadin-dashboard-layout.js';
import '@vaadin/dashboard/vaadin-dashboard-widget.js';
import '@vaadin/dashboard/vaadin-dashboard-section.js';
</script>

<style>
Expand Down Expand Up @@ -56,14 +57,16 @@
<div class="chart"></div>
</vaadin-dashboard-widget>

<vaadin-dashboard-widget widget-title="Sales closed this month">
<div class="kpi-number">54 000€</div>
</vaadin-dashboard-widget>
<vaadin-dashboard-section section-title="Section">
<vaadin-dashboard-widget widget-title="Sales closed this month">
<div class="kpi-number">54 000€</div>
</vaadin-dashboard-widget>

<vaadin-dashboard-widget widget-title="Just some number">
<span slot="header">2014-2024</span>
<div class="kpi-number">1234</div>
</vaadin-dashboard-widget>
<vaadin-dashboard-widget widget-title="Just some number">
<span slot="header">2014-2024</span>
<div class="kpi-number">1234</div>
</vaadin-dashboard-widget>
</vaadin-dashboard-section>

<vaadin-dashboard-widget>
<h2 slot="title">Activity since 2023</h2>
Expand Down
12 changes: 7 additions & 5 deletions packages/dashboard/src/title-controller.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@
import { SlotChildObserveController } from '@vaadin/component-base/src/slot-child-observe-controller.js';

/**
* A controller to manage the widget title element.
* A controller to manage the widget or section title element.
*/
export class TitleController extends SlotChildObserveController {
constructor(host: HTMLElement);

/**
* String used for the widget title.
* String used for the title.
*/
protected widgetTitle: string | null | undefined;
protected title: string | null | undefined;

/**
* Set widget title based on corresponding host property.
* Set title based on corresponding host property.
*/
setWidgetTitle(widgetTitle: string | null | undefined): void;
setTitle(title: string | null | undefined): void;
}
24 changes: 12 additions & 12 deletions packages/dashboard/src/title-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,36 @@
import { SlotChildObserveController } from '@vaadin/component-base/src/slot-child-observe-controller.js';

/**
* A controller to manage the widget title element.
* A controller to manage the widget or section title element.
*/
export class TitleController extends SlotChildObserveController {
constructor(host) {
super(host, 'title', null);
}

/**
* Set widget title based on corresponding host property.
* Set title based on corresponding host property.
*
* @param {string} widgetTitle
* @param {string} title
*/
setWidgetTitle(widgetTitle) {
this.widgetTitle = widgetTitle;
setTitle(title) {
this.title = title;

// Restore the default widgetTitle, if needed.
const widgetTitleNode = this.getSlotChild();
if (!widgetTitleNode) {
// Restore the default title, if needed.
const titleNode = this.getSlotChild();
if (!titleNode) {
this.restoreDefaultNode();
}

// When default widgetTitle is used, update it.
// When default title is used, update it.
if (this.node === this.defaultNode) {
this.updateDefaultNode(this.node);
}
}

/**
* Override method inherited from `SlotChildObserveController`
* to restore and observe the default widget title element.
* to restore and observe the default title element.
*
* @protected
* @override
Expand All @@ -47,15 +47,15 @@ export class TitleController extends SlotChildObserveController {

/**
* Override method inherited from `SlotChildObserveController`
* to update the default widgetTitle element text content.
* to update the default title element text content.
*
* @param {Node | undefined} node
* @protected
* @override
*/
updateDefaultNode(node) {
if (node) {
node.textContent = this.widgetTitle;
node.textContent = this.title;
}

// Notify the host after update.
Expand Down
5 changes: 4 additions & 1 deletion packages/dashboard/src/vaadin-dashboard-layout-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,13 @@ export const DashboardLayoutMixin = (superClass) =>
var(--_vaadin-dashboard-default-col-max-width)
);

/* Effective max column count */
--_vaadin-dashboard-col-max-count: var(--vaadin-dashboard-col-max-count, var(--_vaadin-dashboard-col-count));

/* Effective column count */
--_vaadin-dashboard-effective-col-count: min(
var(--_vaadin-dashboard-col-count),
var(--vaadin-dashboard-col-max-count)
var(--_vaadin-dashboard-col-max-count)
);

display: grid;
Expand Down
30 changes: 30 additions & 0 deletions packages/dashboard/src/vaadin-dashboard-section.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* @license
* Copyright (c) 2000 - 2024 Vaadin Ltd.
*
* This program is available under Vaadin Commercial License and Service Terms.
*
*
* See https://vaadin.com/commercial-license-and-service-terms for the full
* license.
*/
import { ControllerMixin } from '@vaadin/component-base/src/controller-mixin.js';
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';

/**
* A Section component for use with the Dashboard component
*/
declare class DashboardSection extends ControllerMixin(ElementMixin(HTMLElement)) {
/**
* The title of the section
*/
sectionTitle: string | null | undefined;
}

declare global {
interface HTMLElementTagNameMap {
'vaadin-dashboard-section': DashboardSection;
}
}

export { DashboardSection };
119 changes: 119 additions & 0 deletions packages/dashboard/src/vaadin-dashboard-section.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/**
* @license
* Copyright (c) 2000 - 2024 Vaadin Ltd.
*
* This program is available under Vaadin Commercial License and Service Terms.
*
*
* See https://vaadin.com/commercial-license-and-service-terms for the full
* license.
*/
import { html, LitElement } from 'lit';
import { ControllerMixin } from '@vaadin/component-base/src/controller-mixin.js';
import { defineCustomElement } from '@vaadin/component-base/src/define.js';
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
import { css } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
import { TitleController } from './title-controller.js';

/**
* A section component for use with the Dashboard component
*
* @customElement
* @extends HTMLElement
* @mixes ElementMixin
* @mixes ControllerMixin
*/
class DashboardSection extends ControllerMixin(ElementMixin(PolylitMixin(LitElement))) {
static get is() {
return 'vaadin-dashboard-section';
}

static get styles() {
return css`
:host {
display: grid;
grid-template-columns: subgrid;
--_vaadin-dashboard-section-column: 1 / calc(var(--_vaadin-dashboard-effective-col-count) + 1);
grid-column: var(--_vaadin-dashboard-section-column) !important;
gap: var(--vaadin-dashboard-gap, 1rem);
}

:host([hidden]) {
display: none !important;
}

::slotted(*) {
--_vaadin-dashboard-item-column: span
min(
var(--vaadin-dashboard-item-colspan, 1),
var(--_vaadin-dashboard-effective-col-count, var(--_vaadin-dashboard-col-count))
);

grid-column: var(--_vaadin-dashboard-item-column);
}

header {
display: flex;
grid-column: var(--_vaadin-dashboard-section-column);
justify-content: space-between;
align-items: center;
}
`;
}

static get properties() {
return {
/**
* The title of the section
*/
sectionTitle: {
type: String,
value: '',
observer: '__onSectionTitleChanged',
},
};
}

/** @protected */
render() {
return html`
<header>
<slot name="title" @slotchange="${this.__onTitleSlotChange}"></slot>
<div id="header-actions"></div>
</header>

<slot></slot>
`;
}

constructor() {
super();
this.__titleController = new TitleController(this);
this.__titleController.addEventListener('slot-content-changed', (event) => {
const { node } = event.target;
if (node) {
this.setAttribute('aria-labelledby', node.id);
}
});
}

/** @protected */
ready() {
super.ready();
this.addController(this.__titleController);

if (!this.hasAttribute('role')) {
this.setAttribute('role', 'section');
}
}

/** @private */
__onSectionTitleChanged(sectionTitle) {
this.__titleController.setTitle(sectionTitle);
}
}

defineCustomElement(DashboardSection);

export { DashboardSection };
2 changes: 1 addition & 1 deletion packages/dashboard/src/vaadin-dashboard-widget.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class DashboardWidget extends ControllerMixin(ElementMixin(PolylitMixin(LitEleme

/** @private */
__onWidgetTitleChanged(widgetTitle) {
this.__titleController.setWidgetTitle(widgetTitle);
this.__titleController.setTitle(widgetTitle);
}
}

Expand Down
Loading
Loading