Skip to content

Commit

Permalink
Tab group improvements (#1058)
Browse files Browse the repository at this point in the history
  • Loading branch information
jpzwarte authored Mar 22, 2024
1 parent a523759 commit 090c7b0
Show file tree
Hide file tree
Showing 95 changed files with 1,553 additions and 1,205 deletions.
5 changes: 5 additions & 0 deletions .changeset/afraid-wolves-admire.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@sl-design-system/shared": patch
---

Add `getScrollParent()` utility method
5 changes: 5 additions & 0 deletions .changeset/perfect-lemons-teach.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@sl-design-system/menu": patch
---

Add `--sl-menu-(min|max)-inline-size` CSS custom properties
5 changes: 5 additions & 0 deletions .changeset/poor-trees-attend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@sl-design-system/menu": patch
---

Add button part for customization
5 changes: 5 additions & 0 deletions .changeset/smart-lemons-thank.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@sl-design-system/shared": patch
---

When calculating the max size of a popover, do not overwrite any existing max size properties if they are present
5 changes: 5 additions & 0 deletions .changeset/soft-humans-wonder.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@sl-design-system/menu": patch
---

Fix scrolling when menu overflows
40 changes: 30 additions & 10 deletions packages/components/menu/custom-elements.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,12 @@
"kind": "class",
"description": "Custom element that combines a button and a menu and automatically wires them up\ntogether.",
"name": "MenuButton",
"cssParts": [
{
"description": "The button element.",
"name": "button"
}
],
"slots": [
{
"description": "The menu items should be slotted in the default slot.",
Expand Down Expand Up @@ -288,15 +294,7 @@
"type": {
"text": "void"
}
},
"parameters": [
{
"name": "event",
"type": {
"text": "Event"
}
}
]
}
},
{
"kind": "method",
Expand Down Expand Up @@ -540,6 +538,12 @@
"kind": "class",
"description": "Menu item component for use inside a menu.",
"name": "MenuItem",
"cssParts": [
{
"description": "The wrapper around the menu item content.",
"name": "wrapper"
}
],
"slots": [
{
"description": "Content to display inside the menu item.",
Expand Down Expand Up @@ -885,8 +889,24 @@
"declarations": [
{
"kind": "class",
"description": "",
"description": "A menu that can be used as a context menu or as a dropdown menu.",
"name": "Menu",
"cssProperties": [
{
"description": "The maximum inline size of the menu.",
"name": "--sl-menu-max-inline-size"
},
{
"description": "The minimum inline size of the menu.",
"name": "--sl-menu-min-inline-size"
}
],
"slots": [
{
"description": "The menu's content: menu items or menu item groups.",
"name": ""
}
],
"members": [
{
"kind": "method",
Expand Down
10 changes: 5 additions & 5 deletions packages/components/menu/src/menu-button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { type PopoverPosition } from '@sl-design-system/shared';
import { type CSSResultGroup, LitElement, type PropertyValues, type TemplateResult, html, nothing } from 'lit';
import { property, query, state } from 'lit/decorators.js';
import styles from './menu-button.scss.js';
import { MenuItem } from './menu-item.js';
import { Menu } from './menu.js';

declare global {
Expand All @@ -19,6 +18,8 @@ declare global {
* Custom element that combines a button and a menu and automatically wires them up
* together.
*
* @csspart button - The button element.
*
* @slot default - The menu items should be slotted in the default slot.
* @slot button - Any content for the button should be slotted here.
*/
Expand Down Expand Up @@ -89,6 +90,7 @@ export class MenuButton extends ScopedElementsMixin(LitElement) {
.fill=${this.fill}
.size=${this.size}
.variant=${this.variant}
part="button"
>
<slot name="button"></slot>
${this.selects && this.selected ? html`<span class="selected">${this.selected}</span>` : nothing}
Expand Down Expand Up @@ -125,10 +127,8 @@ export class MenuButton extends ScopedElementsMixin(LitElement) {
}
}

#onMenuClick(event: Event): void {
if (event.target instanceof MenuItem) {
this.menu.hidePopover();
}
#onMenuClick(): void {
this.menu.hidePopover();
}

#onSelect(): void {
Expand Down
2 changes: 1 addition & 1 deletion packages/components/menu/src/menu-item.scss
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ slot[name='submenu']::slotted(sl-menu) {
}
}

.wrapper {
[part='wrapper'] {
align-items: center;
background: var(--_background);
border-radius: var(--_border-radius);
Expand Down
4 changes: 3 additions & 1 deletion packages/components/menu/src/menu-item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ declare global {
/**
* Menu item component for use inside a menu.
*
* @csspart wrapper - The wrapper around the menu item content.
*
* @slot default - Content to display inside the menu item.
* @slot submenu - The menu items that will be displayed when the menu item is shown.
*/
Expand Down Expand Up @@ -95,7 +97,7 @@ export class MenuItem extends ScopedElementsMixin(LitElement) {
override render(): TemplateResult {
return html`
<div aria-hidden="true" class="safe-triangle"></div>
<div class="wrapper">
<div part="wrapper">
${this.selected ? html`<sl-icon name="check"></sl-icon>` : nothing}
<slot></slot>
${this.shortcut ? html`<kbd>${this.#shortcut.render(this.shortcut)}</kbd>` : nothing}
Expand Down
7 changes: 5 additions & 2 deletions packages/components/menu/src/menu.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@
display: none;
flex-direction: column;
margin: 0;
max-inline-size: var(--sl-menu-max-inline-size, auto);
min-inline-size: var(--sl-menu-min-inline-size, fit-content);
opacity: 0;
overflow: visible;
overflow: visible auto;
padding-block: var(--_padding-block);
padding-inline: 0;
scrollbar-width: thin;

@media (prefers-reduced-motion: no-preference) {
transition: opacity 0.2s cubic-bezier(0.25, 0, 0.3, 1);
Expand All @@ -40,7 +43,7 @@
border: var(--_border) !important;
color: var(--_color) !important;
margin: 0 !important;
overflow: visible !important;
overflow: visible auto !important;
padding-block: var(--_padding-block) !important;
padding-inline: 0 !important;
position: fixed;
Expand Down
8 changes: 8 additions & 0 deletions packages/components/menu/src/menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ declare global {
}
}

/**
* A menu that can be used as a context menu or as a dropdown menu.
*
* @cssprop --sl-menu-max-inline-size - The maximum inline size of the menu.
* @cssprop --sl-menu-min-inline-size - The minimum inline size of the menu.
*
* @slot - The menu's content: menu items or menu item groups.
*/
export class Menu extends LitElement {
/** The default offset of the menu to its anchor. */
static offset = 4;
Expand Down
43 changes: 43 additions & 0 deletions packages/components/shared/custom-elements.json
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,14 @@
"package": "./src/decorators/observe.js"
}
},
{
"kind": "js",
"name": "*",
"declaration": {
"name": "*",
"package": "./src/dom.js"
}
},
{
"kind": "js",
"name": "*",
Expand Down Expand Up @@ -4516,6 +4524,41 @@
}
]
},
{
"kind": "javascript-module",
"path": "src/dom.ts",
"declarations": [
{
"kind": "function",
"name": "getScrollParent",
"return": {
"type": {
"text": ""
}
},
"parameters": [
{
"name": "element",
"type": {
"text": "Element"
},
"description": "The element to find the scrollable parent of."
}
],
"description": "Returns the first scrollable parent of the given element."
}
],
"exports": [
{
"kind": "js",
"name": "getScrollParent",
"declaration": {
"name": "getScrollParent",
"module": "src/dom.ts"
}
}
]
},
{
"kind": "javascript-module",
"path": "src/events.ts",
Expand Down
1 change: 1 addition & 0 deletions packages/components/shared/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export * from './src/data-source/data-source.js';
export * from './src/decorators/base.js';
export * from './src/decorators/event.js';
export * from './src/decorators/observe.js';
export * from './src/dom.js';
export * from './src/directives/anchor.js';
export * from './src/events.js';
export * from './src/path.js';
Expand Down
14 changes: 14 additions & 0 deletions packages/components/shared/src/dom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* Returns the first scrollable parent of the given element.
* @param element The element to find the scrollable parent of.
* @returns The first scrollable parent of the given element; if no explicit scroll parent, returns the html element.
*/
export const getScrollParent = (element: Element): Element => {
if (element.scrollHeight > element.clientHeight) {
return element;
} else if (element.parentElement) {
return getScrollParent(element.parentElement);
} else {
return element;
}
};
18 changes: 13 additions & 5 deletions packages/components/shared/src/popover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,19 @@ export const positionPopover = (
padding: options.viewportMargin,
apply: ({ availableWidth, availableHeight }) => {
// Make sure that the overlay is contained by the visible page.
const maxHeight = Math.max(MIN_OVERLAY_HEIGHT, Math.floor(availableHeight));
const maxBlockSize =
Math.max(MIN_OVERLAY_HEIGHT, Math.floor(availableHeight)) - (options.viewportMargin ?? 0),
maxInlineSize = options.maxWidth ?? Math.floor(availableWidth);

const style = getComputedStyle(element),
currentMaxBlockSize = parseInt(style.maxBlockSize) ?? 0,
currentMaxInlineSize = parseInt(style.maxInlineSize) ?? 0;

// If the element already has a max inline or block size that is smaller
// than the available space, don't override it.
Object.assign(element.style, {
maxWidth: `${options.maxWidth ?? Math.floor(availableWidth)}px`,
maxHeight: `${maxHeight - (options.viewportMargin ?? 0)}px`
maxInlineSize: maxInlineSize > currentMaxInlineSize ? '' : `${maxInlineSize}px`,
maxBlockSize: maxBlockSize > currentMaxBlockSize ? '' : `${maxBlockSize}px`
});
}
})
Expand Down Expand Up @@ -87,8 +95,8 @@ export const positionPopover = (

if (arrow && arrowElement) {
Object.assign(arrowElement.style, {
'inset-inline-start': typeof arrow.x === 'number' ? `${roundByDPR(arrow.x)}px` : '',
'inset-block-start': typeof arrow.y === 'number' ? `${roundByDPR(arrow.y)}px` : ''
insetInlineStart: typeof arrow.x === 'number' ? `${roundByDPR(arrow.x)}px` : '',
insetBlockStart: typeof arrow.y === 'number' ? `${roundByDPR(arrow.y)}px` : ''
});
}
});
Expand Down
Loading

0 comments on commit 090c7b0

Please sign in to comment.