Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modal, a play in 3 acts #3

Merged
merged 4 commits into from
Sep 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 73 additions & 67 deletions components/Create.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import ReactModal from "react-modal";
import PlateEditor from "../components/Plate/Editor";
import { useState, useEffect } from "react";
import { useState, useEffect, useRef } from "react";
import {
useStoreEditorValue,
useStoreEditorState,
Expand All @@ -14,6 +14,7 @@ import { createOrUpdateSlateJSON, saveNote } from "../model/note";
import { createOrUpdateConceptIndex } from "../model/concept";
import { useWorkspace, useCurrentWorkspace } from "../hooks/app";
import { useConcept } from "../hooks/concepts";
import { Dialog } from '@headlessui/react';

const TabId = {
Concept: "Concept",
Expand All @@ -26,9 +27,8 @@ export function Tab({ title, selected, onClick }) {
"border-transparent text-fog hover:text-storm hover:border-storm";
return (
<button
className={`whitespace-nowrap pb-4 px-1 border-b-2 font-medium text-sm ${
selected ? selectedClasses : defaultClasses
}`}
className={`whitespace-nowrap pb-4 px-1 border-b-2 font-medium text-sm ${selected ? selectedClasses : defaultClasses
}`}
value={title}
onClick={(e) => {
e.preventDefault();
Expand Down Expand Up @@ -120,74 +120,80 @@ export function CreateModal({ isOpen, closeModal }) {
close();
}
};

const firstInputRef = useRef(null)
console.log(isOpen)
return (
<ReactModal isOpen={isOpen}>
<form className="w-full max-w-sm">
<Tabs
tabs={tabs}
selectedTab={selectedTab}
setSelectedTab={setSelectedTab}
/>

{selectedTab === TabId.Concept ? (
<>
<div
className={`flex items-center border-b-2 py-2 ${
conceptExists
<Dialog open={isOpen} onClose={close} initialFocus={firstInputRef}
className="fixed z-10 inset-0 overflow-y-auto"
>
<Dialog.Overlay className="fixed inset-0 bg-black opacity-30" />
<div className="relative bg-white rounded max-w-sm mx-auto">
<form className="w-full max-w-sm">
<Tabs
tabs={tabs}
selectedTab={selectedTab}
setSelectedTab={setSelectedTab}
/>

{selectedTab === TabId.Concept ? (
<>
<div
className={`flex items-center border-b-2 py-2 ${conceptExists
? "border-ember text-ember"
: "border-lagoon text-lagoon"
}`}
>
}`}
>
<input
className="appearance-none focus:ring-0 text-3xl bg-transparent outline-none border-none focus:border-none w-full mr-3 py-1 px-2 leading-tight focus:outline-none"
type="text"
placeholder="Untitled"
aria-label="Concept Name"
value={name}
onChange={(e) => setName(e.target.value)}
ref={firstInputRef}
/>
{conceptExists ? (
<span className="whitespace-nowrap">
concept already exists
</span>
) : (
<></>
)}
</div>

<div className="text-left p-4">
<PlateEditor editorId={editorId} initialValue={value} />
</div>
</>
) : (
<span> upload image or link </span>
)}

<div className="flex justify-end border-t-2 border-echeveria py-2">
<label className="inline-flex items-center">
<input
className="appearance-none focus:ring-0 text-3xl bg-transparent outline-none border-none focus:border-none w-full mr-3 py-1 px-2 leading-tight focus:outline-none"
type="text"
placeholder="Untitled"
aria-label="Concept Name"
value={name}
onChange={(e) => setName(e.target.value)}
className="form-checkbox text-echeveria"
type="checkbox"
checked={createAnother}
onChange={(e) => setCreateAnother(e.target.checked)}
/>
{conceptExists ? (
<span className="whitespace-nowrap">
concept already exists
</span>
) : (
<></>
)}
</div>

<div className="text-left p-4">
<PlateEditor editorId={editorId} initialValue={value} />
</div>
</>
) : (
<span> upload image or link </span>
)}

<div className="flex justify-end border-t-2 border-echeveria py-2">
<label className="inline-flex items-center">
<input
className="form-checkbox text-echeveria"
type="checkbox"
checked={createAnother}
onChange={(e) => setCreateAnother(e.target.checked)}
/>
<span className="mx-2">Create another</span>
</label>
<button
type="button"
disabled={conceptExists || saving || !concept}
className={`btn ${saving ? "cursor-wait" : ""}`}
onClick={onSubmit}
>
Create
</button>
<button type="button" className="btn cancel" onClick={close}>
Cancel
</button>
</div>
</form>
</ReactModal>
<span className="mx-2">Create another</span>
</label>
<button
type="button"
disabled={conceptExists || saving || !concept}
className={`btn ${saving ? "cursor-wait" : ""}`}
onClick={onSubmit}
>
Create
</button>
<button type="button" className="btn cancel" onClick={close}>
Cancel
</button>
</div>
</form>
</div>
</Dialog>
);
}

Expand Down
26 changes: 23 additions & 3 deletions components/Header.jsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,34 @@
import { useState } from 'react'
import { Formik } from 'formik';
import { Search as SearchIcon } from './icons';
import { IconInput } from './inputs';
import { Logo } from './logo';
import Avatar from './Avatar';
import Dropdown from '../components/Dropdown';
import NewNote from '../components/modals/NewNote';
import { Dialog } from '@headlessui/react';

function classNames(...classes) {
return classes.filter(Boolean).join(' ')
}


function NewNoteModal({ isOpen, setIsOpen }) {
return (
<Dialog open={isOpen} onClose={() => setIsOpen(false)}
className="fixed z-10 inset-0 overflow-y-auto"
>
<Dialog.Overlay className="fixed z-0 inset-0 bg-black opacity-30" />

<NewNote />

<button onClick={() => setIsOpen(false)}>Deactivate</button>
<button onClick={() => setIsOpen(false)}>Cancel</button>
</Dialog>)
}

export default function Header({ avatarImgSrc }) {
const [showNewNote, setShowNewNote] = useState(false)
return (
<nav className="bg-my-green rounded-b-2xl flex flex-row justify-between h-18 items-center">
<div className="flex flex-row items-center">
Expand All @@ -30,19 +49,20 @@ export default function Header({ avatarImgSrc }) {
</div>
<Dropdown.Item>
{({ active }) => (
<a
href="#"
<button
onClick={() => setShowNewNote(true)}
className={classNames(
active ? 'bg-gray-100 text-gray-900' : 'text-gray-700',
'block px-4 py-2 text-sm'
)}
>
Note
</a>
</button>
)}
</Dropdown.Item>
</Dropdown.Items>
</Dropdown>
<NewNoteModal isOpen={showNewNote} setIsOpen={setShowNewNote} />
<Avatar src={avatarImgSrc} className="mx-12" />
</div>
</nav>
Expand Down
4 changes: 2 additions & 2 deletions components/icons.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ export const Eyeslash = ({ className="" }) => (
</svg>
)

export const Close = ({ className="" }) => (
<svg className={`${className}`} fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
export const Close = ({ className="", ...props }) => (
<svg className={`${className}`} fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" {...props}>
<path fill="currentColor" fillRule="evenodd" clipRule="evenodd" d="m12 13.275 4.463 4.464a.908.908 0 0 0 1.276 0 .908.908 0 0 0 0-1.276L13.275 12l4.464-4.463a.908.908 0 0 0 0-1.276.908.908 0 0 0-1.276 0L12 10.725 7.537 6.26a.908.908 0 0 0-1.276 0 .908.908 0 0 0 0 1.276L10.725 12 6.26 16.463a.908.908 0 0 0 0 1.276.908.908 0 0 0 1.276 0L12 13.275z" />
</svg>
)
Expand Down
5 changes: 3 additions & 2 deletions components/modals/NewNote.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { PrivacyToggle } from '../toggles'
import { Close as CloseIcon } from '../icons'
import { Input } from '../inputs'

export default function NewNoteModal({isPublic=false}) {
export default function NewNoteModal({ isPublic = false, onClose }) {
const [pub, setPublic] = useState(isPublic)
return (
<div className="rounded-lg overflow-hidden bg-white flex flex-col items-stretch">
Expand All @@ -13,7 +13,8 @@ export default function NewNoteModal({isPublic=false}) {
<h2 className="text-white font-bold text-xl">New {pub ? 'Public' : 'Private'} Note</h2>
<PrivacyToggle enabled={pub} setEnabled={setPublic} />
</div>
<CloseIcon className="text-white h-6 w-6 flex-grow-0" />
<CloseIcon className="text-white h-6 w-6 flex-grow-0 cursor-pointer"
onClick={() => onClose && onClose()} />
</div>
<div className="divide-1 divide-gray-100">
<Formik>
Expand Down
56 changes: 55 additions & 1 deletion stories/NewNoteModal.stories.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import React, { Fragment, useState } from 'react';
import { Dialog, Transition } from '@headlessui/react'
import { ComponentStory, ComponentMeta } from '@storybook/react';

import NewNote from '../components/modals/NewNote';
Expand All @@ -23,3 +24,56 @@ PublicNewNoteModal.args = {
isPublic: true
};

export function ModalNewNoteModal() {
let [isOpen, setIsOpen] = useState(false)
console.log(isOpen)
return (
<>
<button className="btn" onClick={() => setIsOpen(!isOpen)}>
Show Modal
</button>
<Transition.Root show={isOpen} as={Fragment}>
<Dialog as="div" onClose={() => setIsOpen(false)}
className="fixed z-10 inset-0 overflow-y-auto"
>
<div className="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">

<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<Dialog.Overlay className="fixed inset-0 bg-black opacity-75 transition-opacity" />
</Transition.Child>

{/* This element is to trick the browser into centering the modal contents. */}
<span className="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">
&#8203;
</span>

<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
enterTo="opacity-100 translate-y-0 sm:scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
<div className="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-sm ">
<NewNote onClose={() => setIsOpen(false)} />
</div>
</Transition.Child>
</div>
</Dialog>
</Transition.Root>
</>
)
}
ModalNewNoteModal.args = {
label: 'NewNote/Modal'
}