Move Lexical styles to tailwind
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
parent
6b2109735d
commit
4ccfab3e5e
4 changed files with 91 additions and 419 deletions
|
@ -157,11 +157,15 @@ const FloatingLinkEditor = ({
|
|||
}, [isEditMode]);
|
||||
|
||||
return (
|
||||
<div ref={editorRef} className='link-editor'>
|
||||
<div className='link-input'>
|
||||
<div
|
||||
ref={editorRef}
|
||||
className='absolute top-0 left-0 z-10 w-full max-w-sm rounded-lg bg-white opacity-0 shadow-md transition-opacity will-change-transform'
|
||||
>
|
||||
<div className='relative my-2 mx-3 box-border block rounded-2xl border-0 bg-gray-100 py-2 px-3 text-sm text-gray-800 outline-0 dark:bg-gray-800 dark:text-gray-100'>
|
||||
{isEditMode ? (
|
||||
<>
|
||||
<input
|
||||
className='-my-2 -mx-3 w-full border-0 bg-transparent py-2 px-3 text-sm text-gray-900 outline-0'
|
||||
ref={inputRef}
|
||||
value={linkUrl}
|
||||
onChange={(event) => {
|
||||
|
@ -188,7 +192,7 @@ const FloatingLinkEditor = ({
|
|||
}}
|
||||
/>
|
||||
<div
|
||||
className='link-edit'
|
||||
className='absolute inset-y-0 right-0 flex w-9 cursor-pointer items-center justify-center'
|
||||
role='button'
|
||||
tabIndex={0}
|
||||
onMouseDown={(event) => event.preventDefault()}
|
||||
|
@ -201,11 +205,11 @@ const FloatingLinkEditor = ({
|
|||
</>
|
||||
) : (
|
||||
<>
|
||||
<a href={linkUrl} target='_blank' rel='noopener noreferrer'>
|
||||
<a className='mr-8 block overflow-hidden text-ellipsis whitespace-nowrap text-primary-600 no-underline hover:underline dark:text-accent-blue' href={linkUrl} target='_blank' rel='noopener noreferrer'>
|
||||
{linkUrl}
|
||||
</a>
|
||||
<div
|
||||
className='link-edit'
|
||||
className='absolute inset-y-0 right-0 flex w-9 cursor-pointer items-center justify-center'
|
||||
role='button'
|
||||
tabIndex={0}
|
||||
onMouseDown={(event) => event.preventDefault()}
|
||||
|
|
|
@ -80,6 +80,24 @@ const blockTypeToBlockName = {
|
|||
quote: 'Quote',
|
||||
};
|
||||
|
||||
interface IToolbarButton extends React.HTMLAttributes<HTMLButtonElement> {
|
||||
active?: boolean
|
||||
icon: string
|
||||
}
|
||||
|
||||
const ToolbarButton: React.FC<IToolbarButton> = ({ active, icon, ...props }) => (
|
||||
<button
|
||||
className={clsx(
|
||||
'flex cursor-pointer rounded-lg border-0 bg-none p-1 align-middle hover:bg-gray-100 disabled:cursor-not-allowed disabled:hover:bg-none hover:dark:bg-primary-700',
|
||||
{ 'bg-gray-100/30 dark:bg-gray-800/30': active },
|
||||
)}
|
||||
type='button'
|
||||
{...props}
|
||||
>
|
||||
<Icon className='h-5 w-5' src={icon} />
|
||||
</button>
|
||||
);
|
||||
|
||||
const BlockTypeDropdown = ({ editor, anchorElem, blockType, icon }: {
|
||||
editor: LexicalEditor
|
||||
anchorElem: HTMLElement
|
||||
|
@ -172,70 +190,56 @@ const BlockTypeDropdown = ({ editor, anchorElem, blockType, icon }: {
|
|||
<>
|
||||
<button
|
||||
onClick={() => setShowDropDown(!showDropDown)}
|
||||
className='popup-item spaced relative'
|
||||
className='relative flex cursor-pointer rounded-lg border-0 bg-none p-1 align-middle hover:bg-gray-100 disabled:cursor-not-allowed disabled:hover:bg-none hover:dark:bg-primary-700'
|
||||
aria-label=''
|
||||
type='button'
|
||||
>
|
||||
<Icon src={icon} />
|
||||
<Icon src={require('@tabler/icons/chevron-down.svg')} className='-bottom-2 h-4 w-4' />
|
||||
{showDropDown && (
|
||||
<div className='floating-text-format-popup' style={{ opacity: 1, top: 36 }}>
|
||||
<button
|
||||
<div
|
||||
className='absolute top-9 left-0 z-10 flex h-[38px] gap-0.5 rounded-lg bg-white p-1 shadow-lg transition-[opacity] dark:bg-gray-900'
|
||||
>
|
||||
<ToolbarButton
|
||||
onClick={formatParagraph}
|
||||
className={clsx('popup-item spaced', blockType === 'paragraph' && 'active')}
|
||||
type='button'
|
||||
>
|
||||
<Icon src={blockTypeToIcon.paragraph} />
|
||||
</button>
|
||||
<button
|
||||
active={blockType === 'paragraph'}
|
||||
icon={blockTypeToIcon.paragraph}
|
||||
/>
|
||||
<ToolbarButton
|
||||
onClick={() => formatHeading('h1')}
|
||||
className={clsx('popup-item spaced', blockType === 'h1' && 'active')}
|
||||
type='button'
|
||||
>
|
||||
<Icon src={blockTypeToIcon.h1} />
|
||||
</button>
|
||||
<button
|
||||
active={blockType === 'h1'}
|
||||
icon={blockTypeToIcon.h1}
|
||||
/>
|
||||
<ToolbarButton
|
||||
onClick={() => formatHeading('h2')}
|
||||
className={clsx('popup-item spaced', blockType === 'h2' && 'active')}
|
||||
type='button'
|
||||
>
|
||||
<Icon src={blockTypeToIcon.h2} />
|
||||
</button>
|
||||
<button
|
||||
active={blockType === 'h2'}
|
||||
icon={blockTypeToIcon.h2}
|
||||
/>
|
||||
<ToolbarButton
|
||||
onClick={() => formatHeading('h3')}
|
||||
className={clsx('popup-item spaced', blockType === 'h3' && 'active')}
|
||||
type='button'
|
||||
>
|
||||
<Icon src={blockTypeToIcon.h3} />
|
||||
</button>
|
||||
<button
|
||||
active={blockType === 'h3'}
|
||||
icon={blockTypeToIcon.h3}
|
||||
/>
|
||||
<ToolbarButton
|
||||
onClick={formatBulletList}
|
||||
className={clsx('popup-item spaced', blockType === 'bullet' && 'active')}
|
||||
type='button'
|
||||
>
|
||||
<Icon src={blockTypeToIcon.bullet} />
|
||||
</button>
|
||||
<button
|
||||
active={blockType === 'bullet'}
|
||||
icon={blockTypeToIcon.bullet}
|
||||
/>
|
||||
<ToolbarButton
|
||||
onClick={formatNumberedList}
|
||||
className={clsx('popup-item spaced', blockType === 'number' && 'active')}
|
||||
type='button'
|
||||
>
|
||||
<Icon src={blockTypeToIcon.number} />
|
||||
</button>
|
||||
<button
|
||||
active={blockType === 'number'}
|
||||
icon={blockTypeToIcon.number}
|
||||
/>
|
||||
<ToolbarButton
|
||||
onClick={formatQuote}
|
||||
className={clsx('popup-item spaced', blockType === 'quote' && 'active')}
|
||||
type='button'
|
||||
>
|
||||
<Icon src={blockTypeToIcon.quote} />
|
||||
</button>
|
||||
<button
|
||||
active={blockType === 'quote'}
|
||||
icon={blockTypeToIcon.quote}
|
||||
/>
|
||||
<ToolbarButton
|
||||
onClick={formatCode}
|
||||
className={clsx('popup-item spaced', blockType === 'code' && 'active')}
|
||||
type='button'
|
||||
>
|
||||
<Icon src={blockTypeToIcon.code} />
|
||||
</button>
|
||||
active={blockType === 'code'}
|
||||
icon={blockTypeToIcon.code}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</button>
|
||||
|
@ -344,7 +348,10 @@ const TextFormatFloatingToolbar = ({
|
|||
}, [editor, updateTextFormatFloatingToolbar]);
|
||||
|
||||
return (
|
||||
<div ref={popupCharStylesEditorRef} className='floating-text-format-popup'>
|
||||
<div
|
||||
ref={popupCharStylesEditorRef}
|
||||
className='absolute top-0 left-0 z-10 flex h-[38px] gap-0.5 rounded-lg bg-white p-1 opacity-0 shadow-lg transition-[opacity] dark:bg-gray-900'
|
||||
>
|
||||
{editor.isEditable() && (
|
||||
<>
|
||||
<BlockTypeDropdown
|
||||
|
@ -353,64 +360,52 @@ const TextFormatFloatingToolbar = ({
|
|||
blockType={blockType}
|
||||
icon={blockTypeToIcon[blockType]}
|
||||
/>
|
||||
<button
|
||||
<ToolbarButton
|
||||
onClick={() => {
|
||||
editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'bold');
|
||||
}}
|
||||
className={'popup-item spaced ' + (isBold ? 'active' : '')}
|
||||
active={isBold}
|
||||
aria-label='Format text as bold'
|
||||
type='button'
|
||||
>
|
||||
<Icon src={require('@tabler/icons/bold.svg')} />
|
||||
</button>
|
||||
<button
|
||||
icon={require('@tabler/icons/bold.svg')}
|
||||
/>
|
||||
<ToolbarButton
|
||||
onClick={() => {
|
||||
editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'italic');
|
||||
}}
|
||||
className={'popup-item spaced ' + (isItalic ? 'active' : '')}
|
||||
active={isItalic}
|
||||
aria-label='Format text as italics'
|
||||
type='button'
|
||||
>
|
||||
<Icon src={require('@tabler/icons/italic.svg')} />
|
||||
</button>
|
||||
<button
|
||||
icon={require('@tabler/icons/italic.svg')}
|
||||
/>
|
||||
<ToolbarButton
|
||||
onClick={() => {
|
||||
editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'underline');
|
||||
}}
|
||||
className={'popup-item spaced ' + (isUnderline ? 'active' : '')}
|
||||
active={isUnderline}
|
||||
aria-label='Format text to underlined'
|
||||
type='button'
|
||||
>
|
||||
<Icon src={require('@tabler/icons/underline.svg')} />
|
||||
</button>
|
||||
<button
|
||||
icon={require('@tabler/icons/underline.svg')}
|
||||
/>
|
||||
<ToolbarButton
|
||||
onClick={() => {
|
||||
editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'strikethrough');
|
||||
}}
|
||||
className={'popup-item spaced ' + (isStrikethrough ? 'active' : '')}
|
||||
active={isStrikethrough}
|
||||
aria-label='Format text with a strikethrough'
|
||||
type='button'
|
||||
>
|
||||
<Icon src={require('@tabler/icons/strikethrough.svg')} />
|
||||
</button>
|
||||
<button
|
||||
icon={require('@tabler/icons/strikethrough.svg')}
|
||||
/>
|
||||
<ToolbarButton
|
||||
onClick={() => {
|
||||
editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'code');
|
||||
}}
|
||||
className={'popup-item spaced ' + (isCode ? 'active' : '')}
|
||||
active={isCode}
|
||||
aria-label='Insert code block'
|
||||
type='button'
|
||||
>
|
||||
<Icon src={require('@tabler/icons/code.svg')} />
|
||||
</button>
|
||||
<button
|
||||
icon={require('@tabler/icons/code.svg')}
|
||||
/>
|
||||
<ToolbarButton
|
||||
onClick={insertLink}
|
||||
className={'popup-item spaced ' + (isLink ? 'active' : '')}
|
||||
active={isLink}
|
||||
aria-label='Insert link'
|
||||
type='button'
|
||||
>
|
||||
<Icon src={require('@tabler/icons/link.svg')} />
|
||||
</button>
|
||||
icon={require('@tabler/icons/link.svg')}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
@import 'components/crypto-donate';
|
||||
@import 'components/aliases';
|
||||
@import 'components/icon';
|
||||
@import 'components/lexical';
|
||||
@import 'forms';
|
||||
@import 'utilities';
|
||||
@import 'components/datepicker';
|
||||
|
|
|
@ -1,326 +0,0 @@
|
|||
.lexical {
|
||||
.floating-text-format-popup {
|
||||
@apply flex h-[38px] p-1 absolute top-0 left-0 bg-white dark:bg-gray-900 z-10 rounded-lg shadow-lg opacity-0 transition-[opacity];
|
||||
}
|
||||
|
||||
.floating-text-format-popup button.popup-item {
|
||||
border: 0;
|
||||
display: flex;
|
||||
background: none;
|
||||
border-radius: 10px;
|
||||
padding: 5px;
|
||||
cursor: pointer;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.floating-text-format-popup button.popup-item:disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.floating-text-format-popup button.popup-item.spaced {
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.floating-text-format-popup button.popup-item i.format {
|
||||
background-size: contain;
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
margin-top: 2px;
|
||||
vertical-align: -0.25em;
|
||||
display: flex;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.floating-text-format-popup button.popup-item:disabled i.format {
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
.floating-text-format-popup button.popup-item.active {
|
||||
background-color: rgba(223, 232, 250, 0.3);
|
||||
}
|
||||
|
||||
.floating-text-format-popup button.popup-item.active i {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.floating-text-format-popup button.popup-item svg {
|
||||
@apply h-5 w-5;
|
||||
}
|
||||
|
||||
.floating-text-format-popup .popup-item:not([disabled]) {
|
||||
@apply hover:bg-gray-100 hover:dark:bg-primary-700;
|
||||
}
|
||||
|
||||
.floating-text-format-popup select.popup-item {
|
||||
border: 0;
|
||||
display: flex;
|
||||
background: none;
|
||||
border-radius: 10px;
|
||||
padding: 8px;
|
||||
vertical-align: middle;
|
||||
width: 70px;
|
||||
font-size: 14px;
|
||||
color: #777;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.floating-text-format-popup select.code-language {
|
||||
text-transform: capitalize;
|
||||
width: 130px;
|
||||
}
|
||||
|
||||
.floating-text-format-popup .popup-item .text {
|
||||
display: flex;
|
||||
line-height: 20px;
|
||||
vertical-align: middle;
|
||||
font-size: 14px;
|
||||
color: #777;
|
||||
text-overflow: ellipsis;
|
||||
width: 70px;
|
||||
overflow: hidden;
|
||||
height: 20px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.floating-text-format-popup .popup-item .icon {
|
||||
display: flex;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
user-select: none;
|
||||
margin-right: 8px;
|
||||
line-height: 16px;
|
||||
background-size: contain;
|
||||
}
|
||||
|
||||
.floating-text-format-popup i.chevron-down {
|
||||
margin-top: 3px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
display: flex;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.floating-text-format-popup i.chevron-down.inside {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
display: flex;
|
||||
margin-left: -25px;
|
||||
margin-top: 11px;
|
||||
margin-right: 10px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.floating-text-format-popup .divider {
|
||||
width: 1px;
|
||||
background-color: #eee;
|
||||
margin: 0 4px;
|
||||
}
|
||||
|
||||
.link-editor {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 10;
|
||||
max-width: 400px;
|
||||
width: 100%;
|
||||
opacity: 0;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.3);
|
||||
border-radius: 8px;
|
||||
transition: opacity 0.5s;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.link-editor .button {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
display: inline-block;
|
||||
padding: 6px;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
margin: 0 2px;
|
||||
}
|
||||
|
||||
.link-editor .button.hovered {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
display: inline-block;
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.link-editor .button i,
|
||||
.actions i {
|
||||
background-size: contain;
|
||||
display: inline-block;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
vertical-align: -0.25em;
|
||||
}
|
||||
|
||||
.link-editor .button.active,
|
||||
.toolbar .button.active {
|
||||
background-color: rgb(223, 232, 250);
|
||||
}
|
||||
|
||||
.link-editor .link-input {
|
||||
display: block;
|
||||
width: calc(100% - 24px);
|
||||
box-sizing: border-box;
|
||||
margin: 8px 12px;
|
||||
padding: 8px 12px;
|
||||
border-radius: 15px;
|
||||
background-color: #eee;
|
||||
font-size: 15px;
|
||||
color: rgb(5, 5, 5);
|
||||
border: 0;
|
||||
outline: 0;
|
||||
position: relative;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.link-editor .link-input input {
|
||||
width: 100%;
|
||||
margin: -8px -12px;
|
||||
padding: 8px 12px;
|
||||
background: transparent;
|
||||
font-size: 15px;
|
||||
color: rgb(5, 5, 5);
|
||||
border: 0;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.link-editor div.link-edit {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 36px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.link-editor .link-input a {
|
||||
color: rgb(33, 111, 219);
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
margin-right: 30px;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.link-editor .link-input a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.link-editor .font-size-wrapper,
|
||||
.link-editor .font-family-wrapper {
|
||||
display: flex;
|
||||
margin: 0 4px;
|
||||
}
|
||||
|
||||
.link-editor select {
|
||||
padding: 6px;
|
||||
border: none;
|
||||
background-color: rgba(0, 0, 0, 0.075);
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.typeahead-popover {
|
||||
background: #fff;
|
||||
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.3);
|
||||
border-radius: 8px;
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
.typeahead-popover ul {
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
border-radius: 8px;
|
||||
max-height: 200px;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.typeahead-popover ul::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.typeahead-popover ul {
|
||||
-ms-overflow-style: none;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
.typeahead-popover ul li {
|
||||
margin: 0;
|
||||
min-width: 180px;
|
||||
font-size: 14px;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.typeahead-popover ul li.selected {
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
.typeahead-popover li {
|
||||
margin: 0 8px;
|
||||
padding: 8px;
|
||||
color: #050505;
|
||||
cursor: pointer;
|
||||
line-height: 16px;
|
||||
font-size: 15px;
|
||||
display: flex;
|
||||
align-content: center;
|
||||
flex-direction: row;
|
||||
flex-shrink: 0;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.typeahead-popover li.active {
|
||||
display: flex;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-size: contain;
|
||||
}
|
||||
|
||||
.typeahead-popover li:first-child {
|
||||
border-radius: 8px 8px 0 0;
|
||||
}
|
||||
|
||||
.typeahead-popover li:last-child {
|
||||
border-radius: 0 0 8px 8px;
|
||||
}
|
||||
|
||||
.typeahead-popover li:hover {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.typeahead-popover li .text {
|
||||
display: flex;
|
||||
line-height: 20px;
|
||||
flex-grow: 1;
|
||||
min-width: 150px;
|
||||
}
|
||||
|
||||
.typeahead-popover li .icon {
|
||||
display: flex;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
user-select: none;
|
||||
margin-right: 8px;
|
||||
line-height: 16px;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.mentions-menu {
|
||||
width: 250px;
|
||||
}
|
Loading…
Reference in a new issue