Skip to content

Commit 12874ac

Browse files
authored
Merge pull request #235 from qualcomm/olaf/gutters-arrows
fix: popup gutters and arrows
2 parents 2e08907 + 0066b9a commit 12874ac

12 files changed

Lines changed: 55 additions & 34 deletions

File tree

.changeset/better-falcons-stay.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
"@qualcomm-ui/dom": patch
3+
"@qualcomm-ui/qds-core": patch
4+
---
5+
6+
refactor(floating-ui): replace arrow rotation with clip-path diamond
7+
8+
commit: 7717aa9

.changeset/green-planets-argue.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
"@qualcomm-ui/core": minor
3+
"@qualcomm-ui/dom": minor
4+
"@qualcomm-ui/qds-core": minor
5+
---
6+
7+
feat(floating-ui): read gutter from CSS --gutter custom property
8+
9+
commit: 0db5e35

packages/common/core/src/combobox/combobox.machine.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,6 @@ const comboboxMachineBase = {
310310
selectionBehavior: props.multiple ? "clear" : "replace",
311311
...props,
312312
positioning: {
313-
gutter: 2,
314313
placement: "bottom-start",
315314
sameWidth: true,
316315
...props.positioning,

packages/common/core/src/select/select.machine.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,6 @@ export const selectMachine: MachineConfig<SelectSchema> =
626626
...props,
627627
collection: props.collection ?? emptyCollection(),
628628
positioning: {
629-
gutter: 2,
630629
placement: "bottom-start",
631630
sameWidth: true,
632631
...props.positioning,

packages/common/dom/src/floating-ui/get-placement.ts

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ import {
2121

2222
import {getWindow, raf} from "@qualcomm-ui/dom/query"
2323
import {noop, runIfFn} from "@qualcomm-ui/utils/functions"
24-
import {isNull} from "@qualcomm-ui/utils/guard"
2524
import {compact} from "@qualcomm-ui/utils/object"
2625

2726
import {getAnchorElement} from "./get-anchor"
2827
import {
28+
cssVars,
2929
rectMiddleware,
3030
shiftArrowMiddleware,
3131
transformOriginMiddleware,
@@ -43,7 +43,6 @@ const defaultOptions: PositioningOptions = {
4343
arrowSelector: "[data-part=arrow]",
4444
fitViewport: false,
4545
flip: true,
46-
gutter: 8,
4746
listeners: true,
4847
overflowPadding: 8,
4948
overlap: false,
@@ -63,7 +62,6 @@ interface Options extends RequiredBy<
6362
| "strategy"
6463
| "placement"
6564
| "listeners"
66-
| "gutter"
6765
| "flip"
6866
| "slide"
6967
| "overlap"
@@ -93,18 +91,25 @@ function getArrowMiddleware(arrowElement: HTMLElement | null, opts: Options) {
9391
})
9492
}
9593

96-
function getOffsetMiddleware(arrowElement: HTMLElement | null, opts: Options) {
97-
if (isNull(opts.offset ?? opts.gutter)) {
98-
return
94+
function getOffsetMiddleware(
95+
arrowElement: HTMLElement | null,
96+
opts: Options,
97+
contextEl?: Element | null,
98+
) {
99+
let cssGutter: number | undefined
100+
if (contextEl) {
101+
const parsed = parseFloat(
102+
getComputedStyle(contextEl).getPropertyValue(cssVars.gutter.variable),
103+
)
104+
if (!Number.isNaN(parsed)) {
105+
cssGutter = parsed
106+
}
99107
}
108+
100109
return offset(({placement}) => {
101110
const arrowOffset = (arrowElement?.clientHeight || 0) / 2
102-
103-
const gutter = opts.offset?.mainAxis ?? opts.gutter
104-
const mainAxis =
105-
typeof gutter === "number"
106-
? gutter + arrowOffset
107-
: (gutter ?? arrowOffset)
111+
const gutter = opts.offset?.mainAxis ?? opts.gutter ?? cssGutter ?? 2
112+
const mainAxis = gutter + arrowOffset
108113

109114
const {hasAlign} = getPlacementDetails(placement)
110115
const shift = !hasAlign ? opts.shift : undefined
@@ -206,7 +211,7 @@ function getPlacementImpl(
206211
const arrowEl = floating.querySelector<HTMLElement>(options.arrowSelector)
207212

208213
const middleware: (Middleware | undefined)[] = [
209-
getOffsetMiddleware(arrowEl, options),
214+
getOffsetMiddleware(arrowEl, options, reference.contextElement),
210215
getFlipMiddleware(options),
211216
getShiftMiddleware(options),
212217
getArrowMiddleware(arrowEl, options),

packages/common/dom/src/floating-ui/get-styles.ts

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,12 @@
77
import type {Placement} from "@floating-ui/dom"
88

99
import {cssVars} from "./middleware"
10-
import type {PlacementSide, PositioningOptions} from "./types"
10+
import type {PositioningOptions} from "./types"
1111

1212
export interface GetPlacementStylesOptions {
1313
placement?: Placement | undefined
1414
}
1515

16-
const ARROW_FLOATING_STYLE: Record<PlacementSide, string> = {
17-
bottom: "rotate(45deg)",
18-
left: "rotate(135deg)",
19-
right: "rotate(315deg)",
20-
top: "rotate(225deg)",
21-
} as const
22-
2316
interface ArrowPlacementStyle {
2417
[p: string]: string
2518
height: string
@@ -33,7 +26,6 @@ interface ArrowTipPlacementStyle {
3326
left: "0"
3427
position: "absolute"
3528
top: "0"
36-
transform: any
3729
width: "100%"
3830
zIndex: "inherit"
3931
}
@@ -83,9 +75,6 @@ export function getPlacementStyles(
8375
left: "0",
8476
position: "absolute",
8577
top: "0",
86-
transform: placement
87-
? ARROW_FLOATING_STYLE[placement.split("-")[0] as PlacementSide]
88-
: undefined,
8978
width: "100%",
9079
zIndex: "inherit",
9180
} as const,

packages/common/dom/src/floating-ui/middleware.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export const cssVars: Record<
4444
| "arrowHeight"
4545
| "arrowWidth"
4646
| "arrowSizeHalf"
47+
| "gutter"
4748
| "referenceWidth"
4849
| "transformOrigin",
4950
CssVar
@@ -54,6 +55,7 @@ export const cssVars: Record<
5455
arrowSize: toVar("--arrow-size"),
5556
arrowSizeHalf: toVar("--arrow-size-half"),
5657
arrowWidth: toVar("--arrow-width", "--arrow-size"),
58+
gutter: toVar("--gutter"),
5759
referenceWidth: toVar("--reference-width"),
5860
transformOrigin: toVar("--transform-origin"),
5961
} as const

packages/common/qds-core/src/header-bar/qds-header-bar.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
}
4646

4747
.qui-header-bar__nav {
48+
--gutter: 4;
4849
align-items: center;
4950
display: flex;
5051
gap: var(--spacing-110);

packages/common/qds-core/src/number-input/qds-number-input.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@
163163
}
164164

165165
.qui-number-input__unit-select {
166+
--gutter: 3;
166167
align-items: center;
167168
background: var(--color-background-neutral-01);
168169
border: none;

packages/common/qds-core/src/popover/qds-popover.css

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
.qui-popover__content {
22
--arrow-size: 10px;
3+
background: var(--color-surface-overlay);
34
border-radius: 4px;
45
box-shadow: var(--shadow-high);
6+
color: var(--color-text-neutral-primary);
57
display: flex;
68
flex-direction: column;
79
font: var(--font-static-body-xs-default);
@@ -12,8 +14,6 @@
1214
z-index: calc(var(--z-index-popover) + var(--layer-index));
1315

1416
--arrow-background: var(--color-surface-overlay);
15-
background: var(--color-surface-overlay);
16-
color: var(--color-text-neutral-primary);
1717

1818
&[data-emphasis="brand"] {
1919
--arrow-background: var(--color-background-brand-primary);
@@ -22,6 +22,10 @@
2222
}
2323
}
2424

25+
.qui-popover__arrow-tip {
26+
clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
27+
}
28+
2529
.qui-popover__label {
2630
color: inherit;
2731
font: var(--font-static-heading-xxs-bold);

0 commit comments

Comments
 (0)