From e791dc1b3ac08dca6147f20ee3570ef4cd817f83 Mon Sep 17 00:00:00 2001 From: Marco Bonomo Date: Tue, 28 May 2024 14:51:08 +0200 Subject: [PATCH 1/5] =?UTF-8?q?=F0=9F=94=A8=20refactor(highlight):=20remov?= =?UTF-8?q?e=20unnecessary=20padding=20in=20ActiveWord=20styled=20componen?= =?UTF-8?q?t=20=F0=9F=94=A8=20refactor(highlight):=20remove=20unused=20mar?= =?UTF-8?q?gin-left=20style=20in=20StyledWord=20component?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/stories/highlight/index.tsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/stories/highlight/index.tsx b/src/stories/highlight/index.tsx index 1acf6aa5..ce19df46 100644 --- a/src/stories/highlight/index.tsx +++ b/src/stories/highlight/index.tsx @@ -26,17 +26,12 @@ const StyledWord = styled(ZendeskSpan)< &:focus { outline: none; } - - + span:not([observation]) { - margin-left: 2px; - } `} `; const ActiveWord = styled.span` background-color: ${({ theme }) => getColor(theme.palette.fuschia, 400, undefined, 0.4)}; - padding: 0 2px; `; const WordsContainer = styled.div` From ce3b076172a78def7fc2212566fd6815a83a57d9 Mon Sep 17 00:00:00 2001 From: Marco Bonomo Date: Tue, 28 May 2024 15:47:45 +0200 Subject: [PATCH 2/5] =?UTF-8?q?=F0=9F=94=A8=20refactor(=5Ftypes.tsx):=20up?= =?UTF-8?q?date=20tooltipContent=20prop=20to=20accept=20array=20of=20obser?= =?UTF-8?q?vations=20=F0=9F=94=A8=20refactor(index.stories.tsx):=20add=20s?= =?UTF-8?q?tyled=20TagsWrapper=20component=20=F0=9F=94=A8=20refactor(index?= =?UTF-8?q?.stories.tsx):=20update=20tooltipContent=20to=20accept=20array?= =?UTF-8?q?=20of=20observations=20=F0=9F=94=A8=20refactor(index.tsx):=20up?= =?UTF-8?q?date=20StyledWord=20component=20to=20handle=20array=20of=20obse?= =?UTF-8?q?rvations=20=F0=9F=94=A8=20refactor(index.tsx):=20update=20Word?= =?UTF-8?q?=20component=20to=20handle=20array=20of=20observations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/stories/highlight/_types.tsx | 4 +-- src/stories/highlight/index.stories.tsx | 27 +++++++++++---- src/stories/highlight/index.tsx | 45 +++++++++---------------- 3 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/stories/highlight/_types.tsx b/src/stories/highlight/_types.tsx index 4b124240..56f04522 100644 --- a/src/stories/highlight/_types.tsx +++ b/src/stories/highlight/_types.tsx @@ -33,8 +33,6 @@ export interface WordProps extends ISpanProps { currentTime?: number; observations?: Observation[]; text: string; - /** Adjusts the font size. By default font size is medium */ size?: "xs" | "sm" | "md" | "lg" | "xl" | "xxl" | "xxxl"; - - tooltipContent?: (observation: Observation) => ReactNode; + tooltipContent?: (observations: Observation[]) => ReactNode; } diff --git a/src/stories/highlight/index.stories.tsx b/src/stories/highlight/index.stories.tsx index 4011be4f..9c645909 100644 --- a/src/stories/highlight/index.stories.tsx +++ b/src/stories/highlight/index.stories.tsx @@ -17,6 +17,15 @@ import { TDiarization } from "./demo-parts/transcript-diarization"; import { TParagraph } from "./demo-parts/transcript-paragraph"; import { Tag } from "../tags"; import { TSentiment } from "./demo-parts/transcript-sentiment"; +import { styled } from "styled-components"; + +const TagsWrapper = styled.div` + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + gap: ${({ theme }) => theme.space.xs}; +`; export interface StoryArgs extends HighlightArgs { words: Array; @@ -38,6 +47,7 @@ const Template: StoryFn = (args) => { const handleAddObservation = () => { if (selection) { console.log("🚀 ~ handleAddObservation ~ selection:", selection); + const hue = '#' + (Math.random() * 0xFFFFFF << 0).toString(16).padStart(6, '0'); setObservations([ ...observations, { @@ -45,7 +55,8 @@ const Template: StoryFn = (args) => { start: selection.from, end: selection.to, label: `new observation (#${observations.length})`, - hue: '#'+(Math.random() * 0xFFFFFF << 0).toString(16).padStart(6, '0') + hue, + color: "white" }, ]); } @@ -567,11 +578,15 @@ WithTooltip.args = { ...defaultArgs, words: defaultArgs.words.map((w) => ({ ...w, - tooltipContent: (obs: Observation) => ( - alert("Hey")}> - This is a tag of obs "{obs.label}" - - ), + tooltipContent: (obs: Observation[]) => ( + + {obs.map((o) => ( + alert(o.label)}> + This is a tag of obs "{o.label}" + + ))} + + ) })), }; diff --git a/src/stories/highlight/index.tsx b/src/stories/highlight/index.tsx index 1acf6aa5..777de172 100644 --- a/src/stories/highlight/index.tsx +++ b/src/stories/highlight/index.tsx @@ -7,29 +7,25 @@ import { HighlightContextProvider } from "./highlightContext"; import { Searchable } from "./searchable"; import { Tooltip } from "../tooltip"; -const StyledWord = styled(ZendeskSpan)< - WordProps & { observation?: Observation } +const StyledWord = styled(ZendeskSpan) < + WordProps & { observations?: Observation[] } >` font-size: ${({ theme, size }) => theme.fontSizes[size ?? "md"]}; padding: ${({ theme }) => theme.space.xxs} 0; - ${({ observation, theme }) => - observation && + ${({ observations, theme }) => + observations && observations.length > 0 && ` background-color: ${ - observation.hue ?? getColor(theme.palette.azure, 700, undefined, 0.5) + observations[observations.length - 1].hue ?? getColor(theme.palette.azure, 700, undefined, 0.5) }; - color: ${observation.color ?? "white"}; + color: ${observations[observations.length - 1].color ?? "white"}; box-sizing: border-box; font-weight: ${theme.fontWeights.semibold}; &:focus { outline: none; } - - + span:not([observation]) { - margin-left: 2px; - } `} `; @@ -44,7 +40,7 @@ const WordsContainer = styled.div` ${StyledWord}, span { &::selection { background-color: ${({ theme }) => - getColor(theme.palette.kale, 700, undefined, 0.5)}; + getColor(theme.palette.kale, 700, undefined, 0.5)}; } } `; @@ -131,27 +127,19 @@ const Word = (props: WordProps) => { props.currentTime < props.end; // Are there any observations containing this word? - const foundObservations = props.observations?.map((obs) => - props.start >= obs.start && props.end <= obs.end ? obs : null - ); - - // Get the closer observation to the word - const observation = foundObservations?.reduce((prev, current) => { - if (!prev) return current; - if (!current) return prev; - return current.end - current.start < prev.end - prev.start ? current : prev; - }, null); + const foundObservations = props.observations?.filter((obs) => + props.start >= obs.start && props.end <= obs.end + ) ?? []; - if (props.tooltipContent !== undefined && !!observation) { + if (props.tooltipContent !== undefined && foundObservations.length > 0) { return ( - + 0 ? "highlighted" : ""} + {...(foundObservations && { observations: foundObservations })} > {isActive ? ( @@ -170,9 +158,8 @@ const Word = (props: WordProps) => { {...props} data-start={props.start} data-end={props.end} - className={!!observation ? "highlighted" : ""} - {...(observation && { observation })} - {...(!!observation ? { tag: "observation" } : {})} + className={foundObservations.length > 0 ? "highlighted" : ""} + {...(foundObservations && { observations: foundObservations })} > {isActive ? ( From bfe4c8a67469af23245ae85dcb796532b163b1a6 Mon Sep 17 00:00:00 2001 From: Marco Bonomo Date: Tue, 28 May 2024 16:13:03 +0200 Subject: [PATCH 3/5] =?UTF-8?q?=F0=9F=8E=A8=20style(highlight):=20add=20st?= =?UTF-8?q?yled=20component=20for=20Tag=20in=20index.stories.tsx=20?= =?UTF-8?q?=F0=9F=94=A8=20refactor(highlight):=20refactor=20Word=20compone?= =?UTF-8?q?nt=20in=20index.tsx=20for=20better=20performance?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/stories/highlight/index.stories.tsx | 24 +++++++-- src/stories/highlight/index.tsx | 70 +++++++++++++------------ 2 files changed, 57 insertions(+), 37 deletions(-) diff --git a/src/stories/highlight/index.stories.tsx b/src/stories/highlight/index.stories.tsx index 9c645909..f68d10b1 100644 --- a/src/stories/highlight/index.stories.tsx +++ b/src/stories/highlight/index.stories.tsx @@ -19,6 +19,22 @@ import { Tag } from "../tags"; import { TSentiment } from "./demo-parts/transcript-sentiment"; import { styled } from "styled-components"; +const StyledTag = styled(Tag)` + user-select: none; + position: relative; + + &:before { + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: white; + z-index: -1; + } +`; + const TagsWrapper = styled.div` display: flex; justify-content: center; @@ -55,8 +71,8 @@ const Template: StoryFn = (args) => { start: selection.from, end: selection.to, label: `new observation (#${observations.length})`, - hue, - color: "white" + hue: getColor(hue, 700, undefined, 0.5), + color: hue, }, ]); } @@ -581,9 +597,9 @@ WithTooltip.args = { tooltipContent: (obs: Observation[]) => ( {obs.map((o) => ( - alert(o.label)}> + alert(o.label)}> This is a tag of obs "{o.label}" - + ))} ) diff --git a/src/stories/highlight/index.tsx b/src/stories/highlight/index.tsx index 777de172..8523f0e7 100644 --- a/src/stories/highlight/index.tsx +++ b/src/stories/highlight/index.tsx @@ -1,25 +1,25 @@ import { Span as ZendeskSpan } from "@zendeskgarden/react-typography"; -import { PropsWithChildren, useCallback, useEffect, useRef } from "react"; +import { PropsWithChildren, useCallback, useEffect, useMemo, useRef } from "react"; import styled from "styled-components"; import { getColor } from "../theme/utils"; import { HighlightArgs, Observation, WordProps } from "./_types"; import { HighlightContextProvider } from "./highlightContext"; import { Searchable } from "./searchable"; import { Tooltip } from "../tooltip"; +import { theme } from "../theme"; -const StyledWord = styled(ZendeskSpan) < +const StyledWord = styled.div< WordProps & { observations?: Observation[] } >` + display: inline; font-size: ${({ theme, size }) => theme.fontSizes[size ?? "md"]}; padding: ${({ theme }) => theme.space.xxs} 0; + position: relative; ${({ observations, theme }) => observations && observations.length > 0 && ` - background-color: ${ - observations[observations.length - 1].hue ?? getColor(theme.palette.azure, 700, undefined, 0.5) - }; - color: ${observations[observations.length - 1].color ?? "white"}; + color: ${observations[observations.length - 1].color ?? theme.palette.grey[600]}; box-sizing: border-box; font-weight: ${theme.fontWeights.semibold}; @@ -45,6 +45,18 @@ const WordsContainer = styled.div` } `; +const Layer = styled.div<{ + color: string; +}>` + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 0; + background-color: ${({ color }) => getColor(color, 700, undefined, 0.5)}; +`; + /** * Use Highlight to use highlight interation on any text element */ @@ -127,33 +139,12 @@ const Word = (props: WordProps) => { props.currentTime < props.end; // Are there any observations containing this word? - const foundObservations = props.observations?.filter((obs) => - props.start >= obs.start && props.end <= obs.end - ) ?? []; - - if (props.tooltipContent !== undefined && foundObservations.length > 0) { - return ( - - 0 ? "highlighted" : ""} - {...(foundObservations && { observations: foundObservations })} - > - {isActive ? ( - - - - ) : ( - - )}{" "} - - - ); - } + const foundObservations = useMemo(() => + props.observations?.filter((obs) => + props.start >= obs.start && props.end <= obs.end + ) ?? [], [props.observations, props.start, props.end]); - return ( + const ObsWord = useMemo(() => ( { className={foundObservations.length > 0 ? "highlighted" : ""} {...(foundObservations && { observations: foundObservations })} > + {foundObservations.length > 0 && foundObservations.map((obs) => ( + + ))} {isActive ? ( @@ -169,7 +163,17 @@ const Word = (props: WordProps) => { )}{" "} - ); + ), [props, foundObservations, isActive]); + + if (props.tooltipContent !== undefined && foundObservations.length > 0) { + return ( + + {ObsWord} + + ); + } + + return <>{ObsWord}; }; Highlight.Word = Word; From 4d09aa3ef6646bdbc5ac9eccd107bfb0cb4a81ac Mon Sep 17 00:00:00 2001 From: "Luca Cannarozzo (@cannarocks)" Date: Tue, 28 May 2024 16:39:33 +0200 Subject: [PATCH 4/5] refactor(highlight): handle null anchorNode and focusNode in extractText function --- src/stories/highlight/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/stories/highlight/index.tsx b/src/stories/highlight/index.tsx index 8523f0e7..6be26310 100644 --- a/src/stories/highlight/index.tsx +++ b/src/stories/highlight/index.tsx @@ -65,6 +65,7 @@ const Highlight = (props: PropsWithChildren) => { const ref = useRef(null); const extractText = (selection: Selection) => { + if(selection.anchorNode === null || selection.focusNode === null) return ""; var range = selection.getRangeAt(0); var tempDiv = document.createElement("div"); From 7a87f836dad04817bcfc5ac6e9faf7824dd7b0c7 Mon Sep 17 00:00:00 2001 From: Marco Bonomo Date: Tue, 28 May 2024 17:18:47 +0200 Subject: [PATCH 5/5] =?UTF-8?q?=F0=9F=94=A8=20refactor(highlight/index.tsx?= =?UTF-8?q?):=20update=20background=20color=20opacity=20in=20Layer=20compo?= =?UTF-8?q?nent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/stories/highlight/index.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/stories/highlight/index.tsx b/src/stories/highlight/index.tsx index 6be26310..d087f800 100644 --- a/src/stories/highlight/index.tsx +++ b/src/stories/highlight/index.tsx @@ -1,4 +1,3 @@ -import { Span as ZendeskSpan } from "@zendeskgarden/react-typography"; import { PropsWithChildren, useCallback, useEffect, useMemo, useRef } from "react"; import styled from "styled-components"; import { getColor } from "../theme/utils"; @@ -54,7 +53,7 @@ const Layer = styled.div<{ width: 100%; height: 100%; z-index: 0; - background-color: ${({ color }) => getColor(color, 700, undefined, 0.5)}; + background-color: ${({ color }) => getColor(color, undefined, undefined, 0.2)}; `; /**