@codecavepro/brand 3.2.1 → 3.2.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.
|
@@ -1,19 +1,30 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed } from "vue";
|
|
3
3
|
|
|
4
|
-
const props = defineProps<{
|
|
4
|
+
const props = withDefaults(defineProps<{
|
|
5
5
|
isDisabled?: boolean
|
|
6
6
|
title?: string
|
|
7
|
+
ariaLabel?: string
|
|
7
8
|
as?: 'link'
|
|
8
9
|
href?: string
|
|
9
10
|
variant?: 'primary' | 'secondary' | 'tertiary' | 'ghost' | 'text' | 'link' | 'icon'
|
|
10
|
-
type?: 'submit'
|
|
11
|
+
type?: 'button' | 'submit'
|
|
11
12
|
class?: string
|
|
12
|
-
}>()
|
|
13
|
+
}>(), {
|
|
14
|
+
type: 'button',
|
|
15
|
+
})
|
|
16
|
+
|
|
13
17
|
const buttonBaseClass = `flex items-center justify-center
|
|
14
|
-
${props.isDisabled
|
|
18
|
+
${props.isDisabled
|
|
19
|
+
? 'cursor-not-allowed opacity-60'
|
|
20
|
+
: 'cursor-pointer'}
|
|
15
21
|
w-fit max-w-full min-w-12 min-h-12 rounded-full text-body-primary font-bold transition-colors`
|
|
16
|
-
|
|
22
|
+
|
|
23
|
+
const linkBaseClass = `flex transition-colors
|
|
24
|
+
${props.isDisabled
|
|
25
|
+
? 'cursor-not-allowed opacity-60'
|
|
26
|
+
: 'cursor-pointer'}`
|
|
27
|
+
|
|
17
28
|
const variantClass = computed(() => {
|
|
18
29
|
switch (props.variant) {
|
|
19
30
|
case 'secondary':
|
|
@@ -32,14 +43,29 @@ const variantClass = computed(() => {
|
|
|
32
43
|
return `${buttonBaseClass} px-6 py-1 bg-primary-500 hover:bg-primary-700 active:bg-primary-900`
|
|
33
44
|
}
|
|
34
45
|
})
|
|
46
|
+
|
|
47
|
+
const preventDisabledLinkActivation = (event: Event) => {
|
|
48
|
+
if (props.isDisabled) {
|
|
49
|
+
event.preventDefault()
|
|
50
|
+
event.stopPropagation()
|
|
51
|
+
}
|
|
52
|
+
}
|
|
35
53
|
</script>
|
|
36
54
|
|
|
37
55
|
<template>
|
|
38
|
-
<a v-if="props.as === 'link'"
|
|
56
|
+
<a v-if="props.as === 'link'"
|
|
57
|
+
:href="props.isDisabled ? '' : props.href"
|
|
58
|
+
:class="[variantClass, props.class ?? '']"
|
|
59
|
+
:aria-disabled="props.isDisabled ? 'true' : undefined"
|
|
60
|
+
:tabindex="props.isDisabled ? -1 : undefined"
|
|
61
|
+
@click="preventDisabledLinkActivation"
|
|
62
|
+
@keydown.enter="preventDisabledLinkActivation"
|
|
63
|
+
@keydown.space.prevent="preventDisabledLinkActivation">
|
|
39
64
|
<span>{{ title }}</span>
|
|
40
65
|
<slot />
|
|
41
66
|
</a>
|
|
42
|
-
|
|
67
|
+
|
|
68
|
+
<button v-else :type="props.type" :disabled="props.isDisabled" :class="[variantClass, props.class ?? '']" :aria-label="props.ariaLabel">
|
|
43
69
|
{{ title }}
|
|
44
70
|
<slot />
|
|
45
71
|
</button>
|
|
@@ -2,39 +2,53 @@
|
|
|
2
2
|
import { ref } from "vue";
|
|
3
3
|
|
|
4
4
|
defineProps<{
|
|
5
|
-
id: string
|
|
6
|
-
label: string
|
|
7
|
-
placeholder: string
|
|
8
|
-
isRequired?: boolean
|
|
9
|
-
isError?: boolean
|
|
10
|
-
errorMessage?: string
|
|
11
|
-
modelValue?: string
|
|
12
|
-
}>()
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
}
|
|
5
|
+
id: string;
|
|
6
|
+
label: string;
|
|
7
|
+
placeholder: string;
|
|
8
|
+
isRequired?: boolean;
|
|
9
|
+
isError?: boolean;
|
|
10
|
+
errorMessage?: string;
|
|
11
|
+
modelValue?: string;
|
|
12
|
+
}>();
|
|
13
|
+
|
|
14
|
+
const emit = defineEmits(["update:modelValue"]);
|
|
15
|
+
|
|
16
|
+
const textareaRef = ref<HTMLTextAreaElement | null>(null);
|
|
17
|
+
|
|
18
|
+
const MAX_HEIGHT = 300;
|
|
21
19
|
|
|
22
|
-
|
|
20
|
+
const autoResize = (event: Event) => {
|
|
21
|
+
const textarea = event.target as HTMLTextAreaElement;
|
|
22
|
+
|
|
23
|
+
textarea.style.height = "auto";
|
|
24
|
+
|
|
25
|
+
const height = Math.min(textarea.scrollHeight, MAX_HEIGHT);
|
|
26
|
+
textarea.style.height = `${height}px`;
|
|
27
|
+
textarea.style.overflowY =
|
|
28
|
+
textarea.scrollHeight > MAX_HEIGHT ? "auto" : "hidden";
|
|
29
|
+
|
|
30
|
+
emit("update:modelValue", textarea.value);
|
|
31
|
+
};
|
|
23
32
|
</script>
|
|
24
33
|
|
|
25
34
|
<template>
|
|
26
35
|
<div class="w-full relative">
|
|
27
|
-
<div :class="`focus-area flex flex-col min-h-[7.5rem] p-3 rounded-lg bg-surface-secondary border border-surface-tertiary hover:bg-surface-tertiary transition-colors text-heading
|
|
28
|
-
${isError ? 'input-error' : ''}`"
|
|
36
|
+
<div :class="`focus-area flex flex-col min-h-[7.5rem] p-3 rounded-lg bg-surface-secondary border border-surface-tertiary hover:bg-surface-tertiary transition-colors text-heading
|
|
37
|
+
${isError ? 'input-error' : ''}`"
|
|
38
|
+
>
|
|
29
39
|
<label :for="id" class="font-bold text-sm select-none">
|
|
30
40
|
{{ label }}
|
|
31
41
|
</label>
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
ref="textareaRef"
|
|
35
|
-
:id="id"
|
|
36
|
-
:
|
|
37
|
-
|
|
42
|
+
|
|
43
|
+
<textarea
|
|
44
|
+
ref="textareaRef"
|
|
45
|
+
:id="id"
|
|
46
|
+
:placeholder="placeholder"
|
|
47
|
+
:value="modelValue"
|
|
48
|
+
@input="autoResize"
|
|
49
|
+
:class="`w-full flex-grow resize-none placeholder:pt-1.5 placeholder:text-xs placeholder:text-body-secondary outline-none
|
|
50
|
+
${isError ? 'text-error focus:text-error' : 'text-hovered focus:text-hovered'}`"
|
|
51
|
+
/>
|
|
38
52
|
</div>
|
|
39
53
|
<span v-if="isError" class="text-error text-xs">
|
|
40
54
|
{{ errorMessage }}
|
|
@@ -44,12 +58,14 @@ defineEmits(['update:modelValue'])
|
|
|
44
58
|
|
|
45
59
|
<style scoped>
|
|
46
60
|
.focus-area:focus-within {
|
|
47
|
-
box-shadow:
|
|
61
|
+
box-shadow:
|
|
62
|
+
0 0 16px 0 hsl(from var(--color-brand-500) h s l / 0.5),
|
|
48
63
|
0 0 4px 0 hsl(from var(--color-brand-500) h s l / 0.8);
|
|
49
64
|
}
|
|
50
65
|
|
|
51
66
|
.input-error {
|
|
52
|
-
box-shadow:
|
|
67
|
+
box-shadow:
|
|
68
|
+
0 0 16px 0 hsl(from var(--color-error-200) h s l / 0.5),
|
|
53
69
|
0 0 4px 0 hsl(from var(--color-error-100) h s l / 0.6);
|
|
54
70
|
}
|
|
55
71
|
</style>
|
|
@@ -18,19 +18,19 @@ defineProps<{
|
|
|
18
18
|
</script>
|
|
19
19
|
|
|
20
20
|
<template>
|
|
21
|
-
<
|
|
22
|
-
<p class="text-body-secondary uppercase font-bold text-xs">
|
|
21
|
+
<nav :aria-labelledby="`${groupName}-label`" class="space-y-4">
|
|
22
|
+
<p :id="`${groupName}-label`" class="text-body-secondary uppercase font-bold text-xs" >
|
|
23
23
|
{{ groupName }}
|
|
24
24
|
</p>
|
|
25
|
-
<
|
|
26
|
-
<
|
|
25
|
+
<ul class="space-y-3 xl:space-y-2 text-sm">
|
|
26
|
+
<li v-for="(item, index) in items" :key="index">
|
|
27
27
|
<Button
|
|
28
28
|
:title="item.name"
|
|
29
29
|
as="link"
|
|
30
30
|
:href="item.href"
|
|
31
31
|
variant="text"
|
|
32
32
|
/>
|
|
33
|
-
</
|
|
34
|
-
</
|
|
35
|
-
</
|
|
33
|
+
</li>
|
|
34
|
+
</ul>
|
|
35
|
+
</nav>
|
|
36
36
|
</template>
|
|
@@ -76,7 +76,7 @@ const handleCloseMenu = () => {
|
|
|
76
76
|
<template>
|
|
77
77
|
<div>
|
|
78
78
|
<div class="fixed z-50 top-0 w-full bg-surface-primary-transparent backdrop-blur-3xl border-b border-surface-quaternary">
|
|
79
|
-
<div :class="
|
|
79
|
+
<div :class="['px-5 flex flex-col gap-2 transition-all', isMenuOpen ? 'pb-5 h-dvh' : 'pb-0']">
|
|
80
80
|
<div class="flex justify-between items-center py-1.5 shrink-0">
|
|
81
81
|
<a :href="homeHref" class="px-1.5 hover:opacity-80 transition-opacity">
|
|
82
82
|
<img :src="logo" alt="CODECAVE" />
|
|
@@ -85,12 +85,12 @@ const handleCloseMenu = () => {
|
|
|
85
85
|
<span></span>
|
|
86
86
|
</button>
|
|
87
87
|
</div>
|
|
88
|
-
<nav v-if="isMenuOpen" class="flex-1 min-h-0 overflow-
|
|
88
|
+
<nav v-if="isMenuOpen" class="flex-1 min-h-0 overflow-hidden text-sm">
|
|
89
89
|
<div v-if="isServicesOpen" class="h-full flex flex-col min-h-0">
|
|
90
90
|
<h2 class="text-center font-bold text-body-primary py-2.5 shrink-0">
|
|
91
91
|
{{ servicesItem?.submenuTitle }}
|
|
92
92
|
</h2>
|
|
93
|
-
<div class="flex-1 min-h-0 overflow-y-auto">
|
|
93
|
+
<div class="services-scroll flex-1 min-h-0 overflow-y-auto overscroll-contain">
|
|
94
94
|
<slot name="services" />
|
|
95
95
|
</div>
|
|
96
96
|
|
|
@@ -136,4 +136,13 @@ const handleCloseMenu = () => {
|
|
|
136
136
|
background-color: currentColor;
|
|
137
137
|
border-radius: 3rem;
|
|
138
138
|
}
|
|
139
|
+
|
|
140
|
+
.services-scroll {
|
|
141
|
+
min-height: 0;
|
|
142
|
+
overflow-y: auto;
|
|
143
|
+
overflow-x: hidden;
|
|
144
|
+
-webkit-overflow-scrolling: touch;
|
|
145
|
+
overscroll-behavior-y: contain;
|
|
146
|
+
touch-action: pan-y;
|
|
147
|
+
}
|
|
139
148
|
</style>
|
package/package.json
CHANGED