@designcrowd/fe-shared-lib 1.6.10-voiceText → 1.6.10-voiceText-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/.claude/skills/playwright-cli/SKILL.md +278 -0
- package/.claude/skills/playwright-cli/references/request-mocking.md +87 -0
- package/.claude/skills/playwright-cli/references/running-code.md +232 -0
- package/.claude/skills/playwright-cli/references/session-management.md +169 -0
- package/.claude/skills/playwright-cli/references/storage-state.md +275 -0
- package/.claude/skills/playwright-cli/references/test-generation.md +88 -0
- package/.claude/skills/playwright-cli/references/tracing.md +139 -0
- package/.claude/skills/playwright-cli/references/video-recording.md +43 -0
- package/.playwright-cli/page-2026-04-13T02-23-08-374Z.yml +68 -0
- package/.playwright-cli/page-2026-04-13T02-23-13-730Z.yml +421 -0
- package/CLAUDE.md +35 -0
- package/package.json +3 -1
- package/public/css/tailwind-brandCrowd.css +25 -0
- package/public/css/tailwind-brandPage.css +21 -0
- package/public/css/tailwind-crazyDomains.css +25 -0
- package/public/css/tailwind-designCom.css +25 -0
- package/public/css/tailwind-designCrowd.css +25 -0
- package/src/atoms/components/Modal/Modal.vue +9 -0
- package/src/atoms/components/VoiceToTextButton/VoiceToTextButton.stories.js +59 -61
- package/src/atoms/components/VoiceToTextButton/VoiceToTextButton.vue +50 -13
|
@@ -1896,6 +1896,10 @@ video {
|
|
|
1896
1896
|
--tw-text-opacity: 1;
|
|
1897
1897
|
color: rgb(140 18 59 / var(--tw-text-opacity));
|
|
1898
1898
|
}
|
|
1899
|
+
.theme-crazyDomains .tw-text-grayscale-400 {
|
|
1900
|
+
--tw-text-opacity: 1;
|
|
1901
|
+
color: rgb(235 238 243 / var(--tw-text-opacity));
|
|
1902
|
+
}
|
|
1899
1903
|
.theme-crazyDomains .tw-text-grayscale-500 {
|
|
1900
1904
|
--tw-text-opacity: 1;
|
|
1901
1905
|
color: rgb(199 204 207 / var(--tw-text-opacity));
|
|
@@ -2049,6 +2053,11 @@ video {
|
|
|
2049
2053
|
--tw-drop-shadow: drop-shadow(0 1px 1px rgb(0 0 0 / 0.05));
|
|
2050
2054
|
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
|
2051
2055
|
}
|
|
2056
|
+
.theme-crazyDomains .tw-transition-all {
|
|
2057
|
+
transition-property: all;
|
|
2058
|
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
2059
|
+
transition-duration: 150ms;
|
|
2060
|
+
}
|
|
2052
2061
|
.theme-crazyDomains .tw-transition-colors {
|
|
2053
2062
|
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
|
|
2054
2063
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
@@ -2076,6 +2085,10 @@ video {
|
|
|
2076
2085
|
.theme-crazyDomains .tw-ease-out {
|
|
2077
2086
|
transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
|
|
2078
2087
|
}
|
|
2088
|
+
.theme-crazyDomains .hover\:tw-border-grayscale-300:hover {
|
|
2089
|
+
--tw-border-opacity: 1;
|
|
2090
|
+
border-color: rgb(240 240 245 / var(--tw-border-opacity));
|
|
2091
|
+
}
|
|
2079
2092
|
.theme-crazyDomains .hover\:tw-border-grayscale-400:hover {
|
|
2080
2093
|
--tw-border-opacity: 1;
|
|
2081
2094
|
border-color: rgb(235 238 243 / var(--tw-border-opacity));
|
|
@@ -2240,6 +2253,18 @@ video {
|
|
|
2240
2253
|
outline: 2px solid transparent;
|
|
2241
2254
|
outline-offset: 2px;
|
|
2242
2255
|
}
|
|
2256
|
+
.theme-crazyDomains .focus\:tw-ring-2:focus {
|
|
2257
|
+
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
|
2258
|
+
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
|
2259
|
+
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
|
2260
|
+
}
|
|
2261
|
+
.theme-crazyDomains .focus\:tw-ring-primary-500:focus {
|
|
2262
|
+
--tw-ring-opacity: 1;
|
|
2263
|
+
--tw-ring-color: rgb(111 172 47 / var(--tw-ring-opacity));
|
|
2264
|
+
}
|
|
2265
|
+
.theme-crazyDomains .focus\:tw-ring-offset-2:focus {
|
|
2266
|
+
--tw-ring-offset-width: 2px;
|
|
2267
|
+
}
|
|
2243
2268
|
.theme-crazyDomains .tw-group:hover .group-hover\:tw-text-info-500 {
|
|
2244
2269
|
--tw-text-opacity: 1;
|
|
2245
2270
|
color: rgb(0 161 239 / var(--tw-text-opacity));
|
|
@@ -1896,6 +1896,10 @@ video {
|
|
|
1896
1896
|
--tw-text-opacity: 1;
|
|
1897
1897
|
color: rgb(136 44 32 / var(--tw-text-opacity));
|
|
1898
1898
|
}
|
|
1899
|
+
.theme-designCom .tw-text-grayscale-400 {
|
|
1900
|
+
--tw-text-opacity: 1;
|
|
1901
|
+
color: rgb(227 227 227 / var(--tw-text-opacity));
|
|
1902
|
+
}
|
|
1899
1903
|
.theme-designCom .tw-text-grayscale-500 {
|
|
1900
1904
|
--tw-text-opacity: 1;
|
|
1901
1905
|
color: rgb(209 209 209 / var(--tw-text-opacity));
|
|
@@ -2049,6 +2053,11 @@ video {
|
|
|
2049
2053
|
--tw-drop-shadow: drop-shadow(0 1px 1px rgb(0 0 0 / 0.05));
|
|
2050
2054
|
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
|
2051
2055
|
}
|
|
2056
|
+
.theme-designCom .tw-transition-all {
|
|
2057
|
+
transition-property: all;
|
|
2058
|
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
2059
|
+
transition-duration: 150ms;
|
|
2060
|
+
}
|
|
2052
2061
|
.theme-designCom .tw-transition-colors {
|
|
2053
2062
|
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
|
|
2054
2063
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
@@ -2076,6 +2085,10 @@ video {
|
|
|
2076
2085
|
.theme-designCom .tw-ease-out {
|
|
2077
2086
|
transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
|
|
2078
2087
|
}
|
|
2088
|
+
.theme-designCom .hover\:tw-border-grayscale-300:hover {
|
|
2089
|
+
--tw-border-opacity: 1;
|
|
2090
|
+
border-color: rgb(237 237 237 / var(--tw-border-opacity));
|
|
2091
|
+
}
|
|
2079
2092
|
.theme-designCom .hover\:tw-border-grayscale-400:hover {
|
|
2080
2093
|
--tw-border-opacity: 1;
|
|
2081
2094
|
border-color: rgb(227 227 227 / var(--tw-border-opacity));
|
|
@@ -2240,6 +2253,18 @@ video {
|
|
|
2240
2253
|
outline: 2px solid transparent;
|
|
2241
2254
|
outline-offset: 2px;
|
|
2242
2255
|
}
|
|
2256
|
+
.theme-designCom .focus\:tw-ring-2:focus {
|
|
2257
|
+
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
|
2258
|
+
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
|
2259
|
+
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
|
2260
|
+
}
|
|
2261
|
+
.theme-designCom .focus\:tw-ring-primary-500:focus {
|
|
2262
|
+
--tw-ring-opacity: 1;
|
|
2263
|
+
--tw-ring-color: rgb(63 89 246 / var(--tw-ring-opacity));
|
|
2264
|
+
}
|
|
2265
|
+
.theme-designCom .focus\:tw-ring-offset-2:focus {
|
|
2266
|
+
--tw-ring-offset-width: 2px;
|
|
2267
|
+
}
|
|
2243
2268
|
.theme-designCom .tw-group:hover .group-hover\:tw-text-info-500 {
|
|
2244
2269
|
--tw-text-opacity: 1;
|
|
2245
2270
|
color: rgb(63 89 246 / var(--tw-text-opacity));
|
|
@@ -1896,6 +1896,10 @@ video {
|
|
|
1896
1896
|
--tw-text-opacity: 1;
|
|
1897
1897
|
color: rgb(146 38 36 / var(--tw-text-opacity));
|
|
1898
1898
|
}
|
|
1899
|
+
.theme-designCrowd .tw-text-grayscale-400 {
|
|
1900
|
+
--tw-text-opacity: 1;
|
|
1901
|
+
color: rgb(230 230 230 / var(--tw-text-opacity));
|
|
1902
|
+
}
|
|
1899
1903
|
.theme-designCrowd .tw-text-grayscale-500 {
|
|
1900
1904
|
--tw-text-opacity: 1;
|
|
1901
1905
|
color: rgb(204 204 204 / var(--tw-text-opacity));
|
|
@@ -2049,6 +2053,11 @@ video {
|
|
|
2049
2053
|
--tw-drop-shadow: drop-shadow(0 1px 1px rgb(0 0 0 / 0.05));
|
|
2050
2054
|
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
|
2051
2055
|
}
|
|
2056
|
+
.theme-designCrowd .tw-transition-all {
|
|
2057
|
+
transition-property: all;
|
|
2058
|
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
2059
|
+
transition-duration: 150ms;
|
|
2060
|
+
}
|
|
2052
2061
|
.theme-designCrowd .tw-transition-colors {
|
|
2053
2062
|
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
|
|
2054
2063
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
@@ -2076,6 +2085,10 @@ video {
|
|
|
2076
2085
|
.theme-designCrowd .tw-ease-out {
|
|
2077
2086
|
transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
|
|
2078
2087
|
}
|
|
2088
|
+
.theme-designCrowd .hover\:tw-border-grayscale-300:hover {
|
|
2089
|
+
--tw-border-opacity: 1;
|
|
2090
|
+
border-color: rgb(239 239 239 / var(--tw-border-opacity));
|
|
2091
|
+
}
|
|
2079
2092
|
.theme-designCrowd .hover\:tw-border-grayscale-400:hover {
|
|
2080
2093
|
--tw-border-opacity: 1;
|
|
2081
2094
|
border-color: rgb(230 230 230 / var(--tw-border-opacity));
|
|
@@ -2240,6 +2253,18 @@ video {
|
|
|
2240
2253
|
outline: 2px solid transparent;
|
|
2241
2254
|
outline-offset: 2px;
|
|
2242
2255
|
}
|
|
2256
|
+
.theme-designCrowd .focus\:tw-ring-2:focus {
|
|
2257
|
+
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
|
2258
|
+
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
|
2259
|
+
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
|
2260
|
+
}
|
|
2261
|
+
.theme-designCrowd .focus\:tw-ring-primary-500:focus {
|
|
2262
|
+
--tw-ring-opacity: 1;
|
|
2263
|
+
--tw-ring-color: rgb(17 151 235 / var(--tw-ring-opacity));
|
|
2264
|
+
}
|
|
2265
|
+
.theme-designCrowd .focus\:tw-ring-offset-2:focus {
|
|
2266
|
+
--tw-ring-offset-width: 2px;
|
|
2267
|
+
}
|
|
2243
2268
|
.theme-designCrowd .tw-group:hover .group-hover\:tw-text-info-500 {
|
|
2244
2269
|
--tw-text-opacity: 1;
|
|
2245
2270
|
color: rgb(17 151 235 / var(--tw-text-opacity));
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div
|
|
3
3
|
v-show="visible"
|
|
4
|
+
role="dialog"
|
|
5
|
+
aria-modal="true"
|
|
4
6
|
:aria-hidden="visible ? 'false' : 'true'"
|
|
7
|
+
:aria-label="ariaLabel"
|
|
5
8
|
class="tw-bg-black tw-flex tw-items-center tw-justify-center tw-fixed tw-w-full tw-h-full tw-top-0 tw-left-0 tw-z-50"
|
|
6
9
|
:class="{
|
|
7
10
|
'tw-px-4': fullScreenBreakpoint === undefined && !isImageMode,
|
|
@@ -47,6 +50,7 @@
|
|
|
47
50
|
v-if="!mandatory"
|
|
48
51
|
class="tw-absolute tw-right-0 tw-top-0 tw-border-none tw-text-secondary-500 tw-appearance-none tw-bg-transparent tw-p-0 tw-w-8 tw-h-8 tw-ml-auto tw-cursor-pointer"
|
|
49
52
|
data-test-modal-close-btn
|
|
53
|
+
aria-label="Close"
|
|
50
54
|
@click="close($event)"
|
|
51
55
|
>
|
|
52
56
|
<span class="tw-sr-only">Close modal</span>
|
|
@@ -161,6 +165,11 @@ export default {
|
|
|
161
165
|
required: false,
|
|
162
166
|
default: false,
|
|
163
167
|
},
|
|
168
|
+
ariaLabel: {
|
|
169
|
+
type: String,
|
|
170
|
+
required: false,
|
|
171
|
+
default: undefined,
|
|
172
|
+
},
|
|
164
173
|
},
|
|
165
174
|
computed: {
|
|
166
175
|
isImageMode() {
|
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
import VoiceToTextButton from './VoiceToTextButton.vue';
|
|
2
|
-
import TextInput from '../TextInput/TextInput.vue';
|
|
3
2
|
|
|
4
3
|
export default {
|
|
5
4
|
title: 'Components/VoiceToTextButton',
|
|
6
5
|
component: VoiceToTextButton,
|
|
7
6
|
};
|
|
8
7
|
|
|
9
|
-
export const
|
|
8
|
+
export const PromptInputDemo = () => ({
|
|
10
9
|
components: { VoiceToTextButton },
|
|
11
|
-
template: '<VoiceToTextButton />',
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
export const WithTranscriptDisplay = () => ({
|
|
15
|
-
components: { VoiceToTextButton, TextInput },
|
|
16
10
|
data() {
|
|
17
11
|
return {
|
|
18
12
|
transcript: '',
|
|
@@ -21,87 +15,91 @@ export const WithTranscriptDisplay = () => ({
|
|
|
21
15
|
};
|
|
22
16
|
},
|
|
23
17
|
template: `
|
|
24
|
-
<div class="tw-flex tw-flex-col tw-
|
|
25
|
-
<
|
|
26
|
-
|
|
18
|
+
<div class="tw-min-h-[400px] tw-p-8 tw-flex tw-flex-col tw-items-center tw-justify-center" style="background: linear-gradient(180deg, #1a1a2e 0%, #16213e 100%);">
|
|
19
|
+
<h1 class="tw-text-white tw-text-3xl tw-font-bold tw-mb-2 tw-text-center">Design anything with AI</h1>
|
|
20
|
+
<p class="tw-text-grayscale-400 tw-mb-8 tw-text-center">Design a logo, a website, or anything else in seconds with the power of AI</p>
|
|
21
|
+
|
|
22
|
+
<div class="tw-w-full tw-max-w-xl tw-bg-grayscale-800 tw-rounded-full tw-px-6 tw-py-3 tw-flex tw-items-center tw-gap-3">
|
|
23
|
+
<input
|
|
27
24
|
v-model="transcript"
|
|
28
|
-
|
|
29
|
-
placeholder="
|
|
30
|
-
class="tw-flex-1"
|
|
25
|
+
type="text"
|
|
26
|
+
placeholder="What would you like to design?"
|
|
27
|
+
class="tw-flex-1 tw-bg-transparent tw-border-none tw-text-white tw-placeholder-grayscale-500 focus:tw-outline-none tw-text-base"
|
|
31
28
|
/>
|
|
32
29
|
<VoiceToTextButton
|
|
30
|
+
size="md"
|
|
33
31
|
@on-transcript="transcript = $event"
|
|
34
32
|
@on-interim-transcript="transcript = $event"
|
|
35
33
|
@on-start="isListening = true; error = null"
|
|
36
34
|
@on-stop="isListening = false"
|
|
37
35
|
@on-error="error = $event"
|
|
38
36
|
/>
|
|
37
|
+
<button class="tw-w-10 tw-h-10 tw-rounded-full tw-bg-secondary-500 tw-flex tw-items-center tw-justify-center tw-text-white hover:tw-bg-secondary-600 tw-transition-colors">
|
|
38
|
+
<svg xmlns="http://www.w3.org/2000/svg" class="tw-w-5 tw-h-5" viewBox="0 0 20 20" fill="currentColor">
|
|
39
|
+
<path fill-rule="evenodd" d="M10.293 3.293a1 1 0 011.414 0l6 6a1 1 0 010 1.414l-6 6a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-4.293-4.293a1 1 0 010-1.414z" clip-rule="evenodd" />
|
|
40
|
+
</svg>
|
|
41
|
+
</button>
|
|
39
42
|
</div>
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
|
|
44
|
+
<div class="tw-mt-4 tw-text-sm tw-h-6">
|
|
45
|
+
<p v-if="isListening" class="tw-text-error-500 tw-font-medium">
|
|
46
|
+
Recording... speak now
|
|
43
47
|
</p>
|
|
44
|
-
<p v-else-if="error" class="tw-text-error-
|
|
48
|
+
<p v-else-if="error" class="tw-text-error-400">
|
|
45
49
|
{{ error }}
|
|
46
50
|
</p>
|
|
47
|
-
<p v-else>
|
|
48
|
-
Click the microphone button to start voice input
|
|
49
|
-
</p>
|
|
50
51
|
</div>
|
|
51
52
|
</div>
|
|
52
53
|
`,
|
|
53
54
|
});
|
|
54
55
|
|
|
55
|
-
|
|
56
|
-
name: '
|
|
56
|
+
PromptInputDemo.story = {
|
|
57
|
+
name: 'Prompt Input (Dark Theme)',
|
|
57
58
|
};
|
|
58
59
|
|
|
59
|
-
export const
|
|
60
|
+
export const PromptVariantStates = () => ({
|
|
60
61
|
components: { VoiceToTextButton },
|
|
61
62
|
template: `
|
|
62
|
-
<div class="tw-
|
|
63
|
-
<
|
|
64
|
-
<VoiceToTextButton />
|
|
65
|
-
<p class="tw-text-xs tw-mt-2 tw-text-grayscale-600">Enabled</p>
|
|
66
|
-
</div>
|
|
67
|
-
<div class="tw-text-center">
|
|
68
|
-
<VoiceToTextButton :disabled="true" />
|
|
69
|
-
<p class="tw-text-xs tw-mt-2 tw-text-grayscale-600">Disabled</p>
|
|
70
|
-
</div>
|
|
71
|
-
</div>
|
|
72
|
-
`,
|
|
73
|
-
});
|
|
63
|
+
<div class="tw-p-8" style="background: #1a1a2e;">
|
|
64
|
+
<h3 class="tw-text-white tw-text-lg tw-font-semibold tw-mb-6">Prompt Variant - All States</h3>
|
|
74
65
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
66
|
+
<div class="tw-flex tw-gap-8 tw-items-start">
|
|
67
|
+
<div class="tw-text-center">
|
|
68
|
+
<div class="tw-mb-2 tw-p-4 tw-bg-grayscale-800 tw-rounded-lg tw-inline-block">
|
|
69
|
+
<VoiceToTextButton size="sm" />
|
|
70
|
+
</div>
|
|
71
|
+
<p class="tw-text-grayscale-400 tw-text-xs">Small</p>
|
|
72
|
+
</div>
|
|
78
73
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
<p class="tw-text-xs tw-mt-2">{{ lang.name }}</p>
|
|
74
|
+
<div class="tw-text-center">
|
|
75
|
+
<div class="tw-mb-2 tw-p-4 tw-bg-grayscale-800 tw-rounded-lg tw-inline-block">
|
|
76
|
+
<VoiceToTextButton size="md" />
|
|
77
|
+
</div>
|
|
78
|
+
<p class="tw-text-grayscale-400 tw-text-xs">Medium (default)</p>
|
|
79
|
+
</div>
|
|
80
|
+
|
|
81
|
+
<div class="tw-text-center">
|
|
82
|
+
<div class="tw-mb-2 tw-p-4 tw-bg-grayscale-800 tw-rounded-lg tw-inline-block">
|
|
83
|
+
<VoiceToTextButton size="lg" />
|
|
84
|
+
</div>
|
|
85
|
+
<p class="tw-text-grayscale-400 tw-text-xs">Large</p>
|
|
86
|
+
</div>
|
|
87
|
+
|
|
88
|
+
<div class="tw-text-center">
|
|
89
|
+
<div class="tw-mb-2 tw-p-4 tw-bg-grayscale-800 tw-rounded-lg tw-inline-block">
|
|
90
|
+
<VoiceToTextButton :disabled="true" />
|
|
91
|
+
</div>
|
|
92
|
+
<p class="tw-text-grayscale-400 tw-text-xs">Disabled</p>
|
|
93
|
+
</div>
|
|
100
94
|
</div>
|
|
95
|
+
|
|
96
|
+
<p class="tw-text-grayscale-500 tw-text-sm tw-mt-6">
|
|
97
|
+
Click any button to see the recording state with red ring animation
|
|
98
|
+
</p>
|
|
101
99
|
</div>
|
|
102
100
|
`,
|
|
103
101
|
});
|
|
104
102
|
|
|
105
|
-
|
|
106
|
-
name: '
|
|
103
|
+
PromptVariantStates.story = {
|
|
104
|
+
name: 'Prompt Variant States',
|
|
107
105
|
};
|
|
@@ -1,19 +1,29 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
2
|
+
<button
|
|
3
3
|
v-if="isSupported"
|
|
4
|
-
|
|
4
|
+
type="button"
|
|
5
5
|
:disabled="disabled"
|
|
6
|
-
variant="outline"
|
|
7
|
-
:class="{ 'voice-listening': isListening }"
|
|
8
6
|
:aria-label="isListening ? 'Stop voice input' : 'Start voice input'"
|
|
9
7
|
data-test="voice-to-text-button"
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
class="voice-prompt-button tw-rounded-full tw-border-2 tw-bg-transparent tw-flex tw-items-center tw-justify-center tw-transition-all tw-duration-200 tw-cursor-pointer focus:tw-outline-none focus:tw-ring-2 focus:tw-ring-offset-2 focus:tw-ring-primary-500"
|
|
9
|
+
:class="[
|
|
10
|
+
sizeClasses,
|
|
11
|
+
isListening ? 'voice-prompt-listening tw-border-error-500' : 'tw-border-grayscale-400 hover:tw-border-grayscale-300',
|
|
12
|
+
disabled ? 'tw-opacity-50 tw-cursor-not-allowed' : '',
|
|
13
|
+
]"
|
|
14
|
+
@click="toggle"
|
|
15
|
+
>
|
|
16
|
+
<Icon
|
|
17
|
+
name="microphone"
|
|
18
|
+
:size="iconSize"
|
|
19
|
+
:class="isListening ? 'tw-text-error-500' : 'tw-text-grayscale-400'"
|
|
20
|
+
/>
|
|
21
|
+
</button>
|
|
12
22
|
</template>
|
|
13
23
|
|
|
14
24
|
<script setup>
|
|
15
|
-
import { watch, toRef } from 'vue';
|
|
16
|
-
import
|
|
25
|
+
import { watch, toRef, computed } from 'vue';
|
|
26
|
+
import Icon from '../Icon/Icon.vue';
|
|
17
27
|
import { useVoiceToText } from '../../../useVoiceToText';
|
|
18
28
|
|
|
19
29
|
const props = defineProps({
|
|
@@ -25,6 +35,29 @@ const props = defineProps({
|
|
|
25
35
|
type: Boolean,
|
|
26
36
|
default: false,
|
|
27
37
|
},
|
|
38
|
+
size: {
|
|
39
|
+
type: String,
|
|
40
|
+
default: 'md',
|
|
41
|
+
validator: (value) => ['sm', 'md', 'lg'].includes(value),
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const sizeClasses = computed(() => {
|
|
46
|
+
const sizes = {
|
|
47
|
+
sm: 'tw-w-8 tw-h-8',
|
|
48
|
+
md: 'tw-w-10 tw-h-10',
|
|
49
|
+
lg: 'tw-w-12 tw-h-12',
|
|
50
|
+
};
|
|
51
|
+
return sizes[props.size];
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const iconSize = computed(() => {
|
|
55
|
+
const sizes = {
|
|
56
|
+
sm: 'sm',
|
|
57
|
+
md: 'md',
|
|
58
|
+
lg: 'md',
|
|
59
|
+
};
|
|
60
|
+
return sizes[props.size];
|
|
28
61
|
});
|
|
29
62
|
|
|
30
63
|
const emit = defineEmits(['on-transcript', 'on-interim-transcript', 'on-start', 'on-stop', 'on-error']);
|
|
@@ -68,17 +101,21 @@ watch(error, (newError) => {
|
|
|
68
101
|
</script>
|
|
69
102
|
|
|
70
103
|
<style scoped>
|
|
71
|
-
.voice-
|
|
72
|
-
|
|
104
|
+
.voice-prompt-button {
|
|
105
|
+
-webkit-tap-highlight-color: transparent;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.voice-prompt-listening {
|
|
109
|
+
animation: voice-ring-pulse 1.5s ease-in-out infinite;
|
|
73
110
|
}
|
|
74
111
|
|
|
75
|
-
@keyframes voice-pulse {
|
|
112
|
+
@keyframes voice-ring-pulse {
|
|
76
113
|
0%,
|
|
77
114
|
100% {
|
|
78
|
-
box-shadow: 0 0 0 0
|
|
115
|
+
box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.4);
|
|
79
116
|
}
|
|
80
117
|
50% {
|
|
81
|
-
box-shadow: 0 0 0
|
|
118
|
+
box-shadow: 0 0 0 6px rgba(239, 68, 68, 0);
|
|
82
119
|
}
|
|
83
120
|
}
|
|
84
121
|
</style>
|