diff --git a/.changeset/legal-jobs-marry.md b/.changeset/legal-jobs-marry.md new file mode 100644 index 0000000000..c5dde016e7 --- /dev/null +++ b/.changeset/legal-jobs-marry.md @@ -0,0 +1,6 @@ +--- +"@stackoverflow/stacks": minor +"@stackoverflow/stacks-svelte": minor +--- + +Update Menu to SHINE styles; add Svelte component diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index 1d1c6e5c65..17b6452f57 100755 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -28,6 +28,47 @@ - The Award Bling component has been renamed to Bling. - 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. +#### Menu + +The menu component has been updated to use new class names and structure. The following changes are breaking: + +- **Link classes**: Replace `.s-block-link` with `.s-menu--action` on all menu links and buttons. +- **Danger state**: Replace `.s-block-link__danger` with `.s-menu--action__danger`. +- **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 `` or ` -
  • - Example li +
  • + - -
  • - Block link +
  • -
  • - Danger link +
  • `, }, diff --git a/packages/stacks-classic/lib/components/menu/menu.less b/packages/stacks-classic/lib/components/menu/menu.less index 712a8d6bbe..e5c7aedac5 100644 --- a/packages/stacks-classic/lib/components/menu/menu.less +++ b/packages/stacks-classic/lib/components/menu/menu.less @@ -1,39 +1,118 @@ .s-menu { - --_me-divider-bg: var(--bc-light); - --_me-label-btc: var(--bc-light); - --_me-label-cursor: pointer; - - // CONTEXTUAL STYLES - .dark-mode({ - --_me-divider-bg: var(--bc-light); - --_me-label-btc: var(--bc-light); - }); + --_me-action-bg: unset; + --_me-action-fc: var(--black-500); + --_me-item-p: var(--su8); + --_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 // CHILD ELEMENTS & &--divider { - background-color: var(--_me-divider-bg); + background-color: var(--black-200); height: var(--su-static1); margin: var(--su8) 0; } - & &--label { - &.is-disabled { - --_me-label-cursor: not-allowed; + & &--icon { + color: inherit; + margin-right: var(--su8); + } + + & &--item { + &:has(> .s-menu--action){ + --_me-item-p: 0; + } + + &.s-check-control { + --_me-item-p: var(--su6) var(--su8); + + .s-radio, + .s-checkbox { + margin-top: var(--su4); + } + + align-items: flex-start; + } + + &:not(.s-check-control) { + .s-radio, + .s-checkbox { + height: 0; + pointer-events: none; + position: absolute; + opacity: 0; + width: 0; + } + } + + color: var(--_me-action-fc); + padding: var(--_me-item-p); + + align-items: center; + display: flex; + width: 100%; + } + + & &--action { + &:focus-visible, + &:has(> input:focus-visible) { + .focus-styles(true, false); + } + + &:focus-visible, + &:has(> input:focus-visible), + &:hover { + --_me-action-bg: var(--black-150); + --_me-action-fc: var(--black-600); + } + + &__danger { + --_me-action-fc: var(--red-400); + + &:focus-visible, + &:hover { + --_me-action-fc: var(--red-500); + } } - border-top: var(--su-static1) solid var(--_me-label-btc); - cursor: var(--_me-label-cursor); - padding: var(--su12); + &.is-selected, + &:has(input:checked) { + &:after { + background-color: var(--_me-action-fc); + content: ""; + height: var(--su16); + margin-left: auto; + width: var(--su16); + mask-image: var(--_me-after-mask); + mask-size: contain; + mask-repeat: no-repeat; + } + + } + + background-color: var(--_me-action-bg); + color: var(--_me-action-fc); + + align-items: center; + border-radius: var(--br-md); + cursor: pointer; + display: flex; + padding: var(--su8); + width: 100%; + } + + & button&--action { // Normalize for when applying to a button + border: none; + font-family: inherit; + line-height: inherit; + text-align: left; } & &--title { - color: var(--black-500); - font-size: var(--fs-fine); - padding: var(--su8) var(--su12); - text-transform: uppercase; + color: var(--black-600); + font-weight: 700; + padding: var(--su6) var(--su8); } - & li + &--title { + & &--item + &--title { margin-top: var(--su12); } diff --git a/packages/stacks-classic/lib/components/menu/menu.visual.test.ts b/packages/stacks-classic/lib/components/menu/menu.visual.test.ts index 1850474f49..0cd8c42623 100644 --- a/packages/stacks-classic/lib/components/menu/menu.visual.test.ts +++ b/packages/stacks-classic/lib/components/menu/menu.visual.test.ts @@ -8,23 +8,22 @@ describe("menu", () => { children: { default: ` -
  • - Example li +
  • - -
  • - Selected link +
  • -
  • - Example li +
  • + - -
  • - Block link +
  • -
  • - Danger link +
  • `, }, diff --git a/packages/stacks-classic/lib/components/popover/popover.less b/packages/stacks-classic/lib/components/popover/popover.less index f8b213dc8a..d6cd27f08a 100644 --- a/packages/stacks-classic/lib/components/popover/popover.less +++ b/packages/stacks-classic/lib/components/popover/popover.less @@ -12,9 +12,7 @@ // CONTEXTUAL STYLES .dark-mode({ - --_po-bg: var(--black-200); - --_po-bc: var(--bc-light); - --_po-bs: var(--bs-lg); + --_po-bg: var(--black-100); }); // MODIFIERS @@ -44,7 +42,7 @@ } background-color: var(--_po-bg); - border: 1px solid var(--_po-bc); + border: var(--su-static1) solid var(--_po-bc); box-shadow: var(--_po-bs); display: var(--_po-d); min-width: var(--_po-wmn); diff --git a/packages/stacks-docs/_data/menu.json b/packages/stacks-docs/_data/menu.json index 0d79a8cf6f..58eb9954a0 100644 --- a/packages/stacks-docs/_data/menu.json +++ b/packages/stacks-docs/_data/menu.json @@ -3,22 +3,42 @@ { "class": ".s-menu", "applies": "N/A", - "description": "Base container styling for a menu" + "description": "Base container styling for a menu." }, { - "class": ".s-menu--title", + "class": ".s-menu--divider", "applies": ".s-menu", - "description": "Adds appropriate styling for a title within a menu" + "description": "Adds a divider line between menu sections." }, { - "class": ".s-menu--divider", + "class": ".s-menu--item", "applies": ".s-menu", - "description": "Styles a divider and adds the right amount of spacing" + "description": "Applies link styling to link within a menu. Used for actionable elements." }, { - "class": ".s-menu--label", + "class": ".s-menu--title", "applies": ".s-menu", - "description": "This gets applied to radio button labels within a menu for proper cursors and aesthetics" + "description": "Adds appropriate styling for a title within a menu." + }, + { + "class": ".s-menu--icon", + "applies": ".s-menu--item", + "description": "Applies styling to an icon." + }, + { + "class": ".s-menu--action", + "applies": ".s-menu--item", + "description": "Applies link styling to link within a menu. Used for actionable elements." + }, + { + "class": ".s-menu--action__danger", + "applies": ".s-menu--action", + "description": "Applies danger styling to a menu link. Used for destructive actions." + }, + { + "class": ".is-selected", + "applies": ".s-menu--action", + "description": "Applies a checkmark to indicate the selected state of a menu item." } ] } \ No newline at end of file diff --git a/packages/stacks-docs/_data/site-navigation.json b/packages/stacks-docs/_data/site-navigation.json index ef2d30a415..c8fec1e6f7 100644 --- a/packages/stacks-docs/_data/site-navigation.json +++ b/packages/stacks-docs/_data/site-navigation.json @@ -265,7 +265,8 @@ }, { "title": "Menus", - "url": "/product/components/menus/" + "url": "/product/components/menus/", + "new": true }, { "title": "Modals", diff --git a/packages/stacks-docs/assets/js/entry.popovers.js b/packages/stacks-docs/assets/js/entry.popovers.js index c98d6c4b99..cbf30fc996 100644 --- a/packages/stacks-docs/assets/js/entry.popovers.js +++ b/packages/stacks-docs/assets/js/entry.popovers.js @@ -13,7 +13,7 @@ $(document).ready(function() { load() { if (this.loaded) { return; } setTimeout(() => { - Stacks.attachPopover(this.element, `
    `, { autoShow: true, toggleOnClick: true, placement: "bottom" }); + Stacks.attachPopover(this.element, `
    `, { autoShow: true, toggleOnClick: true, placement: "bottom" }); this.loaded = true; }); }, diff --git a/packages/stacks-docs/product/components/menus.html b/packages/stacks-docs/product/components/menus.html index c5c0986ddd..a635d68894 100644 --- a/packages/stacks-docs/product/components/menus.html +++ b/packages/stacks-docs/product/components/menus.html @@ -2,6 +2,8 @@ layout: page title: Menus description: A menu offers a contextual list of actions or functions. +svelte: https://beta.svelte.stackoverflow.design/?path=/docs/components-menu--docs +figma: https://www.figma.com/design/do4Ug0Yws8xCfRjHe9cJfZ/Project-SHINE---Product-UI?node-id=610-18810 tags: components ---
    @@ -35,94 +37,94 @@ {% header "h3", "Basic" %}

    - At its most basic, a menu is a simple styled list of contextual actions. Because they’re contextual, it’s strongly recommended that a menu is contained within a popover or a card. Menu items are either links or buttons styled with the block link component, that can optionally be selected or have destructive styling. When placed in various containers, you’ll need to either account for the padding on the container, or use negative margins on the menu component itself. + At its most basic, a menu is a simple styled list of contextual actions. Because they’re contextual, it’s strongly recommended that a menu is contained within a popover or a card. When placed in various containers, you’ll need to either account for the padding on the container, or use negative margins on the menu component itself.

    {% highlight html %} -
    +
    -
    +
    {% endhighlight %}
    -
    +
    Within a popover
    -
    +
    -
    +
    Within a card
    -
    +
    -
    +
    No container