@energysage/es-ds-components 5.1.0 → 5.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/app/components/es-logo.vue +50 -0
- package/app/components/es-mobile-nav-content.vue +308 -0
- package/app/components/es-mobile-nav-custom-item.vue +9 -0
- package/app/components/es-mobile-nav-link.vue +62 -0
- package/app/components/es-mobile-nav-trigger.vue +29 -0
- package/app/components/es-mobile-nav.vue +219 -0
- package/app/components/es-mobile-sub-nav.vue +243 -0
- package/app/components/es-nav-cta-card.vue +113 -0
- package/app/components/es-sticky-bar.vue +3 -1
- package/app/components/icon/arrow-clockwise.vue +13 -48
- package/app/components/icon/arrow-counter-clockwise.vue +13 -34
- package/app/components/icon/arrow-cycle.vue +13 -40
- package/app/components/icon/arrow-down.vue +16 -0
- package/app/components/icon/arrow-left.vue +13 -36
- package/app/components/icon/arrow-right.vue +13 -36
- package/app/components/icon/arrow-up.vue +13 -36
- package/app/components/icon/battery-charging-vertical.vue +16 -0
- package/app/components/icon/bell.vue +13 -39
- package/app/components/icon/block.vue +13 -43
- package/app/components/icon/bolt.vue +12 -34
- package/app/components/icon/calculator.vue +13 -34
- package/app/components/icon/calendar.vue +13 -43
- package/app/components/icon/cart.vue +13 -43
- package/app/components/icon/charging-station.vue +16 -0
- package/app/components/icon/chat-bubble.vue +13 -37
- package/app/components/icon/chat-dots.vue +13 -39
- package/app/components/icon/check.vue +13 -36
- package/app/components/icon/chevron-down.vue +13 -36
- package/app/components/icon/chevron-horizontal.vue +13 -36
- package/app/components/icon/chevron-left.vue +13 -36
- package/app/components/icon/chevron-right.vue +13 -36
- package/app/components/icon/chevron-up.vue +13 -36
- package/app/components/icon/circle-alert.vue +13 -43
- package/app/components/icon/circle-check.vue +13 -43
- package/app/components/icon/circle-chevron-down.vue +12 -43
- package/app/components/icon/circle-chevron-left.vue +13 -43
- package/app/components/icon/circle-chevron-right.vue +13 -43
- package/app/components/icon/circle-chevron-up.vue +13 -43
- package/app/components/icon/circle-minus.vue +13 -43
- package/app/components/icon/circle-plus.vue +13 -43
- package/app/components/icon/circle-x.vue +13 -43
- package/app/components/icon/circle.vue +13 -39
- package/app/components/icon/clock.vue +13 -43
- package/app/components/icon/copy.vue +13 -42
- package/app/components/icon/envelope.vue +13 -42
- package/app/components/icon/eye.vue +13 -38
- package/app/components/icon/flag.vue +13 -34
- package/app/components/icon/folder.vue +13 -38
- package/app/components/icon/gear.vue +12 -33
- package/app/components/icon/hamburger.vue +13 -35
- package/app/components/icon/heart.vue +13 -36
- package/app/components/icon/house-line.vue +16 -0
- package/app/components/icon/image.vue +13 -42
- package/app/components/icon/info.vue +13 -42
- package/app/components/icon/light-bulb.vue +13 -33
- package/app/components/icon/link-out.vue +13 -35
- package/app/components/icon/location.vue +13 -42
- package/app/components/icon/lock-off.vue +13 -42
- package/app/components/icon/lock-on.vue +13 -45
- package/app/components/icon/minus.vue +13 -35
- package/app/components/icon/money-bag.vue +12 -33
- package/app/components/icon/open-envelope.vue +13 -42
- package/app/components/icon/paper.vue +13 -42
- package/app/components/icon/pencil.vue +13 -42
- package/app/components/icon/person-add.vue +13 -38
- package/app/components/icon/person-check.vue +13 -38
- package/app/components/icon/person-cross.vue +13 -38
- package/app/components/icon/person.vue +13 -38
- package/app/components/icon/phone.vue +13 -38
- package/app/components/icon/play.vue +13 -38
- package/app/components/icon/plus.vue +13 -35
- package/app/components/icon/roof.vue +12 -33
- package/app/components/icon/search.vue +12 -39
- package/app/components/icon/settings-horizontal.vue +13 -54
- package/app/components/icon/settings-vertical.vue +13 -54
- package/app/components/icon/shield-with-check.vue +12 -34
- package/app/components/icon/shield.vue +13 -38
- package/app/components/icon/shopping-bag.vue +13 -36
- package/app/components/icon/solar.vue +12 -33
- package/app/components/icon/sound-down.vue +13 -42
- package/app/components/icon/sound-off.vue +13 -38
- package/app/components/icon/sound-on.vue +13 -38
- package/app/components/icon/sound-up.vue +13 -38
- package/app/components/icon/star-empty.vue +13 -35
- package/app/components/icon/star-full.vue +15 -33
- package/app/components/icon/star-half.vue +15 -52
- package/app/components/icon/thumbs-up.vue +13 -36
- package/app/components/icon/trash-can.vue +13 -38
- package/app/components/icon/tree.vue +12 -33
- package/app/components/icon/upload.vue +12 -37
- package/app/components/icon/verified.vue +13 -37
- package/app/components/icon/wifi.vue +13 -35
- package/app/components/icon/x.vue +13 -35
- package/app/composables/breakpoints.ts +75 -0
- package/nuxt.config.ts +1 -1
- package/package.json +3 -2
- package/app/components/icon/arrow.vue +0 -68
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [5.3.0](https://github.com/EnergySage/es-ds/compare/es-ds-components-v5.2.0...es-ds-components-v5.3.0) (2026-04-06)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add EsMobileNav ([#1722](https://github.com/EnergySage/es-ds/issues/1722)) ([29fcfad](https://github.com/EnergySage/es-ds/commit/29fcfada66e6386df1f58d10f783b29be416ec2e))
|
|
9
|
+
* added EsNavCtaCard for use in mobile/desktop navs ([#1723](https://github.com/EnergySage/es-ds/issues/1723)) ([74b3bbd](https://github.com/EnergySage/es-ds/commit/74b3bbd68c293b9606f9012b5d94ba1c06c60f59))
|
|
10
|
+
* added the breakpoints composable ([#1724](https://github.com/EnergySage/es-ds/issues/1724)) ([de6aa05](https://github.com/EnergySage/es-ds/commit/de6aa058e0783b865930c668b729329333994d3c))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Dependencies
|
|
14
|
+
|
|
15
|
+
* The following workspace dependencies were updated
|
|
16
|
+
* dependencies
|
|
17
|
+
* @energysage/es-ds-styles bumped from ^3.3.4 to ^3.4.0
|
|
18
|
+
|
|
19
|
+
## [5.2.0](https://github.com/EnergySage/es-ds/compare/es-ds-components-v5.1.0...es-ds-components-v5.2.0) (2026-03-27)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
### Features
|
|
23
|
+
|
|
24
|
+
* update to Phosphor icon library ([#1689](https://github.com/EnergySage/es-ds/issues/1689)) ([78bd39b](https://github.com/EnergySage/es-ds/commit/78bd39b2e3325722bfa71e660961cba0de2766ed))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
### Bug Fixes
|
|
28
|
+
|
|
29
|
+
* ensure shadow is not visible when sticky bar is hidden ([#1720](https://github.com/EnergySage/es-ds/issues/1720)) ([68a7396](https://github.com/EnergySage/es-ds/commit/68a73966dba1eabb170eb0e0cb8ae5a22b6057f7))
|
|
30
|
+
|
|
3
31
|
## [5.1.0](https://github.com/EnergySage/es-ds/compare/es-ds-components-v5.0.2...es-ds-components-v5.1.0) (2026-03-27)
|
|
4
32
|
|
|
5
33
|
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// for dark background, set class="text-white" on this component
|
|
3
|
+
interface IProps {
|
|
4
|
+
alt?: string;
|
|
5
|
+
height?: string;
|
|
6
|
+
width?: string;
|
|
7
|
+
}
|
|
8
|
+
withDefaults(defineProps<IProps>(), {
|
|
9
|
+
alt: 'EnergySage',
|
|
10
|
+
height: '45px',
|
|
11
|
+
width: '205px',
|
|
12
|
+
});
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<template>
|
|
16
|
+
<svg
|
|
17
|
+
class="es-logo"
|
|
18
|
+
:style="{
|
|
19
|
+
height: height,
|
|
20
|
+
width: width,
|
|
21
|
+
}"
|
|
22
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
23
|
+
viewBox="0 0 205 45"
|
|
24
|
+
width="205"
|
|
25
|
+
height="45"
|
|
26
|
+
fill="none">
|
|
27
|
+
<title v-if="alt">
|
|
28
|
+
{{ alt }}
|
|
29
|
+
</title>
|
|
30
|
+
<!-- eslint-disable -->
|
|
31
|
+
<path
|
|
32
|
+
d="M47.929 17.293c-4.967 0-8.435 3.573-8.435 8.694 0 5.12 3.533 8.533 8.593 8.533 3.42 0 5.972-1.308 6.895-2.524a.308.308 0 0 0 .029-.327l-.114-.214a.311.311 0 0 0-.466-.097 7.103 7.103 0 0 1-4.452 1.56c-2.536 0-4.866-1.33-6.077-3.47a5.229 5.229 0 0 1-.843-2.076c-.02-.129-.06-.355-.081-.605H55.22c.17 0 .308-.138.308-.307v-.832c0-4.152-2.35-8.344-7.596-8.344v.009h-.004Zm-4.78 6.534c.635-2.306 2.337-3.619 4.715-3.619 2.71 0 3.744 1.89 4.124 3.619h-8.844.004ZM83.472 17.293c-4.967 0-8.435 3.573-8.435 8.694 0 5.12 3.533 8.533 8.593 8.533 3.42 0 5.972-1.308 6.896-2.524a.309.309 0 0 0 .028-.327l-.113-.214a.311.311 0 0 0-.466-.097 7.103 7.103 0 0 1-4.453 1.56c-2.536 0-4.866-1.33-6.077-3.47a5.23 5.23 0 0 1-.843-2.076c-.02-.129-.06-.355-.08-.605h12.243c.17 0 .308-.138.308-.307v-.832c0-4.152-2.35-8.344-7.597-8.344v.009h-.004Zm-4.784 6.534c.636-2.306 2.337-3.619 4.715-3.619 2.71 0 3.744 1.89 4.125 3.619h-8.845.004ZM197.399 17.293c-4.967 0-8.435 3.573-8.435 8.694 0 5.12 3.533 8.533 8.593 8.533 3.42 0 5.972-1.308 6.896-2.524a.308.308 0 0 0 .028-.327l-.113-.214a.311.311 0 0 0-.466-.097 7.103 7.103 0 0 1-4.452 1.56c-2.537 0-4.866-1.33-6.078-3.47-.004-.008-.008-.016-.016-.024a5.219 5.219 0 0 1-.826-2.052c-.021-.129-.061-.355-.081-.605h12.243c.17 0 .308-.138.308-.307v-.832c0-4.152-2.35-8.344-7.596-8.344v.009h-.005Zm-.064 2.915c2.71 0 3.743 1.89 4.124 3.619h-8.844c.636-2.306 2.337-3.619 4.716-3.619h.004ZM27.96 29.287h-3.7a.154.154 0 0 0-.154.153v4.693c0 .084.07.153.154.153h3.7a.154.154 0 0 0 .153-.153V29.44a.154.154 0 0 0-.154-.154Z"
|
|
33
|
+
fill="currentColor" />
|
|
34
|
+
<path
|
|
35
|
+
d="M25.553 17.228h-9.61a.306.306 0 0 1-.304-.303V.303A.306.306 0 0 0 15.335 0H13.35a.454.454 0 0 0-.414.267L3.918 20.37l8.475-13.303v17.668l3.258-4.272h8.062L11.214 40.08V26.197H1.406L0 29.3h7.973V44.7c0 .166.134.299.3.299h3.484a.294.294 0 0 0 .256-.141l13.576-21.311 9.63 10.18-9.67-16.496.004-.004Z"
|
|
36
|
+
fill="#FF9133" />
|
|
37
|
+
<path
|
|
38
|
+
d="M120.195 19.182c-1.945-1.272-4.145-1.89-6.73-1.89-2.37 0-4.57.78-6.186 2.197-1.791 1.567-2.735 3.772-2.735 6.381 0 3.166 1.325 5.165 2.435 6.28 1.43 1.438 3.375 2.261 5.332 2.261 1.523 0 3.184-.634 4.391-1.635a.166.166 0 0 1 .272.129v1.963c0 3.17-1.471 4.777-4.376 4.777-2.256 0-4.29-.856-5.352-1.587-.056-.04-.129-.053-.194-.04a.25.25 0 0 0-.162.117l-1.293 2.18a.166.166 0 0 0 .049.223c1.053.714 3.415 1.974 6.952 1.974 1.455 0 3.537-.29 5.198-1.684 1.641-1.377 2.476-3.489 2.476-6.283V19.324a.171.171 0 0 0-.077-.142Zm-3.221 1.975v7.988a.19.19 0 0 1-.024.093c-.843 1.325-2.496 2.245-4.06 2.245-1.953 0-4.858-1.494-4.858-5.609 0-2.617 1.43-5.674 5.47-5.674 1.6 0 2.787.517 3.387.816a.162.162 0 0 1 .089.15v-.009h-.004ZM139.123 17.943a.249.249 0 0 0-.215-.117h-3.233a.166.166 0 0 0-.149.092l-4.996 10.347a.168.168 0 0 1-.304-.004l-4.55-10.286a.252.252 0 0 0-.226-.15h-3.148a.246.246 0 0 0-.227.351l6.466 13.966c.02.048.02.1-.004.15l-5.202 9.68a.251.251 0 0 0 .004.245.243.243 0 0 0 .214.122h3.084a.25.25 0 0 0 .222-.138l12.272-24.016a.244.244 0 0 0-.008-.242ZM145.796 24.279c-1.531-.743-2.856-1.39-2.856-2.577 0-.864.688-1.736 2.224-1.736 1.535 0 2.889 1.127 3.253 1.518a.251.251 0 0 0 .405-.044l1.155-2.04a.158.158 0 0 0-.024-.193c-.855-.885-2.743-1.947-5.142-1.947-3.034 0-5.323 1.995-5.323 4.636 0 2.504 2.289 3.691 4.307 4.741 1.6.832 2.985 1.551 2.985 2.718 0 2.177-2.021 2.346-2.641 2.346-2.236 0-3.768-1.457-4.185-1.906a.244.244 0 0 0-.207-.076.25.25 0 0 0-.186.117l-1.289 2.076a.17.17 0 0 0 .029.21c.899.831 2.909 2.29 5.972 2.29 3.549 0 5.935-2.056 5.935-5.117 0-2.876-2.342-4.01-4.404-5.016h-.008ZM167.475 19.251a11.564 11.564 0 0 0-6.409-1.954c-4.546 0-9.148 2.935-9.148 8.54 0 4.871 3.2 8.542 7.446 8.542 1.832 0 3.651-.787 4.741-1.97a.167.167 0 0 1 .291.1l.089 1.333a.162.162 0 0 0 .166.153h2.731a.164.164 0 0 0 .166-.165V19.392a.162.162 0 0 0-.073-.137v-.004Zm-3.285 1.914v7.576s0 .04-.013.06c-.474 1.281-2.272 2.678-4.173 2.678-3.16 0-4.602-2.79-4.602-5.387 0-3.4 2.326-5.868 5.534-5.868 1.268 0 2.464.384 3.173.8a.16.16 0 0 1 .081.141ZM186.1 19.182c-1.945-1.272-4.145-1.89-6.725-1.89-2.371 0-4.571.78-6.187 2.197-1.791 1.567-2.735 3.772-2.735 6.381 0 3.166 1.325 5.165 2.435 6.28 1.43 1.438 3.375 2.261 5.332 2.261 1.523 0 3.184-.634 4.392-1.635a.166.166 0 0 1 .271.129v1.963c0 3.17-1.471 4.777-4.376 4.777-2.256 0-4.29-.856-5.351-1.587-.057-.04-.126-.053-.195-.04a.25.25 0 0 0-.162.117l-1.292 2.18a.165.165 0 0 0 .048.223c1.054.714 3.416 1.974 6.952 1.974 1.455 0 3.537-.29 5.199-1.684 1.64-1.377 2.475-3.489 2.475-6.283V19.324a.169.169 0 0 0-.077-.142h-.004Zm-7.305 12.297c-1.953 0-4.858-1.494-4.858-5.609 0-2.617 1.431-5.674 5.47-5.674 1.6 0 2.787.517 3.387.816a.162.162 0 0 1 .089.15v7.983a.19.19 0 0 1-.024.093c-.843 1.325-2.496 2.245-4.06 2.245l-.004-.004ZM72.821 34.294h-3.08a.164.164 0 0 1-.165-.165l-.073-8.8v-.012a5.33 5.33 0 0 0-.584-2.16 4.783 4.783 0 0 0-1.73-1.866c-.753-.477-1.697-.715-2.8-.715-.712 0-1.251.028-1.6.084-.291.049-.579.118-.854.21a.456.456 0 0 0-.316.433V34.12a.168.168 0 0 1-.17.166c-1.102-.008-2.111-.012-3.075-.012a.164.164 0 0 1-.167-.166v-15.33c0-.072.045-.137.114-.157.636-.202 1.454-.4 2.435-.59a19.63 19.63 0 0 1 3.699-.327c1.738 0 3.261.364 4.533 1.075 1.268.71 2.265 1.688 2.954 2.895.672 1.175 1.02 2.504 1.041 3.954v8.492a.164.164 0 0 1-.166.166v.008h.004ZM104.524 18.936a.167.167 0 0 0-.069-.226c-2.95-1.623-7.48-1.006-10.53-.085a.161.161 0 0 0-.113.158v15.33c0 .092.073.165.166.165.964 0 1.977.008 3.075.012.093 0 .17-.073.17-.165V21.307c0-.198.126-.372.312-.432.875-.271 1.305-.283 2.455-.295 1.102 0 2.046.242 2.8.715.129.08.308.258.425.064l1.305-2.427h.004v.004Z"
|
|
39
|
+
fill="currentColor" />
|
|
40
|
+
<!-- eslint-enable -->
|
|
41
|
+
</svg>
|
|
42
|
+
</template>
|
|
43
|
+
|
|
44
|
+
<style lang="scss" scoped>
|
|
45
|
+
@use '@energysage/es-ds-styles/scss/variables';
|
|
46
|
+
|
|
47
|
+
.es-logo {
|
|
48
|
+
color: variables.$blue-900;
|
|
49
|
+
}
|
|
50
|
+
</style>
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { NavigationMenuContent, NavigationMenuList } from 'reka-ui';
|
|
3
|
+
import type { ShallowRef } from 'vue';
|
|
4
|
+
|
|
5
|
+
const mobileNavParentElement = useTemplateRef('mobileNavParentElement');
|
|
6
|
+
|
|
7
|
+
// reactive flags set by hidden sr-only buttons in submenus to simulate focus on visible header buttons
|
|
8
|
+
const backButtonSimulatedFocus = ref(false);
|
|
9
|
+
const closeButtonSimulatedFocus = ref(false);
|
|
10
|
+
|
|
11
|
+
// injected variables provided from EsMobileNav
|
|
12
|
+
const animationDuration = inject('animationDuration', 200);
|
|
13
|
+
const closeMenu: (...args: any[]) => void = inject('closeMenu', () => {});
|
|
14
|
+
const currentDepth = inject(
|
|
15
|
+
'currentDepth',
|
|
16
|
+
computed(() => 0),
|
|
17
|
+
);
|
|
18
|
+
const displayedName = inject('displayedName', '');
|
|
19
|
+
const from = inject('from', ref<'left' | 'right'>('left'));
|
|
20
|
+
const goBack = inject('goBack', () => {});
|
|
21
|
+
const width = inject('width', ref(400));
|
|
22
|
+
const widthPx = inject(
|
|
23
|
+
'widthPx',
|
|
24
|
+
computed(() => '400px'),
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
// derived values for CSS custom properties set directly on the element
|
|
28
|
+
const animationDurationMs = `${animationDuration}ms`;
|
|
29
|
+
const contentPaneTransformXs = computed(() => `translateX(${currentDepth.value * -100}vw)`);
|
|
30
|
+
const contentPaneTransformSm = computed(() => `translateX(${currentDepth.value * -1 * width.value}px)`);
|
|
31
|
+
const left = computed(() => (from.value === 'left' ? '0' : 'auto'));
|
|
32
|
+
const menuClosedTranslateX = computed(() => (from.value === 'right' ? '100%' : '-100%'));
|
|
33
|
+
const registerScrollableContentArea = inject<
|
|
34
|
+
(areaTemplateRef: Readonly<ShallowRef<InstanceType<typeof NavigationMenuContent> | null>>) => void
|
|
35
|
+
>('registerScrollableContentArea', () => {});
|
|
36
|
+
const right = computed(() => (from.value === 'right' ? '0' : 'auto'));
|
|
37
|
+
|
|
38
|
+
// directional animation of the submenu titles as you're going down and back up
|
|
39
|
+
const direction = ref(1);
|
|
40
|
+
const transitionName = computed(() =>
|
|
41
|
+
direction.value > 0 ? 'es-mobile-nav-title-forward' : 'es-mobile-nav-title-back',
|
|
42
|
+
);
|
|
43
|
+
watch(
|
|
44
|
+
currentDepth,
|
|
45
|
+
(newVal, oldVal) => {
|
|
46
|
+
direction.value = newVal > oldVal ? 1 : -1;
|
|
47
|
+
},
|
|
48
|
+
{ flush: 'sync' },
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
const focusOutside = (e: any) => {
|
|
52
|
+
// if focus is on something outside of the overall menu, close it
|
|
53
|
+
if (!isElementWithinMenu(e.target)) {
|
|
54
|
+
closeMenu();
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const isElementWithinMenu = (element: any) => {
|
|
59
|
+
if (!mobileNavParentElement?.value?.$el) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const parent: Node = mobileNavParentElement.value.$el;
|
|
64
|
+
return parent.contains(element);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
onMounted(() => {
|
|
68
|
+
// give EsMobileNav a reference to the scrollable content area so it can set the scroll position
|
|
69
|
+
registerScrollableContentArea(mobileNavParentElement);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
provide('backButtonSimulatedFocus', backButtonSimulatedFocus);
|
|
73
|
+
provide('closeButtonSimulatedFocus', closeButtonSimulatedFocus);
|
|
74
|
+
provide('isElementWithinMenu', isElementWithinMenu);
|
|
75
|
+
</script>
|
|
76
|
+
|
|
77
|
+
<template>
|
|
78
|
+
<!-- teleported to body to escape any ancestor stacking context (e.g. es-sticky-bar) -->
|
|
79
|
+
<teleport to="body">
|
|
80
|
+
<navigation-menu-content
|
|
81
|
+
v-bind="$attrs"
|
|
82
|
+
ref="mobileNavParentElement"
|
|
83
|
+
class="es-mobile-nav-content bg-white d-flex flex-column pb-50 position-fixed px-50"
|
|
84
|
+
:style="{
|
|
85
|
+
'--es-mobile-nav-animation-duration': animationDurationMs,
|
|
86
|
+
'--es-mobile-nav-closed-translate-x': menuClosedTranslateX,
|
|
87
|
+
'--es-mobile-nav-content-pane-transform-sm': contentPaneTransformSm,
|
|
88
|
+
'--es-mobile-nav-content-pane-transform-xs': contentPaneTransformXs,
|
|
89
|
+
'--es-mobile-nav-left': left,
|
|
90
|
+
'--es-mobile-nav-right': right,
|
|
91
|
+
'--es-mobile-nav-width': widthPx,
|
|
92
|
+
}"
|
|
93
|
+
@focus-outside.prevent.stop="focusOutside"
|
|
94
|
+
@interact-outside.prevent.stop
|
|
95
|
+
@pointer-down-outside.prevent.stop>
|
|
96
|
+
<div
|
|
97
|
+
class="es-mobile-nav-content-header align-items-center bg-white d-flex flex-shrink-0 justify-content-center position-sticky w-100">
|
|
98
|
+
<!-- back button -->
|
|
99
|
+
<transition name="es-mobile-nav-back">
|
|
100
|
+
<es-button
|
|
101
|
+
v-if="currentDepth > 0"
|
|
102
|
+
class="es-mobile-nav-back-button p-50 position-absolute text-blue-900"
|
|
103
|
+
:class="{ focus: backButtonSimulatedFocus }"
|
|
104
|
+
inline
|
|
105
|
+
variant="link"
|
|
106
|
+
@click="goBack">
|
|
107
|
+
<icon-arrow-left aria-hidden="true" />
|
|
108
|
+
<span class="sr-only">back</span>
|
|
109
|
+
</es-button>
|
|
110
|
+
</transition>
|
|
111
|
+
|
|
112
|
+
<!-- logo or subnav title, with smooth transition between them -->
|
|
113
|
+
<div class="es-mobile-nav-title-outer-container">
|
|
114
|
+
<transition :name="transitionName">
|
|
115
|
+
<div
|
|
116
|
+
:key="displayedName || 'logo'"
|
|
117
|
+
class="es-mobile-nav-title-inner-container align-items-center d-flex justify-content-center">
|
|
118
|
+
<div
|
|
119
|
+
v-if="displayedName"
|
|
120
|
+
class="font-weight-bolder">
|
|
121
|
+
{{ displayedName }}
|
|
122
|
+
</div>
|
|
123
|
+
<es-logo
|
|
124
|
+
v-else
|
|
125
|
+
alt=""
|
|
126
|
+
aria-hidden="true"
|
|
127
|
+
height="30px"
|
|
128
|
+
width="135px" />
|
|
129
|
+
</div>
|
|
130
|
+
</transition>
|
|
131
|
+
</div>
|
|
132
|
+
|
|
133
|
+
<!-- close button -->
|
|
134
|
+
<es-button
|
|
135
|
+
class="es-mobile-nav-close-button p-50 position-absolute text-blue-900"
|
|
136
|
+
:class="{ focus: closeButtonSimulatedFocus }"
|
|
137
|
+
inline
|
|
138
|
+
variant="link"
|
|
139
|
+
@click="closeMenu">
|
|
140
|
+
<icon-x />
|
|
141
|
+
<span class="sr-only">close</span>
|
|
142
|
+
</es-button>
|
|
143
|
+
</div>
|
|
144
|
+
<div
|
|
145
|
+
class="es-mobile-nav-content-pane d-flex flex-column flex-grow-1 justify-content-between position-relative">
|
|
146
|
+
<navigation-menu-list class="list-unstyled">
|
|
147
|
+
<slot />
|
|
148
|
+
</navigation-menu-list>
|
|
149
|
+
<div class="es-mobile-nav-content-footer">
|
|
150
|
+
<slot name="footer" />
|
|
151
|
+
</div>
|
|
152
|
+
</div>
|
|
153
|
+
</navigation-menu-content>
|
|
154
|
+
</teleport>
|
|
155
|
+
</template>
|
|
156
|
+
|
|
157
|
+
<!-- unscoped: targets Reka UI-rendered elements that don't receive Vue's scoped attribute -->
|
|
158
|
+
<style lang="scss">
|
|
159
|
+
@use '@energysage/es-ds-styles/scss/mixins/breakpoints' as breakpoints;
|
|
160
|
+
@use '@energysage/es-ds-styles/scss/variables';
|
|
161
|
+
|
|
162
|
+
@keyframes esMobileNavOpen {
|
|
163
|
+
from {
|
|
164
|
+
transform: translateX(var(--es-mobile-nav-closed-translate-x));
|
|
165
|
+
}
|
|
166
|
+
to {
|
|
167
|
+
transform: translateX(0);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
@keyframes esMobileNavClose {
|
|
172
|
+
from {
|
|
173
|
+
transform: translateX(0);
|
|
174
|
+
}
|
|
175
|
+
to {
|
|
176
|
+
transform: translateX(var(--es-mobile-nav-closed-translate-x));
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.es-mobile-nav-content {
|
|
181
|
+
--es-mobile-nav-header-height: 88px;
|
|
182
|
+
|
|
183
|
+
bottom: 0;
|
|
184
|
+
box-shadow: 0 0 6px 0 rgba(34, 38, 51, 0.2);
|
|
185
|
+
left: 0;
|
|
186
|
+
overflow-x: hidden;
|
|
187
|
+
position: fixed;
|
|
188
|
+
right: 0;
|
|
189
|
+
top: 0;
|
|
190
|
+
z-index: 1020;
|
|
191
|
+
|
|
192
|
+
@media not (prefers-reduced-motion) {
|
|
193
|
+
&[data-state='open'] {
|
|
194
|
+
animation: esMobileNavOpen var(--es-mobile-nav-animation-duration) ease-out;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
&[data-state='closed'] {
|
|
198
|
+
animation: esMobileNavClose var(--es-mobile-nav-animation-duration) ease-in;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
@include breakpoints.media-breakpoint-up(sm) {
|
|
203
|
+
left: var(--es-mobile-nav-left);
|
|
204
|
+
right: var(--es-mobile-nav-right);
|
|
205
|
+
width: var(--es-mobile-nav-width);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.es-mobile-nav-content-header {
|
|
210
|
+
border-bottom: 1px solid variables.$gray-100;
|
|
211
|
+
height: var(--es-mobile-nav-header-height);
|
|
212
|
+
left: 0;
|
|
213
|
+
right: 0;
|
|
214
|
+
top: 0;
|
|
215
|
+
z-index: 2;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.es-mobile-nav-back-button {
|
|
219
|
+
left: variables.$spacer * 0.5;
|
|
220
|
+
transform: translateY(-50%);
|
|
221
|
+
top: 50%;
|
|
222
|
+
|
|
223
|
+
svg {
|
|
224
|
+
height: 20px !important;
|
|
225
|
+
width: 20px !important;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.es-mobile-nav-close-button {
|
|
230
|
+
right: variables.$spacer;
|
|
231
|
+
transform: translateY(-50%);
|
|
232
|
+
top: 50%;
|
|
233
|
+
|
|
234
|
+
svg {
|
|
235
|
+
height: 20px !important;
|
|
236
|
+
width: 20px !important;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.es-mobile-nav-content-pane {
|
|
241
|
+
transform: var(--es-mobile-nav-content-pane-transform-xs);
|
|
242
|
+
|
|
243
|
+
@media not (prefers-reduced-motion) {
|
|
244
|
+
transition: transform var(--es-mobile-nav-animation-duration) ease-in-out;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
@include breakpoints.media-breakpoint-up(sm) {
|
|
248
|
+
transform: var(--es-mobile-nav-content-pane-transform-sm);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
</style>
|
|
252
|
+
|
|
253
|
+
<!-- scoped: targets native elements directly in this component's template -->
|
|
254
|
+
<style lang="scss" scoped>
|
|
255
|
+
.es-mobile-nav-back-enter-from,
|
|
256
|
+
.es-mobile-nav-back-leave-to {
|
|
257
|
+
opacity: 0;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
@media not (prefers-reduced-motion) {
|
|
261
|
+
.es-mobile-nav-back-enter-active,
|
|
262
|
+
.es-mobile-nav-back-leave-active {
|
|
263
|
+
transition: opacity var(--es-mobile-nav-animation-duration) ease-in-out;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
.es-mobile-nav-title-outer-container {
|
|
268
|
+
/* necessary to keep the logo/titles centered as they show/hide and animate */
|
|
269
|
+
display: grid;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
.es-mobile-nav-title-inner-container {
|
|
273
|
+
/* necessary to keep the logo/titles centered as they show/hide and animate */
|
|
274
|
+
grid-area: 1 / 1;
|
|
275
|
+
height: 30px;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
.es-mobile-nav-title-back-enter-from {
|
|
279
|
+
opacity: 0;
|
|
280
|
+
transform: translateX(-20px);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.es-mobile-nav-title-back-leave-to {
|
|
284
|
+
opacity: 0;
|
|
285
|
+
transform: translateX(20px);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
.es-mobile-nav-title-forward-enter-from {
|
|
289
|
+
opacity: 0;
|
|
290
|
+
transform: translateX(20px);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
.es-mobile-nav-title-forward-leave-to {
|
|
294
|
+
opacity: 0;
|
|
295
|
+
transform: translateX(-20px);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
@media not (prefers-reduced-motion) {
|
|
299
|
+
.es-mobile-nav-title-forward-enter-active,
|
|
300
|
+
.es-mobile-nav-title-forward-leave-active,
|
|
301
|
+
.es-mobile-nav-title-back-enter-active,
|
|
302
|
+
.es-mobile-nav-title-back-leave-active {
|
|
303
|
+
transition:
|
|
304
|
+
opacity var(--es-mobile-nav-animation-duration) ease,
|
|
305
|
+
transform var(--es-mobile-nav-animation-duration) ease;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
</style>
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { NavigationMenuItem, NavigationMenuLink } from 'reka-ui';
|
|
3
|
+
|
|
4
|
+
interface IProps {
|
|
5
|
+
href: string;
|
|
6
|
+
name: string;
|
|
7
|
+
target?: string;
|
|
8
|
+
}
|
|
9
|
+
withDefaults(defineProps<IProps>(), {
|
|
10
|
+
target: '_self',
|
|
11
|
+
});
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<template>
|
|
15
|
+
<navigation-menu-item>
|
|
16
|
+
<navigation-menu-link
|
|
17
|
+
as-child
|
|
18
|
+
@select.prevent.stop>
|
|
19
|
+
<a
|
|
20
|
+
class="es-mobile-nav-link d-block font-size-75 font-weight-bolder"
|
|
21
|
+
:href="href"
|
|
22
|
+
:target="target">
|
|
23
|
+
<span class="d-block p-100 rounded-sm">
|
|
24
|
+
{{ name }}
|
|
25
|
+
</span>
|
|
26
|
+
</a>
|
|
27
|
+
</navigation-menu-link>
|
|
28
|
+
</navigation-menu-item>
|
|
29
|
+
</template>
|
|
30
|
+
|
|
31
|
+
<style lang="scss" scoped>
|
|
32
|
+
@use '@energysage/es-ds-styles/scss/variables';
|
|
33
|
+
|
|
34
|
+
$transition-duration: 100ms;
|
|
35
|
+
|
|
36
|
+
.es-mobile-nav-link {
|
|
37
|
+
/* specify color here so it can be overridden in active state */
|
|
38
|
+
color: variables.$dark-blue;
|
|
39
|
+
|
|
40
|
+
&:hover {
|
|
41
|
+
text-decoration: none;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@media not (prefers-reduced-motion) {
|
|
45
|
+
transition:
|
|
46
|
+
background-color $transition-duration ease-in-out,
|
|
47
|
+
color $transition-duration ease-in-out;
|
|
48
|
+
|
|
49
|
+
& > span {
|
|
50
|
+
transition: background-color $transition-duration ease-in-out;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
&:active {
|
|
55
|
+
color: variables.$white;
|
|
56
|
+
|
|
57
|
+
& > span {
|
|
58
|
+
background-color: variables.$dark-blue;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
</style>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { NavigationMenuTrigger } from 'reka-ui';
|
|
3
|
+
|
|
4
|
+
interface IProps {
|
|
5
|
+
unstyled?: boolean;
|
|
6
|
+
}
|
|
7
|
+
withDefaults(defineProps<IProps>(), {
|
|
8
|
+
unstyled: false,
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const triggerRef = useTemplateRef<InstanceType<typeof NavigationMenuTrigger>>('triggerRef');
|
|
12
|
+
const registerNavTrigger = inject<(el: HTMLElement) => void>('registerNavTrigger');
|
|
13
|
+
|
|
14
|
+
onMounted(() => {
|
|
15
|
+
if (registerNavTrigger && triggerRef.value) {
|
|
16
|
+
registerNavTrigger(triggerRef.value.$el);
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<template>
|
|
22
|
+
<!-- styles defined with :deep() in EsMobileNav due to Reka UI's rendering method -->
|
|
23
|
+
<navigation-menu-trigger
|
|
24
|
+
ref="triggerRef"
|
|
25
|
+
v-bind="$attrs"
|
|
26
|
+
:class="{ 'es-mobile-nav-trigger': !unstyled }">
|
|
27
|
+
<slot />
|
|
28
|
+
</navigation-menu-trigger>
|
|
29
|
+
</template>
|