Skip to content

Commit cd8fb95

Browse files
committed
First pass overlapping menu with source.
1 parent f062747 commit cd8fb95

File tree

7 files changed

+84
-34
lines changed

7 files changed

+84
-34
lines changed

src/pg/menu/menu.css

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,9 @@
55
[part=items] {
66
display: flex;
77
flex-direction: column;
8-
padding: var(--pg-menu-padding, 0);
8+
padding: var(--pg-menu-padding, 0.25rem);
99
border-width: var(--pg-menu-border-width, 0);
1010
border-style: solid;
11-
border-radius: 0.25rem;
11+
border-radius: 0.5rem;
12+
background-color: var(--pg-menu-background-color, #1E1E1E);
1213
}
13-
14-
[part=items] > *:first-child {
15-
--pg-menu-item-border-radius-top: var(--pg-menu-border-radius, 0.25rem);
16-
}
17-
18-
[part=items] > *:last-child {
19-
--pg-menu-item-border-radius-bottom: var(--pg-menu-border-radius, 0.25rem);
20-
}

src/pg/menu/menu.ts

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,28 @@ export default class PgMenu extends HTMLElement {
3535
});
3636
}
3737

38-
focus() {
39-
const first = this.$items.firstChild as HTMLElement;
40-
first?.focus();
38+
focus(index) {
39+
const item = this.$items.children[index] as HTMLElement;
40+
item?.focus();
41+
}
42+
43+
/**
44+
* Calculate height of items + gap + padding
45+
* @param startIndex Start index.
46+
* @param endIndex End index.
47+
*/
48+
getItemHeight(startIndex, endIndex): number {
49+
const computedStyle = getComputedStyle(this.$items);
50+
let height = parseInt(computedStyle.getPropertyValue('padding-top'), 10);
51+
const total = this.$items.children.length;
52+
if (startIndex > total || endIndex > total) {
53+
throw new Error('startIndex or endIndex out of bounds');
54+
}
55+
for (let i = startIndex; i < endIndex; i++) {
56+
const ele = this.$items.children[i] as any;
57+
height += ele.getHeight();
58+
}
59+
return height;
4160
}
4261

4362
}

src/pg/menuItem/menuItem.css

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,25 @@
33
}
44

55
[part=label] {
6+
font-family: var(--pg-font-family);
67
text-align: var(--pg-menu-item-text-align, left);
7-
background: var(--pg-menu-item-background, #FFFFFF);
8+
background: var(--pg-menu-item-background, transparent);
89
padding: var(--pg-menu-padding, 0.25rem 0.5rem);
9-
border-color: #453C4F;
10-
border-width: 1px;
10+
border-color: transparent;
11+
border-width: 0;
1112
border-style: solid;
12-
border-top-left-radius: var(--pg-menu-item-border-radius-top, 0);
13-
border-top-right-radius: var(--pg-menu-item-border-radius-top, 0);
14-
border-bottom-left-radius: var(--pg-menu-item-border-radius-bottom, 0);
15-
border-bottom-right-radius: var(--pg-menu-item-border-radius-bottom, 0);
13+
border-top-left-radius: var(--pg-menu-item-border-radius-top, 0.25rem);
14+
border-top-right-radius: var(--pg-menu-item-border-radius-top, 0.25rem);
15+
border-bottom-left-radius: var(--pg-menu-item-border-radius-bottom, 0.25rem);
16+
border-bottom-right-radius: var(--pg-menu-item-border-radius-bottom, 0.25rem);
17+
color: var(--pg-menu-item-color, #FFFFFF);
18+
}
19+
20+
[part=label]:hover {
21+
background: #248BE5;
22+
color: #FFFFFF;
23+
}
24+
25+
[part=label]:active {
26+
background: #2B9CFF;
1627
}

src/pg/menuItem/menuItem.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,8 @@ export default class PgMenuItem extends HTMLElement {
3434
this.$label.focus();
3535
}
3636

37+
getHeight(): number {
38+
return this.$label.getBoundingClientRect().height;
39+
}
40+
3741
}

src/pg/overlayMenu/__examples__/basic/basic.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,28 @@ export default class XPgOverlayMenuBasic extends HTMLElement {
1717
this.$button.addEventListener('click', this.#handleClick.bind(this));
1818
}
1919

20+
#value = null;
21+
2022
#menuOpen = false;
2123
async #handleClick() {
2224
if (this.#menuOpen) { return; }
25+
const items = [{
26+
label: 'Item 1',
27+
value: 'item1'
28+
},
29+
{
30+
label: 'Item 2',
31+
value: 'item2'
32+
}];
2333
this.#menuOpen = true;
2434
const result = await PgOverlayMenu.open({
2535
source: this.$button,
26-
items: [{
27-
label: 'Item 1',
28-
value: 'item1'
29-
},
30-
{
31-
label: 'Item 2',
32-
value: 'item2'
33-
}]
36+
value: this.#value,
37+
items
3438
});
39+
if (result !== undefined) {
40+
this.#value = result;
41+
}
3542
this.$result.textContent = result;
3643
this.#menuOpen = false;
3744
}

src/pg/overlayMenu/overlayMenu.css

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,8 @@
33
}
44

55
[part="overlay"] {
6-
position-area: end center;
76
margin: 0;
8-
min-width: anchor-size();
97
padding: 0;
108
border: 0;
11-
position-try-fallbacks: flip-block;
9+
background: transparent;
1210
}

src/pg/overlayMenu/overlayMenu.ts

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ export default class PgOverlayMenu extends PgOverlay {
1515
@Part() $menu: PgMenu;
1616

1717
@Prop() source: HTMLElement | null = null;
18-
@Prop() items = [];
18+
@Prop() items: any[] = [];
19+
@Prop() value: any = null;
1920

2021
render(changes) {
2122
if (changes.items) {
@@ -33,7 +34,23 @@ export default class PgOverlayMenu extends PgOverlay {
3334
});
3435
}
3536
this.$overlay.addEventListener('toggle', this.#toggle.bind(this));
36-
this.$menu.focus();
37+
// Position (replace with css once Firefox supports it)
38+
const rect = this.source?.getBoundingClientRect();
39+
let x = rect?.left ?? 0, y = rect?.top ?? 0;
40+
const value = this.value === null || typeof this.value !== 'object'
41+
? this.value
42+
: this.value.value;
43+
// value is an item in the items list
44+
const index = this.value === null
45+
? -1
46+
: this.items.findIndex(x => x.value === value);
47+
if (index !== -1) {
48+
// Overlap item
49+
y -= this.$menu.getItemHeight(0, index);
50+
}
51+
this.$overlay.style.translate = `${x}px ${y}px`;
52+
// Focus
53+
this.$menu.focus(index);
3754
}
3855

3956
#toggle(e: ToggleEvent) {
@@ -46,6 +63,7 @@ export default class PgOverlayMenu extends PgOverlay {
4663
}
4764

4865
#handleSelect(e: any) {
49-
this.close(e.detail.index);
66+
e.detail.item.index = e.detail.index;
67+
this.close(e.detail.item);
5068
}
5169
}

0 commit comments

Comments
 (0)