Newer
Older
iuav-ui / src / components / mobile-menu / mobile-menu.ts
  1. import { LitElement, html, css, unsafeCSS} from 'lit';
  2. import { customElement, property } from 'lit/decorators.js';
  3. import { breakpoints } from '../../breakpoints';
  4.  
  5. @customElement('iu-mobile-menu')
  6.  
  7. export class MobileMenu extends LitElement {
  8.  
  9. static override styles = css`
  10. :host {
  11. position: fixed;
  12. display: none;
  13. left: 0;
  14. height: calc(100dvh - 50px);
  15. width: 100%;
  16. max-width: 48rem;
  17. background: var(--iu-color-white);
  18. top: 50px;
  19. z-index: 50;
  20. overflow: auto;
  21. }
  22. @media ${unsafeCSS(breakpoints.md)} {
  23. :host{
  24. width: calc((100% - var(--iu-grid-offset)) - var(--iu-grid-gutter));
  25. }
  26. }
  27. :host([open]){
  28. display: block;
  29. }
  30. /* fallback if event listener doesn't work */
  31. @media ${unsafeCSS(breakpoints.xl)} {
  32. :host([open]){
  33. display: none;
  34. }
  35. }
  36. ul{
  37. list-style-type: none;
  38. padding: 0;
  39. margin: 0;
  40. }
  41. .secondary-nav{
  42. background: var(--iu-color-black);
  43. ul{
  44. padding-top: var(--iu-spacing-1);
  45. padding-bottom: var(--iu-spacing-2);
  46. }
  47. li:not(:last-child){
  48. margin-bottom: var(--iu-spacing-0);
  49. }
  50. a{
  51. color: var(--iu-color-white);
  52. text-decoration: none;
  53. padding: 0 var(--iu-grid-gutter);
  54. }
  55. }
  56. `;
  57.  
  58. @property({ type: String }) label? = 'Menu principale';
  59. @property({ type: Boolean, reflect: true }) open : boolean = false;
  60. @property({ type: Array, attribute: 'secondary-nav-items' }) secondaryNavItems: Array<{ text: string; href: string }> = [];
  61. @property({ type: String, attribute: 'secondary-nav-label' }) secondaryNavLabel: string = 'Menu secondario';
  62.  
  63. private handleMenuToggle = () => {
  64. this.open = !this.open;
  65. this.requestUpdate();
  66. };
  67.  
  68. override connectedCallback() {
  69. super.connectedCallback();
  70. window.addEventListener('toggle-mobile-menu', this.handleMenuToggle);
  71. }
  72. override disconnectedCallback() {
  73. window.removeEventListener('toggle-mobile-menu', this.handleMenuToggle);
  74. super.disconnectedCallback();
  75. }
  76.  
  77. override render() {
  78. return html`
  79. ${this.secondaryNavItems.length > 0 ? html`
  80. <nav aria-label="${this.secondaryNavLabel}" role="navigation" class="secondary-nav">
  81. <ul>
  82. ${this.secondaryNavItems.map(
  83. item => html`
  84. <li><a href="${item.href}">${item.text}</a></li>
  85. `)
  86. }
  87. </ul>
  88. </nav>
  89. `
  90. : ''
  91. }
  92. <nav aria-label="${this.label}" role="navigation">
  93. <ul>
  94. <slot></slot>
  95. </ul>
  96. </nav>
  97. `;
  98. }
  99. }
  100.  
  101. declare global {
  102. interface HTMLElementTagNameMap {
  103. 'iu-mobile-menu': MobileMenu;
  104. }
  105. }