Menugroup.res

 1%%raw("import logo from '../static/logo.png?inline';")
 2@val external logo: string = "logo"
 3
 4open Preact
 5
 6let isOpen = Signal.make(false)
 7let loggedIn = Preact.Signal.computed(() =>
 8  State.user->Preact.Signal.get->Option.map(data => data.registered)
 9)
10
11@jsx.component
12let make = () => {
13  <>
14    <div className="fixed top-2 right-2 flex flex-row items-center z-1 mr-2">
15      <div className="pr-2">
16        <img className="w-28" src={logo} />
17      </div>
18      <div
19        className="relative bg-paper px-2 pt-1 rounded-sm flex-1"
20        onClick={_evt => {
21          isOpen->Signal.set(!Signal.get(isOpen))
22        }}
23      >
24        {loggedIn->Preact.Signal.get->Option.getOr(false)
25          ? Preact.null
26          : <div
27              className="absolute top-0 right-0 w-4 h-4 rounded-full bg-[var(--color-red)] z-10 translate-x-1/2 -translate-y-1/2 text-xs text-white font-bold text-center"
28            >
29              {"!"->string}
30            </div>}
31        <Menu.Root>
32          <Menu.Trigger>
33            <Icons.Menu className="text-ui-2 m-auto" size=20 strokeWidth=3 />
34          </Menu.Trigger>
35          <Menu.Portal className="max-w-full md:w-fit md:max-w-[20rem] md:min-w-[10rem]">
36            <Menu.Positioner sideOffset={14} className="outline-none">
37              <Menu.Popup
38                className="popup bg-paper shadow-md p-2 rounded-sm py-2 pt-4 outline-none"
39              >
40                {loggedIn->Preact.Signal.get->Option.getOr(false)
41                  ? <Menu.LinkItem
42                      className="w-full rounded-sm py-1 px-14 hover:bg-blue-100 flex flex-row items-center justify-center"
43                      href={`/u/${State.user
44                        ->Preact.Signal.get
45                        ->Option.map(data => data.id)
46                        ->Option.getOr("")}`}
47                    >
48                      {State.user
49                      ->Preact.Signal.get
50                      ->Option.map(data => "@" ++ data.handle ++ "'s account")
51                      ->Option.getOr("Account")
52                      ->Preact.string}
53                    </Menu.LinkItem>
54                  : <Menu.Item
55                      className="w-full rounded-sm px-2 py-1 outline-2 outline-offset-2 outline-solid outline-orange hover:bg-[var(--color-orange)] active:bg-[var(--color-orange)] hover:text-white active:text-white focus:bg-(--color-orange) focus:text-white text-center"
56                      onClick={_evt => {
57                        Log.debug("got login button")
58                        State.content->Signal.set(Some(<Login />))
59                      }}
60                    >
61                      {"Login or Sign up"->string}
62                    </Menu.Item>}
63                <Menu.LinkItem
64                  href="/about"
65                  className="rounded-sm hover:bg-blue-100 py-1 mt-2 w-full flex flex-row items-center justify-center hover:outline-none active:outline-(--color-blue) mx-auto"
66                >
67                  {"About"->string}
68                </Menu.LinkItem>
69                {loggedIn->Preact.Signal.get->Option.getOr(false)
70                  ? Preact.null
71                  : <div className="flex flex-column mt-5 items-center">
72                      <div>
73                        <Icons.OctagonAlert
74                          color="var(--color-red)" size={24} strokeWidth={3} className="pr-1"
75                        />
76                      </div>
77                      <div className="text-xs text-pretty">
78                        {"You'll lose your work after 30 days if you don't log in"->string}
79                      </div>
80                    </div>}
81              </Menu.Popup>
82            </Menu.Positioner>
83          </Menu.Portal>
84        </Menu.Root>
85      </div>
86    </div>
87  </>
88}