Skip to content

Commit 5e49f0b

Browse files
authored
chore(menu): update to SHINE styles (#2046)
* chore(menu): update to SHINE styles * Minor related popover style tweaks * Add svelte menu component * Update a11y tests * Update migration guide * Update visual test (just the test file) * add changeset * formatting * linting * Update menu components outside of menu * Add Svelte and Figma links in frontmatter * Eating dogfood (popover in menu story) * Remove MenuItemControl * Rename MenuItemLink to MenuItem * Rename MenuItem input * Rename s-menu--link to s-menu--action * Improve selected, radio, checkbox styles * Stick to `ul`, remove `iconTitle` * Simplify tests; add i18nSelectedLabel; cleanup * Update migration guide * add comment for selected checkmark * Let's just put that comment inline * fix checkmark background image * proper indentation! * Improve custom checkmark styling * Final cleanup
1 parent 13b6189 commit 5e49f0b

File tree

18 files changed

+988
-181
lines changed

18 files changed

+988
-181
lines changed

.changeset/legal-jobs-marry.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@stackoverflow/stacks": minor
3+
"@stackoverflow/stacks-svelte": minor
4+
---
5+
6+
Update Menu to SHINE styles; add Svelte component

MIGRATION_GUIDE.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,47 @@
2828
- The Award Bling component has been renamed to Bling.
2929
- Bling no longer accepts children elements besides those for screen readers. Please include any visually represented strings (such as counts) as siblings to the bling component.
3030

31+
#### Menu
32+
33+
The menu component has been updated to use new class names and structure. The following changes are breaking:
34+
35+
- **Link classes**: Replace `.s-block-link` with `.s-menu--action` on all menu links and buttons.
36+
- **Danger state**: Replace `.s-block-link__danger` with `.s-menu--action__danger`.
37+
- **Selected state**: The selected state has changed from `.s-block-link__left.is-selected` to just `.is-selected` on the `.s-menu--action` element. The `.is-selected` class should be applied to the `<a>` or `<button>` element, not the `<li>`.
38+
- **Menu item class**: All menu item `<li>` elements must now include the `.s-menu--item` class.
39+
- **Menu label removed**: The `.s-menu--label` class has replaced with `.s-menu--title` for section titles instead.
40+
41+
**Before:**
42+
```html
43+
<ul class="s-menu" role="menu">
44+
<li role="menuitem">
45+
<a href="#" class="s-block-link">Example link</a>
46+
</li>
47+
<li role="menuitem">
48+
<a href="#" class="s-block-link s-block-link__left is-selected">Selected link</a>
49+
</li>
50+
<li role="menuitem" class="s-menu--label">Example label</li>
51+
<li role="menuitem">
52+
<a href="#" class="s-block-link s-block-link__danger">Danger link</a>
53+
</li>
54+
</ul>
55+
```
56+
57+
**After:**
58+
```html
59+
<ul class="s-menu" role="menu">
60+
<li class="s-menu--item" role="menuitem">
61+
<a href="#" class="s-menu--action">Example link</a>
62+
</li>
63+
<li class="s-menu--item" role="menuitem">
64+
<a href="#" class="s-menu--action is-selected">Selected link</a>
65+
</li>
66+
<li class="s-menu--title" role="separator">Section Title</li>
67+
<li class="s-menu--item" role="menuitem">
68+
<a href="#" class="s-menu--action s-menu--action__danger">Danger link</a>
69+
</li>
70+
</ul>
71+
```
3172
#### Pagination
3273
- The next and previous button now uses an `ArrowRight` and `ArrowLeft` icon instead of text. To apply the new styling, use the class `.s-pagination--item__nav`. Since these buttons use icons to represent their behavior, make sure to include descriptive text for screen readers.
3374

packages/stacks-classic/lib/components/menu/menu.a11y.test.ts

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,22 @@ describe("menu", () => {
88
children: {
99
default: `
1010
<li class="s-menu--title" role="separator">Title 1</li>
11-
<li role="menuitem">
12-
<a href="#" class="s-block-link">Example li</a>
11+
<li class="s-menu--item" role="menuitem">
12+
<a href="#" class="s-menu--action">Example link</a>
1313
</li>
14-
<li class="s-menu--title" role="separator">Title 2</li>
15-
<li role="menuitem">
16-
<a href="#" class="s-block-link s-block-link__left is-selected">Selected link</a>
14+
<li class="s-menu--item" role="menuitem">
15+
<button class="s-menu--action">Example button</button>
1716
</li>
18-
<li role="menuitem">
19-
<a href="#" class="s-block-link">Example li</a>
17+
<li class="s-menu--title" role="separator">Title 2</li>
18+
<li class="s-menu--item" role="menuitem">
19+
<a href="#" class="s-menu--action is-selected">Selected link</a>
2020
</li>
21-
<li role="menuitem" class="s-menu--label">Example label</li>
22-
<li role="menuitem">
23-
<a href="#" class="s-block-link">Block link</a>
21+
<li class="s-menu--item" role="menuitem">
22+
<a href="#" class="s-menu--action">Example link</a>
2423
</li>
2524
<li class="s-menu--divider" role="separator"></li>
26-
<li role="menuitem">
27-
<a href="" class="s-block-link s-block-link__danger">Danger link</a>
25+
<li class="s-menu--item" role="menuitem">
26+
<a href="#" class="s-menu--action s-menu--action__danger">Danger link</a>
2827
</li>
2928
`,
3029
},

packages/stacks-classic/lib/components/menu/menu.less

Lines changed: 100 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,118 @@
11
.s-menu {
2-
--_me-divider-bg: var(--bc-light);
3-
--_me-label-btc: var(--bc-light);
4-
--_me-label-cursor: pointer;
5-
6-
// CONTEXTUAL STYLES
7-
.dark-mode({
8-
--_me-divider-bg: var(--bc-light);
9-
--_me-label-btc: var(--bc-light);
10-
});
2+
--_me-action-bg: unset;
3+
--_me-action-fc: var(--black-500);
4+
--_me-item-p: var(--su8);
5+
--_me-after-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='m14 3.88-.44.44-7.34 7.35-.44.44-.44-.44-2.9-2.9L2 8.34l.89-.88.44.44 2.45 2.45 6.9-6.9.44-.44z'/%3E%3C/svg%3E"); // check16
116

127
// CHILD ELEMENTS
138
& &--divider {
14-
background-color: var(--_me-divider-bg);
9+
background-color: var(--black-200);
1510
height: var(--su-static1);
1611
margin: var(--su8) 0;
1712
}
1813

19-
& &--label {
20-
&.is-disabled {
21-
--_me-label-cursor: not-allowed;
14+
& &--icon {
15+
color: inherit;
16+
margin-right: var(--su8);
17+
}
18+
19+
& &--item {
20+
&:has(> .s-menu--action){
21+
--_me-item-p: 0;
22+
}
23+
24+
&.s-check-control {
25+
--_me-item-p: var(--su6) var(--su8);
26+
27+
.s-radio,
28+
.s-checkbox {
29+
margin-top: var(--su4);
30+
}
31+
32+
align-items: flex-start;
33+
}
34+
35+
&:not(.s-check-control) {
36+
.s-radio,
37+
.s-checkbox {
38+
height: 0;
39+
pointer-events: none;
40+
position: absolute;
41+
opacity: 0;
42+
width: 0;
43+
}
44+
}
45+
46+
color: var(--_me-action-fc);
47+
padding: var(--_me-item-p);
48+
49+
align-items: center;
50+
display: flex;
51+
width: 100%;
52+
}
53+
54+
& &--action {
55+
&:focus-visible,
56+
&:has(> input:focus-visible) {
57+
.focus-styles(true, false);
58+
}
59+
60+
&:focus-visible,
61+
&:has(> input:focus-visible),
62+
&:hover {
63+
--_me-action-bg: var(--black-150);
64+
--_me-action-fc: var(--black-600);
65+
}
66+
67+
&__danger {
68+
--_me-action-fc: var(--red-400);
69+
70+
&:focus-visible,
71+
&:hover {
72+
--_me-action-fc: var(--red-500);
73+
}
2274
}
2375

24-
border-top: var(--su-static1) solid var(--_me-label-btc);
25-
cursor: var(--_me-label-cursor);
26-
padding: var(--su12);
76+
&.is-selected,
77+
&:has(input:checked) {
78+
&:after {
79+
background-color: var(--_me-action-fc);
80+
content: "";
81+
height: var(--su16);
82+
margin-left: auto;
83+
width: var(--su16);
84+
mask-image: var(--_me-after-mask);
85+
mask-size: contain;
86+
mask-repeat: no-repeat;
87+
}
88+
89+
}
90+
91+
background-color: var(--_me-action-bg);
92+
color: var(--_me-action-fc);
93+
94+
align-items: center;
95+
border-radius: var(--br-md);
96+
cursor: pointer;
97+
display: flex;
98+
padding: var(--su8);
99+
width: 100%;
100+
}
101+
102+
& button&--action { // Normalize for when applying to a button
103+
border: none;
104+
font-family: inherit;
105+
line-height: inherit;
106+
text-align: left;
27107
}
28108

29109
& &--title {
30-
color: var(--black-500);
31-
font-size: var(--fs-fine);
32-
padding: var(--su8) var(--su12);
33-
text-transform: uppercase;
110+
color: var(--black-600);
111+
font-weight: 700;
112+
padding: var(--su6) var(--su8);
34113
}
35114

36-
& li + &--title {
115+
& &--item + &--title {
37116
margin-top: var(--su12);
38117
}
39118

packages/stacks-classic/lib/components/menu/menu.visual.test.ts

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,22 @@ describe("menu", () => {
88
children: {
99
default: `
1010
<li class="s-menu--title" role="separator">Title 1</li>
11-
<li role="menuitem">
12-
<a href="#" class="s-block-link">Example li</a>
11+
<li class="s-menu--item" role="menuitem">
12+
<a href="#" class="s-menu--action">Example link</a>
1313
</li>
14-
<li class="s-menu--title" role="separator">Title 2</li>
15-
<li role="menuitem">
16-
<a href="#" class="s-block-link s-block-link__left is-selected">Selected link</a>
14+
<li class="s-menu--item" role="menuitem">
15+
<button class="s-menu--action">Example button</button>
1716
</li>
18-
<li role="menuitem">
19-
<a href="#" class="s-block-link">Example li</a>
17+
<li class="s-menu--title" role="separator">Title 2</li>
18+
<li class="s-menu--item" role="menuitem">
19+
<a href="#" class="s-menu--action is-selected">Selected link</a>
2020
</li>
21-
<li role="menuitem" class="s-menu--label">Example label</li>
22-
<li role="menuitem">
23-
<a href="#" class="s-block-link">Block link</a>
21+
<li class="s-menu--item" role="menuitem">
22+
<a href="#" class="s-menu--action">Example link</a>
2423
</li>
2524
<li class="s-menu--divider" role="separator"></li>
26-
<li role="menuitem">
27-
<a href="" class="s-block-link s-block-link__danger">Danger link</a>
25+
<li class="s-menu--item" role="menuitem">
26+
<a href="#" class="s-menu--action s-menu--action__danger">Danger link</a>
2827
</li>
2928
`,
3029
},

packages/stacks-classic/lib/components/popover/popover.less

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@
1212

1313
// CONTEXTUAL STYLES
1414
.dark-mode({
15-
--_po-bg: var(--black-200);
16-
--_po-bc: var(--bc-light);
17-
--_po-bs: var(--bs-lg);
15+
--_po-bg: var(--black-100);
1816
});
1917

2018
// MODIFIERS
@@ -44,7 +42,7 @@
4442
}
4543

4644
background-color: var(--_po-bg);
47-
border: 1px solid var(--_po-bc);
45+
border: var(--su-static1) solid var(--_po-bc);
4846
box-shadow: var(--_po-bs);
4947
display: var(--_po-d);
5048
min-width: var(--_po-wmn);

packages/stacks-docs/_data/menu.json

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,42 @@
33
{
44
"class": ".s-menu",
55
"applies": "N/A",
6-
"description": "Base container styling for a menu"
6+
"description": "Base container styling for a menu."
77
},
88
{
9-
"class": ".s-menu--title",
9+
"class": ".s-menu--divider",
1010
"applies": ".s-menu",
11-
"description": "Adds appropriate styling for a title within a menu"
11+
"description": "Adds a divider line between menu sections."
1212
},
1313
{
14-
"class": ".s-menu--divider",
14+
"class": ".s-menu--item",
1515
"applies": ".s-menu",
16-
"description": "Styles a divider and adds the right amount of spacing"
16+
"description": "Applies link styling to link within a menu. Used for actionable elements."
1717
},
1818
{
19-
"class": ".s-menu--label",
19+
"class": ".s-menu--title",
2020
"applies": ".s-menu",
21-
"description": "This gets applied to radio button labels within a menu for proper cursors and aesthetics"
21+
"description": "Adds appropriate styling for a title within a menu."
22+
},
23+
{
24+
"class": ".s-menu--icon",
25+
"applies": ".s-menu--item",
26+
"description": "Applies styling to an icon."
27+
},
28+
{
29+
"class": ".s-menu--action",
30+
"applies": ".s-menu--item",
31+
"description": "Applies link styling to link within a menu. Used for actionable elements."
32+
},
33+
{
34+
"class": ".s-menu--action__danger",
35+
"applies": ".s-menu--action",
36+
"description": "Applies danger styling to a menu link. Used for destructive actions."
37+
},
38+
{
39+
"class": ".is-selected",
40+
"applies": ".s-menu--action",
41+
"description": "Applies a checkmark to indicate the selected state of a menu item."
2242
}
2343
]
2444
}

packages/stacks-docs/_data/site-navigation.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,8 @@
265265
},
266266
{
267267
"title": "Menus",
268-
"url": "/product/components/menus/"
268+
"url": "/product/components/menus/",
269+
"new": true
269270
},
270271
{
271272
"title": "Modals",

packages/stacks-docs/assets/js/entry.popovers.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ $(document).ready(function() {
1313
load() {
1414
if (this.loaded) { return; }
1515
setTimeout(() => {
16-
Stacks.attachPopover(this.element, `<div class="s-popover wmx1"><ul class="s-menu mxn12 myn8" role="menu"><li role="menuitem"><button class="s-block-link">Share</button></li><li role="menuitem"><button class="s-block-link">Edit</button></li><li role="menuitem"><button class="s-block-link">Flag</button></li><li class="s-menu--divider" role="separator"></li><li role="menuitem"><button class="s-block-link s-block-link__danger">Delete</button></li></ul></div>`, { autoShow: true, toggleOnClick: true, placement: "bottom" });
16+
Stacks.attachPopover(this.element, `<div class="s-popover wmx1 p8"><ul class="s-menu" role="menu"><li class="s-menu--item" role="menuitem"><button class="s-menu--action">Share</button></li><li class="s-menu--item" role="menuitem"><button class="s-menu--action">Edit</button></li><li class="s-menu--item" role="menuitem"><button class="s-menu--action">Flag</button></li><li class="s-menu--divider mxn8" role="separator"></li><li class="s-menu--item" role="menuitem"><button class="s-menu--action s-menu--action__danger">Delete</button></li></ul></div>`, { autoShow: true, toggleOnClick: true, placement: "bottom" });
1717
this.loaded = true;
1818
});
1919
},

0 commit comments

Comments
 (0)