Skip to content

Commit

Permalink
refactor: 💡 layout logic
Browse files Browse the repository at this point in the history
  • Loading branch information
lrodrigues-newstore committed Aug 28, 2024
1 parent d87de52 commit 01da4be
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 44 deletions.
8 changes: 4 additions & 4 deletions src/dom/footnote.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
getAvailableHeight,
repositionPopover,
repositionTooltip,
getMaxHeight,
Expand Down Expand Up @@ -76,9 +75,10 @@ export function footnoteActions({

reposition: () => {
if (isMounted(popover)) {
content.style.maxHeight =
getAvailableHeight(popover, button, maxHeight) + 'px'
position = repositionPopover(popover, button, position)
const [next, height] = repositionPopover(popover, button, position)

position = next
content.style.maxHeight = Math.min(maxHeight, height) + 'px'

if (popover.offsetHeight < content.scrollHeight) {
addClass(popover, CLASS_SCROLLABLE)
Expand Down
62 changes: 22 additions & 40 deletions src/dom/layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,9 @@ import { addClass, removeClass } from './element'

export const CLASS_TOOLTIP = 'littlefoot__tooltip'

const CLASS_POSITION_PREFIX = 'is-'

export type Position = 'above' | 'below'

type Room = Readonly<{ [K in Position]: number }>

function getAvailableRoom(element: HTMLElement): Room {
const height = element.offsetHeight
const above = element.getBoundingClientRect().top + height / 2

return {
above,
below: window.innerHeight - above,
}
}

export function getLeftRelative(element: HTMLElement): number {
function getLeftRelative(element: HTMLElement): number {
const marginLeft = Number.parseFloat(getStyle(element, 'marginLeft'))
const width = element.offsetWidth - marginLeft
const left = element.getBoundingClientRect().left + width / 2
Expand All @@ -38,44 +24,40 @@ export function getLeftInPixels(
return -leftRelative * maxWidth + buttonMarginLeft + button.offsetWidth / 2
}

function popoverPosition(footnote: HTMLElement, room: Room): Position {
const marginSize = Number.parseInt(getStyle(footnote, 'marginTop'), 10)
const totalHeight = 2 * marginSize + footnote.offsetHeight
return room.below < totalHeight && room.below < room.above ? 'above' : 'below'
export function getMaxHeight(element: HTMLElement) {
return Math.round(pixels(getStyle(element, 'maxHeight'), element))
}

export function getAvailableHeight(
footnote: HTMLElement,
function getFootnotePosition(
button: HTMLElement,
maxHeight: number,
): number {
const room = getAvailableRoom(button)
const position = popoverPosition(footnote, room)
const marginSize = Number.parseInt(getStyle(footnote, 'marginTop'), 10)
return Math.min(maxHeight, room[position] - marginSize - 15)
}

export function getMaxHeight(element: HTMLElement) {
return Math.round(pixels(getStyle(element, 'maxHeight'), element))
popover: HTMLElement,
): [Position, number] {
const marginSize = Number.parseInt(getStyle(popover, 'marginTop'), 10)
const popoverHeight = 2 * marginSize + popover.offsetHeight
const roomAbove = button.getBoundingClientRect().top + button.offsetHeight / 2
const roomBelow = window.innerHeight - roomAbove

return roomBelow >= popoverHeight || roomBelow >= roomAbove
? ['below', roomBelow - marginSize - 15]
: ['above', roomAbove - marginSize - 15]
}

export function repositionPopover(
popover: HTMLElement,
button: HTMLElement,
previous: Position,
): Position {
const room = getAvailableRoom(button)
const position = popoverPosition(popover, room)
current: Position,
): [Position, number] {
const [next, room] = getFootnotePosition(button, popover)

if (previous !== position) {
removeClass(popover, CLASS_POSITION_PREFIX + previous)
addClass(popover, CLASS_POSITION_PREFIX + position)
if (current !== next) {
removeClass(popover, 'is-' + current)
addClass(popover, 'is-' + next)
const transformX = getLeftRelative(button) * 100 + '%'
const transformY = position === 'above' ? '100%' : '0'
const transformY = next === 'above' ? '100%' : '0'
popover.style.transformOrigin = transformX + ' ' + transformY
}

return position
return [next, room]
}

export function repositionTooltip(
Expand Down

0 comments on commit 01da4be

Please sign in to comment.