ui: Transition App Chrome to use new Disclosure Menus (#12334)
* Add %panel CSS component * Deprecate old menu-panel component * Various smallish tweaks to disclosure-menu * Move all menus in the app chrome to use new DisclosureMenu * Follow up CSS to move all app chrome menus to new components * Don't prevent default any events from anchors * Add a tick to click steps
This commit is contained in:
parent
067223337d
commit
4ad8a0cfef
|
@ -0,0 +1,3 @@
|
||||||
|
```release-note:enhancement
|
||||||
|
ui: Slightly improve usability of main navigation
|
||||||
|
```
|
|
@ -119,32 +119,32 @@
|
||||||
Logout
|
Logout
|
||||||
</Action>
|
</Action>
|
||||||
</Portal>
|
</Portal>
|
||||||
<PopoverMenu @position="right" as |components api|>
|
<DisclosureMenu as |disclosure|>
|
||||||
<BlockSlot @name="trigger">
|
<disclosure.Action
|
||||||
|
{{on 'click' disclosure.toggle}}
|
||||||
|
>
|
||||||
Logout
|
Logout
|
||||||
</BlockSlot>
|
</disclosure.Action>
|
||||||
<BlockSlot @name="menu">
|
<disclosure.Menu as |panel|>
|
||||||
{{#let components.MenuItem components.MenuSeparator as |MenuItem MenuSeparator|}}
|
{{#if authDialog.token.AccessorID}}
|
||||||
{{!TODO: It might be nice to use one of our recursive components here}}
|
<AuthProfile
|
||||||
{{#if authDialog.token.AccessorID}}
|
@item={{authDialog.token}}
|
||||||
<li role="none">
|
/>
|
||||||
<AuthProfile
|
{{/if}}
|
||||||
@item={{authDialog.token}}
|
<panel.Menu as |menu|>
|
||||||
/>
|
<menu.Separator />
|
||||||
</li>
|
<menu.Item
|
||||||
<MenuSeparator />
|
class="dangerous"
|
||||||
{{/if}}
|
>
|
||||||
<MenuItem
|
<menu.Action
|
||||||
class="dangerous"
|
{{on 'click' (optional authDialog.logout)}}
|
||||||
@onclick={{action authDialog.logout}}
|
|
||||||
>
|
>
|
||||||
<BlockSlot @name="label">
|
Logout
|
||||||
Logout
|
</menu.Action>
|
||||||
</BlockSlot>
|
</menu.Item>
|
||||||
</MenuItem>
|
</panel.Menu>
|
||||||
{{/let}}
|
</disclosure.Menu>
|
||||||
</BlockSlot>
|
</DisclosureMenu>
|
||||||
</PopoverMenu>
|
|
||||||
</:authorized>
|
</:authorized>
|
||||||
</AuthDialog>
|
</AuthDialog>
|
||||||
|
|
||||||
|
|
|
@ -1,74 +1,77 @@
|
||||||
{{#if (can "use nspaces")}}
|
{{#if (can "use nspaces")}}
|
||||||
{{#if (can "choose nspaces")}}
|
{{#if (can "choose nspaces")}}
|
||||||
{{#let
|
{{#let
|
||||||
(or @nspace 'default')
|
(or @nspace 'default')
|
||||||
as |nspace|}}
|
as |nspace|}}
|
||||||
<li
|
<li
|
||||||
class="nspaces"
|
class="nspaces"
|
||||||
data-test-nspace-menu
|
data-test-nspace-menu
|
||||||
>
|
>
|
||||||
<PopoverMenu
|
<DisclosureMenu
|
||||||
aria-label="Namespace"
|
aria-label="Namespace"
|
||||||
@position="left"
|
as |disclosure|>
|
||||||
as |components api|>
|
<disclosure.Action
|
||||||
<BlockSlot @name="trigger">
|
{{on 'click' disclosure.toggle}}
|
||||||
{{nspace}}
|
>
|
||||||
</BlockSlot>
|
{{nspace}}
|
||||||
<BlockSlot @name="menu">
|
</disclosure.Action>
|
||||||
{{#let components.MenuItem components.MenuSeparator as |MenuItem MenuSeparator|}}
|
<disclosure.Menu as |panel|>
|
||||||
{{#if (gt @nspaces.length 0)}}
|
{{#if (gt @nspaces.length 0)}}
|
||||||
<DataSource
|
<DataSource
|
||||||
@src={{uri
|
@src={{uri
|
||||||
'/${partition}/*/${dc}/namespaces'
|
'/${partition}/*/${dc}/namespaces'
|
||||||
(hash
|
(hash
|
||||||
partition=@partition
|
partition=@partition
|
||||||
dc=@dc.Name
|
dc=@dc.Name
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
@onchange={{fn (optional @onchange)}}
|
@onchange={{fn (optional @onchange)}}
|
||||||
@loading="lazy"
|
/>
|
||||||
/>
|
{{else}}
|
||||||
{{else}}
|
<DataSource
|
||||||
<DataSource
|
@src={{uri
|
||||||
@src={{uri
|
'/${partition}/*/${dc}/namespaces'
|
||||||
'/${partition}/*/${dc}/namespaces'
|
(hash
|
||||||
(hash
|
partition=@partition
|
||||||
partition=@partition
|
dc=@dc.Name
|
||||||
dc=@dc.Name
|
)
|
||||||
)
|
}}
|
||||||
}}
|
@onchange={{fn (optional @onchange)}}
|
||||||
@onchange={{fn (optional @onchange)}}
|
/>
|
||||||
/>
|
{{/if}}
|
||||||
{{/if}}
|
<panel.Menu as |menu|>
|
||||||
{{#each (reject-by 'DeletedAt' @nspaces) as |item|}}
|
{{#each (reject-by 'DeletedAt' @nspaces) as |item|}}
|
||||||
<MenuItem
|
<menu.Item
|
||||||
class={{if (eq nspace item.Name) 'is-active'}}
|
aria-current={{if (eq nspace item.Name) 'true'}}
|
||||||
|
>
|
||||||
|
<menu.Action
|
||||||
|
{{on 'click' disclosure.close}}
|
||||||
@href={{href-to '.' params=(hash
|
@href={{href-to '.' params=(hash
|
||||||
partition=(if (gt @partition.length 0) @partition undefined)
|
partition=(if (gt @partition.length 0) @partition undefined)
|
||||||
nspace=item.Name
|
nspace=item.Name
|
||||||
)}}
|
)}}
|
||||||
>
|
>
|
||||||
<BlockSlot @name="label">
|
{{item.Name}}
|
||||||
{{item.Name}}
|
</menu.Action>
|
||||||
</BlockSlot>
|
</menu.Item>
|
||||||
</MenuItem>
|
{{/each}}
|
||||||
{{/each}}
|
{{#if (can 'manage nspaces')}}
|
||||||
{{#if (can 'manage nspaces')}}
|
<menu.Separator />
|
||||||
<MenuSeparator />
|
<menu.Item
|
||||||
<MenuItem
|
data-test-main-nav-nspaces
|
||||||
data-test-main-nav-nspaces
|
>
|
||||||
|
<menu.Action
|
||||||
|
{{on 'click' disclosure.close}}
|
||||||
@href={{href-to 'dc.nspaces' @dc.Name}}
|
@href={{href-to 'dc.nspaces' @dc.Name}}
|
||||||
>
|
>
|
||||||
<BlockSlot @name="label">
|
Manage Namespaces
|
||||||
Manage Namespaces
|
</menu.Action>
|
||||||
</BlockSlot>
|
</menu.Item>
|
||||||
</MenuItem>
|
{{/if}}
|
||||||
{{/if}}
|
</panel.Menu>
|
||||||
{{/let}}
|
</disclosure.Menu>
|
||||||
</BlockSlot>
|
</DisclosureMenu>
|
||||||
</PopoverMenu>
|
</li>
|
||||||
</li>
|
{{/let}}
|
||||||
{{/let}}
|
|
||||||
{{/if}}
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
|
|
|
@ -6,51 +6,56 @@ as |partition|}}
|
||||||
class="partitions"
|
class="partitions"
|
||||||
data-test-partition-menu
|
data-test-partition-menu
|
||||||
>
|
>
|
||||||
<PopoverMenu
|
<DisclosureMenu
|
||||||
aria-label="Admin Partition"
|
aria-label="Admin Partition"
|
||||||
@position="left"
|
as |disclosure|>
|
||||||
as |components api|>
|
<disclosure.Action
|
||||||
<BlockSlot @name="trigger">
|
{{on 'click' disclosure.toggle}}
|
||||||
{{partition}}
|
>
|
||||||
</BlockSlot>
|
{{partition}}
|
||||||
<BlockSlot @name="menu">
|
</disclosure.Action>
|
||||||
{{#let components.MenuItem components.MenuSeparator as |MenuItem MenuSeparator|}}
|
<disclosure.Menu as |panel|>
|
||||||
<DataSource
|
<DataSource
|
||||||
@src={{uri
|
@src={{uri
|
||||||
'/*/*/${dc}/partitions'
|
'/*/*/${dc}/partitions'
|
||||||
(hash
|
(hash
|
||||||
dc=@dc.Name
|
dc=@dc.Name
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
@onchange={{fn (optional @onchange)}}
|
@onchange={{fn (optional @onchange)}}
|
||||||
/>
|
/>
|
||||||
|
<panel.Menu as |menu|>
|
||||||
{{#each (reject-by 'DeletedAt' @partitions) as |item|}}
|
{{#each (reject-by 'DeletedAt' @partitions) as |item|}}
|
||||||
<MenuItem
|
<menu.Item
|
||||||
class={{if (eq partition item.Name) 'is-active'}}
|
class={{if (eq partition item.Name) 'is-active'}}
|
||||||
@href={{href-to '.' params=(hash
|
|
||||||
partition=item.Name
|
|
||||||
nspace=undefined
|
|
||||||
)}}
|
|
||||||
>
|
>
|
||||||
<BlockSlot @name="label">
|
<menu.Action
|
||||||
|
{{on 'click' disclosure.close}}
|
||||||
|
@href={{href-to '.' params=(hash
|
||||||
|
partition=item.Name
|
||||||
|
nspace=undefined
|
||||||
|
)}}
|
||||||
|
>
|
||||||
{{item.Name}}
|
{{item.Name}}
|
||||||
</BlockSlot>
|
</menu.Action>
|
||||||
</MenuItem>
|
</menu.Item>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
{{#if (can 'manage partitions')}}
|
{{#if (can 'manage partitions')}}
|
||||||
<MenuSeparator />
|
<menu.Separator />
|
||||||
<MenuItem
|
<menu.Item
|
||||||
data-test-main-nav-partitions
|
data-test-main-nav-partitions
|
||||||
@href={{href-to 'dc.partitions.index' @dc.Name}}
|
|
||||||
>
|
>
|
||||||
<BlockSlot @name="label">
|
<menu.Action
|
||||||
|
{{on 'click' disclosure.close}}
|
||||||
|
@href={{href-to 'dc.partitions.index' @dc.Name}}
|
||||||
|
>
|
||||||
Manage Partitions
|
Manage Partitions
|
||||||
</BlockSlot>
|
</menu.Action>
|
||||||
</MenuItem>
|
</menu.Item>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/let}}
|
</panel.Menu>
|
||||||
</BlockSlot>
|
</disclosure.Menu>
|
||||||
</PopoverMenu>
|
</DisclosureMenu>
|
||||||
</li>
|
</li>
|
||||||
{{else}}
|
{{else}}
|
||||||
<li
|
<li
|
||||||
|
|
|
@ -52,13 +52,22 @@
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
%main-nav-vertical-hoisted {
|
%main-nav-vertical-hoisted {
|
||||||
top: 11px;
|
top: 18px;
|
||||||
}
|
}
|
||||||
%main-nav-vertical-hoisted > .popover-menu > label > button {
|
%main-nav-vertical-hoisted [aria-label]::before {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
%main-nav-horizontal [aria-haspopup='menu'] ~ * {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
min-width: 192px;
|
||||||
|
}
|
||||||
|
%main-nav-horizontal [aria-expanded],
|
||||||
|
%main-nav-vertical-hoisted [aria-expanded] {
|
||||||
|
@extend %main-nav-horizontal-popover-menu-trigger;
|
||||||
@extend %main-nav-horizontal-action;
|
@extend %main-nav-horizontal-action;
|
||||||
border: none;
|
|
||||||
}
|
}
|
||||||
%main-nav-vertical-hoisted.is-active > label > * {
|
%main-nav-horizontal-popover-menu-trigger {
|
||||||
@extend %main-nav-horizontal-action-active;
|
@extend %main-nav-horizontal-action-active;
|
||||||
}
|
}
|
||||||
%footer,
|
%footer,
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
<li
|
||||||
|
class="dcs"
|
||||||
|
data-test-datacenter-menu
|
||||||
|
>
|
||||||
|
<DisclosureMenu
|
||||||
|
aria-label="Datacenter"
|
||||||
|
as |disclosure|>
|
||||||
|
<disclosure.Action
|
||||||
|
{{on 'click' disclosure.toggle}}
|
||||||
|
>
|
||||||
|
{{@dc.Name}}
|
||||||
|
</disclosure.Action>
|
||||||
|
<disclosure.Menu as |panel|>
|
||||||
|
<DataSource
|
||||||
|
@src={{uri '/*/*/*/datacenters'}}
|
||||||
|
@onchange={{action (mut @dcs) value="data"}}
|
||||||
|
/>
|
||||||
|
<panel.Menu as |menu|>
|
||||||
|
{{#each (sort-by 'Name' @dcs) as |item|}}
|
||||||
|
<menu.Item
|
||||||
|
aria-current={{if (eq @dc.Name item.Name) 'true'}}
|
||||||
|
class={{class-map
|
||||||
|
(array 'is-local' item.Local)
|
||||||
|
(array 'is-primary' item.Primary)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<menu.Action
|
||||||
|
{{on 'click' disclosure.close}}
|
||||||
|
@href={{href-to '.' params=(hash
|
||||||
|
dc=item.Name
|
||||||
|
partition=undefined
|
||||||
|
nspace=(if (gt @nspace.length 0) @nspace undefined)
|
||||||
|
)}}
|
||||||
|
>
|
||||||
|
{{item.Name}}
|
||||||
|
{{#if item.Primary}}
|
||||||
|
<span>Primary</span>
|
||||||
|
{{/if}}
|
||||||
|
{{#if item.Local}}
|
||||||
|
<span>Local</span>
|
||||||
|
{{/if}}
|
||||||
|
</menu.Action>
|
||||||
|
</menu.Item>
|
||||||
|
{{/each}}
|
||||||
|
</panel.Menu>
|
||||||
|
</disclosure.Menu>
|
||||||
|
</DisclosureMenu>
|
||||||
|
</li>
|
||||||
|
|
|
@ -19,13 +19,15 @@ common usecase of having a floating menu.
|
||||||
>
|
>
|
||||||
{{if disclosure.expanded 'Close' 'Open'}}
|
{{if disclosure.expanded 'Close' 'Open'}}
|
||||||
</disclosure.Action>
|
</disclosure.Action>
|
||||||
<disclosure.Menu as |menu|>
|
<disclosure.Menu as |panel|>
|
||||||
<menu.Item>
|
<panel.Menu as |menu|>
|
||||||
<menu.Action>Item 1</menu.Action>
|
<menu.Item>
|
||||||
</menu.Item>
|
<menu.Action>Item 1</menu.Action>
|
||||||
<menu.Item>
|
</menu.Item>
|
||||||
<menu.Action>Item 2</menu.Action>
|
<menu.Item>
|
||||||
</menu.Item>
|
<menu.Action>Item 2</menu.Action>
|
||||||
|
</menu.Item>
|
||||||
|
</panel.Menu>
|
||||||
</disclosure.Menu>
|
</disclosure.Menu>
|
||||||
</DisclosureMenu>
|
</DisclosureMenu>
|
||||||
</figure>
|
</figure>
|
||||||
|
@ -46,13 +48,15 @@ common usecase of having a floating menu.
|
||||||
(array 'top' this.height)
|
(array 'top' this.height)
|
||||||
(array 'background-color' 'rgb(var(--tone-gray-000))')
|
(array 'background-color' 'rgb(var(--tone-gray-000))')
|
||||||
}}
|
}}
|
||||||
as |menu|>
|
as |panel|>
|
||||||
<menu.Item>
|
<panel.Menu as |menu|>
|
||||||
<menu.Action>Item 1</menu.Action>
|
<menu.Item>
|
||||||
</menu.Item>
|
<menu.Action>Item 1</menu.Action>
|
||||||
<menu.Item>
|
</menu.Item>
|
||||||
<menu.Action>Item 2</menu.Action>
|
<menu.Item>
|
||||||
</menu.Item>
|
<menu.Action>Item 2</menu.Action>
|
||||||
|
</menu.Item>
|
||||||
|
</panel.Menu>
|
||||||
</disclosure.Menu>
|
</disclosure.Menu>
|
||||||
</DisclosureMenu>
|
</DisclosureMenu>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
|
@ -4,12 +4,16 @@
|
||||||
}}
|
}}
|
||||||
...attributes
|
...attributes
|
||||||
>
|
>
|
||||||
<Disclosure as |disclosure|>
|
<Disclosure
|
||||||
|
@expanded={{@expanded}}
|
||||||
|
as |disclosure|>
|
||||||
{{yield (hash
|
{{yield (hash
|
||||||
Action=(component 'disclosure-menu/action' disclosure=disclosure)
|
Action=(component 'disclosure-menu/action' disclosure=disclosure)
|
||||||
Menu=(component 'disclosure-menu/menu' disclosure=disclosure)
|
Menu=(component 'disclosure-menu/menu' disclosure=disclosure)
|
||||||
disclosure=disclosure
|
disclosure=disclosure
|
||||||
toggle=disclosure.toggle
|
toggle=disclosure.toggle
|
||||||
|
close=disclosure.close
|
||||||
|
open=disclosure.open
|
||||||
expanded=disclosure.expanded
|
expanded=disclosure.expanded
|
||||||
)}}
|
)}}
|
||||||
</Disclosure>
|
</Disclosure>
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
.disclosure-menu {
|
.disclosure-menu {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
.disclosure-menu [aria-expanded] ~ * {
|
||||||
|
@extend %menu-panel;
|
||||||
|
}
|
||||||
|
|
|
@ -1,15 +1,11 @@
|
||||||
<@disclosure.Details as |details|>
|
<@disclosure.Details as |details|>
|
||||||
<Menu
|
<div
|
||||||
{{on-outside 'click' @disclosure.close}}
|
{{on-outside 'click' @disclosure.close}}
|
||||||
@disclosure={{@disclosure}}
|
...attributes
|
||||||
...attributes
|
>
|
||||||
as |menu|>
|
{{yield (hash
|
||||||
{{yield (hash
|
Menu=(component 'menu' disclosure=@disclosure)
|
||||||
items=menu.items
|
)}}
|
||||||
Item=menu.Item
|
</div>
|
||||||
Action=menu.Action
|
|
||||||
Separator=menu.Separator
|
|
||||||
)}}
|
|
||||||
</Menu>
|
|
||||||
</@disclosure.Details>
|
</@disclosure.Details>
|
||||||
|
|
||||||
|
|
|
@ -87,53 +87,12 @@
|
||||||
|
|
||||||
<:main-nav>
|
<:main-nav>
|
||||||
<ul>
|
<ul>
|
||||||
<li
|
<Consul::Datacenter::Selector
|
||||||
class="dcs"
|
@dc={{@dc}}
|
||||||
data-test-datacenter-menu
|
@partition={{@partition}}
|
||||||
>
|
@nspace={{@nspace}}
|
||||||
<PopoverMenu
|
@dcs={{@dcs}}
|
||||||
aria-label="Datacenter"
|
/>
|
||||||
@position="left"
|
|
||||||
as |components|>
|
|
||||||
<BlockSlot @name="trigger">
|
|
||||||
{{@dc.Name}}
|
|
||||||
</BlockSlot>
|
|
||||||
<BlockSlot @name="menu">
|
|
||||||
{{#let components.MenuItem components.MenuSeparator as |MenuItem MenuSeparator|}}
|
|
||||||
<DataSource
|
|
||||||
@src={{uri '/*/*/*/datacenters'}}
|
|
||||||
@onchange={{action (mut @dcs) value="data"}}
|
|
||||||
@loading="lazy"
|
|
||||||
/>
|
|
||||||
{{#each (sort-by 'Name' @dcs) as |item|}}
|
|
||||||
<MenuItem
|
|
||||||
data-test-datacenter-picker
|
|
||||||
class={{concat
|
|
||||||
(if (eq @dc.Name item.Name) 'is-active')
|
|
||||||
(if item.Local ' is-local')
|
|
||||||
(if item.Primary ' is-primary')
|
|
||||||
}}
|
|
||||||
@href={{href-to '.' params=(hash
|
|
||||||
dc=item.Name
|
|
||||||
partition=undefined
|
|
||||||
nspace=(if (gt @nspace.length 0) @nspace undefined)
|
|
||||||
)}}
|
|
||||||
>
|
|
||||||
<BlockSlot @name="label">
|
|
||||||
{{item.Name}}
|
|
||||||
{{#if item.Primary}}
|
|
||||||
<span>Primary</span>
|
|
||||||
{{/if}}
|
|
||||||
{{#if item.Local}}
|
|
||||||
<span>Local</span>
|
|
||||||
{{/if}}
|
|
||||||
</BlockSlot>
|
|
||||||
</MenuItem>
|
|
||||||
{{/each}}
|
|
||||||
{{/let}}
|
|
||||||
</BlockSlot>
|
|
||||||
</PopoverMenu>
|
|
||||||
</li>
|
|
||||||
<Consul::Partition::Selector
|
<Consul::Partition::Selector
|
||||||
@dc={{@dc}}
|
@dc={{@dc}}
|
||||||
@partition={{@partition}}
|
@partition={{@partition}}
|
||||||
|
@ -182,45 +141,52 @@
|
||||||
<li
|
<li
|
||||||
data-test-main-nav-help
|
data-test-main-nav-help
|
||||||
>
|
>
|
||||||
<PopoverMenu @position="right" as |components|>
|
<DisclosureMenu
|
||||||
<BlockSlot @name="trigger">
|
as |disclosure|>
|
||||||
|
<disclosure.Action
|
||||||
|
{{on 'click' disclosure.toggle}}
|
||||||
|
>
|
||||||
Help
|
Help
|
||||||
</BlockSlot>
|
</disclosure.Action>
|
||||||
<BlockSlot @name="menu">
|
<disclosure.Menu as |panel|>
|
||||||
{{#let components.MenuItem components.MenuSeparator as |MenuItem MenuSeparator|}}
|
<panel.Menu as |menu|>
|
||||||
<MenuSeparator>
|
<menu.Separator>
|
||||||
<BlockSlot @name="label">
|
Consul v{{env 'CONSUL_VERSION'}}
|
||||||
Consul v{{env 'CONSUL_VERSION'}}
|
</menu.Separator>
|
||||||
</BlockSlot>
|
<menu.Item
|
||||||
</MenuSeparator>
|
|
||||||
<MenuItem
|
|
||||||
class="docs-link"
|
class="docs-link"
|
||||||
@href={{env 'CONSUL_DOCS_URL'}}
|
|
||||||
>
|
>
|
||||||
<BlockSlot @name="label">
|
<menu.Action
|
||||||
|
@href={{env 'CONSUL_DOCS_URL'}}
|
||||||
|
@external={{true}}
|
||||||
|
>
|
||||||
Documentation
|
Documentation
|
||||||
</BlockSlot>
|
</menu.Action>
|
||||||
</MenuItem>
|
</menu.Item>
|
||||||
<MenuItem
|
<menu.Item
|
||||||
class="learn-link"
|
class="learn-link"
|
||||||
@href={{concat (env 'CONSUL_DOCS_LEARN_URL') '/consul'}}
|
|
||||||
>
|
>
|
||||||
<BlockSlot @name="label">
|
<menu.Action
|
||||||
|
@href={{concat (env 'CONSUL_DOCS_LEARN_URL') '/consul'}}
|
||||||
|
@external={{true}}
|
||||||
|
>
|
||||||
HashiCorp Learn
|
HashiCorp Learn
|
||||||
</BlockSlot>
|
</menu.Action>
|
||||||
</MenuItem>
|
</menu.Item>
|
||||||
<MenuSeparator />
|
<menu.Separator />
|
||||||
<MenuItem
|
<menu.Item
|
||||||
class="learn-link"
|
class="feedback-link"
|
||||||
@href={{env 'CONSUL_REPO_ISSUES_URL'}}
|
|
||||||
>
|
>
|
||||||
<BlockSlot @name="label">
|
<menu.Action
|
||||||
|
@href={{env 'CONSUL_REPO_ISSUES_URL'}}
|
||||||
|
@external={{true}}
|
||||||
|
>
|
||||||
Provide Feedback
|
Provide Feedback
|
||||||
</BlockSlot>
|
</menu.Action>
|
||||||
</MenuItem>
|
</menu.Item>
|
||||||
{{/let}}
|
</panel.Menu>
|
||||||
</BlockSlot>
|
</disclosure.Menu>
|
||||||
</PopoverMenu>
|
</DisclosureMenu>
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
data-test-main-nav-settings
|
data-test-main-nav-settings
|
||||||
|
|
|
@ -1,11 +1,18 @@
|
||||||
%hashicorp-consul {
|
%hashicorp-consul {
|
||||||
[role='banner'] nav .dcs {
|
nav .dcs {
|
||||||
@extend %main-nav-vertical-hoisted;
|
@extend %main-nav-vertical-hoisted;
|
||||||
left: 100px;
|
left: 100px;
|
||||||
}
|
}
|
||||||
[role='banner'] nav .dcs .popover-menu[aria-label]::before {
|
nav .dcs .menu-panel {
|
||||||
display: none;
|
min-width: 250px;
|
||||||
}
|
}
|
||||||
|
nav li.partitions,
|
||||||
|
nav li.nspaces {
|
||||||
|
@extend %main-nav-vertical-popover-menu;
|
||||||
|
/* --panel-height: 300px;
|
||||||
|
--row-height: 43px; */
|
||||||
|
}
|
||||||
|
|
||||||
[role='banner'] a svg {
|
[role='banner'] a svg {
|
||||||
fill: rgb(var(--tone-brand-600));
|
fill: rgb(var(--tone-brand-600));
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ export default (collection, clickable, attribute, is, authForm, emptyState) => s
|
||||||
':checked',
|
':checked',
|
||||||
'[data-test-nspace-menu] > input[type="checkbox"]'
|
'[data-test-nspace-menu] > input[type="checkbox"]'
|
||||||
);
|
);
|
||||||
page.navigation.dcs = collection('[data-test-datacenter-picker]', {
|
page.navigation.dcs = collection('[data-test-datacenter-menu] li', {
|
||||||
name: clickable('a'),
|
name: clickable('a'),
|
||||||
});
|
});
|
||||||
return page;
|
return page;
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
%main-nav-horizontal > ul > li > a,
|
%main-nav-horizontal > ul > li > a,
|
||||||
%main-nav-horizontal > ul > li > span,
|
%main-nav-horizontal > ul > li > span,
|
||||||
%main-nav-horizontal > ul > li > button,
|
%main-nav-horizontal > ul > li > button,
|
||||||
|
%main-nav-horizontal-popover-menu-trigger,
|
||||||
%main-nav-horizontal > ul > li > .popover-menu > label > button {
|
%main-nav-horizontal > ul > li > .popover-menu > label > button {
|
||||||
@extend %main-nav-horizontal-action;
|
@extend %main-nav-horizontal-action;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,15 @@
|
||||||
%main-nav-horizontal-action > a {
|
%main-nav-horizontal-action > a {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
}
|
}
|
||||||
|
%main-nav-horizontal-popover-menu-trigger::after {
|
||||||
|
@extend %with-chevron-down-mask, %as-pseudo;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
%main-nav-horizontal-popover-menu-trigger[aria-expanded='true']::after {
|
||||||
|
@extend %with-chevron-up-mask;
|
||||||
|
}
|
||||||
/**/
|
/**/
|
||||||
/* reduced size hamburger menu */
|
/* reduced size hamburger menu */
|
||||||
%main-nav-horizontal-toggle {
|
%main-nav-horizontal-toggle {
|
||||||
|
|
|
@ -30,34 +30,12 @@
|
||||||
%main-nav-vertical > ul > li > label {
|
%main-nav-vertical > ul > li > label {
|
||||||
@extend %main-nav-vertical-action;
|
@extend %main-nav-vertical-action;
|
||||||
}
|
}
|
||||||
/**/
|
|
||||||
|
|
||||||
%main-nav-vertical .popover-menu {
|
|
||||||
margin-top: 0.5rem;
|
|
||||||
}
|
|
||||||
%main-nav-vertical .popover-menu .menu-panel {
|
|
||||||
top: 37px !important;
|
|
||||||
border-top-left-radius: 0;
|
|
||||||
border-top-right-radius: 0;
|
|
||||||
}
|
|
||||||
%main-nav-vertical .popover-menu > label > button {
|
|
||||||
border: var(--decor-border-100);
|
|
||||||
border-color: rgb(var(--tone-gray-500));
|
|
||||||
color: rgb(var(--tone-gray-999));
|
|
||||||
width: calc(100% - 20px);
|
|
||||||
z-index: 100;
|
|
||||||
text-align: left;
|
|
||||||
padding: 10px;
|
|
||||||
border-radius: var(--decor-radius-100);
|
|
||||||
}
|
|
||||||
%main-nav-vertical .popover-menu > label > button::after {
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
%main-nav-vertical .popover-menu .menu-panel {
|
|
||||||
top: 28px;
|
|
||||||
z-index: 100;
|
|
||||||
}
|
|
||||||
/* menu-panels in the main navigation are treated slightly differently */
|
/* menu-panels in the main navigation are treated slightly differently */
|
||||||
%main-nav-vertical label + div {
|
%main-nav-vertical-popover-menu .disclosure-menu button + * {
|
||||||
@extend %main-nav-vertical-menu-panel;
|
@extend %main-nav-vertical-menu-panel;
|
||||||
}
|
}
|
||||||
|
/**/
|
||||||
|
%main-nav-vertical-popover-menu .disclosure-menu > button {
|
||||||
|
@extend %main-nav-vertical-popover-menu-trigger;
|
||||||
|
@extend %internal-button;
|
||||||
|
}
|
||||||
|
|
|
@ -11,14 +11,13 @@
|
||||||
%main-nav-vertical:not(.in-viewport) {
|
%main-nav-vertical:not(.in-viewport) {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
%main-nav-vertical li.partitions,
|
|
||||||
%main-nav-vertical li.partition,
|
%main-nav-vertical li.partition,
|
||||||
|
%main-nav-vertical li.partitions,
|
||||||
%main-nav-vertical li.nspaces {
|
%main-nav-vertical li.nspaces {
|
||||||
margin-bottom: 25px;
|
margin-bottom: 25px;
|
||||||
padding: 0 26px;
|
padding: 0 26px;
|
||||||
}
|
}
|
||||||
%main-nav-vertical li.dcs {
|
%main-nav-vertical li.dcs {
|
||||||
margin-bottom: 18px;
|
|
||||||
padding: 0 18px;
|
padding: 0 18px;
|
||||||
}
|
}
|
||||||
// TODO: We no longer have the rule that menu-panel buttons only contain two
|
// TODO: We no longer have the rule that menu-panel buttons only contain two
|
||||||
|
@ -41,9 +40,21 @@
|
||||||
margin-top: 0.7rem;
|
margin-top: 0.7rem;
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
}
|
}
|
||||||
|
%main-nav-vertical-popover-menu .disclosure {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
%main-nav-vertical-popover-menu-trigger {
|
||||||
|
width: 100%;
|
||||||
|
text-align: left;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
%main-nav-vertical-popover-menu-trigger::after {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
%main-nav-vertical-menu-panel {
|
%main-nav-vertical-menu-panel {
|
||||||
min-width: 248px;
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
width: calc(100% - 2px);
|
||||||
}
|
}
|
||||||
%main-nav-vertical-hoisted {
|
%main-nav-vertical-hoisted {
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
%main-nav-vertical-action {
|
%main-nav-vertical-action {
|
||||||
|
@extend %p1;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border-right: var(--decor-border-400);
|
border-right: var(--decor-border-400);
|
||||||
border-color: var(--transparent);
|
border-color: var(--transparent);
|
||||||
@extend %p1;
|
|
||||||
}
|
}
|
||||||
%main-nav-vertical-action > a {
|
%main-nav-vertical-action > a {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
|
@ -41,28 +41,38 @@
|
||||||
background-color: rgb(var(--tone-gray-150));
|
background-color: rgb(var(--tone-gray-150));
|
||||||
border-color: rgb(var(--tone-gray-999));
|
border-color: rgb(var(--tone-gray-999));
|
||||||
}
|
}
|
||||||
%main-nav-vertical li[aria-label]::before,
|
%main-nav-vertical [aria-label]::before {
|
||||||
%main-nav-vertical .popover-menu[aria-label]::before {
|
|
||||||
color: rgb(var(--tone-gray-700));
|
color: rgb(var(--tone-gray-700));
|
||||||
content: attr(aria-label);
|
content: attr(aria-label);
|
||||||
display: block;
|
display: block;
|
||||||
margin-top: -0.5rem;
|
margin-top: -0.5rem;
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
}
|
}
|
||||||
%main-nav-vertical .is-primary span,
|
%main-nav-vertical-popover-menu-trigger {
|
||||||
%main-nav-vertical .is-local span {
|
border: var(--decor-border-100);
|
||||||
@extend %pill-200;
|
border-color: rgb(var(--tone-gray-500));
|
||||||
color: rgb(var(--tone-gray-000));
|
border-radius: var(--decor-radius-100);
|
||||||
background-color: rgb(var(--tone-gray-500));
|
|
||||||
}
|
font-weight: inherit;
|
||||||
%main-nav-vertical .nspaces .menu-panel > div {
|
|
||||||
background-color: rgb(var(--tone-gray-050));
|
background-color: rgb(var(--tone-gray-050));
|
||||||
color: rgb(var(--tone-gray-999));
|
color: rgb(var(--tone-gray-999));
|
||||||
padding-left: 36px;
|
|
||||||
}
|
}
|
||||||
%main-nav-vertical .nspaces .menu-panel > div::before {
|
%main-nav-vertical-popover-menu-trigger[aria-expanded='true'] {
|
||||||
@extend %with-info-circle-fill-mask, %as-pseudo;
|
border-bottom-left-radius: var(--decor-radius-000);
|
||||||
color: rgb(var(--tone-blue-500));
|
border-bottom-right-radius: var(--decor-radius-000);
|
||||||
/* sizes the icon not the text */
|
}
|
||||||
font-size: 1.1em;
|
%main-nav-vertical-popover-menu-trigger::after {
|
||||||
|
@extend %with-chevron-down-mask, %as-pseudo;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
%main-nav-vertical-popover-menu-trigger[aria-expanded='true']::after {
|
||||||
|
@extend %with-chevron-up-mask;
|
||||||
|
}
|
||||||
|
%main-nav-vertical-menu-panel {
|
||||||
|
border-top-left-radius: var(--decor-radius-000);
|
||||||
|
border-top-right-radius: var(--decor-radius-000);
|
||||||
|
border-top: var(--decor-border-000);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,169 @@
|
||||||
|
# MenuPanel
|
||||||
|
|
||||||
|
```hbs preview-template
|
||||||
|
|
||||||
|
{{#each
|
||||||
|
(array 'light' 'dark')
|
||||||
|
as |theme|}}
|
||||||
|
<figure>
|
||||||
|
<figcaption>Without a header</figcaption>
|
||||||
|
<div
|
||||||
|
class={{class-map
|
||||||
|
'menu-panel'
|
||||||
|
(array (concat 'theme-' theme))
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ul role="menu">
|
||||||
|
<li aria-current="true" role="none">
|
||||||
|
<Action role="menuitem">Item 1<span>Label</span><span>Label 2</span></Action>
|
||||||
|
</li>
|
||||||
|
<li role="separator">
|
||||||
|
Item some title text
|
||||||
|
</li>
|
||||||
|
<li role="none">
|
||||||
|
<Action role="menuitem">Item 2</Action>
|
||||||
|
</li>
|
||||||
|
<li role="separator"></li>
|
||||||
|
<li role="none">
|
||||||
|
<Action role="menuitem">Item 3</Action>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</figure>
|
||||||
|
<figure>
|
||||||
|
<figcaption>With a header</figcaption>
|
||||||
|
<div
|
||||||
|
class={{class-map
|
||||||
|
'menu-panel'
|
||||||
|
(array (concat 'theme-' theme))
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<p>Some content explaining what the menu is about</p>
|
||||||
|
</div>
|
||||||
|
<ul role="menu">
|
||||||
|
<li aria-current="true" role="none">
|
||||||
|
<Action role="menuitem">Item 1<span>Label</span><span>Label 2</span></Action>
|
||||||
|
</li>
|
||||||
|
<li role="separator">
|
||||||
|
Item some title text
|
||||||
|
</li>
|
||||||
|
<li role="none">
|
||||||
|
<Action role="menuitem">Item 2</Action>
|
||||||
|
</li>
|
||||||
|
<li role="separator"></li>
|
||||||
|
<li role="none">
|
||||||
|
<Action role="menuitem">Item 3</Action>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
<figure>
|
||||||
|
<StateChart
|
||||||
|
@src={{state-chart 'boolean'}}
|
||||||
|
as |State Guard StateAction dispatch state|>
|
||||||
|
<Action>Focus Left</Action>
|
||||||
|
<DisclosureMenu as |disclosure|>
|
||||||
|
<disclosure.Action
|
||||||
|
{{on 'click' disclosure.toggle}}
|
||||||
|
>
|
||||||
|
{{if disclosure.expanded 'Close' 'Open'}}
|
||||||
|
</disclosure.Action>
|
||||||
|
<disclosure.Menu
|
||||||
|
style={{style-map
|
||||||
|
(array 'max-height' (if (state-matches state 'true') (add 0 this.rect.height)) 'px')
|
||||||
|
}}
|
||||||
|
class={{class-map
|
||||||
|
(array 'menu-panel')
|
||||||
|
(array 'menu-panel-confirming' (state-matches state 'true'))
|
||||||
|
(array (concat 'theme-' theme))
|
||||||
|
}}
|
||||||
|
|
||||||
|
as |panel|>
|
||||||
|
<div
|
||||||
|
{{on-resize
|
||||||
|
(dom-position (set this 'header'))
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<p>Some text in here</p>
|
||||||
|
</div>
|
||||||
|
<panel.Menu as |menu|>
|
||||||
|
<menu.Item
|
||||||
|
aria-current="true"
|
||||||
|
>
|
||||||
|
<menu.Action>
|
||||||
|
Item 1
|
||||||
|
<span>Label</span>
|
||||||
|
<span>Label 2</span>
|
||||||
|
</menu.Action>
|
||||||
|
</menu.Item>
|
||||||
|
<menu.Separator>
|
||||||
|
Item some title text
|
||||||
|
</menu.Separator>
|
||||||
|
<menu.Item>
|
||||||
|
<menu.Action>
|
||||||
|
Item 2
|
||||||
|
</menu.Action>
|
||||||
|
</menu.Item>
|
||||||
|
<menu.Separator />
|
||||||
|
<menu.Item
|
||||||
|
class="dangerous"
|
||||||
|
>
|
||||||
|
<menu.Action
|
||||||
|
{{on "click" (fn dispatch 'TOGGLE')}}
|
||||||
|
>
|
||||||
|
Item 3
|
||||||
|
</menu.Action>
|
||||||
|
|
||||||
|
<div
|
||||||
|
{{on-resize
|
||||||
|
(dom-position (set this 'rect'))
|
||||||
|
}}
|
||||||
|
style={{style-map
|
||||||
|
(array 'top' (if (state-matches state 'true') (sub 0 this.header.height)) 'px')
|
||||||
|
}}
|
||||||
|
class={{class-map
|
||||||
|
'menu-panel-confirmation'
|
||||||
|
'informed-action'
|
||||||
|
'confirmation-alert'
|
||||||
|
'warning'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<header>Hi</header>
|
||||||
|
<p>Body</p>
|
||||||
|
</div>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<Action
|
||||||
|
@tabindex="-1"
|
||||||
|
{{on "click" (queue disclosure.close (fn dispatch 'TOGGLE'))}}
|
||||||
|
>
|
||||||
|
Confirm
|
||||||
|
</Action>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Action
|
||||||
|
@tabindex="-1"
|
||||||
|
{{on "click" (fn dispatch 'TOGGLE')}}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Action>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</menu.Item>
|
||||||
|
</panel.Menu>
|
||||||
|
|
||||||
|
</disclosure.Menu>
|
||||||
|
|
||||||
|
</DisclosureMenu>
|
||||||
|
|
||||||
|
<Action>Focus Right</Action>
|
||||||
|
</StateChart>
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
{{/each}}
|
||||||
|
```
|
|
@ -0,0 +1,58 @@
|
||||||
|
/* old stuff */
|
||||||
|
|
||||||
|
%menu-panel {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
%menu-panel-deprecated {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
%menu-panel-deprecated [type='checkbox'] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
%menu-panel-deprecated {
|
||||||
|
transition: max-height 150ms;
|
||||||
|
}
|
||||||
|
%menu-panel-deprecated {
|
||||||
|
transition: min-height 150ms, max-height 150ms;
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
%menu-panel-deprecated:not(.confirmation) [type='checkbox'] ~ * {
|
||||||
|
transition: transform 150ms;
|
||||||
|
}
|
||||||
|
%menu-panel-deprecated [type='checkbox']:checked ~ * {
|
||||||
|
transform: translateX(calc(-100% - 10px));
|
||||||
|
}
|
||||||
|
%menu-panel-deprecated.confirmation [role='menu'] {
|
||||||
|
min-height: 205px !important;
|
||||||
|
}
|
||||||
|
%menu-panel-deprecated [type='checkbox']:checked ~ * {
|
||||||
|
/* this needs to autocalculate */
|
||||||
|
min-height: 143px;
|
||||||
|
max-height: 143px;
|
||||||
|
}
|
||||||
|
%menu-panel-deprecated [id$='-']:first-child:checked ~ ul label[for$='-'] * [role='menu'],
|
||||||
|
%menu-panel-deprecated [id$='-']:first-child:checked ~ ul > li > [role='menu'] {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
/**/
|
||||||
|
%menu-panel-deprecated > ul > li > div[role='menu'] {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: calc(100% + 10px);
|
||||||
|
}
|
||||||
|
%menu-panel-deprecated > ul > li > *:not(div[role='menu']) {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
%menu-panel-deprecated:not(.left) {
|
||||||
|
right: 0px !important;
|
||||||
|
left: auto !important;
|
||||||
|
}
|
||||||
|
%menu-panel-deprecated.left {
|
||||||
|
left: 0px;
|
||||||
|
}
|
||||||
|
%menu-panel-deprecated:not(.above) {
|
||||||
|
top: 28px;
|
||||||
|
}
|
||||||
|
%menu-panel-deprecated.above {
|
||||||
|
bottom: 42px;
|
||||||
|
}
|
|
@ -3,11 +3,12 @@
|
||||||
change=(action "change")
|
change=(action "change")
|
||||||
) as |api|}}
|
) as |api|}}
|
||||||
<div
|
<div
|
||||||
class={{join ' ' (compact (array
|
class={{class-map
|
||||||
'menu-panel'
|
(array 'menu-panel')
|
||||||
position
|
(array 'menu-panel-deprecated')
|
||||||
(if isConfirmation 'confirmation')
|
(array position)
|
||||||
))}}
|
(array isConfirmation 'confirmation')
|
||||||
|
}}
|
||||||
{{did-insert (action 'connect')}}
|
{{did-insert (action 'connect')}}
|
||||||
>
|
>
|
||||||
<YieldSlot @name="controls">
|
<YieldSlot @name="controls">
|
||||||
|
|
|
@ -1,22 +1,50 @@
|
||||||
@import './skin';
|
@import './skin';
|
||||||
@import './layout';
|
@import './layout';
|
||||||
|
@import './deprecated';
|
||||||
|
|
||||||
.menu-panel {
|
.menu-panel {
|
||||||
@extend %menu-panel;
|
@extend %menu-panel;
|
||||||
}
|
}
|
||||||
|
.menu-panel-deprecated {
|
||||||
|
@extend %menu-panel-deprecated;
|
||||||
|
}
|
||||||
|
%menu-panel {
|
||||||
|
@extend %panel;
|
||||||
|
}
|
||||||
|
%menu-panel-item span {
|
||||||
|
@extend %menu-panel-badge;
|
||||||
|
}
|
||||||
%menu-panel [role='separator'] {
|
%menu-panel [role='separator'] {
|
||||||
|
@extend %panel-separator;
|
||||||
@extend %menu-panel-separator;
|
@extend %menu-panel-separator;
|
||||||
}
|
}
|
||||||
%menu-panel > div {
|
%menu-panel > div {
|
||||||
@extend %menu-panel-header;
|
@extend %menu-panel-header;
|
||||||
}
|
}
|
||||||
// %menu-panel > ul > li > *:not(div),
|
%menu-panel > ul {
|
||||||
%menu-panel [role='menuitem'] {
|
@extend %menu-panel-body;
|
||||||
|
}
|
||||||
|
%menu-panel-body > li {
|
||||||
|
@extend %menu-panel-item;
|
||||||
|
}
|
||||||
|
%menu-panel-body > [role='treeitem'],
|
||||||
|
%menu-panel-body > li > [role='menuitem'],
|
||||||
|
%menu-panel-body > li > [role='option'] {
|
||||||
|
@extend %menu-panel-button;
|
||||||
|
}
|
||||||
|
%menu-panel-button + * {
|
||||||
|
@extend %menu-panel-confirmation;
|
||||||
|
}
|
||||||
|
%menu-panel-item[aria-selected] > *,
|
||||||
|
%menu-panel-item[aria-checked] > *,
|
||||||
|
%menu-panel-item[aria-current] > *,
|
||||||
|
%menu-panel-item.is-active > * {
|
||||||
|
@extend %menu-panel-button-selected;
|
||||||
|
}
|
||||||
|
%menu-panel-button {
|
||||||
@extend %internal-button;
|
@extend %internal-button;
|
||||||
}
|
}
|
||||||
%menu-panel > ul > li.dangerous > *:not(div) {
|
/* first-child is highly likely to be the button/or anchor*/
|
||||||
|
%menu-panel-item.dangerous > *:first-child {
|
||||||
@extend %internal-button-dangerous;
|
@extend %internal-button-dangerous;
|
||||||
}
|
}
|
||||||
%menu-panel .informed-action {
|
|
||||||
border: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,115 +1,7 @@
|
||||||
%menu-panel {
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
%menu-panel [type='checkbox'] {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
%menu-panel {
|
|
||||||
overflow: hidden;
|
|
||||||
transition: min-height 150ms, max-height 150ms;
|
|
||||||
min-height: 0;
|
|
||||||
}
|
|
||||||
%menu-panel:not(.confirmation) [type='checkbox'] ~ * {
|
|
||||||
transition: transform 150ms;
|
|
||||||
}
|
|
||||||
%menu-panel [type='checkbox']:checked ~ * {
|
|
||||||
transform: translateX(calc(-100% - 10px));
|
|
||||||
}
|
|
||||||
%menu-panel.confirmation [role='menu'] {
|
|
||||||
min-height: 200px !important;
|
|
||||||
}
|
|
||||||
%menu-panel [role='menuitem'] {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
%menu-panel [role='menuitem']:after {
|
|
||||||
@extend %as-pseudo;
|
|
||||||
display: block !important;
|
|
||||||
background-position: center right !important;
|
|
||||||
}
|
|
||||||
%menu-panel-sub-panel {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: calc(100% + 10px);
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
/* TODO: once everything is using ListCollection */
|
|
||||||
/* this can go */
|
|
||||||
%menu-panel [type='checkbox']:checked ~ * {
|
|
||||||
/* this needs to autocalculate */
|
|
||||||
min-height: 143px;
|
|
||||||
max-height: 143px;
|
|
||||||
}
|
|
||||||
%menu-panel [id$='-']:first-child:checked ~ ul label[for$='-'] * [role='menu'],
|
|
||||||
%menu-panel [id$='-']:first-child:checked ~ ul > li > [role='menu'] {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
/**/
|
|
||||||
%menu-panel > ul > li > div[role='menu'] {
|
|
||||||
@extend %menu-panel-sub-panel;
|
|
||||||
}
|
|
||||||
%menu-panel > ul > li > *:not(div[role='menu']) {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
%menu-panel:not(.left) {
|
|
||||||
right: 0px;
|
|
||||||
left: auto;
|
|
||||||
}
|
|
||||||
%menu-panel.left {
|
|
||||||
left: 0px;
|
|
||||||
}
|
|
||||||
%menu-panel:not(.above) {
|
|
||||||
top: 28px;
|
|
||||||
}
|
|
||||||
%menu-panel.above {
|
|
||||||
bottom: 42px;
|
|
||||||
}
|
|
||||||
%menu-panel > ul {
|
|
||||||
margin: 0;
|
|
||||||
padding: 4px 0;
|
|
||||||
}
|
|
||||||
%menu-panel > ul,
|
|
||||||
%menu-panel > ul > li,
|
|
||||||
%menu-panel > ul > li > * {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
%menu-panel > ul > li > * {
|
|
||||||
text-align: left !important;
|
|
||||||
}
|
|
||||||
%menu-panel-separator {
|
|
||||||
padding-top: 0.35em;
|
|
||||||
}
|
|
||||||
%menu-panel-separator:not(:first-child) {
|
|
||||||
margin-top: 0.35em;
|
|
||||||
}
|
|
||||||
%menu-panel-separator:not(:empty) {
|
|
||||||
padding-left: 1em;
|
|
||||||
padding-right: 1em;
|
|
||||||
padding-bottom: 0.1em;
|
|
||||||
}
|
|
||||||
%menu-panel-header {
|
%menu-panel-header {
|
||||||
padding: 10px;
|
padding: 0.625rem var(--padding-x); /* 10px */
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
}
|
}
|
||||||
/* here the !important is only needed for what seems to be a difference */
|
|
||||||
/* with the CSS before and after compression */
|
|
||||||
/* i.e. before compression this style is applied */
|
|
||||||
/* after compression it is in the source but doesn't seem to get */
|
|
||||||
/* applied (unless you add the !important) */
|
|
||||||
%menu-panel .is-active {
|
|
||||||
position: relative !important;
|
|
||||||
}
|
|
||||||
%menu-panel .is-active > *::after {
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
margin-top: -8px;
|
|
||||||
right: 10px;
|
|
||||||
}
|
|
||||||
%menu-panel-header::before {
|
|
||||||
position: absolute;
|
|
||||||
left: 15px;
|
|
||||||
top: calc(10px + 0.1em);
|
|
||||||
}
|
|
||||||
%menu-panel-header {
|
%menu-panel-header {
|
||||||
max-width: fit-content;
|
max-width: fit-content;
|
||||||
}
|
}
|
||||||
|
@ -118,3 +10,63 @@
|
||||||
max-width: 200px;
|
max-width: 200px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
%menu-panel-header::before {
|
||||||
|
position: absolute;
|
||||||
|
left: 15px;
|
||||||
|
top: calc(10px + 0.1em);
|
||||||
|
}
|
||||||
|
|
||||||
|
%menu-panel-body {
|
||||||
|
margin: 0;
|
||||||
|
padding: calc(var(--padding-y) - 0.625rem) 0; /* 10px */
|
||||||
|
}
|
||||||
|
%menu-panel-body,
|
||||||
|
%menu-panel-item,
|
||||||
|
%menu-panel-item > * {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
%menu-panel-item,
|
||||||
|
%menu-panel-button {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
%menu-panel-badge {
|
||||||
|
padding: 0 8px;
|
||||||
|
margin-left: 0.5rem; /* 8px */
|
||||||
|
}
|
||||||
|
%menu-panel-button {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
%menu-panel-button::after {
|
||||||
|
margin-left: auto;
|
||||||
|
/* as we are using margin-left for right align */
|
||||||
|
/* we can't use it for an absolute margin-left */
|
||||||
|
/* so cheat with a bit of padding/translate */
|
||||||
|
padding-right: var(--padding-x);
|
||||||
|
transform: translate(calc(var(--padding-x) / 2), 0);
|
||||||
|
}
|
||||||
|
%menu-panel-separator {
|
||||||
|
padding-top: 0.375rem; /* 6px */
|
||||||
|
}
|
||||||
|
%menu-panel-separator:not(:first-child) {
|
||||||
|
margin-top: 0.275rem; /* 6px */
|
||||||
|
}
|
||||||
|
%menu-panel-separator:not(:empty) {
|
||||||
|
padding-left: var(--padding-x);
|
||||||
|
padding-right: var(--padding-x);
|
||||||
|
padding-bottom: 0.125rem; /* 2px */
|
||||||
|
}
|
||||||
|
|
||||||
|
%menu-panel.menu-panel-confirming {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
%menu-panel-confirmation {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: calc(100% + 10px);
|
||||||
|
}
|
||||||
|
%menu-panel-body {
|
||||||
|
transition: transform 150ms;
|
||||||
|
}
|
||||||
|
%menu-panel.menu-panel-confirming > ul {
|
||||||
|
transform: translateX(calc(-100% - 10px));
|
||||||
|
}
|
||||||
|
|
|
@ -1,34 +1,32 @@
|
||||||
%menu-panel {
|
%menu-panel-button-selected::after {
|
||||||
border: var(--decor-border-100);
|
@extend %with-check-plain-mask, %as-pseudo;
|
||||||
border-radius: var(--decor-radius-200);
|
|
||||||
box-shadow: var(--decor-elevation-600);
|
|
||||||
}
|
|
||||||
%menu-panel > ul > li {
|
|
||||||
list-style-type: none;
|
|
||||||
}
|
}
|
||||||
%menu-panel-header {
|
%menu-panel-header {
|
||||||
@extend %p2;
|
@extend %p2;
|
||||||
}
|
}
|
||||||
|
%menu-panel-header + ul {
|
||||||
|
border-top: var(--decor-border-100);
|
||||||
|
border-color: rgb(var(--tone-border, var(--tone-gray-300)));
|
||||||
|
}
|
||||||
|
/* if the first item is a separator and it */
|
||||||
|
/* contains text don't add a line */
|
||||||
|
%menu-panel-separator:first-child:not(:empty) {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
%menu-panel-separator {
|
%menu-panel-separator {
|
||||||
@extend %p3;
|
@extend %p3;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
font-weight: var(--typo-weight-medium);
|
font-weight: var(--typo-weight-medium);
|
||||||
}
|
|
||||||
%menu-panel-header + ul,
|
|
||||||
%menu-panel-separator:not(:first-child) {
|
|
||||||
border-top: var(--decor-border-100);
|
|
||||||
}
|
|
||||||
%menu-panel .is-active > *::after {
|
|
||||||
@extend %with-check-plain-mask, %as-pseudo;
|
|
||||||
}
|
|
||||||
%menu-panel {
|
|
||||||
border-color: rgb(var(--tone-gray-300));
|
|
||||||
background-color: rgb(var(--tone-gray-000));
|
|
||||||
}
|
|
||||||
%menu-panel-separator {
|
|
||||||
color: rgb(var(--tone-gray-600));
|
color: rgb(var(--tone-gray-600));
|
||||||
}
|
}
|
||||||
%menu-panel-header + ul,
|
%menu-panel-item {
|
||||||
%menu-panel-separator:not(:first-child) {
|
list-style-type: none;
|
||||||
border-color: rgb(var(--tone-gray-300));
|
}
|
||||||
|
%menu-panel-badge {
|
||||||
|
@extend %pill;
|
||||||
|
color: rgb(var(--tone-gray-000));
|
||||||
|
background-color: rgb(var(--tone-gray-500));
|
||||||
|
}
|
||||||
|
%menu-panel-body .informed-action {
|
||||||
|
border: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
<Action
|
<Action
|
||||||
role="menuitem"
|
role="menuitem"
|
||||||
...attributes
|
...attributes
|
||||||
|
@href={{@href}}
|
||||||
|
{{on 'click' (if @href @disclosure.close (noop))}}
|
||||||
|
@external={{@external}}
|
||||||
>
|
>
|
||||||
{{yield}}
|
{{yield}}
|
||||||
</Action>
|
</Action>
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{{yield (hash
|
{{yield (hash
|
||||||
Action=(component 'menu/action')
|
Action=(component 'menu/action' disclosure=@disclosure)
|
||||||
Item=(component 'menu/item')
|
Item=(component 'menu/item')
|
||||||
Separator=(component 'menu/separator')
|
Separator=(component 'menu/separator')
|
||||||
)}}
|
)}}
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
<li
|
<li
|
||||||
role="separator"
|
role="separator"
|
||||||
...attributes
|
...attributes
|
||||||
>
|
>{{yield}}</li>
|
||||||
{{yield}}
|
|
||||||
</li>
|
|
||||||
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
---
|
||||||
|
type: css
|
||||||
|
---
|
||||||
|
# Panel
|
||||||
|
|
||||||
|
Very basic 'panel' card-like CSS component currently used for menu-panels.
|
||||||
|
|
||||||
|
When building components using `panel` please make use of the CSS custom
|
||||||
|
properties available to help maintain consistency within the panel.
|
||||||
|
|
||||||
|
**Very important**: Please avoid using style attributes for doing this the
|
||||||
|
below is only for illustrative purposes. Please use this CSS component as a
|
||||||
|
building block for other CSS instead.
|
||||||
|
|
||||||
|
|
||||||
|
```hbs preview-template
|
||||||
|
<figure>
|
||||||
|
<figcaption>Panel with no padding (in dark mode)</figcaption>
|
||||||
|
<div
|
||||||
|
class={{class-map
|
||||||
|
"panel"
|
||||||
|
"theme-dark"
|
||||||
|
}}
|
||||||
|
...attributes
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<p>Some text purposefully with no padding</p>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
<div>
|
||||||
|
<p>Along with a separator ^ again purposefully with no padding</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</figure>
|
||||||
|
<figure>
|
||||||
|
<figcaption>Panel using inherited padding for consistency</figcaption>
|
||||||
|
<div
|
||||||
|
class={{class-map
|
||||||
|
"panel"
|
||||||
|
}}
|
||||||
|
...attributes
|
||||||
|
>
|
||||||
|
<Action
|
||||||
|
style={{style-map
|
||||||
|
(array 'width' '100%')
|
||||||
|
(array 'border-bottom' '1px solid rgb(var(--tone-border))')
|
||||||
|
(array 'padding' 'var(--padding-x) var(--padding-y)')
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Full Width Button
|
||||||
|
</Action>
|
||||||
|
<div
|
||||||
|
style={{style-map
|
||||||
|
(array 'padding' 'var(--padding-x) var(--padding-y)')
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<p>Some text with padding</p>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
<div
|
||||||
|
style={{style-map
|
||||||
|
(array 'padding' 'var(--padding-x) var(--padding-y)')
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<p>Along with a separator ^ again with padding</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</figure>
|
||||||
|
<figure>
|
||||||
|
<figcaption>Panel using larger padding and different color borders</figcaption>
|
||||||
|
<div
|
||||||
|
class={{class-map
|
||||||
|
"panel"
|
||||||
|
}}
|
||||||
|
style={{style-map
|
||||||
|
(array '--padding-x' '24px')
|
||||||
|
(array '--padding-y' '24px')
|
||||||
|
(array '--tone-border' 'var(--tone-strawberry-500)')
|
||||||
|
}}
|
||||||
|
...attributes
|
||||||
|
>
|
||||||
|
<Action
|
||||||
|
style={{style-map
|
||||||
|
(array 'width' '100%')
|
||||||
|
(array 'border-bottom' '1px solid rgb(var(--tone-border))')
|
||||||
|
(array 'padding' 'var(--padding-x) var(--padding-y)')
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Full Width Button
|
||||||
|
</Action>
|
||||||
|
<div
|
||||||
|
style={{style-map
|
||||||
|
(array 'padding' 'var(--padding-x) var(--padding-y)')
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<p>Some text with padding</p>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
<div
|
||||||
|
style={{style-map
|
||||||
|
(array 'padding' 'var(--padding-x) var(--padding-y)')
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<p>Along with a separator ^ again with padding</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</figure>
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
```css
|
||||||
|
.panel {
|
||||||
|
@extend %panel;
|
||||||
|
}
|
||||||
|
.panel hr {
|
||||||
|
@extend %panel-separator;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## CSS Properties
|
||||||
|
|
||||||
|
| Property | Type | Default | Description |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| `--tone-border` | `color` | --tone-gray-300 | Default color for all borders |
|
||||||
|
| `--padding-x` | `length` | 14px | Default x padding to be used for padding values within the component |
|
||||||
|
| `--padding-y` | `length` | 14px | Default y padding to be used for padding values within the component |
|
|
@ -0,0 +1,8 @@
|
||||||
|
#docfy-demo-preview-panel {
|
||||||
|
.panel {
|
||||||
|
@extend %panel;
|
||||||
|
}
|
||||||
|
.panel hr {
|
||||||
|
@extend %panel-separator;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
@import './skin';
|
||||||
|
@import './layout';
|
|
@ -0,0 +1,11 @@
|
||||||
|
%panel {
|
||||||
|
--padding-x: 14px;
|
||||||
|
--padding-y: 14px;
|
||||||
|
/* max-height: var(--panel-height, auto); */
|
||||||
|
}
|
||||||
|
%panel {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
%panel-separator {
|
||||||
|
margin: 0;
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
%panel {
|
||||||
|
--tone-border: var(--tone-gray-300);
|
||||||
|
border: var(--decor-border-100);
|
||||||
|
border-radius: var(--decor-radius-200);
|
||||||
|
box-shadow: var(--decor-elevation-600);
|
||||||
|
}
|
||||||
|
%panel-separator {
|
||||||
|
border-top: var(--decor-border-100);
|
||||||
|
}
|
||||||
|
%panel {
|
||||||
|
color: rgb(var(--tone-gray-900));
|
||||||
|
background-color: rgb(var(--tone-gray-000));
|
||||||
|
}
|
||||||
|
%panel,
|
||||||
|
%panel-separator {
|
||||||
|
border-color: rgb(var(--tone-border));
|
||||||
|
}
|
|
@ -1,6 +1,9 @@
|
||||||
.popover-select {
|
.popover-select {
|
||||||
@extend %popover-select;
|
@extend %popover-select;
|
||||||
}
|
}
|
||||||
|
.popover-menu .menu-panel {
|
||||||
|
position: absolute !important;
|
||||||
|
}
|
||||||
%popover-select label {
|
%popover-select label {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,9 @@ export default Component.extend({
|
||||||
actions: {
|
actions: {
|
||||||
dispatch: function(eventName, e) {
|
dispatch: function(eventName, e) {
|
||||||
if (e && e.preventDefault) {
|
if (e && e.preventDefault) {
|
||||||
e.preventDefault();
|
if (typeof e.target.nodeName === 'undefined' || e.target.nodeName.toLowerCase() !== 'a') {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.dispatch(eventName, e);
|
this.dispatch(eventName, e);
|
||||||
},
|
},
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
@import 'consul-ui/components/more-popover-menu';
|
@import 'consul-ui/components/more-popover-menu';
|
||||||
@import 'consul-ui/components/oidc-select';
|
@import 'consul-ui/components/oidc-select';
|
||||||
@import 'consul-ui/components/radio-card';
|
@import 'consul-ui/components/radio-card';
|
||||||
|
@import 'consul-ui/components/panel';
|
||||||
@import 'consul-ui/components/pill';
|
@import 'consul-ui/components/pill';
|
||||||
@import 'consul-ui/components/popover-menu';
|
@import 'consul-ui/components/popover-menu';
|
||||||
@import 'consul-ui/components/popover-select';
|
@import 'consul-ui/components/popover-select';
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
// temporary component debugging setup
|
// temporary component debugging setup
|
||||||
@import 'consul-ui/components/main-nav-vertical/debug';
|
@import 'consul-ui/components/main-nav-vertical/debug';
|
||||||
@import 'consul-ui/components/badge/debug';
|
@import 'consul-ui/components/badge/debug';
|
||||||
|
@import 'consul-ui/components/panel/debug';
|
||||||
@import 'consul-ui/components/shadow-template/debug';
|
@import 'consul-ui/components/shadow-template/debug';
|
||||||
@import 'consul-ui/components/csv-list/debug';
|
@import 'consul-ui/components/csv-list/debug';
|
||||||
@import 'consul-ui/components/horizontal-kv-list/debug';
|
@import 'consul-ui/components/horizontal-kv-list/debug';
|
||||||
|
@ -11,6 +12,9 @@
|
||||||
@import 'consul-ui/components/inline-alert/debug';
|
@import 'consul-ui/components/inline-alert/debug';
|
||||||
@import 'consul-ui/components/definition-table/debug';
|
@import 'consul-ui/components/definition-table/debug';
|
||||||
|
|
||||||
|
.theme-dark {
|
||||||
|
@extend %theme-dark;
|
||||||
|
}
|
||||||
%debug-grid {
|
%debug-grid {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
|
@ -10,10 +10,11 @@ export default function(scenario, find, click) {
|
||||||
'I click $property on the $component',
|
'I click $property on the $component',
|
||||||
'I click $property on the $component component',
|
'I click $property on the $component component',
|
||||||
],
|
],
|
||||||
function(property, component, next) {
|
async function(property, component, next) {
|
||||||
if (typeof component === 'string') {
|
if (typeof component === 'string') {
|
||||||
property = `${component}.${property}`;
|
property = `${component}.${property}`;
|
||||||
}
|
}
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 0));
|
||||||
return find(property)();
|
return find(property)();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue