Skip to content

feat(WW-4125): bindable position + auto vertical/horizontal opening direction - #18

Open
kevinbarfleur wants to merge 2 commits into
mainfrom
WW-4125_dropdown-auto-direction
Open

feat(WW-4125): bindable position + auto vertical/horizontal opening direction#18
kevinbarfleur wants to merge 2 commits into
mainfrom
WW-4125_dropdown-auto-direction

Conversation

@kevinbarfleur

Copy link
Copy Markdown

No description provided.

Comment thread src/wwElement.vue
Comment on lines 95 to 176
@@ -104,6 +106,73 @@ export default {
width: box.width,
height: box.height,
};
computeResolvedPosition();
};

const computeResolvedPosition = () => {
const position = props.content.position;
const box = triggerBox.value;
if (!box || box.width === undefined) {
resolvedPosition.value = position;
return;
}

const frontWindow = wwLib.getFrontWindow();
const viewportHeight = frontWindow.innerHeight;
const viewportWidth = frontWindow.innerWidth;

const dropdownRect = dropdownElementRef?.value?.getBoundingClientRect();
const dropdownHeight = dropdownRect?.height || box.height;
const dropdownWidth = dropdownRect?.width || box.width;

const parseOffset = (value) => {
const parsed = parseFloat(value);
return Number.isFinite(parsed) ? parsed : 0;
};
const offsetY = parseOffset(props.content.offsetY);
const offsetX = parseOffset(props.content.offsetX);

if (
props.content.autoVertical &&
(position === "top" || position === "bottom")
) {
const spaceBelow = viewportHeight - box.bottom - offsetY;
const spaceAbove = box.top - offsetY;
const fitsBelow = spaceBelow >= dropdownHeight;
const fitsAbove = spaceAbove >= dropdownHeight;
if (!fitsBelow && (fitsAbove || spaceAbove > spaceBelow)) {
resolvedPosition.value = "top";
} else {
resolvedPosition.value = "bottom";
}
return;
}

if (
props.content.autoHorizontal &&
(position === "left" || position === "right")
) {
const spaceRight = viewportWidth - box.right - offsetX;
const spaceLeft = box.left - offsetX;
const fitsRight = spaceRight >= dropdownWidth;
const fitsLeft = spaceLeft >= dropdownWidth;
if (position === "right") {
if (!fitsRight && (fitsLeft || spaceLeft > spaceRight)) {
resolvedPosition.value = "left";
} else {
resolvedPosition.value = "right";
}
} else {
if (!fitsLeft && (fitsRight || spaceRight > spaceLeft)) {
resolvedPosition.value = "right";
} else {
resolvedPosition.value = "left";
}
}
return;
}

resolvedPosition.value = position;
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Est-ce qu’on devrait plutôt se baser sur les dimensions réellement rendues du dropdown ? Avec parseFloat, un offset comme 10% est interprété comme 10px et une variable CSS comme 0, ce qui peut choisir la mauvaise direction.

Comment thread src/wwElement.vue
Comment on lines +294 to +303
watch(
() => [
props.content.position,
props.content.autoVertical,
props.content.autoHorizontal,
],
() => {
computeResolvedPosition();
}
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Est-ce qu’on devrait aussi relancer le calcul quand offsetX, offsetY ou la taille du contenu changent ? Aujourd’hui, un offset bindé ou du contenu chargé après l’ouverture peut faire déborder le dropdown sans nouveau calcul.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants