Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Menu #286

Merged
merged 20 commits into from
Apr 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:
runs-on: ubuntu-latest
needs: [setup]
timeout-minutes: 5
if: ${{ fromJSON(needs.setup.outputs.pending).test-app.test.status == 'MISS' }}
# if: ${{ fromJSON(needs.setup.outputs.pending).test-app.test.status == 'MISS' }}
steps:
- uses: wyvox/action@v1
with:
Expand All @@ -68,7 +68,7 @@ jobs:
runs-on: ubuntu-latest
needs: [test]
timeout-minutes: 5
if: ${{ fromJSON(needs.setup.outputs.pending).test-app.test.status == 'MISS' }}
# if: ${{ fromJSON(needs.setup.outputs.pending).test-app.test.status == 'MISS' }}
steps:
- uses: wyvox/action@v1
with:
Expand All @@ -83,7 +83,7 @@ jobs:
runs-on: ubuntu-latest
needs: [test]
timeout-minutes: 10
if: ${{ fromJSON(needs.setup.outputs.pending).test-app.test.status == 'MISS' }}
# if: ${{ fromJSON(needs.setup.outputs.pending).test-app.test.status == 'MISS' }}
strategy:
fail-fast: false
matrix:
Expand All @@ -110,7 +110,7 @@ jobs:
typecheck:
name: '${{ matrix.typescript-scenario }}'
runs-on: ubuntu-latest
if: ${{ fromJSON(needs.setup.outputs.pending).test-app['lint:types'].status == 'MISS' }}
# if: ${{ fromJSON(needs.setup.outputs.pending).test-app['lint:types'].status == 'MISS' }}
timeout-minutes: 5
needs: [test]
continue-on-error: true
Expand All @@ -137,7 +137,7 @@ jobs:

docs-tests:
name: "Docs' Tests"
if: ${{ fromJSON(needs.setup.outputs.pending).docs-app.test.status == 'MISS' }}
# if: ${{ fromJSON(needs.setup.outputs.pending).docs-app.test.status == 'MISS' }}
runs-on: ubuntu-latest
timeout-minutes: 5
needs: [setup]
Expand Down
112 changes: 112 additions & 0 deletions docs-app/public/docs/5-floaty-bits/menu.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# Menu

Menus are built with Popovers, with added features for keyboard navigation and accessibility.

The placement of the menu content is handled by `<Popover>`, so `<Menu>` accepts the same arguments for positioning the dropdown.

Like `<Popover>`, the `<Menu>` component uses portals in a way that totally solves layering issues. No more worrying about tooltips on varying layers of your UI sometimes appearing behind other floaty bits. See the `<Portal>` and `<PortalTargets>` pages for more information.

<div class="featured-demo">

```gjs live preview no-shadow
import { PortalTargets, Menu } from 'ember-primitives';

<template>
<PortalTargets />

<Menu @offsetOptions={{8}} as |m|>
<m.Trigger class="trigger" aria-label="Options">
<EllipsisVertical />
</m.Trigger>

<m.Content class="content" as |c|>
<c.Item>Item 1</c.Item>
<c.Item>Item 2</c.Item>
<c.Separator />
<c.Item>Item 3</c.Item>
</m.Content>
</Menu>

<style>
.content {
all: unset;
min-width: 180px;
background: #fff;
color: #111827;
padding: 8px 0;
border-radius: 6px;
border: none;
font-size: 14px;
z-index: 10;
box-shadow: 0 0 #0000, 0 0 #0000, 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
display: flex;
flex-direction: column;
}

.content [role="menuitem"] {
all: unset;
display: block;
padding: 4px 12px;
cursor: pointer;
}

.content [role="menuitem"]:focus, .trigger:hover {
background-color: #f9fafb;
}

.content [role="separator"] {
border-bottom: 1px solid rgb(17 24 39 / 0.1);
}

.trigger {
display: inline-block;
border-radius: 4px;
border-width: 0;
background-color: #fff;
color: #111827;
border-radius: 100%;
padding: 10px;
box-shadow: rgba(0, 0, 0, 0.2) 0px 2px 10px;
cursor: pointer;
}

.trigger svg {
width: 15px;
height: 15px;
display: block;
}
</style>
</template>

const EllipsisVertical = <template>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 512" fill="currentColor"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M64 360a56 56 0 1 0 0 112 56 56 0 1 0 0-112zm0-160a56 56 0 1 0 0 112 56 56 0 1 0 0-112zM120 96A56 56 0 1 0 8 96a56 56 0 1 0 112 0z"/></svg>
</template>;
```

</div>


## API Reference

```gjs live no-shadow
import { ComponentSignature } from 'docs-app/docs-support';

<template>
<ComponentSignature @module="components/menu" @name="Signature" />
</template>
```

## Accessibility

Adheres to the [Menu Button WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/).

### Keyboard Interactions

| key | description |
| :---: | :----------- |
| <kbd>Space</kbd> <kbd>Enter</kbd> | When focus is on `Trigger`, opens the menu and focuses the first item. When focus is on an `Item`, activates the focused item. |
| <kbd>ArrowDown</kbd> <kbd>ArrowRight</kbd> | When `Content` is open, moves to the next item. |
| <kbd>ArrowUp</kbd> <kbd>ArrowLeft</kbd> | When `Content` is open, moves to the previous item. |
| <kbd>Esc</kbd> | Closes the menu and moves focus to `Trigger`. |

In addition, a label is required so that users know what the switch is for.
3 changes: 2 additions & 1 deletion docs-app/public/docs/5-floaty-bits/popover.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Popovers are built with [ember-velcro][gh-e-velcro], which is an ergonomic wrapp


<!--
The goal of a popover is to provide additional behavioral functionality to make interacting with floaty bits easier easier:
The goal of a popover is to provide additional behavioral functionality to make interacting with floaty bits easier:
- focus trapping (TODO)
- focus returning (TODO)
-->
Expand Down Expand Up @@ -232,4 +232,5 @@ Since a `Popover` isn't an explicit design pattern provided by W3, but instead,
- [Date Picker Dialog](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/examples/datepicker-dialog/)
- [Date Picker Combobox](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/examples/combobox-datepicker/)
- [Select-Only Combobox](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/examples/combobox-select-only/)
- [Menu Button](https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/)
- and more
15 changes: 11 additions & 4 deletions docs-app/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
{
"extends": "@tsconfig/ember/tsconfig.json",
"glint": {
"environment": ["ember-loose", "ember-template-imports"],
"environment": ["ember-loose", "ember-template-imports"]
},
"compilerOptions": {
// Have to use this because the glimmer types just *don't*
// work with pnpm and being pre v1. if we were to make them post-v1, we could maybe make progress,
// but there are too many scenarios where the wrong glimmer-vm dep is used for type checking,
// when it shouldn't be used at all (like, it's a dependency of a tool).
//
// TODO: remove this
"skipLibCheck": true,
// The combination of `baseUrl` with `paths` allows Ember's classic package
// layout, which is not resolvable with the Node resolution algorithm, to
// work with TypeScript.
"baseUrl": ".",
"paths": {
"docs-app/tests/*": ["tests/*"],
"docs-app/*": ["app/*"],
"*": ["types/*"],
},
"*": ["types/*"]
}
},
"include": ["app/**/*", "tests/**/*", "types/**/*"],
"include": ["app/**/*", "tests/**/*", "types/**/*"]
}
3 changes: 2 additions & 1 deletion ember-primitives/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"decorator-transforms": "^1.1.0",
"ember-element-helper": "^0.8.4",
"reactiveweb": "^1.2.0",
"tabster": "^7.0.1",
"tabster": "^7.1.0",
miguelcobain marked this conversation as resolved.
Show resolved Hide resolved
"tracked-built-ins": "^3.2.0",
"tracked-toolbox": "^2.0.0"
},
Expand Down Expand Up @@ -109,6 +109,7 @@
"./components/external-link.js": "./dist/_app_/components/external-link.js",
"./components/form.js": "./dist/_app_/components/form.js",
"./components/link.js": "./dist/_app_/components/link.js",
"./components/menu.js": "./dist/_app_/components/menu.js",
"./components/popover.js": "./dist/_app_/components/popover.js",
"./components/portal-targets.js": "./dist/_app_/components/portal-targets.js",
"./components/portal.js": "./dist/_app_/components/portal.js",
Expand Down
Loading
Loading