summaryrefslogtreecommitdiff
path: root/src/components/widgets/Header.astro
blob: ff4a3aa6d4d4976f048d22290cdfcdaebadcfdf2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
---
import { Icon } from 'astro-icon/components';
import Logo from '~/components/Logo.astro';
import ToggleTheme from '~/components/common/ToggleTheme.astro';
import ToggleMenu from '~/components/common/ToggleMenu.astro';
import Button from '~/components/ui/Button.astro';

import { getHomePermalink } from '~/utils/permalinks';
import { trimSlash, getAsset } from '~/utils/permalinks';
import type { CallToAction } from '~/types';

interface Link {
  text?: string;
  href?: string;
  ariaLabel?: string;
  icon?: string;
}

interface MenuLink extends Link {
  links?: Array<MenuLink>;
}

export interface Props {
  id?: string;
  links?: Array<MenuLink>;
  actions?: Array<CallToAction>;
  isSticky?: boolean;
  isDark?: boolean;
  isFullWidth?: boolean;
  showToggleTheme?: boolean;
  showRssFeed?: boolean;
  position?: string;
}

const {
  id = 'header',
  links = [],
  actions = [],
  isSticky = false,
  isDark = false,
  isFullWidth = false,
  showToggleTheme = false,
  showRssFeed = false,
  position = 'center',
} = Astro.props;

const currentPath = `/${trimSlash(new URL(Astro.url).pathname)}`;
---

<header
  class:list={[
    { sticky: isSticky, relative: !isSticky, dark: isDark },
    'top-0 z-40 flex-none mx-auto w-full border-b border-gray-50/0 transition-[opacity] ease-in-out',
  ]}
  {...isSticky ? { 'data-aw-sticky-header': true } : {}}
  {...id ? { id } : {}}
>
  <div class="absolute inset-0"></div>
  <div
    class:list={[
      'relative text-default py-3 px-3 md:px-6 mx-auto w-full',
      {
        'md:flex md:justify-between': position !== 'center',
      },
      {
        'md:grid md:grid-cols-3 md:items-center': position === 'center',
      },
      {
        'max-w-7xl': !isFullWidth,
      },
    ]}
  >
    <div class:list={[{ 'mr-auto rtl:mr-0 rtl:ml-auto': position === 'right' }, 'flex justify-between']}>
      <a class="flex items-center" href={getHomePermalink()}>
        <Logo />
      </a>
      <div class="flex items-center md:hidden">
        <ToggleMenu />
      </div>
    </div>
    <nav
      class="items-center w-full md:w-auto hidden md:flex md:mx-5 text-default overflow-y-auto overflow-x-hidden md:overflow-y-visible md:overflow-x-auto md:justify-self-center"
      aria-label="Main navigation"
    >
      <ul
        class="flex flex-col md:flex-row md:self-center w-full md:w-auto text-xl md:text-[0.9375rem] tracking-[0.01rem] font-medium md:justify-center"
      >
        {
          links.map(({ text, href, links }) => (
            <li class={links?.length ? 'dropdown' : ''}>
              {links?.length ? (
                <>
                  <button
                    type="button"
                    class="hover:text-link dark:hover:text-white px-4 py-3 flex items-center whitespace-nowrap"
                  >
                    {text}{' '}
                    <Icon name="tabler:chevron-down" class="w-3.5 h-3.5 ml-0.5 rtl:ml-0 rtl:mr-0.5 hidden md:inline" />
                  </button>
                  <ul class="dropdown-menu md:backdrop-blur-md dark:md:bg-dark rounded md:absolute pl-4 md:pl-0 md:hidden font-medium md:bg-white/90 md:min-w-[200px] drop-shadow-xl">
                    {links.map(({ text: text2, href: href2 }) => (
                      <li>
                        <a
                          class:list={[
                            'first:rounded-t last:rounded-b md:hover:bg-gray-100 hover:text-link dark:hover:text-white dark:hover:bg-gray-700 py-2 px-5 block whitespace-no-wrap',
                            { 'aw-link-active': href2 === currentPath },
                          ]}
                          href={href2}
                        >
                          {text2}
                        </a>
                      </li>
                    ))}
                  </ul>
                </>
              ) : (
                <a
                  class:list={[
                    'hover:text-link dark:hover:text-white px-4 py-3 flex items-center whitespace-nowrap',
                    { 'aw-link-active': href === currentPath },
                  ]}
                  href={href}
                >
                  {text}
                </a>
              )}
            </li>
          ))
        }
      </ul>
    </nav>
    <div
      class:list={[
        { 'ml-auto rtl:ml-0 rtl:mr-auto': position === 'left' },
        'hidden md:self-center md:flex items-center md:mb-0 fixed w-full md:w-auto md:static justify-end left-0 rtl:left-auto rtl:right-0 bottom-0 p-3 md:p-0 md:justify-self-end',
      ]}
    >
      <div class="items-center flex justify-between w-full md:w-auto">
        <div class="flex">
          {showToggleTheme && <ToggleTheme iconClass="w-6 h-6 md:w-5 md:h-5 md:inline-block" />}
          {
            showRssFeed && (
              <a
                class="text-muted dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5 inline-flex items-center"
                aria-label="RSS Feed"
                href={getAsset('/rss.xml')}
              >
                <Icon name="tabler:rss" class="w-5 h-5" />
              </a>
            )
          }
        </div>
        {
          actions?.length ? (
            <span class="ml-4 rtl:ml-0 rtl:mr-4">
              {actions.map((btnProps) => (
                <Button {...btnProps} class="ml-2 py-2.5 px-5.5 md:px-6 font-semibold shadow-none text-sm w-auto" />
              ))}
            </span>
          ) : (
            ''
          )
        }
      </div>
    </div>
  </div>
</header>