Footnote fixpack (#208)

* Footnote hotfixies
This commit is contained in:
Ilya Y 2023-09-05 08:49:19 +03:00 committed by GitHub
parent 37a6547d57
commit 3db98ac6cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 69 additions and 22 deletions

View File

@ -562,11 +562,23 @@ a[data-toggle='tooltip'] {
max-width: 400px;
box-sizing: border-box;
background: var(--black-500);
.tooltipContent {
max-height: 300px;
overflow: auto;
& * {
color: var(--default-color-invert);
}
a {
text-decoration: underline;
}
p:last-child {
margin: 0;
}
}
&::after {
content: '';

View File

@ -138,7 +138,12 @@ export const FullArticle = (props: Props) => {
tooltipElements.forEach((element) => {
const tooltip = document.createElement('div')
tooltip.classList.add(styles.tooltip)
tooltip.innerHTML = element.dataset.originalTitle || element.dataset.value
const tooltipContent = document.createElement('div')
tooltipContent.classList.add(styles.tooltipContent)
tooltipContent.innerHTML = element.dataset.originalTitle || element.dataset.value
tooltip.appendChild(tooltipContent)
document.body.appendChild(tooltip)
if (element.tagName === 'a') {
element.setAttribute('href', 'javascript: void(0);')

View File

@ -1,4 +1,4 @@
import { createEffect, createSignal, Show } from 'solid-js'
import { createEffect, createSignal, onCleanup, Show } from 'solid-js'
import { createTiptapEditor, useEditorHTML } from 'solid-tiptap'
import uniqolor from 'uniqolor'
import * as Y from 'yjs'
@ -63,6 +63,7 @@ export const Editor = (props: Props) => {
const { user } = useSession()
const [isCommonMarkup, setIsCommonMarkup] = createSignal(false)
const [shouldShowTextBubbleMenu, setShouldShowTextBubbleMenu] = createSignal(false)
const docName = `shout-${props.shoutId}`
@ -185,7 +186,11 @@ export const Editor = (props: Props) => {
const { empty } = selection
const isEmptyTextBlock = doc.textBetween(from, to).length === 0 && isTextSelection(selection)
setIsCommonMarkup(e.isActive('figcaption'))
return view.hasFocus() && !empty && !isEmptyTextBlock && !e.isActive('image')
const result =
(view.hasFocus() && !empty && !isEmptyTextBlock && !e.isActive('image')) ||
e.isActive('footnote')
setShouldShowTextBubbleMenu(result)
return result
},
tippyOptions: {
sticky: true
@ -246,6 +251,10 @@ export const Editor = (props: Props) => {
}
})
onCleanup(() => {
editor().destroy()
})
return (
<>
<div class="row">
@ -256,6 +265,7 @@ export const Editor = (props: Props) => {
</div>
<TextBubbleMenu
shouldShow={shouldShowTextBubbleMenu()}
isCommonMarkup={isCommonMarkup()}
editor={editor()}
ref={(el) => (textBubbleMenuRef.current = el)}

View File

@ -263,6 +263,9 @@ footnote {
display: inline-flex;
position: relative;
cursor: pointer;
width: 0.8rem;
height: 1em;
&:before {
content: '';
position: absolute;

View File

@ -55,6 +55,11 @@
bottom: -1rem;
transition: 0.3s ease-in-out;
&.alwaysVisible {
opacity: unset;
bottom: unset;
}
.actions {
display: flex;
align-items: center;

View File

@ -52,9 +52,11 @@ type Props = {
submitByEnter?: boolean
submitByShiftEnter?: boolean
onlyBubbleControls?: boolean
controlsAlwaysVisible?: boolean
}
export const MAX_DESCRIPTION_LIMIT = 400
const SimplifiedEditor = (props: Props) => {
const { t } = useLocalize()
const [counter, setCounter] = createSignal<number>()
@ -217,6 +219,7 @@ const SimplifiedEditor = (props: Props) => {
})
onCleanup(() => {
editor().destroy()
window.removeEventListener('keydown', handleKeyDown)
})
@ -233,6 +236,7 @@ const SimplifiedEditor = (props: Props) => {
setCounter(editor().storage.characterCount.characters())
}
})
return (
<div
ref={(el) => (wrapperEditorElRef.current = el)}
@ -252,7 +256,7 @@ const SimplifiedEditor = (props: Props) => {
</Show>
<div ref={(el) => (editorElRef.current = el)} />
<Show when={!props.onlyBubbleControls}>
<div class={styles.controls}>
<div class={clsx(styles.controls, { [styles.alwaysVisible]: props.controlsAlwaysVisible })}>
<div class={styles.actions}>
<Popover content={t('Bold')}>
{(triggerRef: (el) => void) => (
@ -350,6 +354,7 @@ const SimplifiedEditor = (props: Props) => {
</Show>
<Show when={props.onlyBubbleControls}>
<TextBubbleMenu
shouldShow={true}
isCommonMarkup={true}
editor={editor()}
ref={(el) => (textBubbleMenuRef.current = el)}

View File

@ -1,6 +1,8 @@
.TextBubbleMenu {
background: var(--editor-bubble-menu-background);
box-shadow: 0 4px 10px rgba(#000, 0.25);
max-height: 300px;
overflow: auto;
&.growWidth {
min-width: 460px;

View File

@ -8,13 +8,12 @@ import { useLocalize } from '../../../context/localize'
import { Popover } from '../../_shared/Popover'
import { InsertLinkForm } from '../InsertLinkForm'
import SimplifiedEditor from '../SimplifiedEditor'
import { Button } from '../../_shared/Button'
import { showModal } from '../../../stores/ui'
type BubbleMenuProps = {
editor: Editor
isCommonMarkup: boolean
ref: (el: HTMLDivElement) => void
shouldShow: boolean
}
export const TextBubbleMenu = (props: BubbleMenuProps) => {
@ -32,6 +31,13 @@ export const TextBubbleMenu = (props: BubbleMenuProps) => {
const [footnoteEditorOpen, setFootnoteEditorOpen] = createSignal(false)
const [footNote, setFootNote] = createSignal<string>()
createEffect(() => {
if (!props.shouldShow) {
setFootNote()
setFootnoteEditorOpen(false)
}
})
const isBold = isActive('bold')
const isItalic = isActive('italic')
const isH1 = isActive('heading', { level: 2 })
@ -65,9 +71,15 @@ export const TextBubbleMenu = (props: BubbleMenuProps) => {
}
}
const currentFootnoteValue = createEditorTransaction(
const updateCurrentFootnoteValue = createEditorTransaction(
() => props.editor,
(ed) => (ed && ed.getAttributes('footnote').value) || ''
(ed) => {
if (!isFootnote()) {
return
}
const value = ed.getAttributes('footnote').value
setFootNote(value)
}
)
const handleAddFootnote = (footnote) => {
@ -81,7 +93,7 @@ export const TextBubbleMenu = (props: BubbleMenuProps) => {
}
const handleOpenFootnoteEditor = () => {
setFootNote(currentFootnoteValue())
updateCurrentFootnoteValue()
setFootnoteEditorOpen(true)
}
@ -100,13 +112,13 @@ export const TextBubbleMenu = (props: BubbleMenuProps) => {
<InsertLinkForm editor={props.editor} onClose={() => setLinkEditorOpen(false)} />
</Match>
<Match when={footnoteEditorOpen()}>
<Button size={'S'} onClick={() => showModal('uploadImage')} value={'img'} />
<SimplifiedEditor
controlsAlwaysVisible={true}
imageEnabled={true}
placeholder={t('Enter footnote text')}
onSubmit={(value) => handleAddFootnote(value)}
variant={'bordered'}
initialContent={currentFootnoteValue().value ?? null}
initialContent={footNote()}
onCancel={() => {
setFootnoteEditorOpen(false)
}}

View File

@ -26,11 +26,7 @@ export const Footnote = Node.create({
return {
value: {
default: null,
parseHTML: (element) => {
return {
value: element.dataset.value
}
},
parseHTML: (element) => element.dataset.value || null,
renderHTML: (attributes) => {
return {
'data-value': attributes.value
@ -59,11 +55,8 @@ export const Footnote = Node.create({
({ tr, state }) => {
const { selection } = state
const position = selection.$to.pos
console.log('!!! attributes:', attributes)
const node = this.type.create(attributes)
tr.insert(position, node)
tr.insertText('\u00A0', position + 1) // it's make selection visible
return true
},
updateFootnote: