@codecavepro/brand 2.7.1 → 2.7.3

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.
@@ -32,13 +32,13 @@ if (
32
32
  aria-label="Section"
33
33
  >
34
34
  <div class="ds-subnav-inner">
35
- <ul class="flex w-max min-w-full flex-nowrap">
35
+ <ul>
36
36
  <li
37
37
  v-for="item in items"
38
38
  :key="item.name"
39
39
  >
40
40
  <a
41
- class="btn btn-ghost whitespace-nowrap"
41
+ class="ds-subnav-link"
42
42
  :href="item.href"
43
43
  :aria-current="item.name === current ? 'page' : undefined"
44
44
  >
@@ -48,4 +48,84 @@ if (
48
48
  </ul>
49
49
  </div>
50
50
  </nav>
51
- </template>
51
+ </template>
52
+
53
+ <style>
54
+ .ds-subnav {
55
+ border-bottom: 1px solid var(--color-surface-quaternary);
56
+ background: var(--color-surface-primary-transparent);
57
+ -webkit-backdrop-filter: blur(24px);
58
+ backdrop-filter: blur(24px);
59
+ }
60
+
61
+ .ds-subnav-inner {
62
+ box-sizing: border-box;
63
+ max-width: var(--max-width-desktop);
64
+ margin: 0 auto;
65
+
66
+ overflow-x: auto;
67
+ overflow-y: hidden;
68
+ }
69
+
70
+ @media (min-width: 768px) {
71
+ .ds-subnav-inner {
72
+ padding-left: var(--gutter-md);
73
+ padding-right: var(--gutter-md);
74
+ }
75
+ }
76
+
77
+ @media (min-width: 1280px) {
78
+ .ds-subnav-inner {
79
+ padding-left: var(--gutter-xl);
80
+ padding-right: var(--gutter-xl);
81
+ }
82
+ }
83
+
84
+ /* center links when there is enough space */
85
+ .ds-subnav ul {
86
+ display: flex;
87
+ align-items: center;
88
+ justify-content: center;
89
+
90
+ margin: 0;
91
+ padding: 0;
92
+ list-style: none;
93
+
94
+ /* allow overflow while staying centered */
95
+ width: max-content;
96
+ min-width: 100%;
97
+
98
+ /* prevents wrapping */
99
+ flex-wrap: nowrap;
100
+ }
101
+
102
+ .ds-subnav li {
103
+ margin: 0;
104
+ flex-shrink: 0;
105
+ }
106
+
107
+ .ds-subnav-link {
108
+ box-sizing: border-box;
109
+ display: inline-flex;
110
+ align-items: center;
111
+ justify-content: center;
112
+ min-height: var(--control-height);
113
+ padding: 0.5rem 1.5rem;
114
+ border-radius: var(--radius-pill);
115
+ color: var(--color-body-primary);
116
+ font-family: var(--font-sans);
117
+ font-size: var(--text-body);
118
+ font-weight: var(--font-weight-bold);
119
+ line-height: var(--leading-body);
120
+ text-decoration: none;
121
+ white-space: nowrap;
122
+ cursor: pointer;
123
+ transition: color var(--transition-colors);
124
+ }
125
+
126
+ .ds-subnav-link:hover,
127
+ .ds-subnav-link:active,
128
+ .ds-subnav-link[aria-current="page"] {
129
+ color: var(--color-hovered);
130
+ }
131
+ </style>
@@ -135,7 +135,7 @@ const currentValues = (): ContactFormValues => ({
135
135
  })
136
136
 
137
137
  const isSubmitting = ref(false)
138
-
138
+ const isFormSubmitted = ref(false)
139
139
  const submitContactsForm = async () => {
140
140
  if (isSubmitting.value || !validateForm()) {
141
141
  return
@@ -149,12 +149,10 @@ const submitContactsForm = async () => {
149
149
  const result = await props.client.submit(values)
150
150
 
151
151
  if (result.ok) {
152
+ isFormSubmitted.value = true
152
153
  resetForm()
153
154
  showAlert('success')
154
155
  } else {
155
- /* The previous code logged the failure and showed nothing, so a visitor
156
- * whose enquiry never sent had no way to know. The wording below is a
157
- * placeholder for a writer -- see CCWEB2-325. */
158
156
  showAlert('error')
159
157
  }
160
158
 
@@ -189,6 +187,41 @@ watch(isAlertVisible, () => {
189
187
  })
190
188
  })
191
189
 
190
+ const validateField = (field) => {
191
+ if (isFormSubmitted.value) {
192
+ field.error = ''
193
+ return
194
+ }
195
+
196
+ if (field.required && !field.value) {
197
+ field.error = 'This field is required'
198
+ return
199
+ }
200
+
201
+ field.error = ''
202
+ }
203
+
204
+ const fields = [
205
+ 'email',
206
+ 'firstName',
207
+ 'companyName',
208
+ 'linkedinCompanyPage',
209
+ 'privacyPolicy'
210
+ ]
211
+
212
+ fields.forEach((key) => {
213
+ watch(
214
+ () => formData.value[key].value,
215
+ (value) => {
216
+ if (isFormSubmitted.value && value) {
217
+ isFormSubmitted.value = false
218
+ }
219
+
220
+ validateField(formData.value[key])
221
+ }
222
+ )
223
+ })
224
+
192
225
  </script>
193
226
 
194
227
  <template>
@@ -220,18 +253,18 @@ watch(isAlertVisible, () => {
220
253
  </div>
221
254
  </div>
222
255
  <GlowButton @click="submitContactsForm" title="Leave consultation request" class="self-center lg:self-start" />
223
- <div v-show="isAlertVisible" class="border border-action group absolute bottom-19.25 md:fixed z-50 left-1/2 -translate-x-1/2 md:top-24 form-alert flex gap-2 md:gap-8 items-center justify-between w-full h-fit max-w-139 bg-surface-secondary p-4 md:px-6 md:py-2.5 rounded-3xl">
256
+ </form>
257
+ <div v-show="isAlertVisible" class="border border-action group absolute bottom-19.25 md:fixed z-350 left-1/2 -translate-x-1/2 md:top-40 form-alert flex gap-2 md:gap-8 items-center justify-between w-full h-fit max-w-139 bg-surface-secondary p-4 md:px-6 md:py-2.5 rounded-3xl">
224
258
  <div v-if="alertKind === 'success'" class="w-8 h-8">
225
259
  <component :is="SuccessIcon" class="w-8 h-8" />
226
260
  </div>
227
- <p class="text-sm md:text-lg font-bold text-heading md:max-w-sm">
261
+ <p class="text-sm md:text-lg font-bold text-heading md:max-w-sm ">
228
262
  {{ alertKind ? ALERT_TEXT[alertKind] : '' }}
229
263
  </p>
230
264
  <button @click="alertKind = null" class="group-hover:text-action text-heading transition-colors cursor-pointer">
231
265
  <component :is="CloseIcon" />
232
266
  </button>
233
267
  </div>
234
- </form>
235
268
  </template>
236
269
 
237
270
  <style scoped>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codecavepro/brand",
3
- "version": "2.7.1",
3
+ "version": "2.7.3",
4
4
  "description": "CODECAVE design system — colour, typography and layout tokens as CSS custom properties and as a typed module.",
5
5
  "license": "Unlicense",
6
6
  "type": "module",