feat(panel): add wip select to top of panel

- todo: display popup beneath select
- todo: dynamically register values
- todo: add icons
- todo: change view on select change
This commit is contained in:
dragonwocky 2023-08-07 12:50:37 +10:00
parent 09b24147c5
commit 0ad2b2ff54
Signed by: dragonwocky
GPG Key ID: 7998D08F7D7BD7A8
5 changed files with 53 additions and 35 deletions

View File

@ -7,8 +7,8 @@
function Modal(props, ...children) { function Modal(props, ...children) {
const { html, extendProps, addKeyListener } = globalThis.__enhancerApi; const { html, extendProps, addKeyListener } = globalThis.__enhancerApi;
extendProps(props, { extendProps(props, {
class: `notion-enhancer--menu-modal group class: `notion-enhancer--menu-modal z-[999]
z-[999] fixed inset-0 w-screen h-screen fixed inset-0 w-screen h-screen group/modal
transition pointer-events-none opacity-0 transition pointer-events-none opacity-0
open:(pointer-events-auto opacity-100)`, open:(pointer-events-auto opacity-100)`,
}); });
@ -30,6 +30,9 @@ function Modal(props, ...children) {
_openQueued = true; _openQueued = true;
while (!document.contains($modal)) { while (!document.contains($modal)) {
if (!_openQueued) return; if (!_openQueued) return;
// dont trigger open until menu is in dom,
// to ensure transition is shown when menu
// does initially open
await new Promise(requestAnimationFrame); await new Promise(requestAnimationFrame);
} }
$modal.setAttribute("open", ""); $modal.setAttribute("open", "");
@ -55,11 +58,10 @@ function Modal(props, ...children) {
function Frame(props) { function Frame(props) {
const { html, extendProps } = globalThis.__enhancerApi; const { html, extendProps } = globalThis.__enhancerApi;
extendProps(props, { extendProps(props, {
class: `rounded-[5px] w-[1150px] h-[calc(100vh-100px)] class: `rounded-[5px] w-[1150px] h-[calc(100vh-100px)] opacity-0
max-w-[calc(100vw-100px)] max-h-[715px] overflow-hidden max-w-[calc(100vw-100px)] max-h-[715px] overflow-hidden scale-95
bg-[color:var(--theme--bg-primary)] drop-shadow-xl bg-[color:var(--theme--bg-primary)] drop-shadow-xl transition
group-open:(pointer-events-auto opacity-100 scale-100) group-open/modal:(pointer-events-auto opacity-100 scale-100)`,
transition opacity-0 scale-95`,
}); });
return html`<iframe ...${props}></iframe>`; return html`<iframe ...${props}></iframe>`;
} }

View File

@ -6,6 +6,7 @@
*/ */
import { Tooltip } from "./Tooltip.mjs"; import { Tooltip } from "./Tooltip.mjs";
import { Select } from "../menu/islands/Select.mjs";
function PanelView(props) { function PanelView(props) {
const { html } = globalThis.__enhancerApi; const { html } = globalThis.__enhancerApi;
@ -27,21 +28,21 @@ function Panel({
transitionDuration = 300, transitionDuration = 300,
...props ...props
}) { }) {
const { html, extendProps, setState } = globalThis.__enhancerApi, const { html, extendProps, setState, useState } = globalThis.__enhancerApi,
{ addMutationListener, removeMutationListener } = globalThis.__enhancerApi; { addMutationListener, removeMutationListener } = globalThis.__enhancerApi;
extendProps(props, { extendProps(props, {
class: `notion-enhancer--side-panel order-2 shrink-0 class: `notion-enhancer--side-panel order-2 shrink-0
transition-[width] open:w-[var(--side\\_panel--width)] transition-[width] open:w-[var(--side\\_panel--width)]
w-0 border-l-1 border-[color:var(--theme--fg-border)] border-l-1 border-[color:var(--theme--fg-border)]
relative bg-[color:var(--theme--bg-primary)] group relative bg-[color:var(--theme--bg-primary)] w-0
duration-[${transitionDuration}ms]`, duration-[${transitionDuration}ms] group/panel`,
}); });
const $resizeHandle = html`<div const $resizeHandle = html`<div
class="absolute h-full w-[3px] left-[-3px] class="absolute h-full w-[3px] left-[-3px]
z-10 transition duration-300 hover:(cursor-col-resize z-10 transition duration-300 hover:(cursor-col-resize
shadow-[var(--theme--fg-border)_-2px_0px_0px_0px_inset]) shadow-[var(--theme--fg-border)_-2px_0px_0px_0px_inset])
active:cursor-text group-not-[open]:hidden" active:cursor-text group-not-[open]/panel:hidden"
></div>`, ></div>`,
$chevronClose = html`<button $chevronClose = html`<button
aria-label="Close side panel" aria-label="Close side panel"
@ -49,14 +50,18 @@ function Panel({
transition inline-flex items-center justify-center mr-[10px] transition inline-flex items-center justify-center mr-[10px]
rounded-[3px] hover:bg-[color:var(--theme--bg-hover)]" rounded-[3px] hover:bg-[color:var(--theme--bg-hover)]"
> >
<svg <i
viewBox="0 0 16 16" class="i-chevrons-right w-[20px] h-[20px]
class="w-[16px] h-[16px] fill-[color:var(--theme--fg-secondary)]" text-[color:var(--theme--fg-secondary)]"
><path />
d="M2.25781 14.1211C2.47656 14.1211 2.66797 14.0391 2.81836 13.8887L8.14355 8.67969C8.32812 8.49512 8.41699 8.29688 8.41699 8.06445C8.41699 7.8252 8.32812 7.62012 8.14355 7.44922L2.81836 2.24023C2.66797 2.08984 2.4834 2.00781 2.25781 2.00781C1.81348 2.00781 1.46484 2.35645 1.46484 2.80078C1.46484 3.0127 1.55371 3.21777 1.7041 3.375L6.50977 8.05762L1.7041 12.7539C1.55371 12.9043 1.46484 13.1094 1.46484 13.3281C1.46484 13.7725 1.81348 14.1211 2.25781 14.1211ZM8.36914 14.1211C8.58789 14.1211 8.77246 14.0391 8.92285 13.8887L14.2549 8.67969C14.4395 8.49512 14.5283 8.29688 14.5283 8.06445C14.5283 7.8252 14.4326 7.62012 14.2549 7.44922L8.92285 2.24023C8.77246 2.08984 8.58789 2.00781 8.36914 2.00781C7.9248 2.00781 7.56934 2.35645 7.56934 2.80078C7.56934 3.0127 7.66504 3.21777 7.81543 3.375L12.6211 8.05762L7.81543 12.7539C7.66504 12.9043 7.56934 13.1094 7.56934 13.3281C7.56934 13.7725 7.9248 14.1211 8.36914 14.1211Z"
></path></svg>
</div>`; </div>`;
const values = ["default", "outliner", "word counter"],
_get = () => useState(["panelView"])[0],
_set = (value) => {
setState({ panelView: value, rerender: true });
};
const $panel = html`<aside ...${props}> const $panel = html`<aside ...${props}>
${$resizeHandle} ${$resizeHandle}
<div <div
@ -64,9 +69,12 @@ function Panel({
border-(b [color:var(--theme--fg-border)])" border-(b [color:var(--theme--fg-border)])"
> >
<div <div
style="font-size: 14px; color: rgba(255, 255, 255, 0.81); font-weight: 500; display: flex; align-items: center; padding: 12px 12px 12px 16px;" class="relative flex grow font-medium items-center p-[8.5px] ml-[4px]"
> >
Comments <${Select}
class="w-full text-left"
...${{ _get, _set, values, maxWidth: maxWidth - 56 }}
/>
</div> </div>
${$chevronClose} ${$chevronClose}
</div> </div>

View File

@ -8,7 +8,7 @@ function Tooltip(props, ...children) {
const { html, extendProps } = globalThis.__enhancerApi; const { html, extendProps } = globalThis.__enhancerApi;
extendProps(props, { extendProps(props, {
role: "dialog", role: "dialog",
class: `absolute group z-[999] pointer-events-none`, class: `absolute group/tooltip z-[999] pointer-events-none`,
}); });
const notionApp = ".notion-app-inner", const notionApp = ".notion-app-inner",
@ -18,7 +18,7 @@ function Tooltip(props, ...children) {
text-([color:var(--theme--fg-secondary)] [12px] center) text-([color:var(--theme--fg-secondary)] [12px] center)
leading-[1.4] font-medium py-[4px] px-[8px] rounded-[4px] leading-[1.4] font-medium py-[4px] px-[8px] rounded-[4px]
drop-shadow-md transition duration-200 opacity-0 drop-shadow-md transition duration-200 opacity-0
group-open:(pointer-events-auto opacity-100) group-open/tooltip:(pointer-events-auto opacity-100)
children:text-([color:var(--theme--fg-primary)]" children:text-([color:var(--theme--fg-primary)]"
> >
${children} ${children}

View File

@ -7,10 +7,10 @@
function Popup({ trigger, ...props }, ...children) { function Popup({ trigger, ...props }, ...children) {
const { html, extendProps, setState, useState } = globalThis.__enhancerApi; const { html, extendProps, setState, useState } = globalThis.__enhancerApi;
extendProps(props, { extendProps(props, {
class: `notion-enhancer--menu-popup class: `notion-enhancer--menu-popup group/popup
group absolute top-0 left-0 w-full h-full absolute top-0 left-0 w-full h-full z-20 text-left
flex-(& col) justify-center items-end z-20 flex-(& col) justify-center items-end font-normal
pointer-events-none font-normal text-left`, pointer-events-none`,
}); });
const $popup = html`<div ...${props}> const $popup = html`<div ...${props}>
@ -20,7 +20,7 @@ function Popup({ trigger, ...props }, ...children) {
w-[250px] max-w-[calc(100vw-24px)] max-h-[70vh] w-[250px] max-w-[calc(100vw-24px)] max-h-[70vh]
py-[6px] px-[4px] drop-shadow-xl overflow-y-auto py-[6px] px-[4px] drop-shadow-xl overflow-y-auto
transition duration-200 opacity-0 scale-95 rounded-[4px] transition duration-200 opacity-0 scale-95 rounded-[4px]
group-open:(pointer-events-auto opacity-100 scale-100)" group-open/popup:(pointer-events-auto opacity-100 scale-100)"
> >
${children} ${children}
</div> </div>

View File

@ -32,21 +32,28 @@ function Option({ value, _get, _set }) {
return $option; return $option;
} }
function Select({ values, _get, _set, _requireReload = true, ...props }) { function Select({
values,
_get,
_set,
_requireReload = true,
maxWidth = 256,
...props
}) {
let _initialValue; let _initialValue;
const { html, setState, useState } = globalThis.__enhancerApi, const { html, extendProps, setState, useState } = globalThis.__enhancerApi,
// dir="rtl" overflows to the left during transition // dir="rtl" overflows to the left during transition
$select = html`<div $select = html`<div
dir="rtl" dir="rtl"
role="button" role="button"
tabindex="0" tabindex="0"
class="appearance-none bg-transparent rounded-[4px] cursor-pointer class="appearance-none bg-transparent rounded-[4px]
text-[14px] leading-[28px] h-[28px] max-w-[256px] pl-[8px] pr-[28px] cursor-pointer text-[14px] leading-[28px] h-[28px]
transition duration-[20ms] hover:bg-[color:var(--theme--bg-hover)]" max-w-[${maxWidth}px] pl-[8px] pr-[28px] transition
...${props} duration-[20ms] hover:bg-[color:var(--theme--bg-hover)]"
></div>`; ></div>`;
useState(["rerender"], async () => { useState(["rerender"], async () => {
const value = (await _get?.()) ?? $select.innerText; const value = (await _get?.()) ?? ($select.innerText || values[0]);
$select.innerText = value; $select.innerText = value;
if (_requireReload) { if (_requireReload) {
_initialValue ??= value; _initialValue ??= value;
@ -54,7 +61,8 @@ function Select({ values, _get, _set, _requireReload = true, ...props }) {
} }
}); });
return html`<div class="notion-enhancer--menu-select relative"> extendProps(props, { class: "notion-enhancer--menu-select relative" });
return html`<div ...${props}>
${$select} ${$select}
<${Popup} <${Popup}
trigger=${$select} trigger=${$select}