From 8128d4432f8fce676b5b115c5831116761fd9ada Mon Sep 17 00:00:00 2001 From: portikM Date: Mon, 3 Jun 2024 17:01:00 -0400 Subject: [PATCH 01/38] feat(kpop): refactor using floating ui [KHCP-11957] --- package.json | 3 +- src/components/KPop/KPop.vue | 867 +++++++++++++++-------------------- src/types/pop.ts | 17 +- yarn.lock | 30 +- 4 files changed, 408 insertions(+), 509 deletions(-) diff --git a/package.json b/package.json index 7f68741493..241bee1d4e 100644 --- a/package.json +++ b/package.json @@ -53,13 +53,12 @@ "semantic-release": "semantic-release" }, "dependencies": { + "@floating-ui/dom": "^1.6.5", "@kong/icons": "^1.9.2", - "@popperjs/core": "^2.11.8", "date-fns": "^2.30.0", "date-fns-tz": "^2.0.1", "focus-trap": "^7.5.4", "focus-trap-vue": "^4.0.3", - "popper.js": "^1.16.1", "sortablejs": "^1.15.2", "swrv": "^1.0.4", "uuid": "^9.0.1", diff --git a/src/components/KPop/KPop.vue b/src/components/KPop/KPop.vue index e4f5595c97..0f3bd6a6b2 100644 --- a/src/components/KPop/KPop.vue +++ b/src/components/KPop/KPop.vue @@ -1,41 +1,42 @@ - @@ -438,6 +312,15 @@ $kPopCaretOffset: 16px; /* Component mixins */ +@mixin popoverInitialStyles { + // needs to be set for positioning to work smoothly + // https://floating-ui.com/docs/computePosition#initial-layout + left: 0; + position: fixed; + top: 0; + width: max-content; +} + @mixin kPopCaret { &:after, &:before { border: solid var(--kui-color-border-transparent, $kui-color-border-transparent); @@ -461,195 +344,203 @@ $kPopCaretOffset: 16px; /* Component styles */ -.k-popover, :deep(.k-popover) { - background-color: var(--kui-color-background, $kui-color-background); - border: var(--kui-border-width-10, $kui-border-width-10) solid var(--kui-color-border, $kui-color-border); - border-radius: var(--kui-border-radius-30, $kui-border-radius-30); - box-shadow: var(--kui-shadow, $kui-shadow); - display: flex; - flex-direction: column; - font-family: var(--kui-font-family-text, $kui-font-family-text); - gap: var(--kui-space-40, $kui-space-40); - max-width: none; - padding: var(--kui-space-60, $kui-space-60); - position: relative; - text-align: left; - white-space: normal; - z-index: v-bind('zIndex'); - - .popover-close-button { - @include defaultButtonReset; - - border-radius: var(--kui-border-radius-20, $kui-border-radius-20); - color: var(--kui-color-text-neutral, $kui-color-text-neutral); - margin: var(--kui-space-60, $kui-space-60) var(--kui-space-60, $kui-space-60) var(--kui-space-0, $kui-space-0) var(--kui-space-0, $kui-space-0); - outline: none; - position: absolute; - right: 0; - top: 0; +.k-popover { + .popover-trigger-wrapper { + display: inline-block; + } - &:hover, &:focus { - color: var(--kui-color-text-neutral-strong, $kui-color-text-neutral-strong) !important; - } + .popover { + @include popoverInitialStyles; - &:focus-visible { - box-shadow: var(--kui-shadow-focus, $kui-shadow-focus); - } + background-color: var(--kui-color-background, $kui-color-background); + border: var(--kui-border-width-10, $kui-border-width-10) solid var(--kui-color-border, $kui-color-border); + border-radius: var(--kui-border-radius-30, $kui-border-radius-30); + box-shadow: var(--kui-shadow, $kui-shadow); + display: flex; + flex-direction: column; + font-family: var(--kui-font-family-text, $kui-font-family-text); + gap: var(--kui-space-40, $kui-space-40); + max-width: none; + padding: var(--kui-space-60, $kui-space-60); + position: relative; + text-align: left; + white-space: normal; + z-index: v-bind('zIndex'); + + .popover-close-button { + @include defaultButtonReset; + + border-radius: var(--kui-border-radius-20, $kui-border-radius-20); + color: var(--kui-color-text-neutral, $kui-color-text-neutral); + margin: var(--kui-space-60, $kui-space-60) var(--kui-space-60, $kui-space-60) var(--kui-space-0, $kui-space-0) var(--kui-space-0, $kui-space-0); + outline: none; + position: absolute; + right: 0; + top: 0; + + &:hover, &:focus { + color: var(--kui-color-text-neutral-strong, $kui-color-text-neutral-strong) !important; + } + + &:focus-visible { + box-shadow: var(--kui-shadow-focus, $kui-shadow-focus); + } - .popover-close-icon { - pointer-events: none; + .popover-close-icon { + pointer-events: none; + } } - } - .popover-header { - align-items: baseline; - display: flex; + .popover-header { + align-items: baseline; + display: flex; - .popover-title { - color: var(--kui-color-text, $kui-color-text); - font-size: var(--kui-font-size-40, $kui-font-size-40); - font-weight: var(--kui-font-weight-bold, $kui-font-weight-bold); - line-height: var(--kui-line-height-30, $kui-line-height-30); + .popover-title { + color: var(--kui-color-text, $kui-color-text); + font-size: var(--kui-font-size-40, $kui-font-size-40); + font-weight: var(--kui-font-weight-bold, $kui-font-weight-bold); + line-height: var(--kui-line-height-30, $kui-line-height-30); - &.close-icon-spacing { - margin-right: var(--kui-space-60, $kui-space-60); + &.close-icon-spacing { + margin-right: var(--kui-space-60, $kui-space-60); + } } } - } - .popover-content { - color: var(--kui-color-text-neutral-stronger, $kui-color-text-neutral-stronger); - font-size: var(--kui-font-size-20, $kui-font-size-20); - font-weight: var(--kui-font-weight-regular, $kui-font-weight-regular); - line-height: var(--kui-line-height-20, $kui-line-height-20); + .popover-content { + color: var(--kui-color-text-neutral-stronger, $kui-color-text-neutral-stronger); + font-size: var(--kui-font-size-20, $kui-font-size-20); + font-weight: var(--kui-font-weight-regular, $kui-font-weight-regular); + line-height: var(--kui-line-height-20, $kui-line-height-20); - &.close-icon-spacing { - margin-right: var(--kui-space-60, $kui-space-60); + &.close-icon-spacing { + margin-right: var(--kui-space-60, $kui-space-60); + } } - } - .popover-footer { - align-items: center; - display: flex; - gap: var(--kui-space-40, $kui-space-40); - } + .popover-footer { + align-items: center; + display: flex; + gap: var(--kui-space-40, $kui-space-40); + } - // placement and caret styles + // placement and caret styles - &[x-placement^="bottom"] { - margin-top: var(--kui-space-50, $kui-space-50); + &[x-placement^="bottom"] { + margin-top: var(--kui-space-50, $kui-space-50); - @include kPopCaret; + @include kPopCaret; - &:after, &:before { - bottom: 100%; - left: 50%; - } + &:after, &:before { + bottom: 100%; + left: 50%; + } - &:after { - /* stylelint-disable-next-line @kong/design-tokens/use-proper-token */ - border-bottom-color: var(--kui-color-background, $kui-color-background); - } + &:after { + /* stylelint-disable-next-line @kong/design-tokens/use-proper-token */ + border-bottom-color: var(--kui-color-background, $kui-color-background); + } - &:before { - border-bottom-color: var(--kui-color-border, $kui-color-border); + &:before { + border-bottom-color: var(--kui-color-border, $kui-color-border); + } } - } - &[x-placement^="top"] { - margin-bottom: var(--kui-space-60, $kui-space-60); + &[x-placement^="top"] { + margin-bottom: var(--kui-space-60, $kui-space-60); - @include kPopCaret; + @include kPopCaret; - &:after, &:before { - left: 50%; - top: 100%; - } + &:after, &:before { + left: 50%; + top: 100%; + } - &:after { - /* stylelint-disable-next-line @kong/design-tokens/use-proper-token */ - border-top-color: var(--kui-color-background, $kui-color-background); - } + &:after { + /* stylelint-disable-next-line @kong/design-tokens/use-proper-token */ + border-top-color: var(--kui-color-background, $kui-color-background); + } - &:before { - border-top-color: var(--kui-color-border, $kui-color-border); + &:before { + border-top-color: var(--kui-color-border, $kui-color-border); + } } - } - &[x-placement^="left"] { - margin-right: var(--kui-space-60, $kui-space-60); + &[x-placement^="left"] { + margin-right: var(--kui-space-60, $kui-space-60); - @include kPopCaret; + @include kPopCaret; - &:after, &:before { - left: 100%; - top: 50%; - transform: translate(50%, -50%); - } + &:after, &:before { + left: 100%; + top: 50%; + transform: translate(50%, -50%); + } - &:after { - /* stylelint-disable-next-line @kong/design-tokens/use-proper-token */ - border-left-color: var(--kui-color-background, $kui-color-background); - } + &:after { + /* stylelint-disable-next-line @kong/design-tokens/use-proper-token */ + border-left-color: var(--kui-color-background, $kui-color-background); + } - &:before { - border-left-color: var(--kui-color-border, $kui-color-border); + &:before { + border-left-color: var(--kui-color-border, $kui-color-border); + } } - } - &[x-placement^="right"] { - margin-left: var(--kui-space-60, $kui-space-60); + &[x-placement^="right"] { + margin-left: var(--kui-space-60, $kui-space-60); - @include kPopCaret; + @include kPopCaret; - &:after, &:before { - right: 100%; - top: 50%; - transform: translateY(-50%); - } + &:after, &:before { + right: 100%; + top: 50%; + transform: translateY(-50%); + } - &:after { - /* stylelint-disable-next-line @kong/design-tokens/use-proper-token */ - border-right-color: var(--kui-color-background, $kui-color-background); - } + &:after { + /* stylelint-disable-next-line @kong/design-tokens/use-proper-token */ + border-right-color: var(--kui-color-background, $kui-color-background); + } - &:before { - border-right-color: var(--kui-color-border, $kui-color-border); + &:before { + border-right-color: var(--kui-color-border, $kui-color-border); + } } - } - &[x-placement^="top-start"], - &[x-placement^="bottom-start"] { - &:after, &:before { - left: $kPopCaretOffset; + &[x-placement^="top-start"], + &[x-placement^="bottom-start"] { + &:after, &:before { + left: $kPopCaretOffset; + } } - } - &[x-placement^="top-end"], - &[x-placement^="bottom-end"] { - &:after, &:before { - left: calc(100% - $kPopCaretOffset); + &[x-placement^="top-end"], + &[x-placement^="bottom-end"] { + &:after, &:before { + left: calc(100% - $kPopCaretOffset); + } } - } - &[x-placement^="right-start"], - &[x-placement^="left-start"] { - &:after, &:before { - top: $kPopCaretOffset; + &[x-placement^="right-start"], + &[x-placement^="left-start"] { + &:after, &:before { + top: $kPopCaretOffset; + } } - } - &[x-placement^="right-end"], - &[x-placement^="left-end"] { - &:after, &:before { - top: calc(100% - $kPopCaretOffset); + &[x-placement^="right-end"], + &[x-placement^="left-end"] { + &:after, &:before { + top: calc(100% - $kPopCaretOffset); + } } - } - &.hide-caret { - &:after, - &:before { - display: none; + &.hide-caret { + &:after, + &:before { + display: none; + } } } } diff --git a/src/types/pop.ts b/src/types/pop.ts index 2c63536f68..4afcb53c16 100644 --- a/src/types/pop.ts +++ b/src/types/pop.ts @@ -5,19 +5,18 @@ export const PopTriggerArray = ['click', 'hover'] as const export type PopTrigger = AnyElementOf export const PopPlacementsArray = [ - 'auto', 'top', - 'topStart', - 'topEnd', + 'top-start', + 'top-end', 'left', - 'leftStart', - 'leftEnd', + 'left-start', + 'left-end', 'right', - 'rightStart', - 'rightEnd', + 'right-start', + 'right-end', 'bottom', - 'bottomStart', - 'bottomEnd', + 'bottom-start', + 'bottom-end', ] as const export type PopPlacements = AnyElementOf diff --git a/yarn.lock b/yarn.lock index c07f09cab7..81135a2584 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1026,6 +1026,26 @@ resolved "https://registry.yarnpkg.com/@evilmartians/lefthook/-/lefthook-1.6.13.tgz#dd2c1f771acd7f5ff2249a3d85fe4b975d3b9b6a" integrity sha512-w89+h5IXkGzJQwxVycgDuVGAQkERKeB084lNdE/2Ree2e1TCFCWtXZxkrzuvFICcEXwDGiElvZbwRE/wnrqUKQ== +"@floating-ui/core@^1.0.0": + version "1.6.2" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.2.tgz#d37f3e0ac1f1c756c7de45db13303a266226851a" + integrity sha512-+2XpQV9LLZeanU4ZevzRnGFg2neDeKHgFLjP6YLW+tly0IvrhqT4u8enLGjLH3qeh85g19xY5rsAusfwTdn5lg== + dependencies: + "@floating-ui/utils" "^0.2.0" + +"@floating-ui/dom@^1.6.5": + version "1.6.5" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.5.tgz#323f065c003f1d3ecf0ff16d2c2c4d38979f4cb9" + integrity sha512-Nsdud2X65Dz+1RHjAIP0t8z5e2ff/IRbei6BqFrl1urT8sDVzM1HMQ+R0XcU5ceRfyO3I6ayeqIfh+6Wb8LGTw== + dependencies: + "@floating-ui/core" "^1.0.0" + "@floating-ui/utils" "^0.2.0" + +"@floating-ui/utils@^0.2.0": + version "0.2.2" + resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.2.tgz#d8bae93ac8b815b2bd7a98078cf91e2724ef11e5" + integrity sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw== + "@gar/promisify@^1.1.3": version "1.1.3" resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" @@ -1473,11 +1493,6 @@ resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.25.tgz#f077fdc0b5d0078d30893396ff4827a13f99e817" integrity sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ== -"@popperjs/core@^2.11.8": - version "2.11.8" - resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f" - integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A== - "@rollup/pluginutils@^5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.1.0.tgz#7e53eddc8c7f483a4ad0b94afb1f7f5fd3c771e0" @@ -7333,11 +7348,6 @@ plimit-lit@^1.2.6: dependencies: queue-lit "^1.5.0" -popper.js@^1.16.1: - version "1.16.1" - resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b" - integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ== - postcss-cli@^11.0.0: version "11.0.0" resolved "https://registry.yarnpkg.com/postcss-cli/-/postcss-cli-11.0.0.tgz#649f4b9af447501feb6cbca7f7505a132f90442b" From d73838523029236e80635f2e319addd21dccf4d0 Mon Sep 17 00:00:00 2001 From: portikM Date: Tue, 4 Jun 2024 11:09:23 -0400 Subject: [PATCH 02/38] fix(kpop): refactor using @floating-ui/vue [KHCP-11957] --- package.json | 3 +- src/components/KPop/KPop.vue | 258 ++++++++++++++++------------------- yarn.lock | 23 +++- 3 files changed, 139 insertions(+), 145 deletions(-) diff --git a/package.json b/package.json index 241bee1d4e..4eee8a6804 100644 --- a/package.json +++ b/package.json @@ -53,8 +53,9 @@ "semantic-release": "semantic-release" }, "dependencies": { - "@floating-ui/dom": "^1.6.5", + "@floating-ui/vue": "^1.0.6", "@kong/icons": "^1.9.2", + "@popperjs/core": "^2.11.8", "date-fns": "^2.30.0", "date-fns-tz": "^2.0.1", "focus-trap": "^7.5.4", diff --git a/src/components/KPop/KPop.vue b/src/components/KPop/KPop.vue index 0f3bd6a6b2..6247a144db 100644 --- a/src/components/KPop/KPop.vue +++ b/src/components/KPop/KPop.vue @@ -30,45 +30,47 @@ :style="popoverStyle" :x-placement="placement" > - -
+
+
- - {{ title }} - +
+ + {{ title }} + +
+
+
+ +
+ -
-
- -
-
@@ -78,14 +80,13 @@ \ No newline at end of file From 27ea6e4745258e04fb0d6d4196cb7f7c843e0958 Mon Sep 17 00:00:00 2001 From: portikM Date: Wed, 5 Jun 2024 14:49:56 -0400 Subject: [PATCH 21/38] fix(kpop): add comment [KHCP-11957] --- src/components/KPop/KPop.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/KPop/KPop.vue b/src/components/KPop/KPop.vue index feeb6fe4f6..aa198753da 100644 --- a/src/components/KPop/KPop.vue +++ b/src/components/KPop/KPop.vue @@ -265,6 +265,7 @@ onMounted(() => { } if (popoverTrigger.value && popoverElement.value) { + // start the auto updates for the popover position autoUpdate(popoverTrigger.value, popoverElement.value, updatePosition) } }) From c25487926b13fcaaae0591fd24ede73c71b3e16a Mon Sep 17 00:00:00 2001 From: portikM Date: Wed, 5 Jun 2024 16:31:01 -0400 Subject: [PATCH 22/38] fix(kpop): cleanup auto updates [KHCP-11957] --- src/components/KPop/KPop.vue | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/components/KPop/KPop.vue b/src/components/KPop/KPop.vue index aa198753da..6c527a0d82 100644 --- a/src/components/KPop/KPop.vue +++ b/src/components/KPop/KPop.vue @@ -239,6 +239,8 @@ const { floatingStyles, placement: calculatedPlacement, update: updatePosition } strategy: props.positionFixed ? 'fixed' : 'absolute', }) +const floatingUpdates = ref(null) + defineExpose({ hidePopover, }) @@ -266,7 +268,9 @@ onMounted(() => { if (popoverTrigger.value && popoverElement.value) { // start the auto updates for the popover position - autoUpdate(popoverTrigger.value, popoverElement.value, updatePosition) + // autoUpdate cleanup function + // docs: https://floating-ui.com/docs/autoUpdate#usage + floatingUpdates.value = autoUpdate(popoverTrigger.value, popoverElement.value, updatePosition) } }) @@ -288,6 +292,11 @@ onBeforeUnmount(() => { popoverElement.value.removeEventListener('focusout', hidePopover) } } + + if (floatingUpdates.value) { + // need to cleanup the auto updates + floatingUpdates.value() + } }) watch(isVisible, (val) => { From d9bd325243c8623c4b780e4bc22836fa7c1463df Mon Sep 17 00:00:00 2001 From: portikM Date: Wed, 5 Jun 2024 16:57:40 -0400 Subject: [PATCH 23/38] fix(kpop): popover flip and shift [KHCP-11957] --- sandbox/pages/SandboxDateTimePicker.vue | 2 +- src/components/KPop/KPop.vue | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sandbox/pages/SandboxDateTimePicker.vue b/sandbox/pages/SandboxDateTimePicker.vue index ace221584d..b4c0bf6290 100644 --- a/sandbox/pages/SandboxDateTimePicker.vue +++ b/sandbox/pages/SandboxDateTimePicker.vue @@ -139,7 +139,7 @@
diff --git a/src/components/KPop/KPop.vue b/src/components/KPop/KPop.vue index 6c527a0d82..4ef91e281f 100644 --- a/src/components/KPop/KPop.vue +++ b/src/components/KPop/KPop.vue @@ -82,7 +82,7 @@