@energie360/ui-library 0.1.8 → 0.1.10

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.
Files changed (48) hide show
  1. package/base/abstracts/_variables.scss +1 -0
  2. package/components/context-menu/context-menu.scss +28 -0
  3. package/components/context-menu/u-context-menu.vue +113 -0
  4. package/components/context-menu-divider/context-menu-divider.scss +6 -0
  5. package/components/context-menu-divider/u-context-menu-divider.vue +5 -0
  6. package/components/context-menu-link/context-menu-link.scss +26 -0
  7. package/components/context-menu-link/u-context-menu-link.vue +27 -0
  8. package/components/index.js +38 -5
  9. package/components/navigation-toolbar-link/navigation-toolbar-link.scss +177 -0
  10. package/components/navigation-toolbar-link/u-navigation-toolbar-link.vue +108 -0
  11. package/components/text-block/text-block.scss +58 -0
  12. package/components/text-block/u-text-block.vue +26 -0
  13. package/components/tooltip/popover.ts +74 -12
  14. package/dist/base-style.css +1 -0
  15. package/dist/base-style.css.map +1 -1
  16. package/dist/elements/text-link.css +1 -0
  17. package/dist/elements/text-link.css.map +1 -1
  18. package/dist/layout/split.css +1 -0
  19. package/dist/layout/split.css.map +1 -1
  20. package/elements/button-chip/button-chip.scss +2 -2
  21. package/elements/index.js +13 -0
  22. package/elements/text-field/u-text-field.vue +9 -1
  23. package/elements/types.ts +0 -2
  24. package/i18n/i18n.ts +8 -0
  25. package/modules/index.js +5 -0
  26. package/modules/navigation-toolbar-side/navigation-toolbar-side.scss +89 -0
  27. package/modules/navigation-toolbar-side/u-navigation-toolbar-side.vue +93 -0
  28. package/modules/navigation-toolbar-top/navigation-toolbar-top.scss +89 -0
  29. package/modules/navigation-toolbar-top/u-navigation-toolbar-top.vue +130 -0
  30. package/package.json +4 -7
  31. package/utils/a11y/focus-trap.js +128 -0
  32. package/elements/button/index.js +0 -1
  33. package/elements/button-chip/index.js +0 -1
  34. package/elements/icon/index.js +0 -1
  35. package/elements/icon-button/index.js +0 -1
  36. package/elements/image/index.js +0 -1
  37. package/elements/loader/index.js +0 -1
  38. package/elements/numeric-stepper/index.js +0 -1
  39. package/elements/password-progress/index.js +0 -1
  40. package/elements/radio/index.js +0 -1
  41. package/elements/radio-group/index.js +0 -1
  42. package/elements/select/index.js +0 -1
  43. package/elements/select-chip/index.js +0 -1
  44. package/elements/select-chips/index.js +0 -1
  45. package/elements/spectro/index.js +0 -1
  46. package/elements/text-field/index.js +0 -1
  47. package/elements/textarea/index.js +0 -1
  48. package/elements/toggle-switch/index.js +0 -1
@@ -35,6 +35,7 @@ $grid-gutter-s: math.div(dt.$space-5, $container-inner-s) * 100%;
35
35
 
36
36
  // Transition
37
37
  $trs-default: var(--e-trs-duration-faster) var(--e-trs-easing-default);
38
+ $trs-ease-out: var(--e-trs-duration-faster) cubic-bezier(0.215, 0.61, 0.355, 1); /* easeOutCubic */
38
39
 
39
40
  // CMS-Section
40
41
  $section-default-padding-2xl: dt.$space-28;
@@ -0,0 +1,28 @@
1
+ @use '../../base/abstracts/' as a;
2
+
3
+ // .context-menu {
4
+ // // position: relative;
5
+ // }
6
+
7
+ .context-menu__menu {
8
+ position: absolute;
9
+ display: flex;
10
+ flex-direction: column;
11
+ row-gap: var(--e-space-2);
12
+ padding: var(--e-space-2);
13
+ border-radius: var(--e-brd-radius-2);
14
+ border: 1px solid var(--e-c-mono-200);
15
+ box-shadow: var(--e-elevation-md);
16
+ background-color: var(--e-c-mono-00);
17
+ min-width: a.rem(240);
18
+ }
19
+
20
+ .menu-enter-active,
21
+ .menu-leave-active {
22
+ transition: opacity a.$trs-default;
23
+ }
24
+
25
+ .menu-enter-from,
26
+ .menu-leave-to {
27
+ opacity: 0;
28
+ }
@@ -0,0 +1,113 @@
1
+ <script lang="ts" setup>
2
+ import { ref, useTemplateRef, watch } from 'vue'
3
+ import { PopoverPositionParams, getPopoverPosition } from '../tooltip/popover'
4
+ import { debounceRaf } from '../../utils/functions/debounce'
5
+ import { focusTrap } from '../../utils/a11y/focus-trap'
6
+
7
+ const {
8
+ placement = 'top-center',
9
+ offset = 8,
10
+ viewportPadding = 20,
11
+ } = defineProps<PopoverPositionParams>()
12
+
13
+ // TODO: Key codes should be defined globally
14
+ const ESC = 'Escape'
15
+
16
+ const triggerEl = useTemplateRef('trigger')
17
+ const menuEl = useTemplateRef('menu')
18
+ const isOpen = ref(false)
19
+ let focusTrapInstance
20
+
21
+ const onToggleMenu = (e: Event) => {
22
+ e.stopPropagation()
23
+ e.preventDefault()
24
+
25
+ isOpen.value = !isOpen.value
26
+ }
27
+
28
+ const onResize = () => {
29
+ // Clear right position value, so we can get actual width of popover.
30
+ menuEl.value!.style.right = ''
31
+
32
+ const popoverPosition = getPopoverPosition(
33
+ triggerEl.value as HTMLElement,
34
+ menuEl.value as HTMLElement,
35
+ {
36
+ placement,
37
+ offset,
38
+ viewportPadding,
39
+ },
40
+ )
41
+
42
+ menuEl.value!.style.top = `${popoverPosition.top}px`
43
+ menuEl.value!.style.left = `${popoverPosition.left}px`
44
+ if (popoverPosition.right) {
45
+ menuEl.value!.style.right = `${popoverPosition.right}px`
46
+ }
47
+ }
48
+
49
+ const onResizeDebounced = debounceRaf(onResize)
50
+
51
+ const onEnter = () => {
52
+ // 1. Position context-menu
53
+ onResize()
54
+
55
+ // 2. Set focus to first focusable element in menu
56
+ focusTrapInstance = focusTrap(menuEl.value, {
57
+ focusFirstElement: true,
58
+ allowArrowUpDown: true,
59
+ allowArrowLeftRight: true,
60
+ })
61
+
62
+ // 3. Bind events
63
+ menuEl.value.addEventListener('keydown', onEsc)
64
+ document.addEventListener('click', onDocumentClick)
65
+ window.addEventListener('resize', onResizeDebounced)
66
+ }
67
+
68
+ const onAfterLeave = () => {
69
+ focusTrapInstance.release()
70
+ window.removeEventListener('resize', onResizeDebounced)
71
+ document.removeEventListener('click', onDocumentClick)
72
+ menuEl.value?.removeEventListener('keydown', onEsc)
73
+ }
74
+
75
+ const onEsc = (e) => {
76
+ if (e.code === ESC) {
77
+ isOpen.value = false
78
+
79
+ // Set focus back to the trigger element
80
+ triggerEl.value.focus()
81
+ }
82
+ }
83
+
84
+ const onDocumentClick = (e: Event) => {
85
+ e.stopPropagation()
86
+ e.preventDefault()
87
+
88
+ // Close context menu when any click happens.
89
+ isOpen.value = false
90
+ }
91
+
92
+ watch([() => placement, () => offset, () => viewportPadding], () => {
93
+ if (isOpen.value) {
94
+ onResize()
95
+ }
96
+ })
97
+ </script>
98
+
99
+ <template>
100
+ <div class="context-menu" :class="{ 'is-open': isOpen, 'is-closed': !isOpen }">
101
+ <div ref="trigger" class="context-menu__trigger" @click="onToggleMenu">
102
+ <slot name="trigger"></slot>
103
+ </div>
104
+
105
+ <Transition name="menu" @enter="onEnter" @after-leave="onAfterLeave">
106
+ <div v-if="isOpen" ref="menu" class="context-menu__menu">
107
+ <slot></slot>
108
+ </div>
109
+ </Transition>
110
+ </div>
111
+ </template>
112
+
113
+ <style lang="scss" scoped src="./context-menu.scss"></style>
@@ -0,0 +1,6 @@
1
+ .context-menu-divider {
2
+ height: 1px;
3
+ margin: 0;
4
+ border: 0;
5
+ background-color: var(--e-c-mono-200);
6
+ }
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <hr class="context-menu-divider" />
3
+ </template>
4
+
5
+ <style scoped lang="scss" src="./context-menu-divider.scss"></style>
@@ -0,0 +1,26 @@
1
+ @use '../../base/abstracts/' as a;
2
+
3
+ .context-menu-link {
4
+ @include a.type(200, strong);
5
+
6
+ display: flex;
7
+ column-gap: var(--e-space-2);
8
+ padding: var(--e-space-1_5) var(--e-space-3);
9
+ color: var(--e-c-mono-700);
10
+ border-radius: var(--e-brd-radius-2);
11
+ text-wrap: nowrap;
12
+ transition:
13
+ background-color a.$trs-ease-out,
14
+ color a.$trs-ease-out;
15
+
16
+ &:hover,
17
+ &:active {
18
+ background-color: var(--e-c-primary-01-50);
19
+ color: var(--e-c-primary-01-700);
20
+ }
21
+
22
+ &.active {
23
+ background-color: var(--e-c-primary-01-100);
24
+ color: var(--e-c-primary-01-900);
25
+ }
26
+ }
@@ -0,0 +1,27 @@
1
+ <script setup lang="ts">
2
+ import { computed } from 'vue'
3
+ import { UIcon } from '../../elements'
4
+
5
+ interface Props {
6
+ icon: string
7
+ label?: string
8
+ href?: string
9
+ target?: string
10
+ active?: boolean
11
+ }
12
+
13
+ const { href, active = false } = defineProps<Props>()
14
+
15
+ const tag = computed(() => {
16
+ return href ? 'a' : 'span'
17
+ })
18
+ </script>
19
+
20
+ <template>
21
+ <component :is="tag" class="context-menu-link" :class="{ active }">
22
+ <UIcon :name="icon" />
23
+ <slot>{{ label }}</slot>
24
+ </component>
25
+ </template>
26
+
27
+ <style scoped lang="scss" src="./context-menu-link.scss"></style>
@@ -2,13 +2,46 @@
2
2
  * It's not recommended to import components from this file, because tree-shaking won't work then.
3
3
  * -> https://vite.dev/guide/performance#avoid-barrel-files
4
4
  */
5
+ export { default as UAccordionItem } from './accordion-item/u-accordion-item.vue'
6
+
7
+ // Cards
8
+ export { default as UCard } from './card/u-card.vue'
9
+ export { default as UCardFooter } from './card-footer/u-card-footer.vue'
10
+ export { default as UCardGroup } from './card-group/u-card-group.vue'
11
+ export { default as UCardHeader } from './card-header/u-card-header.vue'
12
+ export { default as UCardHint } from './card-hint/u-card-hint.vue'
13
+ export { default as UCardPrice } from './card-price/u-card-price.vue'
14
+ export { default as UCardSection } from './card-section/u-card-section.vue'
15
+ export { default as UCardTable } from './card-table/u-card-table.vue'
16
+ export { default as UCardToggleSwitches } from './card-toggle-switches/u-card-toggle-switches.vue'
17
+
18
+ // Collapsible
19
+ export { default as UCollapsible } from './collapsible/u-collapsible.vue'
20
+ export { default as UCollapsibleGroup } from './collapsible-group/u-collapsible-group.vue'
21
+
5
22
  export { default as UIconTextBlock } from './icon-text-block/u-icon-text-block.vue'
6
23
  export { default as UIconTextBlockGroup } from './icon-text-block-group/u-icon-text-block-group.vue'
7
- export { default as UTable } from './table/u-table.vue'
8
- export { default as UTableHeader } from './table/u-table-header.vue'
9
- export { default as UTableRow } from './table/u-table-row.vue'
24
+ export { default as UInlineEdit } from './inline-edit/u-inline-edit.vue'
25
+ export { default as ULanguageNav } from './language-nav/u-language-nav.vue'
26
+ export { default as UPanel } from './panel/u-panel.vue'
27
+ export { default as UProgressBar } from './progress-bar/u-progress-bar.vue'
28
+ export { default as URichtext } from './richtext/u-richtext.vue'
29
+
30
+ // Table
31
+ export { default as UCellCtas } from './table/u-cell-ctas.vue'
32
+ export { default as UCellIconGroup } from './table/u-cell-icon-group.vue'
33
+ export { default as UCellIconText } from './table/u-cell-icon-text.vue'
34
+ export { default as UCellProgressBar } from './table/u-cell-progress-bar.vue'
10
35
  export { default as UTableCell } from './table/u-table-cell.vue'
36
+ export { default as UTableHeader } from './table/u-table-header.vue'
11
37
  export { default as UTableHeading } from './table/u-table-heading.vue'
12
- export { default as UCellIconText } from './table/u-cell-icon-text.vue'
13
- export { default as UCellCtas } from './table/u-cell-ctas.vue'
38
+ export { default as UTableRow } from './table/u-table-row.vue'
39
+ export { default as UTable } from './table/u-table.vue'
40
+
41
+ export { default as UTabs } from './tabs/u-tabs.vue'
42
+ export { default as UTextBlock } from './text-block/u-text-block.vue'
14
43
  export { default as UTooltip } from './tooltip/u-tooltip.vue'
44
+ export { default as UNavigationToolbarLink } from './navigation-toolbar-link/u-navigation-toolbar-link.vue'
45
+ export { default as UContextMenu } from './context-menu/u-context-menu.vue'
46
+ export { default as UContextMenuLink } from './context-menu-link/u-context-menu-link.vue'
47
+ export { default as UContextMenuDivider } from './context-menu-divider/u-context-menu-divider.vue'
@@ -0,0 +1,177 @@
1
+ // TODO: How to handle text overflow?
2
+
3
+ @use '../../base/abstracts/' as a;
4
+
5
+ @keyframes fadeInLabel {
6
+ 0% {
7
+ opacity: 0;
8
+ transform: translateX(calc(100% + #{a.rem(8)}));
9
+ }
10
+
11
+ 100% {
12
+ opacity: 1;
13
+ transform: translateX(100%);
14
+ }
15
+ }
16
+
17
+ @keyframes fadeOutLabel {
18
+ 0% {
19
+ opacity: 1;
20
+ transform: translateX(100%);
21
+ width: auto;
22
+ height: auto;
23
+ padding: var(--e-space-1_5) var(--e-space-2);
24
+ }
25
+
26
+ 100% {
27
+ opacity: 0;
28
+ transform: translateX(calc(100% + #{a.rem(8)}));
29
+ width: auto;
30
+ height: auto;
31
+ padding: var(--e-space-1_5) var(--e-space-2);
32
+ }
33
+ }
34
+
35
+ @keyframes collapse {
36
+ 0% {
37
+ overflow: hidden;
38
+ padding: var(--e-space-1_5) var(--e-space-3);
39
+ width: 100%;
40
+ }
41
+
42
+ 100% {
43
+ overflow: hidden;
44
+ padding: var(--e-space-1_5);
45
+ width: a.rem(36);
46
+ }
47
+ }
48
+
49
+ @keyframes expand {
50
+ 0% {
51
+ overflow: hidden;
52
+ padding: var(--e-space-1_5);
53
+ width: a.rem(36);
54
+ }
55
+
56
+ 100% {
57
+ overflow: hidden;
58
+ padding: var(--e-space-1_5) var(--e-space-3);
59
+ width: 100%;
60
+ }
61
+ }
62
+
63
+ .navigation-toolbar-link {
64
+ --transition-ease-out: cubic-bezier(0.215, 0.61, 0.355, 1); /* easeOutCubic */
65
+
66
+ position: relative;
67
+ padding: var(--e-space-1_5) var(--e-space-3);
68
+ height: a.rem(36);
69
+ display: flex;
70
+ justify-content: flex-start;
71
+ align-items: center;
72
+ flex-wrap: nowrap;
73
+ white-space: nowrap;
74
+ width: 100%;
75
+ column-gap: var(--e-space-2);
76
+ background-color: var(--e-c-secondary-01-1000);
77
+ color: var(--e-c-mono-00);
78
+ border-radius: var(--e-brd-radius-2);
79
+ cursor: pointer;
80
+ transition:
81
+ background-color a.$trs-default,
82
+ color a.$trs-default;
83
+
84
+ @include a.type(200, strong);
85
+
86
+ > * {
87
+ flex: 0 0 auto;
88
+ }
89
+
90
+ &:active,
91
+ &:hover:not(.is-collapsing, .is-expanding) {
92
+ background-color: var(--e-c-secondary-01-950);
93
+ color: var(--e-c-primary-01-100);
94
+ }
95
+
96
+ // Active Page
97
+ &.active {
98
+ background-color: var(--e-c-secondary-01-900);
99
+ color: var(--e-c-primary-01-50);
100
+ }
101
+
102
+ // Collapsed
103
+ &.collapsed {
104
+ padding: var(--e-space-1_5);
105
+ width: a.rem(36);
106
+
107
+ .navigation-toolbar-link__label {
108
+ position: absolute;
109
+ top: 0;
110
+ right: calc(var(--e-space-2) * -1);
111
+ transform: translateX(calc(100% + #{a.rem(8)}));
112
+ border-radius: var(--e-brd-radius-2);
113
+ background-color: var(--e-c-mono-900);
114
+ color: var(--e-c-mono-00);
115
+
116
+ // Hide visually
117
+ width: 0;
118
+ height: 0;
119
+ opacity: 0;
120
+ overflow: hidden;
121
+ pointer-events: none;
122
+ }
123
+
124
+ &.hover-out:not(.is-expanding, .is-collapsing, .label-hidden) {
125
+ .navigation-toolbar-link__label {
126
+ // TODO: Maybe just use transitions instead of keyframe animations
127
+ animation-name: fadeOutLabel;
128
+ animation-duration: var(--e-trs-duration-faster);
129
+ animation-timing-function: ease-out;
130
+ }
131
+ }
132
+
133
+ &:hover:not(.is-expanding, .is-collapsing, .label-hidden) {
134
+ .navigation-toolbar-link__label {
135
+ animation-name: fadeInLabel;
136
+ animation-duration: var(--e-trs-duration-faster);
137
+ animation-timing-function: ease-out;
138
+
139
+ padding: var(--e-space-1_5) var(--e-space-2);
140
+ transform: translateX(100%);
141
+ width: auto;
142
+ height: auto;
143
+ opacity: 1;
144
+ }
145
+ }
146
+ }
147
+ }
148
+
149
+ // Animation
150
+ .navigation-toolbar-link {
151
+ &.is-collapsing,
152
+ &.is-expanding {
153
+ animation-duration: var(--e-trs-duration-faster);
154
+
155
+ .navigation-toolbar-link__label {
156
+ animation: none;
157
+ position: static;
158
+ width: auto;
159
+ height: auto;
160
+ opacity: 1;
161
+ background-color: transparent;
162
+ transform: none;
163
+ }
164
+ }
165
+
166
+ &.is-collapsing {
167
+ // TODO: Maybe just use transitions instead of keyframe animations
168
+ animation-name: collapse;
169
+ animation-timing-function: var(--transition-ease-out);
170
+ }
171
+
172
+ &.is-expanding {
173
+ // TODO: Maybe just use transitions instead of keyframe animations
174
+ animation-name: expand;
175
+ animation-timing-function: var(--transition-ease-out);
176
+ }
177
+ }
@@ -0,0 +1,108 @@
1
+ <script setup lang="ts">
2
+ import { ref, watch, computed, useTemplateRef } from 'vue'
3
+ import { UIcon } from '../../elements'
4
+
5
+ // TODO: Label animation when collapsed is a mess. Refactor it as soon as possbile!
6
+
7
+ interface Props {
8
+ label?: string
9
+ icon: string
10
+ href?: string
11
+ target?: string
12
+ active?: boolean
13
+ collapsed?: boolean
14
+ labelHidden?: boolean
15
+ }
16
+
17
+ const {
18
+ active = false,
19
+ collapsed = false,
20
+ labelHidden = false,
21
+ href = '',
22
+ target = '_self',
23
+ } = defineProps<Props>()
24
+
25
+ const isCollapsed = ref(collapsed)
26
+ const isCollapsing = ref(false)
27
+ const isExpanding = ref(false)
28
+ const isHovering = ref(false)
29
+ const isHoverout = ref(false)
30
+ const labelEl = useTemplateRef('label')
31
+
32
+ const onWrapperAnimationEnd = (e: Event) => {
33
+ if (e.target === labelEl.value) {
34
+ isHoverout.value = false
35
+ return
36
+ }
37
+
38
+ isCollapsing.value = false
39
+ isExpanding.value = false
40
+ isHoverout.value = false
41
+
42
+ isCollapsed.value = !isCollapsed.value
43
+ }
44
+
45
+ const onHover = () => {
46
+ isHovering.value = true
47
+ }
48
+
49
+ const onHoverOut = () => {
50
+ isHovering.value = false
51
+ }
52
+
53
+ watch(
54
+ () => collapsed,
55
+ (newV) => {
56
+ if (newV) {
57
+ // Start collapsing animation
58
+ isCollapsing.value = true
59
+ } else {
60
+ // Start expanding animation
61
+ isExpanding.value = true
62
+ }
63
+ },
64
+ )
65
+
66
+ watch(isHovering, (newV) => {
67
+ if (!newV) {
68
+ isHoverout.value = true
69
+ }
70
+ })
71
+
72
+ const tag = computed(() => {
73
+ if (href) {
74
+ return 'a'
75
+ } else {
76
+ return 'span'
77
+ }
78
+ })
79
+ </script>
80
+
81
+ <template>
82
+ <component
83
+ :is="tag"
84
+ :href="tag === 'a' ? href : null"
85
+ :target="tag === 'a' ? target : null"
86
+ :class="[
87
+ 'navigation-toolbar-link',
88
+ {
89
+ active,
90
+ collapsed: isCollapsed,
91
+ 'hover-out': isHoverout,
92
+ 'is-collapsing': isCollapsing,
93
+ 'is-expanding': isExpanding,
94
+ 'label-hidden': labelHidden,
95
+ },
96
+ ]"
97
+ @animationend="onWrapperAnimationEnd"
98
+ @mouseenter="onHover"
99
+ @mouseleave="onHoverOut"
100
+ >
101
+ <UIcon :name="icon" />
102
+ <span ref="label" class="navigation-toolbar-link__label">
103
+ <slot>{{ label }}</slot>
104
+ </span>
105
+ </component>
106
+ </template>
107
+
108
+ <style lang="scss" src="./navigation-toolbar-link.scss" scoped></style>
@@ -0,0 +1,58 @@
1
+ @use '../../base/abstracts/' as a;
2
+
3
+ .wizard-text-block {
4
+ .wizard-text-block__title {
5
+ @include a.type(800, strong);
6
+
7
+ + .wizard-text-block__text {
8
+ margin-top: var(--e-space-4);
9
+ }
10
+ }
11
+
12
+ .wizard-text-block__title--small {
13
+ @include a.type(500, strong);
14
+ }
15
+
16
+ .wizard-text-block__text {
17
+ @include a.type(300);
18
+ }
19
+
20
+ @include a.bp(lg) {
21
+ .wizard-text-block__title {
22
+ @include a.type(700, strong);
23
+
24
+ + .wizard-text-block__text {
25
+ margin-top: var(--e-space-3);
26
+ }
27
+ }
28
+ }
29
+
30
+ // Modifiers
31
+ &.wizard-text-block--sub {
32
+ .wizard-text-block__title {
33
+ @include a.type(300, strong);
34
+
35
+ + .wizard-text-block__text {
36
+ margin-top: var(--e-space-2);
37
+ }
38
+ }
39
+
40
+ .wizard-text-block__text {
41
+ @include a.type(300);
42
+ }
43
+
44
+ @include a.bp(lg) {
45
+ .wizard-text-block__title {
46
+ @include a.type(200, strong);
47
+
48
+ + .wizard-text-block__text {
49
+ margin-top: var(--e-space-2);
50
+ }
51
+ }
52
+
53
+ .wizard-text-block__text {
54
+ @include a.type(200);
55
+ }
56
+ }
57
+ }
58
+ }
@@ -0,0 +1,26 @@
1
+ <script setup lang="ts">
2
+ interface Props {
3
+ variant: 'lead' | 'sub'
4
+ title?: string
5
+ text?: string
6
+ centered?: boolean
7
+ }
8
+
9
+ const { centered = false } = defineProps<Props>()
10
+ </script>
11
+
12
+ <template>
13
+ <div :class="['wizard-text-block', `wizard-text-block--${variant}`, { centered }]">
14
+ <h2 v-if="title" class="wizard-text-block__title" v-html="title" />
15
+
16
+ <div v-if="text" class="wizard-text-block__text richtext" v-html="text" />
17
+ </div>
18
+ </template>
19
+
20
+ <style scoped lang="scss">
21
+ @use './text-block.scss';
22
+
23
+ .centered {
24
+ text-align: center;
25
+ }
26
+ </style>