From 886928b70a9ea34a11e2fda741adff501a2e870b Mon Sep 17 00:00:00 2001 From: nicosammito Date: Fri, 22 Dec 2023 12:46:57 +0100 Subject: [PATCH 01/13] init tooltip component --- src/components/tooltip/Tooltip.stories.tsx | 0 src/components/tooltip/Tooltip.style.scss | 0 src/components/tooltip/Tooltip.tsx | 0 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/components/tooltip/Tooltip.stories.tsx create mode 100644 src/components/tooltip/Tooltip.style.scss create mode 100644 src/components/tooltip/Tooltip.tsx diff --git a/src/components/tooltip/Tooltip.stories.tsx b/src/components/tooltip/Tooltip.stories.tsx new file mode 100644 index 00000000..e69de29b diff --git a/src/components/tooltip/Tooltip.style.scss b/src/components/tooltip/Tooltip.style.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/components/tooltip/Tooltip.tsx b/src/components/tooltip/Tooltip.tsx new file mode 100644 index 00000000..e69de29b From 7cb2a4c7f7926c33618ca9537e4a02d7f4157a1f Mon Sep 17 00:00:00 2001 From: nicosammito Date: Fri, 22 Dec 2023 13:43:18 +0100 Subject: [PATCH 02/13] implementation of tooltip --- src/components/tooltip/Tooltip.stories.tsx | 23 ++++ src/components/tooltip/Tooltip.style.scss | 107 ++++++++++++++++ src/components/tooltip/Tooltip.tsx | 136 +++++++++++++++++++++ 3 files changed, 266 insertions(+) diff --git a/src/components/tooltip/Tooltip.stories.tsx b/src/components/tooltip/Tooltip.stories.tsx index e69de29b..850bf787 100644 --- a/src/components/tooltip/Tooltip.stories.tsx +++ b/src/components/tooltip/Tooltip.stories.tsx @@ -0,0 +1,23 @@ +import {Meta} from "@storybook/react"; +import Tooltip from "./Tooltip"; +import Button from "../button/Button"; +import React from "react"; + +const meta: Meta = { + title: "Tooltip" +} + +export const TooltipExample = () => { + return + + + + + Test 2 + + +} + +export default meta \ No newline at end of file diff --git a/src/components/tooltip/Tooltip.style.scss b/src/components/tooltip/Tooltip.style.scss index e69de29b..214049c6 100644 --- a/src/components/tooltip/Tooltip.style.scss +++ b/src/components/tooltip/Tooltip.style.scss @@ -0,0 +1,107 @@ +@import "../../styles/helpers"; + +.tooltip { + + $color: $secondary; + + position: relative; + width: fit-content; + + &__trigger { + width: fit-content; + position: relative; + + > * { + margin: 0 !important; + } + } + + &__trigger:hover + &__menu { + display: block; + } + + &__menu { + @include box(false, $color); + + position: absolute; + display: none; + z-index: 99999; + padding: .5rem; + + &:hover { + display: block; + } + + &[data-position="left"] { + inset: 0 auto auto 0; + top: 50%; + transform: translateX(calc(-100% - .5rem)) translateY(-50%); + + &:before { + position: absolute; + content: ""; + top: 0; + right: -.5rem; + background: transparent; + width: .5rem; + height: 100%; + } + } + + &[data-position="right"] { + top: 50%; + right: 0; + transform: translateX(calc(100% + .5rem)) translateY(-50%); + + &:before { + position: absolute; + content: ""; + top: 0; + left: -.5rem; + background: transparent; + width: .5rem; + height: 100%; + } + } + + &[data-position="bottom"] { + top: calc(100% + .5em); + + &:before { + position: absolute; + content: ""; + top: -.5rem; + left: 0; + background: transparent; + width: 100%; + height: .5rem; + } + } + + &[data-position="top"] { + bottom: calc(100% + .5rem); + + &:before { + position: absolute; + content: ""; + bottom: -.5rem; + left: 0; + background: transparent; + width: 100%; + height: .5rem; + } + } + + &[data-align="start"] { + right: auto; + left: 0; + } + + &[data-align="end"] { + left: auto; + right: 0; + } + + } + +} \ No newline at end of file diff --git a/src/components/tooltip/Tooltip.tsx b/src/components/tooltip/Tooltip.tsx index e69de29b..c027efe5 100644 --- a/src/components/tooltip/Tooltip.tsx +++ b/src/components/tooltip/Tooltip.tsx @@ -0,0 +1,136 @@ +import React, {cloneElement, ReactElement, ReactNode} from "react"; +import {getChild, getPositionAroundTarget} from "../../utils/utils"; +import "./Tooltip.style.scss" + +export interface DropdownType { + children: ReactElement[], + //defaults to 'bottom' + position?: 'top' | 'bottom' | 'left' | 'right' + //defaults to 'start' + align?: 'start' | 'end' +} + +export interface TooltipTriggerType { + children: ReactNode +} + +export interface TooltipMenuType { + children: ReactNode +} + +const Tooltip: React.FC = (props) => { + + const {position, align, children, ...args} = props + const trigger = getChild(children, TooltipTrigger) + const menu = getChild(children, TooltipMenu) + + /** + * finds the head dropdown component because click target could be a + * child component and we cant work with this + */ + const getTooltipNodes = (target: HTMLElement): { + tooltip: HTMLElement, + trigger: HTMLElement, + menu: HTMLElement + } => { + let tooltip = (target as HTMLDivElement).parentNode as HTMLElement + while (!(tooltip.className.split(" ")[0] == "tooltip")) { + tooltip = tooltip.parentNode as HTMLElement + } + + return { + tooltip, + trigger: tooltip.querySelector(".tooltip__trigger") as HTMLElement, + menu: tooltip.querySelector(".tooltip__menu") as HTMLElement + } + } + + /** + * click listener that shows and removes the dropdown menu + */ + const triggerOnMouseOver = (event: React.MouseEvent) => { + + const {tooltip, trigger, menu} = getTooltipNodes(event.target as HTMLElement) + + //show dropdown menu + tooltip.classList.add("tooltip--active") + + const calculatePosition = () => { + const calculatedPosition = getPositionAroundTarget(trigger, menu, position) + menu.setAttribute("data-position", calculatedPosition) + } + + //calculate right position for the menu and set this as new attribute + calculatePosition() + + //outside clicks that disables the dropdown + + + //change position of menu when screen is resized + window.addEventListener("resize", function temp() { + calculatePosition() + if (!tooltip.classList.contains("tooltip--active")) + window.removeEventListener("resize", temp) + }) + + } + + const triggerOnMouseOut = (event: React.MouseEvent) => { + const {tooltip, trigger, menu} = getTooltipNodes(event.target as HTMLElement) + //show dropdown menu + tooltip.classList.remove("tooltip--active") + } + + return
+ {trigger} + + {/*calculate position based on props*/} + {!!menu ? React.cloneElement(menu as ReactElement, { + "data-position": position, + "data-align": align, + }) : null} +
+} + +/** + * Wrapper component for the trigger that activates or deactivates the + * {@link TooltipMenu} component + * + * @author Nico Sammito + * @since 0.1.0 + */ +const TooltipTrigger: React.FC = (props) => { + + const {children, ...args} = props + + return
+ {children} +
+} + +/** + * Component to create the menu that will open when the + * {@link TooltipTrigger} is clicked + * + * @author Nico Sammito + * @since 0.1.0 + */ +const TooltipMenu: React.FC = (props) => { + + const {children, ...args} = props + + //this stops the mousedown event from the window on the menu component + const preventClickable = (event: React.MouseEvent) => { + event.preventDefault() + event.stopPropagation() + } + + return
+ {children} +
+} + +export default Object.assign(Tooltip, { + Trigger: TooltipTrigger, + Menu: TooltipMenu +}) \ No newline at end of file From 5fc2f3b54da61ebdbf774ac7ad9bd007e500e455 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Sun, 24 Dec 2023 11:40:26 +0100 Subject: [PATCH 03/13] change logo to new one --- .storybook/theme.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.storybook/theme.js b/.storybook/theme.js index a3efeb1a..b3623f38 100644 --- a/.storybook/theme.js +++ b/.storybook/theme.js @@ -10,7 +10,7 @@ export default create({ brandTitle: 'Code0 Pictor', brandUrl: 'https://code0.tech', - brandImage: 'https://cdn.discordapp.com/attachments/1173726744130375791/1176472242469740604/Logo.png', + brandImage: 'https://cdn.discordapp.com/attachments/1187919509298888746/1187921987868299388/Logo.png', brandTarget: '_self', // UI From 45156a215056bc18ac1e344159d3fbc717242ad1 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Wed, 27 Dec 2023 18:03:34 +0100 Subject: [PATCH 04/13] switching to translate for Tooltips. Need to add alignment later --- src/components/button/Button.stories.tsx | 26 ++++++++++- src/components/tooltip/Tooltip.stories.tsx | 52 +++++++++++++++++----- src/components/tooltip/Tooltip.style.scss | 33 +++----------- src/components/tooltip/Tooltip.tsx | 20 ++++++++- src/utils/utils.ts | 34 +++++++++++--- 5 files changed, 121 insertions(+), 44 deletions(-) diff --git a/src/components/button/Button.stories.tsx b/src/components/button/Button.stories.tsx index cf016af5..7845d967 100644 --- a/src/components/button/Button.stories.tsx +++ b/src/components/button/Button.stories.tsx @@ -3,6 +3,7 @@ import {StoryObj} from "@storybook/react"; import React from "react"; import ButtonGroup from "../button-group/ButtonGroup"; import {IconAbc} from "@tabler/icons-react"; +import Tooltip from "../tooltip/Tooltip"; const meta = { title: "Button", @@ -20,7 +21,7 @@ const meta = { } } -type ButtonStory = StoryObj<{ icon: boolean, disabled: boolean}>; +type ButtonStory = StoryObj<{ icon: boolean, disabled: boolean }>; type ButtonGroupStory = StoryObj; export default meta @@ -88,4 +89,27 @@ export const ButtonGroups: ButtonGroupStory = { } +} + +export const ButtonImage = () => { + return + { + ["Pictor", "Sculptor", "Reticulum"].map(value => { + return + + + + + React Component Library + + + }) + } + } \ No newline at end of file diff --git a/src/components/tooltip/Tooltip.stories.tsx b/src/components/tooltip/Tooltip.stories.tsx index 850bf787..9f43cdba 100644 --- a/src/components/tooltip/Tooltip.stories.tsx +++ b/src/components/tooltip/Tooltip.stories.tsx @@ -8,16 +8,48 @@ const meta: Meta = { } export const TooltipExample = () => { - return - - - - - Test 2 - - + return <> + + + + + + Test 2 + + + + + + + + Test 2 + + + + + + + + Test 2 + + + + + + + + Test 2 + + + } export default meta \ No newline at end of file diff --git a/src/components/tooltip/Tooltip.style.scss b/src/components/tooltip/Tooltip.style.scss index 214049c6..c98921a2 100644 --- a/src/components/tooltip/Tooltip.style.scss +++ b/src/components/tooltip/Tooltip.style.scss @@ -3,8 +3,6 @@ .tooltip { $color: $secondary; - - position: relative; width: fit-content; &__trigger { @@ -23,7 +21,10 @@ &__menu { @include box(false, $color); - position: absolute; + position: fixed; + top: 0; + word-break: break-word; + left: 0; display: none; z-index: 99999; padding: .5rem; @@ -33,10 +34,6 @@ } &[data-position="left"] { - inset: 0 auto auto 0; - top: 50%; - transform: translateX(calc(-100% - .5rem)) translateY(-50%); - &:before { position: absolute; content: ""; @@ -49,10 +46,6 @@ } &[data-position="right"] { - top: 50%; - right: 0; - transform: translateX(calc(100% + .5rem)) translateY(-50%); - &:before { position: absolute; content: ""; @@ -65,8 +58,6 @@ } &[data-position="bottom"] { - top: calc(100% + .5em); - &:before { position: absolute; content: ""; @@ -79,29 +70,17 @@ } &[data-position="top"] { - bottom: calc(100% + .5rem); - &:before { position: absolute; content: ""; - bottom: -.5rem; + bottom: calc(-.5rem - 1px); left: 0; background: transparent; - width: 100%; + width: calc(100% + 2px); height: .5rem; } } - &[data-align="start"] { - right: auto; - left: 0; - } - - &[data-align="end"] { - left: auto; - right: 0; - } - } } \ No newline at end of file diff --git a/src/components/tooltip/Tooltip.tsx b/src/components/tooltip/Tooltip.tsx index c027efe5..75958676 100644 --- a/src/components/tooltip/Tooltip.tsx +++ b/src/components/tooltip/Tooltip.tsx @@ -57,7 +57,17 @@ const Tooltip: React.FC = (props) => { const calculatePosition = () => { const calculatedPosition = getPositionAroundTarget(trigger, menu, position) - menu.setAttribute("data-position", calculatedPosition) + menu.setAttribute("data-position", calculatedPosition.position) + + if (calculatedPosition.position == "top") { + menu.style.transform = `translate(${calculatedPosition.x}px,${calculatedPosition.y}px)` + } else if (calculatedPosition.position == "left") { + menu.style.transform = `translate(${calculatedPosition.x}px,${calculatedPosition.y}px)` + } else if (calculatedPosition.position == "bottom") { + menu.style.transform = `translate(${calculatedPosition.x}px,${calculatedPosition.y}px)` + } else { + menu.style.transform = `translate(${calculatedPosition.x}px,${calculatedPosition.y}px)` + } } //calculate right position for the menu and set this as new attribute @@ -81,11 +91,19 @@ const Tooltip: React.FC = (props) => { tooltip.classList.remove("tooltip--active") } + return
{trigger} {/*calculate position based on props*/} {!!menu ? React.cloneElement(menu as ReactElement, { + "style": { + //left-right top-bottom + "transform": position == "top" ? `translate(0px, 0px)` : + position == "right" ? `` : + position == "left" ? `` : + `` + }, "data-position": position, "data-align": align, }) : null} diff --git a/src/utils/utils.ts b/src/utils/utils.ts index cc63b5f0..b30b9d18 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -51,38 +51,62 @@ export const getPositionAroundTarget = (target: HTMLElement, element: HTMLElemen { name: "bottom", hierarchy: ["top", "left", "right"], + calculationY: (targetPos.y + targetPos.height + margin), + calculationX: (targetPos.x), conditionFit: ((targetPos.y + targetPos.height + margin + elementPos.height) <= windowSize.height) }, { name: "top", hierarchy: ["bottom", "left", "right"], + calculationY: (targetPos.y - margin - elementPos.height), + calculationX: (targetPos.x), conditionFit: ((targetPos.y - margin - elementPos.height) >= 0) }, { name: "left", hierarchy: ["right", "bottom", "top"], + calculationY: (targetPos.y - ((elementPos.height - targetPos.height) / 2)), + calculationX: (targetPos.x - margin - elementPos.width), conditionFit: ((targetPos.x - margin - elementPos.width) >= 0) }, { name: "right", hierarchy: ["left", "bottom", "top"], + calculationY: (targetPos.y - ((elementPos.height - targetPos.height) / 2)), + calculationX: (targetPos.x + margin + targetPos.width), conditionFit: ((targetPos.x + targetPos.width + margin + elementPos.width) <= windowSize.width) } ] const currentPositionObject = positionObject.find(value => value.name == position) - if (!currentPositionObject) return "bottom" - if (currentPositionObject.conditionFit) return position + if (!currentPositionObject) return { + position: "bottom", + y: positionObject[0].calculationY, + x: positionObject[0].calculationX + } + + if (currentPositionObject.conditionFit) return { + position, + y: currentPositionObject.calculationY, + x: currentPositionObject.calculationX + } for (let i = 0; i < currentPositionObject.hierarchy.length; i++) { const tempPositionObject = positionObject.find(value => value.name == currentPositionObject.hierarchy[i]) - if (tempPositionObject?.conditionFit) { - return tempPositionObject.name + if (tempPositionObject?.conditionFit) return { + position: tempPositionObject.name, + y: tempPositionObject.calculationY, + x: tempPositionObject.calculationX } + } - return "bottom" + return { + position: "bottom", + y: positionObject[0].calculationY, + x: positionObject[0].calculationX + } } \ No newline at end of file From 2d3d78d57a31ea72bf88ecc3e2409fcf6894d19d Mon Sep 17 00:00:00 2001 From: nicosammito Date: Wed, 27 Dec 2023 18:35:45 +0100 Subject: [PATCH 05/13] fixed dropdown position by using translate --- src/components/dropdown/Dropdown.style.scss | 25 ++++----------------- src/components/dropdown/Dropdown.tsx | 12 +++++++++- 2 files changed, 15 insertions(+), 22 deletions(-) diff --git a/src/components/dropdown/Dropdown.style.scss b/src/components/dropdown/Dropdown.style.scss index 8c2ae0f6..ed309987 100644 --- a/src/components/dropdown/Dropdown.style.scss +++ b/src/components/dropdown/Dropdown.style.scss @@ -77,35 +77,18 @@ &__menu { @include box(false, $color); - position: absolute; + position: fixed; + top: 0; + word-break: break-word; + left: 0; display: none; z-index: 99999; padding: .5rem; - width: 200px; &--active { display: block; } - &[data-position="left"] { - inset: 0 auto auto 0; - top: 50%; - transform: translateX(calc(-100% - .5rem)) translateY(-50%); - } - - &[data-position="right"] { - top: 50%; - right: 0; - transform: translateX(calc(100% + .5rem)) translateY(-50%); - } - - &[data-position="bottom"] { - top: calc(100% + 1rem); - } - - &[data-position="top"] { - bottom: calc(100% + .5rem); - } &[data-align="start"] { right: auto; diff --git a/src/components/dropdown/Dropdown.tsx b/src/components/dropdown/Dropdown.tsx index ec3e5c56..ef6253d5 100644 --- a/src/components/dropdown/Dropdown.tsx +++ b/src/components/dropdown/Dropdown.tsx @@ -70,7 +70,17 @@ const Dropdown: React.FC = (props) => { const calculatePosition = () => { const calculatedPosition = getPositionAroundTarget(trigger, menu, position) - menu.setAttribute("data-position", calculatedPosition) + menu.setAttribute("data-position", calculatedPosition.position) + + if (calculatedPosition.position == "top") { + menu.style.transform = `translate(${calculatedPosition.x}px,${calculatedPosition.y}px)` + } else if (calculatedPosition.position == "left") { + menu.style.transform = `translate(${calculatedPosition.x}px,${calculatedPosition.y}px)` + } else if (calculatedPosition.position == "bottom") { + menu.style.transform = `translate(${calculatedPosition.x}px,${calculatedPosition.y}px)` + } else { + menu.style.transform = `translate(${calculatedPosition.x}px,${calculatedPosition.y}px)` + } } //calculate right position for the menu and set this as new attribute From 90507c8492b92c640e3e7da98a70fa269da0aae3 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Thu, 28 Dec 2023 18:31:04 +0100 Subject: [PATCH 06/13] fixed pipline error --- src/components/button/Button.stories.tsx | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/src/components/button/Button.stories.tsx b/src/components/button/Button.stories.tsx index 7845d967..f97bfb23 100644 --- a/src/components/button/Button.stories.tsx +++ b/src/components/button/Button.stories.tsx @@ -89,27 +89,4 @@ export const ButtonGroups: ButtonGroupStory = { } -} - -export const ButtonImage = () => { - return - { - ["Pictor", "Sculptor", "Reticulum"].map(value => { - return - - - - - React Component Library - - - }) - } - } \ No newline at end of file From 90af7fe8cbc0339c71f97ae46287115baa33dc8e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 28 Dec 2023 17:35:06 +0000 Subject: [PATCH 07/13] Update image snapshots --- .../tooltip--tooltip-example-chromium.png | Bin 0 -> 1588 bytes .../tooltip--tooltip-example-firefox.png | Bin 0 -> 1920 bytes .../tooltip--tooltip-example-webkit.png | Bin 0 -> 1552 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 __snapshots__/tooltip--tooltip-example-chromium.png create mode 100644 __snapshots__/tooltip--tooltip-example-firefox.png create mode 100644 __snapshots__/tooltip--tooltip-example-webkit.png diff --git a/__snapshots__/tooltip--tooltip-example-chromium.png b/__snapshots__/tooltip--tooltip-example-chromium.png new file mode 100644 index 0000000000000000000000000000000000000000..4d1399562f7635358b09d768cae4008764b6f728 GIT binary patch literal 1588 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 VJ*JkKE&JjX++ATV4CnJ1e*s+5`6mDX literal 0 HcmV?d00001 From f222064379c06b98924ffcfb72c33f6b869a2f92 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Sun, 31 Dec 2023 01:42:09 +0100 Subject: [PATCH 08/13] adding maxWidthFactor prop --- src/components/dropdown/Dropdown.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/components/dropdown/Dropdown.tsx b/src/components/dropdown/Dropdown.tsx index ef6253d5..2bc09907 100644 --- a/src/components/dropdown/Dropdown.tsx +++ b/src/components/dropdown/Dropdown.tsx @@ -7,11 +7,13 @@ import {DropdownItem} from "./DropdownItem"; import {DropdownItemGroup} from "./DropdownItemGroup"; export interface DropdownType { - children: ReactElement[], + children: ReactElement[] //defaults to 'bottom' position?: 'top' | 'bottom' | 'left' | 'right' //defaults to 'start' align?: 'start' | 'end' + //defaults to 3 times the size of trigger + maxWidthFactor?: number } export interface DropdownTriggerType { @@ -24,7 +26,7 @@ export interface DropdownMenuType { const Dropdown: React.FC = (props) => { - const {position, align, children, ...args} = props + const {position = "bottom", align = "start", maxWidthFactor = 3, children, ...args} = props const trigger = getChild(children, DropdownTrigger) const menu = getChild(children, DropdownMenu) @@ -71,7 +73,7 @@ const Dropdown: React.FC = (props) => { const calculatePosition = () => { const calculatedPosition = getPositionAroundTarget(trigger, menu, position) menu.setAttribute("data-position", calculatedPosition.position) - + menu.style.maxWidth = `${trigger.offsetWidth * maxWidthFactor}px` if (calculatedPosition.position == "top") { menu.style.transform = `translate(${calculatedPosition.x}px,${calculatedPosition.y}px)` } else if (calculatedPosition.position == "left") { @@ -112,7 +114,6 @@ const Dropdown: React.FC = (props) => { "onClick": triggerOnClick })} - {/*calculate position based on props*/} {!!menu ? React.cloneElement(menu as ReactElement, { "data-position": position, "data-align": align, From 0d6ceadb788181bdc5232f0368fe3020f1db419d Mon Sep 17 00:00:00 2001 From: nicosammito Date: Sun, 31 Dec 2023 02:00:26 +0100 Subject: [PATCH 09/13] adding alignment to dropdown --- src/components/dropdown/Dropdown.stories.tsx | 2 +- src/components/dropdown/Dropdown.style.scss | 11 ---------- src/components/dropdown/Dropdown.tsx | 21 ++++++++++++-------- src/utils/utils.ts | 4 ++-- 4 files changed, 16 insertions(+), 22 deletions(-) diff --git a/src/components/dropdown/Dropdown.stories.tsx b/src/components/dropdown/Dropdown.stories.tsx index 517dfcbc..f5e01d0e 100644 --- a/src/components/dropdown/Dropdown.stories.tsx +++ b/src/components/dropdown/Dropdown.stories.tsx @@ -25,7 +25,7 @@ export const Dropdowns = () => { - + diff --git a/src/components/dropdown/Dropdown.style.scss b/src/components/dropdown/Dropdown.style.scss index ed309987..670b15aa 100644 --- a/src/components/dropdown/Dropdown.style.scss +++ b/src/components/dropdown/Dropdown.style.scss @@ -89,17 +89,6 @@ display: block; } - - &[data-align="start"] { - right: auto; - left: 0; - } - - &[data-align="end"] { - left: auto; - right: 0; - } - } } \ No newline at end of file diff --git a/src/components/dropdown/Dropdown.tsx b/src/components/dropdown/Dropdown.tsx index 2bc09907..4d948d59 100644 --- a/src/components/dropdown/Dropdown.tsx +++ b/src/components/dropdown/Dropdown.tsx @@ -11,7 +11,7 @@ export interface DropdownType { //defaults to 'bottom' position?: 'top' | 'bottom' | 'left' | 'right' //defaults to 'start' - align?: 'start' | 'end' + align?: 'start' | 'center' | 'end' //defaults to 3 times the size of trigger maxWidthFactor?: number } @@ -74,14 +74,19 @@ const Dropdown: React.FC = (props) => { const calculatedPosition = getPositionAroundTarget(trigger, menu, position) menu.setAttribute("data-position", calculatedPosition.position) menu.style.maxWidth = `${trigger.offsetWidth * maxWidthFactor}px` - if (calculatedPosition.position == "top") { - menu.style.transform = `translate(${calculatedPosition.x}px,${calculatedPosition.y}px)` - } else if (calculatedPosition.position == "left") { - menu.style.transform = `translate(${calculatedPosition.x}px,${calculatedPosition.y}px)` - } else if (calculatedPosition.position == "bottom") { - menu.style.transform = `translate(${calculatedPosition.x}px,${calculatedPosition.y}px)` + if (calculatedPosition.position == "top" || calculatedPosition.position == "bottom") { + const alignmentX = align == "start" ? calculatedPosition.x : + align == "center" ? calculatedPosition.x - ((menu.offsetWidth - trigger.offsetWidth) / 2) : + calculatedPosition.x - (menu.offsetWidth - trigger.offsetWidth) + + menu.style.transform = `translate(${alignmentX}px,${calculatedPosition.y}px)` } else { - menu.style.transform = `translate(${calculatedPosition.x}px,${calculatedPosition.y}px)` + + const alignmentY = align == "start" ? calculatedPosition.y : + align == "center" ? calculatedPosition.y - ((menu.offsetHeight - trigger.offsetHeight) / 2) : + calculatedPosition.y - (menu.offsetHeight - trigger.offsetHeight) + + menu.style.transform = `translate(${calculatedPosition.x}px,${alignmentY}px)` } } diff --git a/src/utils/utils.ts b/src/utils/utils.ts index b30b9d18..37f5ac30 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -65,14 +65,14 @@ export const getPositionAroundTarget = (target: HTMLElement, element: HTMLElemen { name: "left", hierarchy: ["right", "bottom", "top"], - calculationY: (targetPos.y - ((elementPos.height - targetPos.height) / 2)), + calculationY: (targetPos.y), calculationX: (targetPos.x - margin - elementPos.width), conditionFit: ((targetPos.x - margin - elementPos.width) >= 0) }, { name: "right", hierarchy: ["left", "bottom", "top"], - calculationY: (targetPos.y - ((elementPos.height - targetPos.height) / 2)), + calculationY: (targetPos.y), calculationX: (targetPos.x + margin + targetPos.width), conditionFit: ((targetPos.x + targetPos.width + margin + elementPos.width) <= windowSize.width) } From 1121c2de2f86b4dbd4af44833d127e0c3b140fce Mon Sep 17 00:00:00 2001 From: nicosammito Date: Sun, 31 Dec 2023 02:04:10 +0100 Subject: [PATCH 10/13] adding box-shadow to appearing boxes --- src/components/dropdown/Dropdown.style.scss | 1 + src/components/tooltip/Tooltip.style.scss | 1 + 2 files changed, 2 insertions(+) diff --git a/src/components/dropdown/Dropdown.style.scss b/src/components/dropdown/Dropdown.style.scss index 670b15aa..73db8a27 100644 --- a/src/components/dropdown/Dropdown.style.scss +++ b/src/components/dropdown/Dropdown.style.scss @@ -76,6 +76,7 @@ &__menu { @include box(false, $color); + box-shadow: 0 0 2rem .5rem rgba($bodyBg, 1); position: fixed; top: 0; diff --git a/src/components/tooltip/Tooltip.style.scss b/src/components/tooltip/Tooltip.style.scss index c98921a2..0a1ca407 100644 --- a/src/components/tooltip/Tooltip.style.scss +++ b/src/components/tooltip/Tooltip.style.scss @@ -20,6 +20,7 @@ &__menu { @include box(false, $color); + box-shadow: 0 0 2rem .5rem rgba($bodyBg, 1); position: fixed; top: 0; From e132c17f96bacfc2557f355e96d344d756951a2e Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 2 Jan 2024 09:19:09 +0100 Subject: [PATCH 11/13] adding alignment for tooltip as well --- src/components/tooltip/Tooltip.tsx | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/components/tooltip/Tooltip.tsx b/src/components/tooltip/Tooltip.tsx index 75958676..00d3402b 100644 --- a/src/components/tooltip/Tooltip.tsx +++ b/src/components/tooltip/Tooltip.tsx @@ -7,7 +7,7 @@ export interface DropdownType { //defaults to 'bottom' position?: 'top' | 'bottom' | 'left' | 'right' //defaults to 'start' - align?: 'start' | 'end' + align?: 'start' | 'center' | 'end' } export interface TooltipTriggerType { @@ -20,7 +20,7 @@ export interface TooltipMenuType { const Tooltip: React.FC = (props) => { - const {position, align, children, ...args} = props + const {position = "bottom", align = "start", children, ...args} = props const trigger = getChild(children, TooltipTrigger) const menu = getChild(children, TooltipMenu) @@ -59,14 +59,19 @@ const Tooltip: React.FC = (props) => { const calculatedPosition = getPositionAroundTarget(trigger, menu, position) menu.setAttribute("data-position", calculatedPosition.position) - if (calculatedPosition.position == "top") { - menu.style.transform = `translate(${calculatedPosition.x}px,${calculatedPosition.y}px)` - } else if (calculatedPosition.position == "left") { - menu.style.transform = `translate(${calculatedPosition.x}px,${calculatedPosition.y}px)` - } else if (calculatedPosition.position == "bottom") { - menu.style.transform = `translate(${calculatedPosition.x}px,${calculatedPosition.y}px)` + if (calculatedPosition.position == "top" || calculatedPosition.position == "bottom") { + const alignmentX = align == "start" ? calculatedPosition.x : + align == "center" ? calculatedPosition.x - ((menu.offsetWidth - trigger.offsetWidth) / 2) : + calculatedPosition.x - (menu.offsetWidth - trigger.offsetWidth) + + menu.style.transform = `translate(${alignmentX}px,${calculatedPosition.y}px)` } else { - menu.style.transform = `translate(${calculatedPosition.x}px,${calculatedPosition.y}px)` + + const alignmentY = align == "start" ? calculatedPosition.y : + align == "center" ? calculatedPosition.y - ((menu.offsetHeight - trigger.offsetHeight) / 2) : + calculatedPosition.y - (menu.offsetHeight - trigger.offsetHeight) + + menu.style.transform = `translate(${calculatedPosition.x}px,${alignmentY}px)` } } From dedb2efdaf51cf33053a029626bda49766e5cf8a Mon Sep 17 00:00:00 2001 From: nicosammito Date: Thu, 4 Jan 2024 01:48:25 +0100 Subject: [PATCH 12/13] remove import --- src/components/button/Button.stories.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/button/Button.stories.tsx b/src/components/button/Button.stories.tsx index f97bfb23..47a5ec6e 100644 --- a/src/components/button/Button.stories.tsx +++ b/src/components/button/Button.stories.tsx @@ -3,7 +3,6 @@ import {StoryObj} from "@storybook/react"; import React from "react"; import ButtonGroup from "../button-group/ButtonGroup"; import {IconAbc} from "@tabler/icons-react"; -import Tooltip from "../tooltip/Tooltip"; const meta = { title: "Button", From 8bbff1901d1a65edf74233c8e33b4ad7976696dc Mon Sep 17 00:00:00 2001 From: nicosammito Date: Thu, 4 Jan 2024 01:49:10 +0100 Subject: [PATCH 13/13] remove comment --- src/components/tooltip/Tooltip.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/components/tooltip/Tooltip.tsx b/src/components/tooltip/Tooltip.tsx index 00d3402b..721ec3ec 100644 --- a/src/components/tooltip/Tooltip.tsx +++ b/src/components/tooltip/Tooltip.tsx @@ -78,9 +78,6 @@ const Tooltip: React.FC = (props) => { //calculate right position for the menu and set this as new attribute calculatePosition() - //outside clicks that disables the dropdown - - //change position of menu when screen is resized window.addEventListener("resize", function temp() { calculatePosition()