@awes-io/ui 2.99.0 → 2.100.1

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 CHANGED
@@ -3,6 +3,38 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [2.100.1](https://github.com/awes-io/client/compare/@awes-io/ui@2.100.0...@awes-io/ui@2.100.1) (2024-04-05)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * styles fixes ([baf58ba](https://github.com/awes-io/client/commit/baf58ba2e65709e5faed5203246c07c609c945f8))
12
+
13
+
14
+
15
+
16
+
17
+ # [2.100.0](https://github.com/awes-io/client/compare/@awes-io/ui@2.99.0...@awes-io/ui@2.100.0) (2024-04-04)
18
+
19
+
20
+ ### Bug Fixes
21
+
22
+ * **nuxt-auth:** remove auth interceptor fixed ([389b092](https://github.com/awes-io/client/commit/389b092e4d95771104c747b29e8324689624f6d5))
23
+ * fix style in page single ([bb63361](https://github.com/awes-io/client/commit/bb633613ec304753bc9af4336590cfcdbb2d1cca))
24
+ * select native caret properly named ([87cfef9](https://github.com/awes-io/client/commit/87cfef93f6b5c0cba9b84d20bab721705481d791))
25
+ * toggle show aside z-index increeased ([6d6aeb9](https://github.com/awes-io/client/commit/6d6aeb961d7ab6a9185c2b8303d35163dc0c6bc2))
26
+ * typography styles updated ([f998b63](https://github.com/awes-io/client/commit/f998b63107374516647ad31ba799bcddaf152094))
27
+
28
+
29
+ ### Features
30
+
31
+ * add new header for aw page ([a2d895a](https://github.com/awes-io/client/commit/a2d895a84182f849db86c0c8a5cee0df077bc428))
32
+ * page headers unified ([00afeb8](https://github.com/awes-io/client/commit/00afeb8655c8c76e8cd96a80734ed77af229bdb0))
33
+
34
+
35
+
36
+
37
+
6
38
  # [2.99.0](https://github.com/awes-io/client/compare/@awes-io/ui@2.98.2...@awes-io/ui@2.99.0) (2024-03-25)
7
39
 
8
40
 
@@ -1,10 +1,15 @@
1
1
  .aw-action-button {
2
2
  @apply bg-surface;
3
3
 
4
+ --min-header-height: 2.875rem;
5
+
4
6
  display: grid;
5
7
  align-items: start;
6
8
  grid-template-columns: auto 1fr auto;
7
- grid-template-rows: max-content minmax(0, auto);
9
+ grid-template-rows: minmax(var(--min-header-height), max-content) minmax(
10
+ 0,
11
+ auto
12
+ );
8
13
  gap: 0 1rem;
9
14
 
10
15
  padding: 2rem;
@@ -38,12 +43,14 @@
38
43
 
39
44
  &__text {
40
45
  font-size: 1rem;
46
+ font-weight: 700;
41
47
  line-height: 1.5;
42
48
  align-self: center;
43
49
  }
44
50
 
45
51
  &__description {
46
52
  display: block;
53
+ font-weight: normal;
47
54
  margin-top: 0.25rem;
48
55
  }
49
56
 
@@ -61,4 +68,11 @@
61
68
  &--narrow {
62
69
  padding: 1rem;
63
70
  }
71
+
72
+ & > :where(.aw-action-icon) {
73
+ margin-top: max(
74
+ 0px,
75
+ calc((var(--min-header-height) - var(--size)) / 2)
76
+ );
77
+ }
64
78
  }
@@ -1,12 +1,6 @@
1
1
  .aw-description {
2
2
  font-size: theme('fontSize.sm', 0.875rem);
3
+ line-height: 1.2857;
3
4
  color: var(--c-mono-400);
4
5
  }
5
6
 
6
- span.aw-description {
7
- line-height: 16px;
8
- }
9
-
10
- p.aw-description {
11
- line-height: 21px;
12
- }
@@ -21,6 +21,7 @@
21
21
 
22
22
  &.aw-layout-menu--hide-submenu {
23
23
  max-width: 6rem;
24
+ z-index: 11;
24
25
  }
25
26
 
26
27
  & ~ * {
@@ -42,7 +43,6 @@
42
43
  }
43
44
 
44
45
  .layout {
45
-
46
46
  &&--default,
47
47
  &&--simple {
48
48
  position: relative;
@@ -130,7 +130,6 @@
130
130
  }
131
131
 
132
132
  @media (min-width: 35rem) {
133
-
134
133
  .layout {
135
134
  &&--frame-center,
136
135
  &&--frame-left {
@@ -151,7 +150,6 @@
151
150
 
152
151
  @media (max-width: 35rem) {
153
152
  .layout {
154
-
155
153
  &&--frame-center,
156
154
  &&--frame-left {
157
155
  background-image: none !important;
@@ -182,7 +180,7 @@
182
180
  }
183
181
 
184
182
  &&--simple &__content {
185
- @apply pl-0;
183
+ @apply pl-0;
186
184
  }
187
185
 
188
186
  &__logo {
@@ -2,10 +2,29 @@
2
2
  display: flex;
3
3
  align-items: center;
4
4
  gap: 1rem;
5
- padding: var(--header-padding-top) 1.5rem var(--header-padding-bottom);
5
+
6
+ padding: var(--header-padding-top) var(--header-padding-horizontal)
7
+ var(--header-padding-bottom);
6
8
  height: var(--header-height);
9
+ box-shadow: none;
7
10
 
8
11
  position: relative;
12
+ z-index: 10;
13
+
14
+ transition: none;
15
+
16
+ &--is-stuck {
17
+ @apply bg-surface;
18
+ width: 100%;
19
+
20
+ box-shadow: 0px 10px 20px 0px rgba(0, 19, 106, 0.1);
21
+
22
+ transition: 60ms box-shadow 120ms;
23
+ animation: aw-page-header-slide 180ms ease-out;
24
+
25
+ position: sticky;
26
+ top: 0;
27
+ }
9
28
 
10
29
  .aw-progress {
11
30
  position: absolute;
@@ -13,14 +32,22 @@
13
32
  left: 0;
14
33
  }
15
34
 
35
+ &--container {
36
+ max-width: 100%;
37
+ width: var(--header-container-width);
38
+ margin-left: auto;
39
+ margin-right: auto;
40
+ }
41
+
16
42
  &--primary {
17
43
  @apply bg-surface;
44
+ width: 100%;
18
45
  }
19
46
 
20
47
  &__title {
21
48
  @apply font-body;
22
49
 
23
- flex: 1 1 50%;
50
+ flex: 1 1 calc(100% - 6rem);
24
51
 
25
52
  display: -webkit-box;
26
53
  -webkit-line-clamp: 2;
@@ -37,7 +64,7 @@
37
64
 
38
65
  &__breadcrumbs,
39
66
  &__buttons {
40
- flex: 1 1 25%;
67
+ flex: 1 1 3rem;
41
68
 
42
69
  display: flex;
43
70
  gap: 1rem;
@@ -51,27 +78,73 @@
51
78
 
52
79
  @screen md {
53
80
  .aw-page-header {
81
+ &__title {
82
+ flex: 10 1 max-content;
83
+ }
54
84
 
55
- &__title,
56
- &__breadcrumbs {
57
- flex: 1 1 calc(100% / 3);
85
+ &__breadcrumbs,
86
+ &__buttons {
87
+ flex: 1 10 max-content;
58
88
  }
59
89
 
60
90
  &__buttons {
61
- flex: 1 0 auto;
62
- min-width: calc(100% / 3);
91
+ min-width: max-content;
63
92
  }
64
93
  }
65
94
  }
66
95
 
67
96
  @screen lg {
68
97
  .aw-page-header {
69
- padding-left: 2.5rem;
70
- padding-right: 2.5rem;
98
+ /* padding-left: 2.5rem;
99
+ padding-right: 2.5rem; */
71
100
 
72
101
  &__title {
73
102
  font-size: 1.25rem;
74
103
  line-height: 1.2;
75
104
  }
105
+
106
+ &__breadcrumbs {
107
+ padding-right: 1rem;
108
+ }
109
+
110
+ &--container {
111
+ gap: 0;
112
+ width: 100%;
113
+ margin-left: 0;
114
+ margin-right: 0;
115
+ }
116
+
117
+ :where(&--container) &__breadcrumbs {
118
+ flex: 0 0
119
+ calc(
120
+ 50% - var(--header-container-width) / 2 +
121
+ var(--header-padding-horizontal)
122
+ );
123
+ }
124
+
125
+ :where(&--container) &__title {
126
+ text-align: left;
127
+ margin-right: 1rem;
128
+ }
129
+
130
+ :where(&--container) &__buttons {
131
+ margin-right: max(
132
+ 0px,
133
+ calc(
134
+ 50% - var(--header-container-width) / 2 +
135
+ var(--header-padding-horizontal)
136
+ )
137
+ );
138
+ }
139
+ }
140
+ }
141
+
142
+ @keyframes aw-page-header-slide {
143
+ from {
144
+ transform: translateY(-100%);
145
+ }
146
+
147
+ to {
148
+ transform: translateY(0);
76
149
  }
77
150
  }
@@ -5,24 +5,6 @@
5
5
  flex-direction: column;
6
6
  min-height: 100dvh;
7
7
 
8
- &__header {
9
- box-shadow: none;
10
-
11
- transition: none;
12
-
13
- z-index: 10;
14
-
15
- &--is-stuck {
16
- box-shadow: 0px 10px 20px 0px rgba(0, 19, 106, 0.1);
17
-
18
- transition: 60ms box-shadow 120ms;
19
- animation: aw-page-single-header-slide 180ms ease-out;
20
-
21
- position: sticky;
22
- top: 0;
23
- }
24
- }
25
-
26
8
  &__container {
27
9
  flex-grow: 1;
28
10
 
@@ -45,8 +27,8 @@
45
27
 
46
28
  padding: 0 1.5rem;
47
29
 
48
- font-size: 1.5rem;
49
- line-height: 1;
30
+ font-size: 1.25rem;
31
+ line-height: 1.2;
50
32
  font-weight: bold;
51
33
  }
52
34
 
@@ -121,10 +103,10 @@
121
103
  &__header {
122
104
  position: sticky;
123
105
  top: 0;
106
+ }
124
107
 
125
- &--is-stuck {
126
- animation: none;
127
- }
108
+ .aw-page-header--is-stuck {
109
+ animation: none;
128
110
  }
129
111
 
130
112
  &__container {
@@ -179,13 +161,3 @@
179
161
  }
180
162
  }
181
163
  }
182
-
183
- @keyframes aw-page-single-header-slide {
184
- from {
185
- transform: translateY(-100%);
186
- }
187
-
188
- to {
189
- transform: translateY(0);
190
- }
191
- }
@@ -88,26 +88,36 @@
88
88
 
89
89
  /* TODO: remove when block removed */
90
90
  &__heading {
91
- display: contents;
91
+ display: contents;
92
+ }
93
+
94
+ &__header {
95
+ &--is-empty.aw-page-header {
96
+ display: none;
97
+ }
98
+ }
99
+
100
+ &__mobile-title {
101
+ padding: 0;
102
+
103
+ font-size: 1.25rem;
104
+ line-height: 1.2;
105
+ font-weight: bold;
106
+ margin-bottom: 1.5rem;
107
+ }
108
+
109
+ &__top-scroll-mark {
110
+ height: 1px;
111
+ margin-top: -1.5rem;
112
+ margin-bottom: 1.5rem;
92
113
  }
93
114
  }
94
115
 
95
116
  @screen lg {
96
117
  .aw-page {
97
- &__heading {
98
- position: relative;
99
-
100
- &--sticky {
101
- position: sticky;
102
- top: 0;
103
- background-color: var(--c-mono-900);
104
- border-bottom-width: 1px;
105
- z-index: 1;
106
-
107
- .aw-page-headline__container {
108
- padding-top: 0;
109
- }
110
- }
118
+ &__mobile-title,
119
+ &__top-scroll-mark {
120
+ display: none;
111
121
  }
112
122
 
113
123
  &__content {
@@ -8,6 +8,10 @@
8
8
  padding-top: 0.1875rem;
9
9
  padding-bottom: 0.1875rem;
10
10
 
11
+ &--page {
12
+ background-color: var(--c-page-bg);
13
+ }
14
+
11
15
  &.aw-search {
12
16
  padding-top: 0;
13
17
  padding-bottom: 0;
@@ -48,6 +52,12 @@
48
52
  margin-bottom: -0.1875rem;
49
53
  }
50
54
 
55
+ &--uncolor-prefix &__prefix,
56
+ &--uncolor-postfix &__postfix {
57
+ background-color: inherit;
58
+ color: inherit;
59
+ }
60
+
51
61
  &__prefix {
52
62
  @apply rounded-l;
53
63
  }
@@ -99,6 +109,10 @@
99
109
  }
100
110
  }
101
111
 
112
+ &--page &__element {
113
+ @apply bg-page-bg;
114
+ }
115
+
102
116
  &__fake-input {
103
117
  --icon-width: 2.5rem;
104
118
  --icon-count: 0;
@@ -114,6 +128,9 @@
114
128
  &.is-select,
115
129
  &.is-select &__element {
116
130
  cursor: pointer;
131
+ }
132
+
133
+ &.is-select &__element {
117
134
  position: relative;
118
135
  z-index: 1;
119
136
  background-color: transparent;
@@ -1,6 +1,7 @@
1
1
  .aw-toggle-show-aside {
2
2
  transition: width 300ms ease-in-out 0s;
3
3
  position: relative;
4
+ z-index: 29;
4
5
 
5
6
  &--hide {
6
7
  width: 1rem !important;
@@ -31,17 +31,17 @@ export const CUSTOM_COLORS_BG_LIGHT = {
31
31
  }
32
32
 
33
33
  export const CUSTOM_COLORS_BG_DARK = {
34
- red: '#791a1f',
35
- peach: '#7c3118',
36
- yellow: '#7c4a15',
37
- magenta: '#551c3b',
38
- purple: '#3e2069',
39
- 'light-blue': '#164c7e',
40
- blue: '#1c2755',
41
- green: '#306317',
42
- lime: '#3e4f13',
43
- grey: '#060709',
44
- 'light-grey': '#434447'
34
+ red: '#583433',
35
+ peach: '#583C36',
36
+ yellow: '#584729',
37
+ magenta: '#56273E',
38
+ purple: '#3F3158',
39
+ 'light-blue': '#234657',
40
+ blue: '#2E3A5C',
41
+ green: '#2D4A2C',
42
+ lime: '#464C29',
43
+ grey: '#393A3D',
44
+ 'light-grey': '#41444B'
45
45
  }
46
46
 
47
47
  export default {
@@ -130,15 +130,29 @@ export default {
130
130
  )
131
131
  return false
132
132
  }
133
+ },
134
+
135
+ theme: {
136
+ type: String,
137
+ default: ''
133
138
  }
134
139
  },
135
140
 
136
141
  computed: {
137
142
  elClasses() {
138
143
  let base = this.$options._config.baseClass
144
+ const theme = String(this.theme)
139
145
 
140
146
  return {
141
- base,
147
+ base: [
148
+ base,
149
+ {
150
+ [`${base}--page`]: theme.includes('page'),
151
+ [`${base}--uncolor-prefix`]: theme.includes(
152
+ 'uncolor-prefix'
153
+ )
154
+ }
155
+ ],
142
156
  el: `${base}__element`,
143
157
  label: `${base}__label`,
144
158
  labelRequired: `${base}__label--required`,
@@ -30,7 +30,7 @@
30
30
  </label>
31
31
 
32
32
  <div class="aw-text-field__caret pl-2 pr-4">
33
- <AwIcon name="triangle-d" size="12" />
33
+ <AwIcon name="awesio/triangle" />
34
34
  </div>
35
35
  </div>
36
36
 
@@ -2,15 +2,18 @@
2
2
  <div
3
3
  ref="element"
4
4
  class="aw-select-fake-input flex max-w-full aw-text-field is-text"
5
- :class="{
6
- 'is-filled': value === 0 || !!value,
7
- 'has-label': !!label,
8
- 'has-error': hasError,
9
- 'is-disabled': isDisabled,
10
- 'has-icon': $slots.icon,
11
- 'has-prefix': prefix,
12
- 'has-postfix': postfix
13
- }"
5
+ :class="[
6
+ themeClasses,
7
+ {
8
+ 'is-filled': value === 0 || !!value,
9
+ 'has-label': !!label,
10
+ 'has-error': hasError,
11
+ 'is-disabled': isDisabled,
12
+ 'has-icon': $slots.icon,
13
+ 'has-prefix': prefix,
14
+ 'has-postfix': postfix
15
+ }
16
+ ]"
14
17
  @click="$emit('open')"
15
18
  >
16
19
  <span
@@ -23,7 +26,7 @@
23
26
  <slot name="prefix">{{ prefix }}</slot>
24
27
  </span>
25
28
 
26
- <span class="block relative w-full">
29
+ <span class="block relative w-full min-w-0">
27
30
  <span
28
31
  class="aw-text-field__element aw-text-field__element--fake"
29
32
  tabindex="0"
@@ -95,6 +98,7 @@
95
98
  </template>
96
99
 
97
100
  <script>
101
+ import { isType } from 'rambdax'
98
102
  import TextFieldMixin from '@AwMixins/text-field'
99
103
 
100
104
  export default {
@@ -123,6 +127,11 @@ export default {
123
127
  default: ''
124
128
  },
125
129
 
130
+ theme: {
131
+ type: String,
132
+ default: ''
133
+ },
134
+
126
135
  clearable: Boolean,
127
136
 
128
137
  caret: Boolean,
@@ -135,6 +144,14 @@ export default {
135
144
  return this.size === 'md' ? 'p-3' : 'p-2'
136
145
  },
137
146
 
147
+ themeClasses() {
148
+ return isType('String', this.theme)
149
+ ? this.theme
150
+ .split(',')
151
+ .map((modifier) => `aw-text-field--${modifier.trim()}`)
152
+ : []
153
+ },
154
+
138
155
  iconCount() {
139
156
  return 0 + this.clearable + this.caret
140
157
  }
@@ -1,9 +1,23 @@
1
1
  <template>
2
- <div class="aw-modal-buttons" :class="{ 'aw-modal-buttons--desktop': isDesktop, 'aw-modal-buttons--mobile': !isDesktop }">
2
+ <div
3
+ class="aw-modal-buttons"
4
+ :class="{
5
+ 'aw-modal-buttons--desktop': isDesktop,
6
+ 'aw-modal-buttons--mobile': !isDesktop
7
+ }"
8
+ >
3
9
  <!-- visible buttons -->
4
10
  <slot name="buttons" :buttons="groupedButtons.buttons">
5
11
  <AwButton
6
- v-for="({ listeners, tooltip, size, cssClass, autoWidth, ...attrs }, i) in groupedButtons.buttons"
12
+ v-for="({
13
+ listeners,
14
+ tooltip,
15
+ size,
16
+ cssClass,
17
+ autoWidth,
18
+ ...attrs
19
+ },
20
+ i) in groupedButtons.buttons"
7
21
  :key="i"
8
22
  v-tooltip.prepend="tooltip"
9
23
  v-bind="attrs"
@@ -12,22 +26,38 @@
12
26
  :class="[
13
27
  cssClass,
14
28
  {
15
- 'aw-modal-buttons__button--equal': !isDesktop && !autoWidth
29
+ 'aw-modal-buttons__button--equal':
30
+ !isDesktop && !autoWidth
16
31
  }
17
32
  ]"
18
33
  v-on="listeners"
19
34
  />
20
35
  </slot>
21
36
 
37
+ <!-- single non-cta button -->
38
+ <AwButton
39
+ v-if="singleDropdownButton"
40
+ v-bind="singleDropdownButton.attrs"
41
+ v-tooltip.prepend="singleDropdownButton.tooltip"
42
+ v-on="singleDropdownButton.listeners"
43
+ />
44
+
22
45
  <!-- dropdown buttons -->
23
- <template v-if="groupedButtons.dropdown.length">
24
- <slot name="toggler" :v-bind="{ togglerProps, isOpened, open, close }">
46
+ <template v-else-if="groupedButtons.dropdown.length">
47
+ <slot
48
+ name="toggler"
49
+ :v-bind="{ togglerProps, isOpened, open, close }"
50
+ >
25
51
  <AwButton v-bind="togglerProps" @click="open" />
26
52
  </slot>
27
- <AwDropdown :show.sync="isOpened" :options="$options.dropdownOptions">
53
+ <AwDropdown
54
+ :show.sync="isOpened"
55
+ :options="$options.dropdownOptions"
56
+ >
28
57
  <slot name="dropdown" :buttons="groupedButtons.dropdown">
29
58
  <AwDropdownButton
30
- v-for="({ listeners, tooltip, ...attrs }, i) in groupedButtons.dropdown"
59
+ v-for="({ listeners, tooltip, ...attrs },
60
+ i) in groupedButtons.dropdown"
31
61
  :key="i"
32
62
  v-tooltip.prepend="tooltip"
33
63
  v-bind="attrs"
@@ -88,7 +118,10 @@ export default {
88
118
  groupedButtons() {
89
119
  return this.items.reduce(
90
120
  (acc, item) => {
91
- const { cta, dropdown, show = true, ...itemProps } = { ...this.options, ...item }
121
+ const { cta, dropdown, show = true, ...itemProps } = {
122
+ ...this.options,
123
+ ...item
124
+ }
92
125
 
93
126
  // rename class prop
94
127
  if (itemProps.class) {
@@ -98,10 +131,20 @@ export default {
98
131
 
99
132
  // add button if visible
100
133
  if (show !== false) {
101
- const group = this.isDesktop ? (dropdown ? 'dropdown' : 'buttons') : cta ? 'buttons' : 'dropdown'
134
+ const group = this.isDesktop
135
+ ? dropdown
136
+ ? 'dropdown'
137
+ : 'buttons'
138
+ : cta
139
+ ? 'buttons'
140
+ : 'dropdown'
102
141
 
103
142
  // omit not available colors
104
- if (group === 'dropdown' && itemProps.color && !DROPDOWN_BUTTON_COLORS.includes(itemProps.color)) {
143
+ if (
144
+ group === 'dropdown' &&
145
+ itemProps.color &&
146
+ !DROPDOWN_BUTTON_COLORS.includes(itemProps.color)
147
+ ) {
105
148
  itemProps.color = undefined
106
149
  }
107
150
 
@@ -114,12 +157,42 @@ export default {
114
157
  )
115
158
  },
116
159
 
160
+ singleDropdownButton() {
161
+ const singleButton =
162
+ this.groupedButtons.dropdown.length === 1
163
+ ? this.groupedButtons.dropdown[0]
164
+ : null
165
+
166
+ if (
167
+ singleButton &&
168
+ !!singleButton.icon &&
169
+ (singleButton.hideText || !singleButton.text)
170
+ ) {
171
+ const {
172
+ listeners,
173
+ tooltip,
174
+ ...attrs
175
+ } = this.groupedButtons.dropdown[0]
176
+
177
+ return { listeners, tooltip, attrs }
178
+ }
179
+
180
+ return null
181
+ },
182
+
117
183
  togglerSize() {
118
- return path([this.groupedButtons.buttons.length - 1, 'size'], this.groupedButtons.buttons)
184
+ return path(
185
+ [this.groupedButtons.buttons.length - 1, 'size'],
186
+ this.groupedButtons.buttons
187
+ )
119
188
  },
120
189
 
121
190
  togglerProps() {
122
- return { ...omit(['cta'], this.options || {}), size: this.togglerSize, ...this.togglerOptions }
191
+ return {
192
+ ...omit(['cta'], this.options || {}),
193
+ size: this.togglerSize,
194
+ ...this.togglerOptions
195
+ }
123
196
  }
124
197
  },
125
198
 
@@ -1,32 +1,61 @@
1
1
  <template>
2
- <div class="aw-page">
3
- <div
4
- class="aw-page__heading"
5
- :class="{
6
- 'aw-page__heading--sticky': stickyHeader
7
- }"
8
- >
2
+ <div
3
+ class="aw-page"
4
+ :style="{
5
+ '--page-buttons-bottom': _hideBottomBar ? null : '3.5rem'
6
+ }"
7
+ >
8
+ <div class="aw-page__heading">
9
9
  <slot name="heading" v-bind="{ titleTag, title, breadcrumb }">
10
- <AwPageHeadline
10
+ <AwPageHeader
11
+ ref="header"
12
+ :primary="!isDesktop && isHeaderStuck"
13
+ :title="_title"
14
+ :hide-title="!isDesktop && !isHeaderStuck"
15
+ :container="container"
16
+ :is-stuck="isHeaderStuck && !isDesktop"
17
+ hide-menu
18
+ class="aw-page__header"
19
+ :class="{
20
+ 'aw-page__header--is-empty':
21
+ !isHeaderStuck &&
22
+ !isDesktop &&
23
+ !$scopedSlots['buttons'] &&
24
+ !$scopedSlots['after-breadcrumb'] &&
25
+ !$scopedSlots['headline-breadcrumb'] &&
26
+ !backUrl &&
27
+ !isMenuToggler
28
+ }"
11
29
  :style="{
12
- '--page-buttons-bottom': _hideBottomBar
13
- ? null
14
- : '3.5rem'
30
+ '--breadcrumb-width':
31
+ backUrl || isMenuToggler ? '2.5rem' : '0px'
15
32
  }"
16
- :title="_title"
17
- :breadcrumb="breadcrumb"
18
- :breadcrumb-menu="breadcrumbMenu"
19
- :buttons-breakpoint="buttonsBreakpoint"
20
- :container="headerContainer || container"
21
- :title-centered="titleCentered || stickyHeader"
22
33
  >
23
- <template
24
- v-for="(index, name) in $scopedSlots"
25
- v-slot:[name]="data"
26
- >
27
- <slot :name="name" v-bind="data"></slot>
34
+ <template #breadcrumbs>
35
+ <slot name="headline-breadcrumb">
36
+ <AwButton
37
+ v-if="backUrl || isMenuToggler"
38
+ :color="
39
+ isDesktop || !isHeaderStuck
40
+ ? 'mono'
41
+ : 'mono-light'
42
+ "
43
+ :href="backUrl || '/more'"
44
+ :aria-label="breadcrumb?.title ?? $t('Back')"
45
+ >
46
+ <template #icon>
47
+ <AwIconSystemMono name="arrow" />
48
+ </template>
49
+ </AwButton>
50
+ </slot>
51
+
52
+ <slot name="after-breadcrumb" />
53
+ </template>
54
+
55
+ <template #default>
56
+ <slot name="buttons"></slot>
28
57
  </template>
29
- </AwPageHeadline>
58
+ </AwPageHeader>
30
59
  </slot>
31
60
 
32
61
  <!-- subnav -->
@@ -55,9 +84,20 @@
55
84
  >
56
85
  <!-- eslint-disable prettier/prettier -->
57
86
  <div :class="[containerClass, { 'aw-page__grid': hasAside }]">
87
+ <div class="aw-page__mobile-title" aria-hidden="true">
88
+ {{ _title }}
89
+ </div>
90
+
91
+ <div
92
+ ref="topScrollMark"
93
+ class="aw-page__top-scroll-mark"
94
+ aria-hidden="true"
95
+ ></div>
96
+
58
97
  <div v-if="hasAside">
59
98
  <slot />
60
99
  </div>
100
+
61
101
  <slot v-else></slot>
62
102
 
63
103
  <div v-if="hasAside">
@@ -117,7 +157,7 @@
117
157
  import { pathOr } from 'rambdax'
118
158
  import pageMixin from '@AwMixins/page'
119
159
  import AwBottomBar from '@AwOrganisms/AwBottomBar.vue'
120
- import AwPageHeadline from '@AwPages/_AwPageHeadline.vue'
160
+ import { conf } from '@AwUtils/component'
121
161
 
122
162
  export default {
123
163
  name: 'AwPage',
@@ -126,7 +166,7 @@ export default {
126
166
 
127
167
  components: {
128
168
  AwBottomBar,
129
- AwPageHeadline
169
+ AwPageHeader: () => import('@AwPages/_AwPageHeader.vue')
130
170
  },
131
171
 
132
172
  props: {
@@ -154,10 +194,6 @@ export default {
154
194
  default: null
155
195
  },
156
196
 
157
- stickyHeader: Boolean,
158
-
159
- titleCentered: Boolean,
160
-
161
197
  // Disable mobile bottom menu
162
198
  hideBottomBar: {
163
199
  type: Boolean,
@@ -178,11 +214,30 @@ export default {
178
214
  data() {
179
215
  return {
180
216
  isFullscreen: false,
181
- isFakeFullscreen: false
217
+ isFakeFullscreen: false,
218
+ isHeaderStuck: false
219
+ }
220
+ },
221
+
222
+ provide() {
223
+ return {
224
+ teleportButtonsTo: '.aw-page'
182
225
  }
183
226
  },
184
227
 
185
228
  computed: {
229
+ isMenuToggler() {
230
+ return (
231
+ !this.backUrl &&
232
+ !this.$screen.lg &&
233
+ this.breadcrumbMenu !== false
234
+ )
235
+ },
236
+
237
+ isDesktop() {
238
+ return this.$screen[this.buttonsBreakpoint] || false
239
+ },
240
+
186
241
  _hideBottomBar() {
187
242
  return this.hideBottomBar === null
188
243
  ? this._hasBreadcrumb
@@ -38,36 +38,38 @@
38
38
  </AwFlow>
39
39
 
40
40
  <!-- fixed button -->
41
- <div
41
+ <Teleport
42
42
  v-if="!isExpanded && splitButtons.fixed"
43
- class="aw-page-menu-buttons__fixed-btns"
43
+ :to="teleportButtonsTo"
44
44
  >
45
- <AwButton
46
- v-for="({ listeners, tooltip, ...attrs },
47
- i) in splitButtons.fixed"
48
- :key="i"
49
- v-tooltip="tooltip"
50
- v-bind="attrs"
51
- auto-width
52
- v-on="listeners"
53
- >
54
- <template #icon="{ icon }">
55
- <AwIcon :name="icon" />
56
- </template>
57
-
58
- <template #default="{ text }">
59
- <span
60
- v-if="text"
61
- class="aw-page-menu-buttons__fixed-btn-text truncate"
62
- :class="{
63
- 'aw-page-menu-buttons__fixed-btn-text--expanded': isInTopPosition
64
- }"
65
- >
66
- {{ text }}
67
- </span>
68
- </template>
69
- </AwButton>
70
- </div>
45
+ <div class="aw-page-menu-buttons__fixed-btns">
46
+ <AwButton
47
+ v-for="({ listeners, tooltip, ...attrs },
48
+ i) in splitButtons.fixed"
49
+ :key="i"
50
+ v-tooltip="tooltip"
51
+ v-bind="attrs"
52
+ auto-width
53
+ v-on="listeners"
54
+ >
55
+ <template #icon="{ icon }">
56
+ <AwIcon :name="icon" />
57
+ </template>
58
+
59
+ <template #default="{ text }">
60
+ <span
61
+ v-if="text"
62
+ class="aw-page-menu-buttons__fixed-btn-text truncate"
63
+ :class="{
64
+ 'aw-page-menu-buttons__fixed-btn-text--expanded': isInTopPosition
65
+ }"
66
+ >
67
+ {{ text }}
68
+ </span>
69
+ </template>
70
+ </AwButton>
71
+ </div>
72
+ </Teleport>
71
73
  </div>
72
74
  </template>
73
75
 
@@ -85,6 +87,10 @@ const toIconButton = (props) => ({
85
87
  export default {
86
88
  name: 'AwPageMenuButtons',
87
89
 
90
+ components: {
91
+ Teleport: () => import('vue2-teleport')
92
+ },
93
+
88
94
  props: {
89
95
  items: {
90
96
  type: Array,
@@ -96,6 +102,11 @@ export default {
96
102
  default: 'lg'
97
103
  },
98
104
 
105
+ teleportFixedTo: {
106
+ type: String,
107
+ default: 'body'
108
+ },
109
+
99
110
  /* max window scroll when fixed buttons expanded */
100
111
  /* pass -1 to collapse button eventually */
101
112
  expandOffset: {
@@ -118,7 +129,18 @@ export default {
118
129
  }
119
130
  },
120
131
 
132
+ inject: {
133
+ injectedTeleportButtonsTo: {
134
+ from: 'teleportButtonsTo',
135
+ default: ''
136
+ }
137
+ },
138
+
121
139
  computed: {
140
+ teleportButtonsTo() {
141
+ return this.injectedTeleportButtonsTo || this.teleportButtonsTo
142
+ },
143
+
122
144
  isExpanded() {
123
145
  return (
124
146
  this.breakpoint === 'default' || this.$screen[this.breakpoint]
@@ -7,8 +7,8 @@
7
7
  :title="_title"
8
8
  :hide-title="!isDesktop && !isHeaderStuck"
9
9
  :hide-menu="hideMenu"
10
+ :is-stuck="isHeaderStuck"
10
11
  class="aw-page-single__header"
11
- :class="{ 'aw-page-single__header--is-stuck': isHeaderStuck }"
12
12
  >
13
13
  <template #breadcrumbs>
14
14
  <slot name="breadcrumb">
@@ -174,7 +174,6 @@ export default {
174
174
 
175
175
  data() {
176
176
  return {
177
- isHeaderStuck: false,
178
177
  isActionButtonStuck: false
179
178
  }
180
179
  },
@@ -211,25 +210,6 @@ export default {
211
210
  }
212
211
  },
213
212
 
214
- watch: {
215
- isDesktop() {
216
- if (this.$options.$observer) {
217
- this.$nextTick(() => {
218
- this._disableScrollWatcher()
219
- this._initScrollWatcher()
220
- })
221
- }
222
- }
223
- },
224
-
225
- mounted() {
226
- this._initScrollWatcher()
227
- },
228
-
229
- beforeDestroy() {
230
- this._disableScrollWatcher()
231
- },
232
-
233
213
  methods: {
234
214
  _initScrollWatcher() {
235
215
  if (this.$options.$observer) return
@@ -252,13 +232,6 @@ export default {
252
232
 
253
233
  this.$options.$observer.observe(topScrollMark)
254
234
  this.$options.$observer.observe(bottomScrollMark)
255
- },
256
-
257
- _disableScrollWatcher() {
258
- if (!this.$options.$observer) return
259
-
260
- this.$options.$observer.disconnect()
261
- this.$options.$observer = null
262
235
  }
263
236
  }
264
237
  }
@@ -1,5 +1,13 @@
1
1
  <template>
2
- <div class="aw-page-header" :class="{ 'aw-page-header--primary': primary }">
2
+ <div
3
+ class="aw-page-header"
4
+ :class="{
5
+ 'aw-page-header--primary': primary,
6
+ 'aw-page-header--is-stuck': isStuck,
7
+ 'aw-page-header--container': container !== 'full'
8
+ }"
9
+ :style="{ '--header-container-width': headerContainerWidth }"
10
+ >
3
11
  <div class="aw-page-header__breadcrumbs">
4
12
  <slot name="breadcrumbs"> </slot>
5
13
  </div>
@@ -48,16 +56,40 @@ export default {
48
56
  default: ''
49
57
  },
50
58
 
59
+ container: {
60
+ type: String,
61
+ default: 'full'
62
+ },
63
+
51
64
  hideTitle: Boolean,
52
65
 
53
66
  hideMenu: Boolean,
54
67
 
55
- primary: Boolean
68
+ primary: Boolean,
69
+
70
+ isStuck: Boolean
56
71
  },
57
72
 
58
73
  computed: {
59
74
  showProgress() {
60
75
  return isType('Number', this.progress)
76
+ },
77
+
78
+ headerContainerWidth() {
79
+ let name = ''
80
+
81
+ switch (this.container) {
82
+ case 'default':
83
+ name = '--container-width'
84
+ break
85
+ case 'small':
86
+ name = '--container-small-width'
87
+ break
88
+ }
89
+
90
+ return name
91
+ ? `var(${name}, calc(100% + 2 * var(--header-padding-horizontal)))`
92
+ : null
61
93
  }
62
94
  }
63
95
  }
@@ -17,11 +17,13 @@
17
17
  class="aw-mobile-menu-item__icon-bg"
18
18
  :style="iconColor"
19
19
  >
20
- <AwIcon
21
- :name="(active && iconActive) || icon"
22
- size="24"
23
- class="aw-mobile-menu-item__icon"
24
- />
20
+ <slot name="icon">
21
+ <AwIcon
22
+ :name="(active && iconActive) || icon"
23
+ size="24"
24
+ class="aw-mobile-menu-item__icon"
25
+ />
26
+ </slot>
25
27
  </span>
26
28
 
27
29
  <span class="aw-mobile-menu-item__text" tabindex="-1">
package/mixins/page.js CHANGED
@@ -24,6 +24,12 @@ export default {
24
24
  }
25
25
  },
26
26
 
27
+ data() {
28
+ return {
29
+ isHeaderStuck: false
30
+ }
31
+ },
32
+
27
33
  head() {
28
34
  return {
29
35
  title: this.metaTitle || this.title || undefined
@@ -31,6 +37,10 @@ export default {
31
37
  },
32
38
 
33
39
  computed: {
40
+ isDesktop() {
41
+ return this.$screen.lg || false
42
+ },
43
+
34
44
  backUrl() {
35
45
  if (!this.breadcrumb) return null
36
46
 
@@ -54,5 +64,53 @@ export default {
54
64
  _hasBreadcrumb() {
55
65
  return this.breadcrumb ? !!this.breadcrumb.href : false
56
66
  }
67
+ },
68
+
69
+ watch: {
70
+ isDesktop() {
71
+ if (this.$options.$observer) {
72
+ this.$nextTick(() => {
73
+ this._disableScrollWatcher()
74
+ this._initScrollWatcher()
75
+ })
76
+ }
77
+ }
78
+ },
79
+
80
+ mounted() {
81
+ this._initScrollWatcher()
82
+ },
83
+
84
+ beforeDestory() {
85
+ this._disableScrollWatcher()
86
+ },
87
+
88
+ methods: {
89
+ _initScrollWatcher() {
90
+ if (this.$options.$observer) return
91
+
92
+ const { topScrollMark } = this.$refs
93
+
94
+ if (!topScrollMark) return
95
+
96
+ this.$options.$observer = new IntersectionObserver((entries) => {
97
+ for (let i = 0; i < entries.length; i++) {
98
+ const entry = entries[i]
99
+
100
+ if (entry.target === topScrollMark) {
101
+ this.isHeaderStuck = !entry.isIntersecting
102
+ }
103
+ }
104
+ })
105
+
106
+ this.$options.$observer.observe(topScrollMark)
107
+ },
108
+
109
+ _disableScrollWatcher() {
110
+ if (!this.$options.$observer) return
111
+
112
+ this.$options.$observer.disconnect()
113
+ this.$options.$observer = null
114
+ }
57
115
  }
58
116
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@awes-io/ui",
3
- "version": "2.99.0",
3
+ "version": "2.100.1",
4
4
  "description": "User Interface (UI) components",
5
5
  "keywords": [
6
6
  "ui",
@@ -114,5 +114,5 @@
114
114
  "rollup-plugin-visualizer": "^2.6.0",
115
115
  "rollup-plugin-vue": "^5.0.1"
116
116
  },
117
- "gitHead": "1b79780032eecf84dc91941f9d11fbebcd1f97ae"
117
+ "gitHead": "d3cadf5921e51b1a8f4af71e028928a7f072733c"
118
118
  }
@@ -14,7 +14,9 @@ module.exports = function({ addComponents, theme }) {
14
14
  const container = [
15
15
  {
16
16
  ':root': {
17
- '--container-padding': paddingDefault
17
+ '--container-padding': paddingDefault,
18
+ '--container-width': maxWidth,
19
+ '--container-small-width': smallWidth
18
20
  },
19
21
  '.container, .container-fluid, .container-small': _.merge(
20
22
  { width: '100%' },