Add multiple highlight colors
This commit is contained in:
@ -102,6 +102,8 @@ export function makeApolloServer(): ApolloServer {
|
||||
const apollo = new ApolloServer({
|
||||
schema: schema,
|
||||
context: contextFunc,
|
||||
cache: 'bounded',
|
||||
persistedQueries: false,
|
||||
formatError: (err) => {
|
||||
logger.info('server error', err)
|
||||
Sentry.captureException(err)
|
||||
|
||||
@ -246,6 +246,18 @@ export const Button = styled('button', {
|
||||
},
|
||||
'&:focus': { outline: 'none' },
|
||||
},
|
||||
highlightBarIcon: {
|
||||
p: '0px',
|
||||
lineHeight: '0px',
|
||||
bg: 'transparent',
|
||||
border: 'none',
|
||||
cursor: 'pointer',
|
||||
'&:hover': {
|
||||
opacity: 0.5,
|
||||
},
|
||||
|
||||
'&:focus': { outline: 'none' },
|
||||
},
|
||||
articleActionIcon: {
|
||||
bg: 'transparent',
|
||||
border: 'none',
|
||||
|
||||
@ -6,9 +6,20 @@ import { StyledText } from '../elements/StyledText'
|
||||
import { Button } from '../elements/Button'
|
||||
import { HStack, Box } from '../elements/LayoutPrimitives'
|
||||
import { PenWithColorIcon } from '../elements/images/PenWithColorIcon'
|
||||
import { Note, Tag, Trash, Copy } from 'phosphor-react'
|
||||
import {
|
||||
Note,
|
||||
Tag,
|
||||
Trash,
|
||||
Copy,
|
||||
Circle,
|
||||
CopySimple,
|
||||
CheckCircle,
|
||||
} from 'phosphor-react'
|
||||
import { TrashIcon } from '../elements/icons/TrashIcon'
|
||||
import { LabelIcon } from '../elements/icons/LabelIcon'
|
||||
import { NotebookIcon } from '../elements/icons/NotebookIcon'
|
||||
import { highlightColor, highlightColors } from '../../lib/themeUpdater'
|
||||
import { useState } from 'react'
|
||||
|
||||
type PageCoordinates = {
|
||||
pageX: number
|
||||
@ -24,27 +35,29 @@ export type HighlightAction =
|
||||
| 'unshare'
|
||||
| 'setHighlightLabels'
|
||||
| 'copy'
|
||||
| 'updateColor'
|
||||
|
||||
type HighlightBarProps = {
|
||||
anchorCoordinates: PageCoordinates
|
||||
isNewHighlight: boolean
|
||||
isSharedToFeed: boolean
|
||||
displayAtBottom: boolean
|
||||
handleButtonClick: (action: HighlightAction) => void
|
||||
highlightColor?: string
|
||||
handleButtonClick: (action: HighlightAction, param?: string) => void
|
||||
}
|
||||
|
||||
export function HighlightBar(props: HighlightBarProps): JSX.Element {
|
||||
return (
|
||||
<Box
|
||||
css={{
|
||||
width: '100%',
|
||||
maxWidth: props.isNewHighlight ? '330px' : '380px',
|
||||
height: '48px',
|
||||
// width: '295px',
|
||||
// height: '50px',
|
||||
position: props.displayAtBottom ? 'fixed' : 'absolute',
|
||||
background: '$grayBg',
|
||||
borderRadius: '4px',
|
||||
border: '1px solid $grayBorder',
|
||||
boxShadow: theme.shadows.cardBoxShadow.toString(),
|
||||
background: '$thBackground2',
|
||||
borderRadius: '5px',
|
||||
border: '1px solid $thHighlightBar',
|
||||
boxShadow: `0px 4px 4px 0px rgba(0, 0, 0, 0.15)`,
|
||||
|
||||
...(props.displayAtBottom && {
|
||||
bottom: 'calc(38px + env(safe-area-inset-bottom, 40px))',
|
||||
}),
|
||||
@ -65,113 +78,139 @@ export function HighlightBar(props: HighlightBarProps): JSX.Element {
|
||||
)
|
||||
}
|
||||
|
||||
type BarButtonProps = {
|
||||
title: string
|
||||
onClick: VoidFunction
|
||||
iconElement: JSX.Element
|
||||
text: string
|
||||
}
|
||||
|
||||
function BarButton({ text, title, iconElement, onClick }: BarButtonProps) {
|
||||
return (
|
||||
<Button
|
||||
style="plainIcon"
|
||||
title={title}
|
||||
onClick={onClick}
|
||||
css={{
|
||||
flexDirection: 'column',
|
||||
height: '100%',
|
||||
m: 0,
|
||||
p: 0,
|
||||
alignItems: 'baseline',
|
||||
}}
|
||||
>
|
||||
<HStack css={{ height: '100%', alignItems: 'center' }}>
|
||||
{iconElement}
|
||||
<StyledText
|
||||
style="body"
|
||||
css={{
|
||||
pl: '4px',
|
||||
m: '0px',
|
||||
color: '$readerFont',
|
||||
fontWeight: '400',
|
||||
fontSize: '16px',
|
||||
}}
|
||||
>
|
||||
{text}
|
||||
</StyledText>
|
||||
</HStack>
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
const Separator = styled('div', {
|
||||
width: '1px',
|
||||
height: '20px',
|
||||
mx: '5px',
|
||||
background: '$thHighlightBar',
|
||||
})
|
||||
|
||||
function BarContent(props: HighlightBarProps): JSX.Element {
|
||||
const Separator = styled('div', {
|
||||
width: '1px',
|
||||
maxWidth: '1px',
|
||||
height: '100%',
|
||||
background: '$grayBorder',
|
||||
})
|
||||
const [hovered, setHovered] = useState<string | undefined>(undefined)
|
||||
|
||||
return (
|
||||
<HStack
|
||||
distribution="evenly"
|
||||
distribution="start"
|
||||
alignment="center"
|
||||
css={{
|
||||
height: '100%',
|
||||
alignItems: 'center',
|
||||
display: 'flex',
|
||||
padding: '5px 10px',
|
||||
gap: '5px',
|
||||
width: props.displayAtBottom ? '100%' : 'auto',
|
||||
}}
|
||||
>
|
||||
{props.isNewHighlight ? (
|
||||
<BarButton
|
||||
text="Highlight"
|
||||
title="Create Highlight"
|
||||
iconElement={<PenWithColorIcon />}
|
||||
onClick={() => props.handleButtonClick('create')}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<BarButton
|
||||
text="Delete"
|
||||
title="Remove Highlight"
|
||||
iconElement={
|
||||
<TrashIcon
|
||||
size={20}
|
||||
color={theme.colors.omnivoreRed.toString()}
|
||||
{highlightColors.map((color) => {
|
||||
return (
|
||||
<Button
|
||||
key={`color-${color}`}
|
||||
style="highlightBarIcon"
|
||||
title={`Create Highlight (${color})`}
|
||||
onClick={() => {
|
||||
if (!props.isNewHighlight && props.highlightColor != color) {
|
||||
props.handleButtonClick('updateColor', color)
|
||||
} else if (
|
||||
!props.isNewHighlight &&
|
||||
props.highlightColor == color
|
||||
) {
|
||||
props.handleButtonClick('delete')
|
||||
} else {
|
||||
props.handleButtonClick('create', color)
|
||||
}
|
||||
}}
|
||||
onMouseEnter={() => {
|
||||
setHovered(color)
|
||||
}}
|
||||
onMouseLeave={() => {
|
||||
setHovered(undefined)
|
||||
}}
|
||||
>
|
||||
{props.isNewHighlight || props.highlightColor != color ? (
|
||||
<Circle
|
||||
key={color}
|
||||
width={25}
|
||||
height={25}
|
||||
color={highlightColor(color)}
|
||||
weight="fill"
|
||||
/>
|
||||
}
|
||||
onClick={() => props.handleButtonClick('delete')}
|
||||
/>
|
||||
<Separator />
|
||||
<BarButton
|
||||
text="Labels"
|
||||
title="Set Labels"
|
||||
iconElement={
|
||||
<LabelIcon size={20} color={theme.colors.readerFont.toString()} />
|
||||
}
|
||||
) : (
|
||||
<CheckCircle
|
||||
key={color}
|
||||
width={25}
|
||||
height={25}
|
||||
color={highlightColor(color)}
|
||||
weight="fill"
|
||||
/>
|
||||
)}
|
||||
</Button>
|
||||
)
|
||||
})}
|
||||
<Separator />
|
||||
{!props.isNewHighlight && (
|
||||
<>
|
||||
<Button
|
||||
title={`Set Labels`}
|
||||
style="highlightBarIcon"
|
||||
onClick={() => props.handleButtonClick('setHighlightLabels')}
|
||||
/>
|
||||
onMouseEnter={() => {
|
||||
setHovered('labels')
|
||||
}}
|
||||
onMouseLeave={() => {
|
||||
setHovered(undefined)
|
||||
}}
|
||||
>
|
||||
<LabelIcon
|
||||
size={25}
|
||||
color={
|
||||
hovered == 'labels'
|
||||
? theme.colors.thTextContrast.toString()
|
||||
: theme.colors.thHighlightBar.toString()
|
||||
}
|
||||
/>
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
<Separator />
|
||||
<BarButton
|
||||
text="Note"
|
||||
title="Add Note to Highlight"
|
||||
iconElement={
|
||||
<Note size={20} color={theme.colors.readerFont.toString()} />
|
||||
}
|
||||
|
||||
<Button
|
||||
title={props.isNewHighlight ? `Create Highlight w/note` : 'Add Note'}
|
||||
style="highlightBarIcon"
|
||||
onClick={() => props.handleButtonClick('comment')}
|
||||
/>
|
||||
<Separator />
|
||||
<BarButton
|
||||
text="Copy"
|
||||
title="Copy Text to Clipboard"
|
||||
iconElement={
|
||||
<Copy size={20} color={theme.colors.readerFont.toString()} />
|
||||
}
|
||||
onMouseEnter={() => {
|
||||
setHovered('note')
|
||||
}}
|
||||
onMouseLeave={() => {
|
||||
setHovered(undefined)
|
||||
}}
|
||||
>
|
||||
<NotebookIcon
|
||||
size={25}
|
||||
color={
|
||||
hovered == 'note'
|
||||
? theme.colors.thTextContrast.toString()
|
||||
: theme.colors.thHighlightBar.toString()
|
||||
}
|
||||
/>
|
||||
</Button>
|
||||
<Button
|
||||
title={`Copy`}
|
||||
style="highlightBarIcon"
|
||||
onClick={() => props.handleButtonClick('copy')}
|
||||
/>
|
||||
onMouseEnter={() => {
|
||||
setHovered('copy')
|
||||
}}
|
||||
onMouseLeave={() => {
|
||||
setHovered(undefined)
|
||||
}}
|
||||
>
|
||||
<CopySimple
|
||||
width={25}
|
||||
height={25}
|
||||
color={
|
||||
hovered == 'copy'
|
||||
? theme.colors.thTextContrast.toString()
|
||||
: theme.colors.thHighlightBar.toString()
|
||||
}
|
||||
/>
|
||||
</Button>
|
||||
</HStack>
|
||||
)
|
||||
}
|
||||
|
||||
@ -13,7 +13,11 @@ import { styled, theme } from '../tokens/stitches.config'
|
||||
import { HighlightViewNote } from './HighlightNotes'
|
||||
import ReactMarkdown from 'react-markdown'
|
||||
import remarkGfm from 'remark-gfm'
|
||||
import { isDarkTheme } from '../../lib/themeUpdater'
|
||||
import {
|
||||
highlightColor,
|
||||
highlightColorVar,
|
||||
isDarkTheme,
|
||||
} from '../../lib/themeUpdater'
|
||||
import { ReadableItem } from '../../lib/networking/queries/useGetLibraryItemsQuery'
|
||||
import { UserBasicData } from '../../lib/networking/queries/useGetViewerQuery'
|
||||
import {
|
||||
@ -70,7 +74,7 @@ export function HighlightView(props: HighlightViewProps): JSX.Element {
|
||||
const hover = useHover(context)
|
||||
|
||||
const { getReferenceProps, getFloatingProps } = useInteractions([hover])
|
||||
const highlightAlpha = isDark ? 0.5 : 0.35
|
||||
const highlightColor = highlightColorVar(props.highlight.color)
|
||||
|
||||
return (
|
||||
<VStack
|
||||
@ -111,9 +115,8 @@ export function HighlightView(props: HighlightViewProps): JSX.Element {
|
||||
css={{
|
||||
'> *': {
|
||||
display: 'inline',
|
||||
padding: '2px',
|
||||
backgroundColor: `rgba(var(--colors-highlightBackground), ${highlightAlpha})`,
|
||||
boxShadow: `3px 0 0 rgba(var(--colors-highlightBackground), ${highlightAlpha}), -3px 0 0 rgba(var(--colors-highlightBackground), ${highlightAlpha})`,
|
||||
padding: '3px',
|
||||
backgroundColor: `rgba(${highlightColor}, var(--colors-highlightBackgroundAlpha))`,
|
||||
boxDecorationBreak: 'clone',
|
||||
borderRadius: '2px',
|
||||
},
|
||||
|
||||
@ -30,6 +30,7 @@ import 'react-sliding-pane/dist/react-sliding-pane.css'
|
||||
import { NotebookContent } from './Notebook'
|
||||
import { NotebookHeader } from './NotebookHeader'
|
||||
import useGetWindowDimensions from '../../../lib/hooks/useGetWindowDimensions'
|
||||
import { ConfirmationModal } from '../../patterns/ConfirmationModal'
|
||||
|
||||
type HighlightsLayerProps = {
|
||||
viewer: UserBasicData
|
||||
@ -88,20 +89,26 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element {
|
||||
undefined
|
||||
)
|
||||
|
||||
const [
|
||||
confirmDeleteHighlightWithNoteId,
|
||||
setConfirmDeleteHighlightWithNoteId,
|
||||
] = useState<string | undefined>(undefined)
|
||||
|
||||
const windowDimensions = useGetWindowDimensions()
|
||||
|
||||
const createHighlightFromSelection = useCallback(
|
||||
async (
|
||||
selection: SelectionAttributes,
|
||||
note?: string
|
||||
options: { annotation?: string; color?: string } | undefined
|
||||
): Promise<Highlight | undefined> => {
|
||||
const result = await createHighlight(
|
||||
{
|
||||
selection: selection,
|
||||
articleId: props.articleId,
|
||||
existingHighlights: highlights,
|
||||
color: options?.color,
|
||||
highlightStartEndOffsets: highlightLocations,
|
||||
annotation: note,
|
||||
annotation: options?.annotation,
|
||||
highlightPositionPercent: selectionPercentPos(selection.selection),
|
||||
highlightPositionAnchorIndex: selectionAnchorIndex(
|
||||
selection.selection
|
||||
@ -190,8 +197,10 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element {
|
||||
setHighlights(highlights.filter(($0) => $0.id !== highlightId))
|
||||
setFocusedHighlight(undefined)
|
||||
document.dispatchEvent(new Event('highlightsUpdated'))
|
||||
showSuccessToast('Highlight removed')
|
||||
} else {
|
||||
console.error('Failed to delete highlight')
|
||||
showErrorToast('Error removing highlight')
|
||||
}
|
||||
},
|
||||
[focusedHighlight, highlights, highlightLocations, props.articleMutations]
|
||||
@ -271,14 +280,14 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element {
|
||||
}
|
||||
|
||||
const createHighlightCallback = useCallback(
|
||||
async (annotation?: string) => {
|
||||
async (options: { annotation?: string; color?: string } | undefined) => {
|
||||
if (!selectionData) {
|
||||
return
|
||||
}
|
||||
try {
|
||||
const result = await createHighlightFromSelection(
|
||||
selectionData,
|
||||
annotation
|
||||
options
|
||||
)
|
||||
if (!result) {
|
||||
showErrorToast('Error saving highlight', { position: 'bottom-right' })
|
||||
@ -436,13 +445,25 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element {
|
||||
}, [handleSingleClick, handleDoubleClick])
|
||||
|
||||
const handleAction = useCallback(
|
||||
async (action: HighlightAction) => {
|
||||
async (action: HighlightAction, param?: string) => {
|
||||
switch (action) {
|
||||
case 'delete':
|
||||
await removeHighlightCallback()
|
||||
if (focusedHighlight?.annotation == undefined) {
|
||||
await removeHighlightCallback()
|
||||
} else {
|
||||
setConfirmDeleteHighlightWithNoteId(focusedHighlight?.id)
|
||||
}
|
||||
break
|
||||
case 'create':
|
||||
await createHighlightCallback()
|
||||
await createHighlightCallback({
|
||||
color: param,
|
||||
})
|
||||
break
|
||||
case 'updateColor':
|
||||
if (focusedHighlight) {
|
||||
focusedHighlight.color = param
|
||||
await updateHighlightsCallback(focusedHighlight)
|
||||
}
|
||||
break
|
||||
case 'comment':
|
||||
if (props.highlightBarDisabled || focusedHighlight) {
|
||||
@ -517,6 +538,7 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element {
|
||||
removeHighlightCallback,
|
||||
selectionData,
|
||||
setSelectionData,
|
||||
confirmDeleteHighlightWithNoteId,
|
||||
]
|
||||
)
|
||||
|
||||
@ -751,6 +773,20 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element {
|
||||
onOpenChange={() => setLabelsTarget(undefined)}
|
||||
/>
|
||||
)}
|
||||
{confirmDeleteHighlightWithNoteId && (
|
||||
<ConfirmationModal
|
||||
message="Are you sure you want to delete this highlight? The note associated with it will also be deleted."
|
||||
onAccept={() => {
|
||||
;(async () => {
|
||||
await removeHighlightCallback(confirmDeleteHighlightWithNoteId)
|
||||
setConfirmDeleteHighlightWithNoteId(undefined)
|
||||
})()
|
||||
}}
|
||||
onOpenChange={() => {
|
||||
setConfirmDeleteHighlightWithNoteId(undefined)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{/* // Display the button bar if we are not in the native app and there // is
|
||||
a focused highlight or selection data */}
|
||||
{!props.highlightBarDisabled && (focusedHighlight || selectionData) && (
|
||||
@ -761,6 +797,7 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element {
|
||||
handleButtonClick={handleAction}
|
||||
isSharedToFeed={focusedHighlight?.sharedAt != undefined}
|
||||
displayAtBottom={isTouchScreenDevice()}
|
||||
highlightColor={focusedHighlight?.color ?? 'yellow'}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import type * as Stitches from '@stitches/react'
|
||||
import { createStitches, createTheme } from '@stitches/react'
|
||||
import { highlightColor } from '../../lib/themeUpdater'
|
||||
|
||||
export enum ThemeId {
|
||||
Light = 'Light',
|
||||
@ -198,6 +199,16 @@ export const { styled, css, theme, getCssText, globalCss, keyframes, config } =
|
||||
thProgressFg: '#FFD234',
|
||||
|
||||
thHighContrast: '#3D3D3D',
|
||||
thHighlightBar: '#D9D9D9',
|
||||
|
||||
highlightBackgroundGreen: '85, 198, 137',
|
||||
highlightBackgroundBlue: '106, 177, 255',
|
||||
highlightBackgroundOrange: '254, 181, 109',
|
||||
highlightBackgroundYellow: '255, 210, 52',
|
||||
highlightBackgroundRed: '251, 154, 154',
|
||||
|
||||
highlightBackgroundAlpha: '0.2',
|
||||
highlightUnderlineAlpha: '1',
|
||||
},
|
||||
},
|
||||
media: {
|
||||
@ -298,6 +309,10 @@ const darkThemeSpec = {
|
||||
thProgressFg: '#FFD234',
|
||||
|
||||
thHighContrast: '#D9D9D9',
|
||||
|
||||
thHighlightBar: '#6A6968',
|
||||
highlightUnderlineAlpha: '0.5',
|
||||
highlightBackgroundAlpha: '0.35',
|
||||
},
|
||||
shadows: {
|
||||
cardBoxShadow:
|
||||
|
||||
@ -17,6 +17,7 @@ type CreateHighlightInput = {
|
||||
selection: SelectionAttributes
|
||||
articleId: string
|
||||
annotation?: string
|
||||
color?: string
|
||||
existingHighlights: Highlight[]
|
||||
highlightStartEndOffsets: HighlightLocation[]
|
||||
highlightPositionPercent?: number
|
||||
@ -94,7 +95,8 @@ export async function createHighlight(
|
||||
const highlightAttributes = makeHighlightNodeAttributes(
|
||||
patch,
|
||||
id,
|
||||
annotations.length > 0
|
||||
annotations.length > 0,
|
||||
input.color
|
||||
)
|
||||
|
||||
const newHighlightAttributes = {
|
||||
@ -102,6 +104,7 @@ export async function createHighlight(
|
||||
shortId: nanoid(8),
|
||||
patch,
|
||||
|
||||
color: input.color,
|
||||
prefix: highlightAttributes.prefix,
|
||||
suffix: highlightAttributes.suffix,
|
||||
quote: htmlToMarkdown(container.innerHTML),
|
||||
|
||||
@ -68,9 +68,7 @@ function nodeAttributesFromHighlight(
|
||||
const id = highlight.id
|
||||
const withNote = !!highlight.annotation
|
||||
const tooltip = undefined
|
||||
const customColor = highlight.createdByMe
|
||||
? undefined
|
||||
: 'var(--colors-recommendedHighlightBackground)'
|
||||
const customColor = highlight.color
|
||||
|
||||
return makeHighlightNodeAttributes(patch, id, withNote, customColor, tooltip)
|
||||
}
|
||||
@ -142,15 +140,17 @@ export function makeHighlightNodeAttributes(
|
||||
}
|
||||
|
||||
const newHighlightSpan = document.createElement('span')
|
||||
newHighlightSpan.className = withNote
|
||||
? highlightWithNoteClassName
|
||||
: highlightClassname
|
||||
newHighlightSpan.className = highlightClassname
|
||||
|
||||
if (withNote) {
|
||||
newHighlightSpan.className = `${newHighlightSpan.className} ${highlightWithNoteClassName}`
|
||||
}
|
||||
|
||||
if (customColor) {
|
||||
newHighlightSpan.className = `${newHighlightSpan.className} highlight_${customColor}`
|
||||
}
|
||||
|
||||
newHighlightSpan.setAttribute(highlightIdAttribute, id)
|
||||
customColor &&
|
||||
newHighlightSpan.setAttribute(
|
||||
'style',
|
||||
`background-color: ${customColor} !important`
|
||||
)
|
||||
tooltip && newHighlightSpan.setAttribute('title', tooltip)
|
||||
newHighlightSpan.appendChild(newTextNode)
|
||||
lastElement = newHighlightSpan
|
||||
@ -162,7 +162,7 @@ export function makeHighlightNodeAttributes(
|
||||
if (withNote && lastElement) {
|
||||
lastElement.classList.add('last_element')
|
||||
|
||||
const svg = noteImage()
|
||||
const svg = noteImage(customColor)
|
||||
svg.setAttribute(highlightNoteIdAttribute, id)
|
||||
|
||||
const ctr = document.createElement('div')
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { highlightColor, highlightColorVar } from '../themeUpdater'
|
||||
|
||||
export type SelectionAttributes = {
|
||||
selection: Selection
|
||||
range: Range
|
||||
@ -25,7 +27,7 @@ export function getHighlightNoteButton(highlightId: string): Element[] {
|
||||
)
|
||||
}
|
||||
|
||||
export function noteImage(): SVGSVGElement {
|
||||
export function noteImage(color: string | undefined): SVGSVGElement {
|
||||
const svgURI = 'http://www.w3.org/2000/svg'
|
||||
const svg = document.createElementNS(svgURI, 'svg')
|
||||
svg.setAttribute('viewBox', '0 0 14 14')
|
||||
@ -38,7 +40,7 @@ export function noteImage(): SVGSVGElement {
|
||||
'd',
|
||||
'M1 5.66602C1 3.7804 1 2.83759 1.58579 2.2518C2.17157 1.66602 3.11438 1.66602 5 1.66602H9C10.8856 1.66602 11.8284 1.66602 12.4142 2.2518C13 2.83759 13 3.7804 13 5.66602V7.66601C13 9.55163 13 10.4944 12.4142 11.0802C11.8284 11.666 10.8856 11.666 9 11.666H4.63014C4.49742 11.666 4.43106 11.666 4.36715 11.6701C3.92582 11.6984 3.50632 11.8722 3.17425 12.1642C3.12616 12.2065 3.07924 12.2534 2.98539 12.3473V12.3473C2.75446 12.5782 2.639 12.6937 2.55914 12.7475C1.96522 13.1481 1.15512 12.8125 1.01838 12.1093C1 12.0148 1 11.8515 1 11.5249V5.66602Z'
|
||||
)
|
||||
path.setAttribute('stroke', 'rgba(255, 210, 52, 0.8)')
|
||||
path.setAttribute('stroke', `rgba(${highlightColorVar(color)}, 0.8)`)
|
||||
path.setAttribute('stroke-width', '1.8')
|
||||
path.setAttribute('stroke-linejoin', 'round')
|
||||
svg.appendChild(path)
|
||||
|
||||
@ -10,6 +10,7 @@ export const highlightFragment = gql`
|
||||
prefix
|
||||
suffix
|
||||
patch
|
||||
color
|
||||
annotation
|
||||
createdByMe
|
||||
createdAt
|
||||
@ -41,6 +42,7 @@ export type Highlight = {
|
||||
updatedAt: string
|
||||
sharedAt: string
|
||||
labels?: Label[]
|
||||
color?: string
|
||||
highlightPositionPercent?: number
|
||||
highlightPositionAnchorIndex?: number
|
||||
}
|
||||
|
||||
@ -15,6 +15,7 @@ export type CreateHighlightInput = {
|
||||
suffix?: string
|
||||
quote?: string
|
||||
html?: string
|
||||
color?: string
|
||||
annotation?: string
|
||||
|
||||
patch?: string
|
||||
|
||||
@ -40,6 +40,7 @@ export async function mergeHighlightMutation(
|
||||
prefix
|
||||
suffix
|
||||
patch
|
||||
color
|
||||
createdAt
|
||||
updatedAt
|
||||
annotation
|
||||
|
||||
@ -111,3 +111,37 @@ export function isDarkTheme(): boolean {
|
||||
currentTheme == 'Black'
|
||||
)
|
||||
}
|
||||
|
||||
export const highlightColors = ['yellow', 'red', 'green', 'blue']
|
||||
|
||||
export const highlightColor = (name: string | undefined) => {
|
||||
switch (name) {
|
||||
case 'green':
|
||||
return '#55C689'
|
||||
case 'blue':
|
||||
return '#6AB1FF'
|
||||
case 'yellow':
|
||||
return '#FFD234'
|
||||
case 'orange':
|
||||
return '#FEB56D'
|
||||
case 'red':
|
||||
return '#FB9A9A'
|
||||
}
|
||||
return '#FFD234'
|
||||
}
|
||||
|
||||
export const highlightColorVar = (name: string | undefined) => {
|
||||
switch (name) {
|
||||
case 'green':
|
||||
return 'var(--colors-highlightBackgroundGreen)'
|
||||
case 'blue':
|
||||
return 'var(--colors-highlightBackgroundBlue)'
|
||||
case 'yellow':
|
||||
return 'var(--colors-highlightBackgroundYellow)'
|
||||
case 'orange':
|
||||
return 'var(--colors-highlightBackgroundOrange)'
|
||||
case 'red':
|
||||
return 'var(--colors-highlightBackgroundRed)'
|
||||
}
|
||||
return 'var(--colors-highlightBackground)'
|
||||
}
|
||||
|
||||
@ -19,12 +19,29 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.highlight_with_note {
|
||||
color: var(--colors-highlightText);
|
||||
background-color: rgba(var(--colors-highlightBackground), 0.35);
|
||||
border-bottom: 2px rgb(var(--colors-highlightBackground)) solid;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
.highlight_green {
|
||||
background-color: rgba(var(--colors-highlightBackgroundGreen), var(--colors-highlightBackgroundAlpha));
|
||||
border-bottom: 2px rgba(var(--colors-highlightBackgroundGreen), var(--colors-highlightUnderlineAlpha)) solid;
|
||||
}
|
||||
|
||||
.highlight_red {
|
||||
background-color: rgba(var(--colors-highlightBackgroundRed), var(--colors-highlightBackgroundAlpha));
|
||||
border-bottom: 2px rgba(var(--colors-highlightBackgroundRed), var(--colors-highlightUnderlineAlpha)) solid;
|
||||
}
|
||||
|
||||
.highlight_blue {
|
||||
background-color: rgba(var(--colors-highlightBackgroundBlue), var(--colors-highlightBackgroundAlpha));
|
||||
border-bottom: 2px rgba(var(--colors-highlightBackgroundBlue), var(--colors-highlightUnderlineAlpha)) solid;
|
||||
}
|
||||
|
||||
.highlight_yellow {
|
||||
background-color: rgba(var(--colors-highlightBackgroundYellow), var(--colors-highlightBackgroundAlpha));
|
||||
border-bottom: 2px rgba(var(--colors-highlightBackgroundYellow), var(--colors-highlightUnderlineAlpha)) solid;
|
||||
}
|
||||
|
||||
.highlight_orange {
|
||||
background-color: rgba(var(--colors-highlightBackgroundOrange), var(--colors-highlightBackgroundAlpha));
|
||||
border-bottom: 2px rgba(var(--colors-highlightBackgroundOrange), var(--colors-highlightUnderlineAlpha)) solid;
|
||||
}
|
||||
|
||||
.article-inner-css {
|
||||
|
||||
Reference in New Issue
Block a user