diff --git a/packages/fiori/src/Timeline.ts b/packages/fiori/src/Timeline.ts index 0d475528ecab..e1568426d49f 100644 --- a/packages/fiori/src/Timeline.ts +++ b/packages/fiori/src/Timeline.ts @@ -5,14 +5,19 @@ import slot from "@ui5/webcomponents-base/dist/decorators/slot.js"; import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js"; import { getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js"; import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js"; -import { isTabNext, isTabPrevious } from "@ui5/webcomponents-base/dist/Keys.js"; -import ItemNavigation from "@ui5/webcomponents-base/dist/delegate/ItemNavigation.js"; +import { + isTabNext, + isTabPrevious, +} from "@ui5/webcomponents-base/dist/Keys.js"; import type { ITabbable } from "@ui5/webcomponents-base/dist/delegate/ItemNavigation.js"; +import type ToggleButton from "@ui5/webcomponents/dist/ToggleButton.js"; +import ItemNavigation from "@ui5/webcomponents-base/dist/delegate/ItemNavigation.js"; import NavigationMode from "@ui5/webcomponents-base/dist/types/NavigationMode.js"; import { getEventMark } from "@ui5/webcomponents-base/dist/MarkedEvents.js"; import { TIMELINE_ARIA_LABEL } from "./generated/i18n/i18n-defaults.js"; import TimelineTemplate from "./generated/templates/TimelineTemplate.lit.js"; import TimelineItem from "./TimelineItem.js"; +import TimelineGroupItem from "./TimelineGroupItem.js"; // Styles import TimelineCss from "./generated/themes/Timeline.css.js"; @@ -23,11 +28,18 @@ import TimelineLayout from "./types/TimelineLayout.js"; * @public */ interface ITimelineItem extends UI5Element, ITabbable { - layout: `${TimelineLayout}`, - icon?: string, - forcedLineWidth?: string, - nameClickable: boolean, - focusLink: () => void, + layout: `${TimelineLayout}`; + isGroupItem: boolean; + forcedLineWidth?: string; + icon?: string; + nameClickable?: boolean; + positionInGroup?: number; + collapsed?: boolean; + items?: Array; + focusLink?(): void; + lastItem: boolean; + isNextItemGroup?: boolean; + firstItemInTimeline?: boolean; } const SHORT_LINE_WIDTH = "ShortLineWidth"; @@ -54,7 +66,7 @@ const LARGE_LINE_WIDTH = "LargeLineWidth"; renderer: litRender, styles: TimelineCss, template: TimelineTemplate, - dependencies: [TimelineItem], + dependencies: [TimelineItem, TimelineGroupItem], }) class Timeline extends UI5Element { /** @@ -90,7 +102,7 @@ class Timeline extends UI5Element { super(); this._itemNavigation = new ItemNavigation(this, { - getItemsCallback: () => this.items, + getItemsCallback: () => this._navigatableItems, }); } @@ -105,7 +117,11 @@ class Timeline extends UI5Element { } _onfocusin(e: FocusEvent) { - const target = e.target as TimelineItem; + let target = e.target as ITimelineItem | ToggleButton; + + if ((target as ITimelineItem).isGroupItem) { + target = target.shadowRoot!.querySelector("[ui5-toggle-button]")!; + } this._itemNavigation.setCurrentItem(target); } @@ -113,6 +129,10 @@ class Timeline extends UI5Element { onBeforeRendering() { this._itemNavigation._navigationMode = this.layout === TimelineLayout.Horizontal ? NavigationMode.Horizontal : NavigationMode.Vertical; + if (!this.items.length) { + return; + } + for (let i = 0; i < this.items.length; i++) { this.items[i].layout = this.layout; if (this.items[i + 1] && !!this.items[i + 1].icon) { @@ -121,35 +141,94 @@ class Timeline extends UI5Element { this.items[i].forcedLineWidth = LARGE_LINE_WIDTH; } } + + this._setLastItem(); + this._setIsNextItemGroup(); + this.items[0].firstItemInTimeline = true; + } + + _setLastItem() { + const items = this.items; + + for (let i = 0; i < items.length; i++) { + items[i].lastItem = false; + } + + if (items.length > 0) { + items[items.length - 1].lastItem = true; + } + } + + _setIsNextItemGroup() { + for (let i = 0; i < this.items.length; i++) { + this.items[i].isNextItemGroup = false; + } + + for (let i = 0; i < this.items.length; i++) { + if (this.items[i + 1] && this.items[i + 1].isGroupItem) { + this.items[i].isNextItemGroup = true; + } + } } _onkeydown(e: KeyboardEvent) { - const target = e.target as TimelineItem; + const target = e.target as ITimelineItem; + + if (target.nameClickable && getEventMark(e) !== "link") { + return; + } if (isTabNext(e)) { - if (!target.nameClickable || getEventMark(e) === "link") { - this._handleTabNextOrPrevious(e, isTabNext(e)); - } + this._handleNextOrPreviousItem(e, true); } else if (isTabPrevious(e)) { - this._handleTabNextOrPrevious(e); + this._handleNextOrPreviousItem(e); } } - _handleTabNextOrPrevious(e: KeyboardEvent, isNext?: boolean) { - const target = e.target as TimelineItem; - const nextTargetIndex = isNext ? this.items.indexOf(target) + 1 : this.items.indexOf(target) - 1; - const nextTarget = this.items[nextTargetIndex] as TimelineItem; + _handleNextOrPreviousItem(e: KeyboardEvent, isNext?: boolean) { + const target = e.target as ITimelineItem | ToggleButton; + let updatedTarget = target; + + if ((target as ITimelineItem).isGroupItem) { + updatedTarget = target.shadowRoot!.querySelector("[ui5-toggle-button]")!; + } + + const nextTargetIndex = isNext ? this._navigatableItems.indexOf(updatedTarget) + 1 : this._navigatableItems.indexOf(updatedTarget) - 1; + const nextTarget = this._navigatableItems[nextTargetIndex]; + if (!nextTarget) { return; } - if (nextTarget.nameClickable && !isNext) { + + if (nextTarget) { e.preventDefault(); - nextTarget.focusLink(); - return; + nextTarget.focus(); + this._itemNavigation.setCurrentItem(nextTarget); } - e.preventDefault(); - nextTarget.focus(); - this._itemNavigation.setCurrentItem(nextTarget); + } + + get _navigatableItems() { + const navigatableItems: Array = []; + + if (!this.items.length) { + return []; + } + + this.items.forEach(item => { + if (!item.isGroupItem) { + navigatableItems.push(item); + } else { + navigatableItems.push(item.shadowRoot!.querySelector("[ui5-toggle-button]")!); + } + + if (item.isGroupItem && !item.collapsed) { + item.items?.forEach(groupItem => { + navigatableItems.push(groupItem); + }); + } + }); + + return navigatableItems; } } diff --git a/packages/fiori/src/TimelineGroupItem.hbs b/packages/fiori/src/TimelineGroupItem.hbs new file mode 100644 index 000000000000..fd8f7be50e77 --- /dev/null +++ b/packages/fiori/src/TimelineGroupItem.hbs @@ -0,0 +1,25 @@ +
+
+
+
+
+ +
+
+
+ + {{groupName}} +
+
    + {{#each items}} +
  • + +
  • + {{/each}} +
+
\ No newline at end of file diff --git a/packages/fiori/src/TimelineGroupItem.ts b/packages/fiori/src/TimelineGroupItem.ts new file mode 100644 index 000000000000..fd1b67b6f20e --- /dev/null +++ b/packages/fiori/src/TimelineGroupItem.ts @@ -0,0 +1,175 @@ +import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js"; +import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js"; +import property from "@ui5/webcomponents-base/dist/decorators/property.js"; +import slot from "@ui5/webcomponents-base/dist/decorators/slot.js"; +import event from "@ui5/webcomponents-base/dist/decorators/event.js"; +import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js"; +import ToggleButton from "@ui5/webcomponents/dist/ToggleButton.js"; +import TimelineLayout from "./types/TimelineLayout.js"; +import TimelineItem from "./TimelineItem.js"; +import type { ITimelineItem } from "./Timeline.js"; + +import TimelineGroupItemTemplate from "./generated/templates/TimelineGroupItemTemplate.lit.js"; + +// Styles +import TimelineGroupItemCss from "./generated/themes/TimelineGroupItem.css.js"; + +const SHORT_LINE_WIDTH = "ShortLineWidth"; +const LARGE_LINE_WIDTH = "LargeLineWidth"; + +/** + * @class + * + * ### Overview + * + * An entry posted on the timeline. + * It is intented to represent a group of ``s. + * + * **Note**: Please do not use empty groups in order to preserve the intended design. + * + * @constructor + * @extends UI5Element + * @implements {ITimelineItem} + * @public + * @since 2.1.0 + */ +@customElement({ + tag: "ui5-timeline-group-item", + renderer: litRender, + styles: TimelineGroupItemCss, + template: TimelineGroupItemTemplate, + dependencies: [TimelineItem, ToggleButton], +}) +/** + * Fired when the group item is expanded or collapsed. + * @public + */ +@event("toggle") +class TimelineGroupItem extends UI5Element implements ITimelineItem { + /** + * Defines the text of the button that expands and collapses the group. + * @default undefined + * @public + */ + @property() + groupName?: string; + + /** + * Determines if the group is collapsed or expanded. + * @default false + * @public + */ + @property({ type: Boolean }) + collapsed = false; + + /** + * Determines the content of the `ui5-timeline-group-item`. + * @public + */ + @slot({ type: HTMLElement, individualSlots: true, "default": true }) + items!: Array; + + /** + * Defines the items orientation. + * @default "Vertical" + * @private + */ + @property() + layout: `${TimelineLayout}` = "Vertical"; + + /** + * Applies to the last item in the group. + * @private + */ + @property({ type: Boolean }) + lastItem = false; + + /** + * Determines if the item afterwards is a group item. + * Intended for styling purposes. + * @private + */ + @property({ type: Boolean }) + isNextItemGroup = false; + + @property({ type: Boolean }) + hidden = false; + + /** + * @private + */ + @property({ type: Boolean }) + firstItemInTimeline = false; + + @property({ noAttribute: true }) + forcedTabIndex = "-1"; + + onBeforeRendering() { + if (!this.items.length) { + return; + } + + this._setGroupItemProps(); + } + + _setGroupItemProps() { + const items = this.items; + const itemsLength = items.length; + + if (itemsLength && this.firstItemInTimeline) { + items[0].firstItemInTimeline = true; + } + + for (let i = 0; i < itemsLength; i++) { + items[i].lastItem = false; + items[i].isNextItemGroup = false; + } + + if (itemsLength > 0) { + items[itemsLength - 1].isNextItemGroup = this.isNextItemGroup; + if (this.collapsed) { + items[itemsLength - 1].lastItem = false; + } else if (this.lastItem) { + items[itemsLength - 1].lastItem = true; + } + } + + for (let i = 0; i < itemsLength; i++) { + const item = items[i]; + item.positionInGroup = i + 1; + item.hidden = !!this.collapsed; + item.layout = this.layout; + + if (items[i + 1] && !!items[i + 1].icon) { + item.forcedLineWidth = SHORT_LINE_WIDTH; + } else if (item.icon && items[i + 1] && !items[i + 1].icon) { + item.forcedLineWidth = LARGE_LINE_WIDTH; + } + } + } + + onGroupItemClick() { + this.collapsed = !this.collapsed; + this.fireEvent("toggle"); + } + + get isGroupItem() { + return true; + } + + get _groupName() { + return this.groupName; + } + + get _groupItemIcon() { + if (this.layout === TimelineLayout.Vertical) { + return this.collapsed ? "slim-arrow-left" : "slim-arrow-down"; + } + + return this.collapsed ? "slim-arrow-up" : "slim-arrow-right"; + } +} + +TimelineGroupItem.define(); + +export default TimelineGroupItem; diff --git a/packages/fiori/src/TimelineItem.hbs b/packages/fiori/src/TimelineItem.hbs index a7865ba75b00..dca419e7ff20 100644 --- a/packages/fiori/src/TimelineItem.hbs +++ b/packages/fiori/src/TimelineItem.hbs @@ -1,6 +1,4 @@ -
+
{{#if icon}} @@ -10,22 +8,24 @@ {{/if}}
-
-
- {{#if name}} - {{> name}} + {{#unless hideBubble}} +
+
+ {{#if name}} + {{> name}} + {{/if}} + {{titleText}} +
+
{{subtitleText}}
+ + {{#if this.content}} +
+ +
{{/if}} - {{titleText}} +
-
{{subtitleText}}
- - {{#if innerHTML}} -
- -
- {{/if}} - -
+ {{/unless}}
{{#*inline "name"}} diff --git a/packages/fiori/src/TimelineItem.ts b/packages/fiori/src/TimelineItem.ts index 078f37f0329d..dfb10e4ec905 100644 --- a/packages/fiori/src/TimelineItem.ts +++ b/packages/fiori/src/TimelineItem.ts @@ -2,6 +2,7 @@ import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js"; import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js"; import event from "@ui5/webcomponents-base/dist/decorators/event.js"; import property from "@ui5/webcomponents-base/dist/decorators/property.js"; +import slot from "@ui5/webcomponents-base/dist/decorators/slot.js"; import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js"; import Icon from "@ui5/webcomponents/dist/Icon.js"; import Link from "@ui5/webcomponents/dist/Link.js"; @@ -24,7 +25,6 @@ const LARGE_LINE_WIDTH = "LargeLineWidth"; * @extends UI5Element * @implements { ITimelineItem } * @public - * @slot {Node[]} default - Determines the description of the `ui5-timeline-item`. */ @customElement({ tag: "ui5-timeline-item", @@ -89,8 +89,27 @@ class TimelineItem extends UI5Element implements ITimelineItem { @property() subtitleText?: string; + /** + * Defines the content of the `ui5-timeline-item`. + * @public + */ + @slot({ type: HTMLElement, "default": true }) + content!: Array; + + /** + * @private + */ + @property({ type: Boolean }) + firstItemInTimeline = false; + + /** + * @private + */ + @property({ type: Boolean }) + isNextItemGroup = false; + @property({ noAttribute: true }) - forcedTabIndex?: string; + forcedTabIndex = "-1"; /** * Defines the items orientation. @@ -104,9 +123,35 @@ class TimelineItem extends UI5Element implements ITimelineItem { * Defines the indicator line width. * @private */ - @property() + @property({ noAttribute: true }) forcedLineWidth?: string; + /** + * @private + */ + @property({ type: Boolean }) + hideBubble = false; + + /** + * Marks the last `` + * @private + */ + @property({ type: Boolean }) + lastItem = false; + + /** + * @private + */ + @property({ type: Boolean }) + hidden = false; + + /** + * Defines the position of the item in a group. + * @private + */ + @property({ type: Number }) + positionInGroup?: number; + constructor() { super(); } @@ -136,6 +181,10 @@ class TimelineItem extends UI5Element implements ITimelineItem { }, }; } + + get isGroupItem() { + return false; + } } TimelineItem.define(); diff --git a/packages/fiori/src/themes/Timeline.css b/packages/fiori/src/themes/Timeline.css index 1cd093fd7288..757a68c70f71 100644 --- a/packages/fiori/src/themes/Timeline.css +++ b/packages/fiori/src/themes/Timeline.css @@ -14,6 +14,11 @@ padding: 0; } +:host([layout="Vertical"]) .ui5-timeline-list { + display: flex; + flex-direction: column; +} + .ui5-timeline-list-item { margin-bottom: var(--_ui5_tl_li_margin_bottom); } @@ -27,6 +32,7 @@ list-style: none; margin: 0; padding: 0; + display: flex; } :host([layout="Horizontal"]) .ui5-timeline-list-item { diff --git a/packages/fiori/src/themes/TimelineGroupItem.css b/packages/fiori/src/themes/TimelineGroupItem.css new file mode 100644 index 000000000000..ece6d5754f87 --- /dev/null +++ b/packages/fiori/src/themes/TimelineGroupItem.css @@ -0,0 +1,184 @@ +:host .ui5-timeline-group-list-item { + list-style: none; +} + +:host([collapsed]) .ui5-timeline-group-list-item { + display: none; +} + +.ui5-tl-group-item { + width: 100%; + display: flex; + flex-direction: column; + margin: 0; + padding: 0; + gap: 1.25rem; +} +.ui5-tlgi-root { + display: flex; + flex-direction: column; + gap: var(--_ui5_timeline_tlgi_compact_root_gap, 1.25rem); +} + +.ui5-tlgi-btn-root { + display: flex; + justify-content: space-between; + gap: 0.125rem; +} + +.ui5-tlgi-icon-placeholder { + display: flex; + justify-content: center; + position: relative; + width: 2rem; + align-self: center; +} + +:host([collapsed]) .ui5-tlgi-icon-dot { + width: 0.375rem; + height: 0.375rem; + box-sizing: border-box; + border: 0.0625rem solid var(--sapContent_NonInteractiveIconColor); + background-color: var(--sapBackgroundColor); + border-radius: 50%; + margin-inline-start: 0.0625rem; +} + +.ui5-tlgi-line-placeholder { + display: flex; + justify-content: center; + position: relative; + align-self: center; + flex-grow: 1; + margin-inline-end: 0.5rem; + margin-inline-start: -0.9375rem; +} + +:host([collapsed]) .ui5-tlgi-line { + width: 100%; + height: 0.0625rem; + border-block-start: 0.0625rem dashed var(--sapContent_NonInteractiveIconColor); +} + +:host([layout="Vertical"]:not(:last-child)[collapsed]) .ui5-tlgi-icon-dot::before { + content: ""; + display: inline-block; + background-color: var(--sapContent_ForegroundBorderColor); + width: 0.0625rem; + position: absolute; + inset-block-start: 0.375rem; + inset-inline-start: 50%; + height: var(--_ui5_timeline_tlgi_compact_icon_before_height, calc(100% + 4.5rem)); +} + +:host([layout="Vertical"]:not(:last-child)[collapsed]:not([is-next-item-group])) .ui5-tlgi-icon-dot::before { + height: var(--_ui5_timeline_tlgi_compact_icon_before_height, calc(100% + 3.75rem)); +} + +:host([layout="Vertical"]:not([first-item-in-timeline])[collapsed]) .ui5-tlgi-icon-dot::after { + content: ""; + display: inline-block; + background-color: var(--sapContent_ForegroundBorderColor); + width: 0.0625rem; + position: absolute; + inset-block-start: -2rem; + inset-inline-start: 50%; + height: 2rem; +} + +/* Horizontal */ +:host([layout="Horizontal"]) .ui5-tl-group-item { + flex-direction: row; +} + +:host([layout="Horizontal"]) .ui5-tl-group-item { + height: 100%; +} + +:host([layout="Horizontal"]) .ui5-tlgi-root { + height: var(--_ui5_timeline_tlgi_root_horizontal_height); +} + +:host([layout="Horizontal"]) .ui5-tlgi-btn-root { + flex-direction: row-reverse; +} + +:host([layout="Horizontal"][collapsed]) .ui5-tlgi-btn-root, +:host([layout="Horizontal"][collapsed]) .ui5-tlgi-root { + flex-direction: column; + gap: 0.8275rem; + margin-block-start: 0.4375rem; + margin-inline-end: var(--_ui5_timeline_tlgi_horizontal_compact_root_margin_left, 0); +} + +:host([layout="Horizontal"][collapsed]) .ui5-tlgi-root:last-child { + margin-block-end: -0.4375rem; +} + +:host([layout="Horizontal"][collapsed]):first-child .ui5-tlgi-btn-root { + padding-inline-end: 2rem; +} + +:host([layout="Horizontal"][collapsed]) .ui5-tlgi-icon-placeholder { + align-self: unset; + justify-content: unset; +} + + +:host([layout="Horizontal"]) .ui5-tlgi-btn { + margin-inline-start: -0.75rem; +} + +:host([layout="Horizontal"][collapsed]) .ui5-tlgi-line { + width: 100%; + height: calc(100% + 1rem); + border-block-start: none; + border-inline-start: 0.0625rem dashed var(--sapContent_NonInteractiveIconColor); + margin-block-start: -0.8125rem; +} + +:host([layout="Horizontal"]) .ui5-tlgi-line-placeholder { + height: var(--_ui5_timeline_tlgi_line_horizontal_height); + align-self: unset; + margin-inline-end: 0; + margin-inline-start: 0.25rem; +} + +:host([layout="Horizontal"]:not([collapsed])) .ui5-tlgi-line-placeholder { + display: none; +} + +:host([layout="Horizontal"][collapsed]) .ui5-tlgi-root > :last-child { /* Removes the gap after the last-child, so it doesnt affect the height of wrapper containers */ + margin-block-end: -0.8275rem; +} + +:host([layout="Horizontal"]) .ui5-tl-group-item { + flex-direction: row; +} + +:host([layout="Horizontal"]) .ui5-tl-group-item:last-child { + margin-inline-end: 0.25rem; +} + +:host([layout="Horizontal"]) .ui5-tlgi-root { + flex-direction: column-reverse; +} + +:host([layout="Horizontal"]) .ui5-tlgi-btn-root { + flex-direction: row-reverse; +} + +:host([layout="Horizontal"]:not(:last-child)[collapsed]) .ui5-tlgi-line-placeholder::before { + content: ""; + display: inline-block; + background-color: var(--sapContent_ForegroundBorderColor); + height: 0.0625rem; + inset-block-start: -1.0625rem; + position: absolute; + inset-inline-start: 0.125rem; + width: var(--_ui5_timeline_tlgi_horizontal_line_placeholder_before_width, calc(100% + 1.5625rem)); +} + +:host(:not([is-next-item-group])[layout="Horizontal"]:not(:last-child)[collapsed]) .ui5-tlgi-line-placeholder::before { + width: var(--_ui5_timeline_tlgi_horizontal_line_placeholder_before_width, calc(100% + 1.9375rem)); +} \ No newline at end of file diff --git a/packages/fiori/src/themes/TimelineItem.css b/packages/fiori/src/themes/TimelineItem.css index 02fdd3e52424..9b145271891a 100644 --- a/packages/fiori/src/themes/TimelineItem.css +++ b/packages/fiori/src/themes/TimelineItem.css @@ -10,7 +10,7 @@ flex-direction: column; } -:host(:not([layout="Horizontal"])) .ui5-tli-indicator { +:host([layout="Vertical"]) .ui5-tli-indicator { position: relative; width: 2rem; } @@ -22,54 +22,65 @@ align-items: center; } -:host(:not([layout="Horizontal"])) .ui5-tli-indicator::before { +:host([layout="Vertical"]) .ui5-tli-indicator::before { content: ""; display: inline-block; background-color: var(--sapContent_ForegroundBorderColor); - width: 1px; + width: 0.0625rem; position: absolute; - top: 2.125rem; + inset-block-start: 2rem; bottom: var(--_ui5_timeline_tli_indicator_before_bottom); - left: 50%; + inset-inline-start: 50%; +} + +:host(:not([icon])[layout="Vertical"]) .ui5-tli-indicator::before { + inset-block-start: 1.75rem; +} + +:host([position-in-group][layout="Vertical"]) .ui5-tli-indicator::before { + bottom: -1.5rem; } -:host([layout="Horizontal"]) .ui5-tli-indicator::before { +:host([position-in-group][layout="Vertical"]) .ui5-tli-indicator.ui5-tli-indicator-large-line::before { + bottom: -1.75rem; +} + +:host(:first-child[layout="Vertical"]:not([first-item-in-timeline])[icon]) .ui5-tli-indicator::after { content: ""; display: inline-block; background-color: var(--sapContent_ForegroundBorderColor); - height: 1px; - top: 50%; + width: 0.0625rem; position: absolute; - left: 2.0625rem; - right: var(--_ui5_timeline_tli_indicator_before_right); + inset-block-start: var(--_ui5_timeline_tli_indicator_after_top); + bottom: var(--_ui5_timeline_tli_indicator_before_bottom); + inset-inline-start: 50%; + height: var(--_ui5_timeline_tli_indicator_after_height); } -:host(:not([layout="Horizontal"])) .ui5-tli-indicator.ui5-tli-indicator-large-line::before { + +:host(:not([position-in-group])[layout="Vertical"]) .ui5-tli-indicator.ui5-tli-indicator-large-line::before { bottom: var(--_ui5_timeline_tli_indicator_before_without_icon_bottom); } -:host([layout="Horizontal"]) .ui5-tli-indicator.ui5-tli-indicator-large-line::before{ - right: var(--_ui5_timeline_tli_indicator_before_without_icon_right); -} /* Line when no Icon is provided */ -:host(:not([layout="Horizontal"])):not([icon]) .ui5-tli-indicator::before { +:host([layout="Vertical"]):not([icon]) .ui5-tli-indicator::before { bottom: var(--_ui5_timeline_tli_indicator_before_without_icon_bottom); - top: 1.875rem; + inset-block-start: 1.875rem; } /* Line when no Icon is provided in horizontal*/ :host([layout="Horizontal"]:not([icon])) .ui5-tli-indicator::before { - top: 50%; - right: var(--_ui5_timeline_tli_indicator_before_without_icon_right); - left: 1.6875rem; + inset-block-start: 50%; + inset-inline-end: var(--_ui5_timeline_tli_indicator_before_without_icon_right); + inset-inline-start: 1rem; } -:host(:not([layout="Horizontal"])):not([icon]) .ui5-tli-indicator.ui5-tli-indicator-short-line::before { +:host([layout="Vertical"]):not([icon]) .ui5-tli-indicator.ui5-tli-indicator-short-line::before { bottom: var(--_ui5_timeline_tli_indicator_before_bottom); } :host([layout="Horizontal"]:not([icon])) .ui5-tli-indicator.ui5-tli-indicator-short-line::before { - right: var(--_ui5_timeline_tli_indicator_before_right); + inset-inline-end: var(--_ui5_timeline_tli_indicator_before_right); } /* No Icon Dot */ @@ -77,21 +88,21 @@ content: ""; display: inline-block; box-sizing: border-box; - border: 1px solid var(--sapContent_NonInteractiveIconColor); + border: 0.0625rem solid var(--sapContent_NonInteractiveIconColor); background-color: var(--sapContent_NonInteractiveIconColor); border-radius: 50%; width: 0.375rem; height: 0.375rem; position: absolute; - top: 0.9375rem; - left: 51.75%; + inset-block-start: 0.9375rem; + inset-inline-start: 51.75%; transform: translateX(-50%); } /* No Icon Dot in Hotizontal */ :host([layout="Horizontal"]:not([icon])) .ui5-tli-indicator::after { - top: 0.84rem; - left: 0.9625rem; + inset-block-start: 0.84rem; + inset-inline-start: 0.9625rem; } :host(:last-child) .ui5-tli-indicator::before { @@ -106,13 +117,13 @@ display: flex; justify-content: center; align-items: center; - margin-top: .25rem; + margin-block-start: .25rem; height: 1.625rem; width: 2rem; } :host([layout="Horizontal"]) .ui5-tli-icon-outer { - margin-top: 0rem; + margin-block-start: 0rem; height: 1.3125rem; } @@ -131,7 +142,7 @@ .ui5-tli-bubble { background: var(--sapGroup_ContentBackground); - border: 1px solid var(--_ui5_TimelineItem_bubble_border_color); + border: 0.0625rem solid var(--_ui5_TimelineItem_bubble_border_color); box-sizing: border-box; border-radius: var(--_ui5_TimelineItem_bubble_border_radius); flex: 1; @@ -151,19 +162,19 @@ .ui5-tli-bubble:focus::after { content: ""; - border: var(--_ui5_TimelineItem_bubble_border_width) var(--_ui5_TimelineItem_bubble_border_style) var(--sapContent_FocusColor); - border-radius: var(--_ui5_TimelineItem_bubble_focus_border_radius); + border: var(--_ui5_TimelineItem_bubble_border_width) var(--_ui5_TimelineItem_bubble_border_style) var(--sapContent_FocusColor); + border-radius: var(--_ui5_TimelineItem_bubble_focus_border_radius); position: absolute; - top: var(--_ui5_TimelineItem_bubble_border_top); - right: var(--_ui5_TimelineItem_bubble_border_right); + inset-block-start: var(--_ui5_TimelineItem_bubble_border_top); + inset-inline-end: var(--_ui5_TimelineItem_bubble_border_right); bottom: var(--_ui5_TimelineItem_bubble_border_bottom); - left: var(--_ui5_TimelineItem_bubble_border_left); + inset-inline-start: var(--_ui5_TimelineItem_bubble_border_left); pointer-events: none; } :host([layout="Horizontal"]) .ui5-tli-bubble:focus::after { - top: var(--_ui5_TimelineItem_horizontal_bubble_focus_top_offset); - left: var(--_ui5_TimelineItem_horizontal_bubble_focus_left_offset); + inset-block-start: var(--_ui5_TimelineItem_horizontal_bubble_focus_top_offset); + inset-inline-start: var(--_ui5_TimelineItem_horizontal_bubble_focus_left_offset); } .ui5-tli-bubble-arrow { @@ -179,7 +190,7 @@ .ui5-tli-bubble-arrow::before { content: ""; background: var(--sapGroup_ContentBackground); - border: 1px solid var(--_ui5_TimelineItem_bubble_border_color); + border: 0.0625rem solid var(--_ui5_TimelineItem_bubble_border_color); position: absolute; top: 0; left: 0; @@ -198,7 +209,7 @@ } .ui5-tli-bubble-arrow--top { - top: calc(-1 * var(--_ui5_TimelineItem_arrow_size)); + inset-block-start: calc(-1 * var(--_ui5_TimelineItem_arrow_size)); } .ui5-tli-bubble-arrow--left::before { @@ -230,11 +241,11 @@ font-family: var(--sapFontFamily); font-weight: 400; font-size: var(--sapFontSmallSize); - padding-top: var(--_ui5_TimelineItem_bubble_content_subtitle_padding_top); + padding-block-start: var(--_ui5_TimelineItem_bubble_content_subtitle_padding_top); } .ui5-tli-desc { - padding-top: var(--_ui5_TimelineItem_bubble_content_description_padding_top); + padding-block-start: var(--_ui5_TimelineItem_bubble_content_description_padding_top); } :dir(rtl) .ui5-tli-bubble-arrow--left { @@ -280,4 +291,138 @@ :host([layout="Horizontal"]:dir(rtl)) .ui5-tli-indicator::before { left: var(--_ui5_timeline_tli_indicator_before_right); right: 2.125rem; +} + +:host { + align-content: end; +} + +:host([hide-bubble]) { + display: none; +} + +.ui5-tli-group-item-btn-arrow { + position: absolute; + width: 0.5rem; + height: 0.5rem; + transform: rotate(45deg); + border: 0.0625rem solid var(--sapButton_BorderColor); + background-color: var(--sapButton_Background); + inset-inline-end: 4.25rem; + inset-block-start: 0.8125rem; + border-inline-end-color: transparent; + border-block-start-color: transparent; +} + +.ui5-tli-root:hover .ui5-tli-group-item-btn-arrow { + background-color: var(--sapButton_Hover_Background); +} + +:host([layout="Horizontal"]) .ui5-tli-root { + flex-direction: column; +} + +:host([layout="Horizontal"][is-next-item-group]:last-child:not([last-item])) .ui5-tli-indicator::before { + height: 0.0625rem; + inset-block-start: 50%; + inset-inline-start: 1.75rem; +} + +:host([position-in-group][layout="Horizontal"][is-next-item-group]:last-child:not([last-item])) .ui5-tli-indicator::before { + inset-inline-start: 1.625rem; + width: calc(100% + 0.5rem); +} + +:host([layout="Vertical"]:last-child:not([last-item])) .ui5-tli-indicator::before { + content: ""; + display: inline-block; + background-color: var(--sapContent_ForegroundBorderColor); + inset-block-start: 2rem; + position: absolute; + height: var(--_ui5_timeline_tli_indicator_before_height); +} + +:host(:not([icon])[layout="Vertical"]:last-child:not([last-item])) .ui5-tli-indicator::before { + inset-block-start: 1.75rem; +} + +/* Styles for horizontal */ + +:host([layout="Horizontal"]) { + height: auto; + min-width: 3rem; + margin-inline-end: 0.25rem; +} + +:host([icon][layout="Horizontal"]:not([last-item])) .ui5-tli-indicator::after, +:host(:not([icon])[layout="Horizontal"]:not([last-item])) .ui5-tli-indicator::before { + content: ""; + display: inline-block; + background-color: var(--sapContent_ForegroundBorderColor); + height: 0.0625rem; + inset-block-start: 1rem; + position: absolute; + width: var(--_ui5_timeline_tli_horizontal_indicator_after_width); + inset-inline-start: 1.5rem; +} + +:host([icon][layout="Horizontal"]:not([last-item])) .ui5-tli-indicator::after { + inset-inline-start: var(--_ui5_timeline_tli_horizontal_indicator_after_left); +} + +:host([icon][layout="Horizontal"]:not([last-item]):not([is-next-item-group])) .ui5-tli-indicator::after { + width: calc(var(--_ui5_timeline_tli_icon_horizontal_indicator_after_width) + 1.25rem); +} + +:host(:not([icon])[layout="Horizontal"]:not([last-item])[is-next-item-group]) .ui5-tli-indicator::before { + width: var(--_ui5_timeline_tli_horizontal_without_icon_indicator_before_width); +} + +:host([is-next-item-group][icon][layout="Horizontal"]:not([last-item])) .ui5-tli-indicator.ui5-tli-indicator-large-line::after { + width: var(--_ui5_timeline_tli_horizontal_indicator_short_after_width); +} + +:host([icon][layout="Horizontal"]:not([last-item])) .ui5-tli-indicator-short-line::after { + content: ""; + display: inline-block; + background-color: var(--sapContent_ForegroundBorderColor); + height: 0.0625rem; + inset-block-start: 1rem; + position: absolute; + width: 100%; + inset-inline-start: 1.9375rem; +} + +:host(:not([position-in-group])[icon][layout="Horizontal"]:not([last-item])) .ui5-tli-indicator-short-line::after { + width: var(--_ui5_timeline_tli_horizontal_indicator_short_after_width); +} + +:host([position-in-group][icon][layout="Horizontal"]:not([last-item])) .ui5-tli-indicator-short-line::after { + width: calc(100% - 0.5rem); +} + +:host([icon][layout="Horizontal"]:not([last-item]):not([is-next-item-group])) .ui5-tli-indicator-large-line::after { + width: var(--_ui5_timeline_tli_icon_horizontal_indicator_after_width); +} + +:host([position-in-group]:not([icon])[layout="Horizontal"]:not([last-item]):not([is-next-item-group])) .ui5-tli-indicator::before { + width: calc(100% + 0.125rem); +} + +:host([position-in-group]:not([icon])[layout="Horizontal"]:not([last-item]):not([is-next-item-group])) .ui5-tli-indicator.ui5-tli-indicator-short-line::before { + width: 100%; +} + +:host([position-in-group][icon][layout="Horizontal"]:not([last-item]):not([is-next-item-group])) .ui5-tli-indicator-large-line::after { + width: calc(100% - 0.25rem); +} + +:host(:not([icon])[layout="Horizontal"]:not([last-item]):not([is-next-item-group])) .ui5-tli-indicator::before { + width: var(--_ui5_timeline_tli_horizontal_indicator_before_width); + inset-inline-start: 1.625rem; +} + +:host(:not([icon])[layout="Horizontal"]:not([last-item])) .ui5-tli-indicator.ui5-tli-indicator-short-line::before { + width: var(--_ui5_timeline_tli_without_icon_horizontal_indicator_before_width); + inset-inline-start: 1.5rem; } \ No newline at end of file diff --git a/packages/fiori/src/themes/base/TimelineGroupItem-parameters.css b/packages/fiori/src/themes/base/TimelineGroupItem-parameters.css new file mode 100644 index 000000000000..e65d36cdb019 --- /dev/null +++ b/packages/fiori/src/themes/base/TimelineGroupItem-parameters.css @@ -0,0 +1,4 @@ +:root { + --_ui5_timeline_tlgi_line_horizontal_height: 14.8125rem; + --_ui5_timeline_tlgi_root_horizontal_height: 19.9375rem; +} \ No newline at end of file diff --git a/packages/fiori/src/themes/sap_fiori_3/TimelineGroupItem-parameters.css b/packages/fiori/src/themes/sap_fiori_3/TimelineGroupItem-parameters.css new file mode 100644 index 000000000000..a7b1612b396c --- /dev/null +++ b/packages/fiori/src/themes/sap_fiori_3/TimelineGroupItem-parameters.css @@ -0,0 +1,6 @@ +@import "../base/TimelineGroupItem-parameters.css"; + +:root { + --_ui5_timeline_tlgi_line_horizontal_height: 16.375rem; + --_ui5_timeline_tlgi_root_horizontal_height: 21.53125rem; +} \ No newline at end of file diff --git a/packages/fiori/src/themes/sap_fiori_3/parameters-bundle.css b/packages/fiori/src/themes/sap_fiori_3/parameters-bundle.css index aab94d1a633a..0d99c3514de1 100644 --- a/packages/fiori/src/themes/sap_fiori_3/parameters-bundle.css +++ b/packages/fiori/src/themes/sap_fiori_3/parameters-bundle.css @@ -16,3 +16,4 @@ @import "./DynamicPageTitle-parameters.css"; @import "../base/DynamicPageHeader-parameters.css"; @import "./DynamicPageHeaderActions-parameters.css"; +@import "./TimelineGroupItem-parameters.css"; diff --git a/packages/fiori/src/themes/sap_fiori_3_dark/parameters-bundle.css b/packages/fiori/src/themes/sap_fiori_3_dark/parameters-bundle.css index 088522a7bdd8..e9cedd325d1a 100644 --- a/packages/fiori/src/themes/sap_fiori_3_dark/parameters-bundle.css +++ b/packages/fiori/src/themes/sap_fiori_3_dark/parameters-bundle.css @@ -16,3 +16,4 @@ @import "../base/DynamicPageTitle-parameters.css"; @import "../base/DynamicPageHeader-parameters.css"; @import "../sap_fiori_3/DynamicPageHeaderActions-parameters.css"; +@import "../sap_fiori_3/TimelineGroupItem-parameters.css"; diff --git a/packages/fiori/src/themes/sap_fiori_3_hcb/parameters-bundle.css b/packages/fiori/src/themes/sap_fiori_3_hcb/parameters-bundle.css index dccdbfcb0349..b8e85f845bdb 100644 --- a/packages/fiori/src/themes/sap_fiori_3_hcb/parameters-bundle.css +++ b/packages/fiori/src/themes/sap_fiori_3_hcb/parameters-bundle.css @@ -17,3 +17,4 @@ @import "./DynamicPageTitle-parameters.css"; @import "../base/DynamicPageHeader-parameters.css"; @import "../sap_fiori_3/DynamicPageHeaderActions-parameters.css"; +@import "../sap_fiori_3/TimelineGroupItem-parameters.css"; \ No newline at end of file diff --git a/packages/fiori/src/themes/sap_fiori_3_hcw/parameters-bundle.css b/packages/fiori/src/themes/sap_fiori_3_hcw/parameters-bundle.css index dccdbfcb0349..b8e85f845bdb 100644 --- a/packages/fiori/src/themes/sap_fiori_3_hcw/parameters-bundle.css +++ b/packages/fiori/src/themes/sap_fiori_3_hcw/parameters-bundle.css @@ -17,3 +17,4 @@ @import "./DynamicPageTitle-parameters.css"; @import "../base/DynamicPageHeader-parameters.css"; @import "../sap_fiori_3/DynamicPageHeaderActions-parameters.css"; +@import "../sap_fiori_3/TimelineGroupItem-parameters.css"; \ No newline at end of file diff --git a/packages/fiori/src/themes/sap_horizon/parameters-bundle.css b/packages/fiori/src/themes/sap_horizon/parameters-bundle.css index c9c606d96283..3981e9262165 100644 --- a/packages/fiori/src/themes/sap_horizon/parameters-bundle.css +++ b/packages/fiori/src/themes/sap_horizon/parameters-bundle.css @@ -18,3 +18,4 @@ @import "./DynamicPageTitle-parameters.css"; @import "../base/DynamicPageHeader-parameters.css"; @import "./DynamicPageHeaderActions-parameters.css"; +@import "../base/TimelineGroupItem-parameters.css"; diff --git a/packages/fiori/src/themes/sap_horizon_dark/parameters-bundle.css b/packages/fiori/src/themes/sap_horizon_dark/parameters-bundle.css index 75bad925821d..3b8eff035df8 100644 --- a/packages/fiori/src/themes/sap_horizon_dark/parameters-bundle.css +++ b/packages/fiori/src/themes/sap_horizon_dark/parameters-bundle.css @@ -18,3 +18,4 @@ @import "../sap_horizon/DynamicPageTitle-parameters.css"; @import "../base/DynamicPageHeader-parameters.css"; @import "../sap_horizon/DynamicPageHeaderActions-parameters.css"; +@import "../base/TimelineGroupItem-parameters.css"; diff --git a/packages/fiori/src/themes/sap_horizon_dark_exp/parameters-bundle.css b/packages/fiori/src/themes/sap_horizon_dark_exp/parameters-bundle.css index 6a246805dacb..c6621d9b5d6a 100644 --- a/packages/fiori/src/themes/sap_horizon_dark_exp/parameters-bundle.css +++ b/packages/fiori/src/themes/sap_horizon_dark_exp/parameters-bundle.css @@ -17,3 +17,4 @@ @import "../base/DynamicPageTitle-parameters.css"; @import "../base/DynamicPageHeader-parameters.css"; @import "../sap_horizon/DynamicPageHeaderActions-parameters.css"; +@import "../base/TimelineGroupItem-parameters.css"; diff --git a/packages/fiori/src/themes/sap_horizon_exp/parameters-bundle.css b/packages/fiori/src/themes/sap_horizon_exp/parameters-bundle.css index 6a246805dacb..c6621d9b5d6a 100644 --- a/packages/fiori/src/themes/sap_horizon_exp/parameters-bundle.css +++ b/packages/fiori/src/themes/sap_horizon_exp/parameters-bundle.css @@ -17,3 +17,4 @@ @import "../base/DynamicPageTitle-parameters.css"; @import "../base/DynamicPageHeader-parameters.css"; @import "../sap_horizon/DynamicPageHeaderActions-parameters.css"; +@import "../base/TimelineGroupItem-parameters.css"; diff --git a/packages/fiori/src/themes/sap_horizon_hcb/parameters-bundle.css b/packages/fiori/src/themes/sap_horizon_hcb/parameters-bundle.css index 27c258f610c6..ea0ecea71891 100644 --- a/packages/fiori/src/themes/sap_horizon_hcb/parameters-bundle.css +++ b/packages/fiori/src/themes/sap_horizon_hcb/parameters-bundle.css @@ -16,3 +16,4 @@ @import "./DynamicPageTitle-parameters.css"; @import "../base/DynamicPageHeader-parameters.css"; @import "../sap_horizon/DynamicPageHeaderActions-parameters.css"; +@import "../sap_fiori_3/TimelineGroupItem-parameters.css"; diff --git a/packages/fiori/src/themes/sap_horizon_hcb_exp/parameters-bundle.css b/packages/fiori/src/themes/sap_horizon_hcb_exp/parameters-bundle.css index c4c162c2d9fb..3366cfe13917 100644 --- a/packages/fiori/src/themes/sap_horizon_hcb_exp/parameters-bundle.css +++ b/packages/fiori/src/themes/sap_horizon_hcb_exp/parameters-bundle.css @@ -15,3 +15,4 @@ @import "../base/DynamicPageTitle-parameters.css"; @import "../base/DynamicPageHeader-parameters.css"; @import "../sap_horizon/DynamicPageHeaderActions-parameters.css"; +@import "../sap_fiori_3/TimelineGroupItem-parameters.css"; diff --git a/packages/fiori/src/themes/sap_horizon_hcw/parameters-bundle.css b/packages/fiori/src/themes/sap_horizon_hcw/parameters-bundle.css index 627a7c145e0c..3f2bda423e46 100644 --- a/packages/fiori/src/themes/sap_horizon_hcw/parameters-bundle.css +++ b/packages/fiori/src/themes/sap_horizon_hcw/parameters-bundle.css @@ -18,3 +18,4 @@ @import "../base/DynamicPageHeader-parameters.css"; @import "../sap_horizon/DynamicPageHeaderActions-parameters.css"; @import "./DynamicPageTitle-parameters.css"; +@import "../sap_fiori_3/TimelineGroupItem-parameters.css"; diff --git a/packages/fiori/src/themes/sap_horizon_hcw_exp/parameters-bundle.css b/packages/fiori/src/themes/sap_horizon_hcw_exp/parameters-bundle.css index e2d08b5915d3..bbc555b5dad1 100644 --- a/packages/fiori/src/themes/sap_horizon_hcw_exp/parameters-bundle.css +++ b/packages/fiori/src/themes/sap_horizon_hcw_exp/parameters-bundle.css @@ -16,3 +16,4 @@ @import "../base/DynamicPageTitle-parameters.css"; @import "../base/DynamicPageHeader-parameters.css"; @import "../sap_horizon/DynamicPageHeaderActions-parameters.css"; +@import "../sap_fiori_3/TimelineGroupItem-parameters.css"; diff --git a/packages/fiori/test/pages/Timeline.html b/packages/fiori/test/pages/Timeline.html index 805506c5e57d..15e6abfca042 100644 --- a/packages/fiori/test/pages/Timeline.html +++ b/packages/fiori/test/pages/Timeline.html @@ -124,6 +124,170 @@

Basic Timeline - Horizontal

+
+ +
+

Basic Timeline - Vertical With groups

+
+ + + + + Morning event + + + Good morning + + + 20.02.2017 11:30 + + + + + + + 20.02.2017 11:30 + + + + + + + + + + + + +
+
+ +
+

Basic Timeline - Vertical

+
+ + + + Good morning + + + 20.02.2017 11:30 + + 20.02.2017 11:30 + + + + + + +
+
+ +
+

Basic Timeline - Horizontal With Groups

+
+ + + + + + + + 20.02.2017 11:30 + + + + + + + + +
+
+ +
+

Basic Timeline - Horizontal

+
+ + Test item + Lorem ipsum dolor sit amet consectetur adipisicing elit. Ad sequi magnam nam sed numquam. + + Lorem ipsum dolor sit amet consectetur adipisicing elit. Ad sequi magnam nam sed numquam. + Lorem ipsum dolor sit amet consectetur adipisicing elit. Ad sequi magnam nam sed numquam. + + 20.02.2017 11:30 + + + Lorem ipsum dolor sit amet consectetur adipisicing elit. Ad sequi magnam nam sed numquam. + Lorem ipsum dolor sit amet consectetur adipisicing elit. Ad sequi magnam nam sed numquam. + + +
+
+ +
+

Advanced Timeline - Horizontal With Groups and Diverse Components

+
+ + + +
Discussion about upcoming projects
+ Meeting Link +
+ + Important +
Topics: UI5 Basics, Advanced Concepts
+ Workshop Details +
+ + +
Speaker: Sarah Kerrigan
+ Join Webinar +
+
+ + + + + + + +
Quarterly planning session
+
+ + +
Reviewing the budget for Q1
+
+ + +
Manager: John Smith
+ +
+
+ + + High Priority +
Task progress update
+
+ + Deadline +
Upload final project documents
+ Submit +
+ + + + + + +
Review project deliverables
+
+
+
+
+
+
+ - + \ No newline at end of file diff --git a/packages/fiori/test/specs/Timeline.spec.js b/packages/fiori/test/specs/Timeline.spec.js index 7415372f62bd..28bb92da2a3c 100644 --- a/packages/fiori/test/specs/Timeline.spec.js +++ b/packages/fiori/test/specs/Timeline.spec.js @@ -26,3 +26,63 @@ describe("Timeline general interaction", () => { assert.ok(timelineItem, "Item within Timeline Item is rendered"); }) }); + +describe("Timeline with group items interactions", () => { + before(async () => { + await browser.url(`test/pages/Timeline.html`); + }); + + it("Group items are rendered", async () => { + const timeline = await browser.$("#verticalWithGrps"); + const groupItem = await timeline.$$("ui5-timeline-group-item[group-name='Events']"); + const groupItemsLength = await groupItem[0].$$("ui5-timeline-item").length; + + + assert.strictEqual(groupItemsLength, 4, "Group items are rendered"); + }) + + it("Group items are collapsed on button click", async () => { + const timeline = await browser.$("#verticalWithGrps"); + const groupItem = await timeline.$$("ui5-timeline-group-item[group-name='Events']"); + const groupItemButton = await groupItem[0].shadow$("ui5-toggle-button"); + + await groupItemButton.click(); + + await browser.keys("Tab"); + + const nextGroupItem = await timeline.$$("ui5-timeline-group-item[group-name='Meetings']"); + const nextGroupItemButton = nextGroupItem[0].shadow$("ui5-toggle-button"); + + assert.ok(nextGroupItemButton.matches(":focus"), "Items are hidden on group collapse"); + }) + + it("Group items are navigatable", async () => { + const timeline = await browser.$("#verticalWithGrps"); + const groupItem = await timeline.$$("ui5-timeline-group-item[group-name='Events']"); + + await browser.keys("Tab"); + await browser.keys("ArrowDown"); + await browser.keys("ArrowDown"); + await browser.keys("ArrowUp"); + + const secondItemInGroup = await groupItem[0].$$("ui5-timeline-item"); + + assert.ok(secondItemInGroup[1].matches(":focus"), "Group items are navigatable with tab and arrow keys"); + }) + + it("Group can be collapsed/expanded using keyboard", async () => { + const timeline = await browser.$("#verticalWithGrps"); + const groupItem = await timeline.$$("ui5-timeline-group-item[group-name='Meetings']"); + const groupItemButton = await groupItem[0].shadow$("ui5-toggle-button"); + + await groupItemButton.click(); + await browser.keys("Enter"); + + assert.strictEqual(await groupItem[0].hasAttribute("collapsed"), false, "Group can be expanded with keyboard"); + + await browser.keys("Space"); + + assert.strictEqual(await groupItem[0].hasAttribute("collapsed"), true, "Group can be collapsed with keyboard"); + } + ); +}) diff --git a/packages/main/src/themes/base/sizes-parameters.css b/packages/main/src/themes/base/sizes-parameters.css index 577750868c20..755eb6ba2d14 100644 --- a/packages/main/src/themes/base/sizes-parameters.css +++ b/packages/main/src/themes/base/sizes-parameters.css @@ -135,11 +135,24 @@ --_ui5-tree-toggle-icon-size: 1.0625rem; /* Timeline */ - --_ui5_timeline_tli_indicator_before_bottom: -1.625rem; + --_ui5_timeline_tli_indicator_before_bottom: -1.5rem; --_ui5_timeline_tli_indicator_before_right: -1.625rem; --_ui5_timeline_tli_indicator_before_without_icon_bottom: -1.875rem; --_ui5_timeline_tli_indicator_before_without_icon_right: -1.9375rem; + /* TimelineItem COZY */ + --_ui5_timeline_tli_indicator_after_top: calc(-100% - 1rem); + --_ui5_timeline_tli_indicator_after_height: calc(100% + 1rem); + --_ui5_timeline_tli_indicator_before_height: 100%; + --_ui5_timeline_tli_horizontal_indicator_after_width: calc(100% + 0.25rem); + --_ui5_timeline_tli_horizontal_indicator_after_left: 1.9375rem; + --_ui5_timeline_tli_horizontal_without_icon_indicator_before_width: calc(100% + 0.5rem); + --_ui5_timeline_tli_horizontal_indicator_before_width: calc(100% + 0.5rem); + --_ui5_timeline_tli_icon_horizontal_indicator_after_width: calc(100% + 0.25rem); + --_ui5_timeline_tli_without_icon_horizontal_indicator_before_width: calc(100% + 0.375rem); + --_ui5_timeline_tli_horizontal_indicator_short_after_width: 100%; + --_ui5_timeline_tli_last_child_vertical_indicator_before_height: calc(100% - 1.5rem); + /* SplitButton */ --_ui5_split_button_middle_separator_top: -0.0625rem; --_ui5_split_button_middle_separator_height: 2.25rem; @@ -353,11 +366,32 @@ --_ui5-tree-toggle-icon-size: 0.8125rem; /* Timeline */ - --_ui5_timeline_tli_indicator_before_bottom: -0.5rem; + --_ui5_timeline_tli_indicator_before_bottom: -0.75rem; --_ui5_timeline_tli_indicator_before_right: -0.5rem; - --_ui5_timeline_tli_indicator_before_without_icon_bottom: -0.75rem; + --_ui5_timeline_tli_indicator_before_without_icon_bottom: -1rem; --_ui5_timeline_tli_indicator_before_without_icon_right: -0.8125rem; + /* TimelineItem */ + --_ui5_timeline_tli_indicator_before_height: calc(100% - 1.25rem); + --_ui5_timeline_tli_horizontal_without_icon_indicator_before_width: var(--_ui5_timeline_tli_indicator_after_height); + --_ui5_timeline_tli_horizontal_indicator_after_width: var(--_ui5_timeline_tli_indicator_after_height); + --_ui5_timeline_tli_horizontal_indicator_before_width: var(--_ui5_timeline_tli_indicator_after_height); + --_ui5_timeline_tli_icon_horizontal_indicator_after_width: var(--_ui5_timeline_tli_indicator_after_height); + --_ui5_timeline_tli_indicator_after_top: calc(-100% + 0.9375rem); + --_ui5_timeline_tli_indicator_after_height: calc(100% - 0.75rem); + --_ui5_timeline_tli_horizontal_indicator_after_left: 1.8625rem; + --_ui5_timeline_tli_horizontal_indicator_short_after_width: calc(100% - 1rem); + --_ui5_timeline_tli_without_icon_horizontal_indicator_before_width: calc(100% - 0.625rem); + --_ui5_timeline_tli_last_child_vertical_indicator_before_height: calc(100% - 2.5rem); + + /* TimelineGroupItem */ + --_ui5_timeline_tlgi_compact_icon_before_height: calc(100% + 1.5rem); + --_ui5_timeline_tlgi_horizontal_line_placeholder_before_width: var(--_ui5_timeline_tlgi_compact_icon_before_height); + --_ui5_timeline_tlgi_horizontal_compact_root_margin_left: 0.5rem; + --_ui5_timeline_tlgi_compact_root_gap: 0.5rem; + --_ui5_timeline_tlgi_root_horizontal_height: 19.375rem; + + /* ViewSettingsDialog */ --_ui5_vsd_header_container: 2.5rem; --_ui5_vsd_sub_header_container_height: 2rem; diff --git a/packages/main/src/themes/sap_fiori_3/sizes-parameters.css b/packages/main/src/themes/sap_fiori_3/sizes-parameters.css index 8c9bdd82ee9b..4079a56e6d86 100644 --- a/packages/main/src/themes/sap_fiori_3/sizes-parameters.css +++ b/packages/main/src/themes/sap_fiori_3/sizes-parameters.css @@ -2,5 +2,17 @@ :root { /* CalendarLegend */ - --_ui5-calendar-legend-item-root-focus-offset: -0.0625rem; + --_ui5-calendar-legend-item-root-focus-offset: -0.0625rem; +} + +[data-ui5-compact-size], +.ui5-content-density-compact, +.sapUiSizeCompact { + /* Timeline Item */ + --_ui5_timeline_tli_indicator_after_height: 50%; + --_ui5_timeline_tli_indicator_after_top: -50%; + --_ui5_timeline_tli_horizontal_indicator_after_width: calc(100% - 1rem); + + /* Timeline Group Item */ + --_ui5_timeline_tlgi_root_horizontal_height: 20.90625rem; } diff --git a/packages/main/src/themes/sap_fiori_3_dark/sizes-parameters.css b/packages/main/src/themes/sap_fiori_3_dark/sizes-parameters.css index 7f959da6d0e3..a27f56354911 100644 --- a/packages/main/src/themes/sap_fiori_3_dark/sizes-parameters.css +++ b/packages/main/src/themes/sap_fiori_3_dark/sizes-parameters.css @@ -4,3 +4,12 @@ /* CalendarLegend */ --_ui5-calendar-legend-item-root-focus-offset: -0.0625rem; } + +[data-ui5-compact-size], +.ui5-content-density-compact, +.sapUiSizeCompact { + /* Timeline Item */ + --_ui5_timeline_tli_indicator_after_height: 50%; + --_ui5_timeline_tli_indicator_after_top: -50%; + --_ui5_timeline_tli_horizontal_indicator_after_width: calc(100% - 1rem); +} diff --git a/packages/main/src/themes/sap_fiori_3_hcb/sizes-parameters.css b/packages/main/src/themes/sap_fiori_3_hcb/sizes-parameters.css index 513b993ab84f..bb16053d7cc8 100644 --- a/packages/main/src/themes/sap_fiori_3_hcb/sizes-parameters.css +++ b/packages/main/src/themes/sap_fiori_3_hcb/sizes-parameters.css @@ -9,4 +9,9 @@ /* SplitButton */ --_ui5_split_button_text_button_width: 2.25rem; + + /* Timeline Item */ + --_ui5_timeline_tli_indicator_after_height: 50%; + --_ui5_timeline_tli_indicator_after_top: -50%; + --_ui5_timeline_tli_horizontal_indicator_after_width: calc(100% - 1rem); } \ No newline at end of file diff --git a/packages/main/src/themes/sap_fiori_3_hcw/sizes-parameters.css b/packages/main/src/themes/sap_fiori_3_hcw/sizes-parameters.css index 513b993ab84f..bb16053d7cc8 100644 --- a/packages/main/src/themes/sap_fiori_3_hcw/sizes-parameters.css +++ b/packages/main/src/themes/sap_fiori_3_hcw/sizes-parameters.css @@ -9,4 +9,9 @@ /* SplitButton */ --_ui5_split_button_text_button_width: 2.25rem; + + /* Timeline Item */ + --_ui5_timeline_tli_indicator_after_height: 50%; + --_ui5_timeline_tli_indicator_after_top: -50%; + --_ui5_timeline_tli_horizontal_indicator_after_width: calc(100% - 1rem); } \ No newline at end of file diff --git a/packages/website/docs/_components_pages/fiori/Timeline/Timeline.mdx b/packages/website/docs/_components_pages/fiori/Timeline/Timeline.mdx index 7a787d14c09f..0fe7dc4d04e8 100644 --- a/packages/website/docs/_components_pages/fiori/Timeline/Timeline.mdx +++ b/packages/website/docs/_components_pages/fiori/Timeline/Timeline.mdx @@ -1,6 +1,7 @@ import Basic from "../../../_samples/fiori/Timeline/Basic/Basic.md"; import Horizontal from "../../../_samples/fiori/Timeline/Horizontal/Horizontal.md"; import InCard from "../../../_samples/fiori/Timeline/InCard/InCard.md"; +import WithGroups from "../../../_samples/fiori/Timeline/WithGroups/WithGroups.md"; <%COMPONENT_OVERVIEW%> @@ -17,4 +18,8 @@ import InCard from "../../../_samples/fiori/Timeline/InCard/InCard.md"; ### Timeline in Card - \ No newline at end of file + + +### Timeline with Groups + + \ No newline at end of file diff --git a/packages/website/docs/_components_pages/fiori/Timeline/TimelineGroupItem.mdx b/packages/website/docs/_components_pages/fiori/Timeline/TimelineGroupItem.mdx new file mode 100644 index 000000000000..41ff1dcbc5d6 --- /dev/null +++ b/packages/website/docs/_components_pages/fiori/Timeline/TimelineGroupItem.mdx @@ -0,0 +1,8 @@ +--- +slug: ../TimelineGroupItem +sidebar_class_name: newComponentBadge +--- + +<%COMPONENT_OVERVIEW%> + +<%COMPONENT_METADATA%> \ No newline at end of file diff --git a/packages/website/docs/_samples/fiori/Timeline/WithGroups/WithGroups.md b/packages/website/docs/_samples/fiori/Timeline/WithGroups/WithGroups.md new file mode 100644 index 000000000000..ffccbf6dd13e --- /dev/null +++ b/packages/website/docs/_samples/fiori/Timeline/WithGroups/WithGroups.md @@ -0,0 +1,4 @@ +import html from '!!raw-loader!./sample.html'; +import js from '!!raw-loader!./main.js'; + + \ No newline at end of file diff --git a/packages/website/docs/_samples/fiori/Timeline/WithGroups/main.js b/packages/website/docs/_samples/fiori/Timeline/WithGroups/main.js new file mode 100644 index 000000000000..98fc68e6301b --- /dev/null +++ b/packages/website/docs/_samples/fiori/Timeline/WithGroups/main.js @@ -0,0 +1,9 @@ +import "@ui5/webcomponents/dist/Label.js"; +import "@ui5/webcomponents-fiori/dist/Timeline.js"; +import "@ui5/webcomponents-fiori/dist/TimelineItem.js"; +import "@ui5/webcomponents/dist/Avatar.js"; +import "@ui5/webcomponents/dist/Label.js"; +import "@ui5/webcomponents-icons/dist/phone.js"; +import "@ui5/webcomponents-icons/dist/calendar.js"; +import "@ui5/webcomponents-icons/dist/slim-arrow-down.js"; +import "@ui5/webcomponents-icons/dist/slim-arrow-left.js"; \ No newline at end of file diff --git a/packages/website/docs/_samples/fiori/Timeline/WithGroups/sample.html b/packages/website/docs/_samples/fiori/Timeline/WithGroups/sample.html new file mode 100644 index 000000000000..e80fadb5c93d --- /dev/null +++ b/packages/website/docs/_samples/fiori/Timeline/WithGroups/sample.html @@ -0,0 +1,41 @@ + + + + + + + + Sample + + + + + + + + + + + + + + + + + + + + + + + + Has ended the call + + + + + + + + + \ No newline at end of file