@designcrowd/fe-shared-lib 1.7.1 → 1.8.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.md CHANGED
@@ -78,6 +78,41 @@ Themes are compiled into separate CSS files via `tailwind.build.js` → `dist/cs
78
78
  - Stories pattern: `src/**/components/**/*.stories.@(js|jsx|ts|tsx)`
79
79
  - Supports theme switching (5 brands) and locale switching (8 languages)
80
80
 
81
+ ## Verifying UI Changes
82
+
83
+ After modifying Vue components or Storybook stories, verify changes visually using playwright-cli.
84
+
85
+ ### Workflow
86
+
87
+ 1. **Start Storybook** (runs in background):
88
+ ```bash
89
+ npm start
90
+ ```
91
+
92
+ 2. **Wait for availability** - Storybook runs on http://localhost:6006. Check with:
93
+ ```bash
94
+ curl -s -o /dev/null -w "%{http_code}" http://localhost:6006
95
+ ```
96
+
97
+ 3. **Navigate and screenshot** using playwright-cli:
98
+ ```bash
99
+ playwright-cli open "http://localhost:6006/?path=/story/components-buttonname--default"
100
+ playwright-cli snapshot # See page structure
101
+ playwright-cli screenshot f1e4 --filename=component.png # Screenshot specific element
102
+ playwright-cli close
103
+ ```
104
+
105
+ ### Story URL Pattern
106
+
107
+ Stories are accessed via: `http://localhost:6006/?path=/story/{title-path}--{story-name}`
108
+ - Title path: lowercase, hyphens instead of spaces/slashes (e.g., `Components/VoiceToTextButton` becomes `components-voicetotextbutton`)
109
+ - Story name: lowercase export name (e.g., `Default` becomes `default`)
110
+
111
+ ### Common Issues
112
+
113
+ - **package.json parse errors**: Ensure valid JSON (watch for missing commas after version changes)
114
+ - **React dependency errors**: Storybook 9 requires `react` and `react-dom` as devDependencies
115
+
81
116
  ## Local Development
82
117
 
83
118
  Use `npm link` for local development with consumer projects:
@@ -1896,6 +1896,10 @@ video {
1896
1896
  --tw-text-opacity: 1;
1897
1897
  color: rgb(145 16 38 / var(--tw-text-opacity));
1898
1898
  }
1899
+ .tw-text-grayscale-400 {
1900
+ --tw-text-opacity: 1;
1901
+ color: rgb(230 230 230 / var(--tw-text-opacity));
1902
+ }
1899
1903
  .tw-text-grayscale-500 {
1900
1904
  --tw-text-opacity: 1;
1901
1905
  color: rgb(208 208 208 / 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
+ .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
  .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);
@@ -2124,6 +2133,10 @@ video {
2124
2133
  --tw-bg-opacity: 1;
2125
2134
  background-color: rgb(208 208 208 / var(--tw-bg-opacity));
2126
2135
  }
2136
+ .hover\:tw-bg-grayscale-700:hover {
2137
+ --tw-bg-opacity: 1;
2138
+ background-color: rgb(43 43 43 / var(--tw-bg-opacity));
2139
+ }
2127
2140
  .hover\:tw-bg-info-100:hover {
2128
2141
  --tw-bg-opacity: 1;
2129
2142
  background-color: rgb(204 234 247 / var(--tw-bg-opacity));
@@ -2240,6 +2253,18 @@ video {
2240
2253
  outline: 2px solid transparent;
2241
2254
  outline-offset: 2px;
2242
2255
  }
2256
+ .focus-visible\:tw-ring-2:focus-visible {
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
+ .focus-visible\:tw-ring-primary-500:focus-visible {
2262
+ --tw-ring-opacity: 1;
2263
+ --tw-ring-color: rgb(242 27 63 / var(--tw-ring-opacity));
2264
+ }
2265
+ .focus-visible\:tw-ring-offset-2:focus-visible {
2266
+ --tw-ring-offset-width: 2px;
2267
+ }
2243
2268
  .tw-group:hover .group-hover\:tw-text-info-500 {
2244
2269
  --tw-text-opacity: 1;
2245
2270
  color: rgb(0 151 215 / var(--tw-text-opacity));
@@ -1736,6 +1736,10 @@ video {
1736
1736
  --tw-text-opacity: 1;
1737
1737
  color: rgb(0 0 0 / var(--tw-text-opacity));
1738
1738
  }
1739
+ .tw-text-grayscale-400 {
1740
+ --tw-text-opacity: 1;
1741
+ color: rgb(230 230 230 / var(--tw-text-opacity));
1742
+ }
1739
1743
  .tw-text-grayscale-500 {
1740
1744
  --tw-text-opacity: 1;
1741
1745
  color: rgb(208 208 208 / var(--tw-text-opacity));
@@ -1837,6 +1841,11 @@ video {
1837
1841
  --tw-drop-shadow: drop-shadow(0 1px 1px rgb(0 0 0 / 0.05));
1838
1842
  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);
1839
1843
  }
1844
+ .tw-transition-all {
1845
+ transition-property: all;
1846
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
1847
+ transition-duration: 150ms;
1848
+ }
1840
1849
  .tw-transition-colors {
1841
1850
  transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
1842
1851
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
@@ -1888,6 +1897,10 @@ video {
1888
1897
  --tw-bg-opacity: 1;
1889
1898
  background-color: rgb(208 208 208 / var(--tw-bg-opacity));
1890
1899
  }
1900
+ .hover\:tw-bg-grayscale-700:hover {
1901
+ --tw-bg-opacity: 1;
1902
+ background-color: rgb(43 43 43 / var(--tw-bg-opacity));
1903
+ }
1891
1904
  .hover\:tw-text-white:hover {
1892
1905
  --tw-text-opacity: 1;
1893
1906
  color: rgb(255 255 255 / var(--tw-text-opacity));
@@ -1916,6 +1929,14 @@ video {
1916
1929
  outline: 2px solid transparent;
1917
1930
  outline-offset: 2px;
1918
1931
  }
1932
+ .focus-visible\:tw-ring-2:focus-visible {
1933
+ --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
1934
+ --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
1935
+ box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
1936
+ }
1937
+ .focus-visible\:tw-ring-offset-2:focus-visible {
1938
+ --tw-ring-offset-width: 2px;
1939
+ }
1919
1940
  @media (min-width: 640px) {
1920
1941
 
1921
1942
  .sm\:tw-absolute {
@@ -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
+ .tw-text-grayscale-400 {
1900
+ --tw-text-opacity: 1;
1901
+ color: rgb(235 238 243 / var(--tw-text-opacity));
1902
+ }
1899
1903
  .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
+ .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
  .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);
@@ -2124,6 +2133,10 @@ video {
2124
2133
  --tw-bg-opacity: 1;
2125
2134
  background-color: rgb(199 204 207 / var(--tw-bg-opacity));
2126
2135
  }
2136
+ .hover\:tw-bg-grayscale-700:hover {
2137
+ --tw-bg-opacity: 1;
2138
+ background-color: rgb(87 97 99 / var(--tw-bg-opacity));
2139
+ }
2127
2140
  .hover\:tw-bg-info-100:hover {
2128
2141
  --tw-bg-opacity: 1;
2129
2142
  background-color: rgb(230 246 253 / var(--tw-bg-opacity));
@@ -2240,6 +2253,18 @@ video {
2240
2253
  outline: 2px solid transparent;
2241
2254
  outline-offset: 2px;
2242
2255
  }
2256
+ .focus-visible\:tw-ring-2:focus-visible {
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
+ .focus-visible\:tw-ring-primary-500:focus-visible {
2262
+ --tw-ring-opacity: 1;
2263
+ --tw-ring-color: rgb(111 172 47 / var(--tw-ring-opacity));
2264
+ }
2265
+ .focus-visible\:tw-ring-offset-2:focus-visible {
2266
+ --tw-ring-offset-width: 2px;
2267
+ }
2243
2268
  .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
+ .tw-text-grayscale-400 {
1900
+ --tw-text-opacity: 1;
1901
+ color: rgb(227 227 227 / var(--tw-text-opacity));
1902
+ }
1899
1903
  .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
+ .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
  .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);
@@ -2124,6 +2133,10 @@ video {
2124
2133
  --tw-bg-opacity: 1;
2125
2134
  background-color: rgb(209 209 209 / var(--tw-bg-opacity));
2126
2135
  }
2136
+ .hover\:tw-bg-grayscale-700:hover {
2137
+ --tw-bg-opacity: 1;
2138
+ background-color: rgb(38 38 38 / var(--tw-bg-opacity));
2139
+ }
2127
2140
  .hover\:tw-bg-info-100:hover {
2128
2141
  --tw-bg-opacity: 1;
2129
2142
  background-color: rgb(236 238 254 / var(--tw-bg-opacity));
@@ -2240,6 +2253,18 @@ video {
2240
2253
  outline: 2px solid transparent;
2241
2254
  outline-offset: 2px;
2242
2255
  }
2256
+ .focus-visible\:tw-ring-2:focus-visible {
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
+ .focus-visible\:tw-ring-primary-500:focus-visible {
2262
+ --tw-ring-opacity: 1;
2263
+ --tw-ring-color: rgb(63 89 246 / var(--tw-ring-opacity));
2264
+ }
2265
+ .focus-visible\:tw-ring-offset-2:focus-visible {
2266
+ --tw-ring-offset-width: 2px;
2267
+ }
2243
2268
  .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
+ .tw-text-grayscale-400 {
1900
+ --tw-text-opacity: 1;
1901
+ color: rgb(230 230 230 / var(--tw-text-opacity));
1902
+ }
1899
1903
  .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
+ .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
  .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);
@@ -2124,6 +2133,10 @@ video {
2124
2133
  --tw-bg-opacity: 1;
2125
2134
  background-color: rgb(204 204 204 / var(--tw-bg-opacity));
2126
2135
  }
2136
+ .hover\:tw-bg-grayscale-700:hover {
2137
+ --tw-bg-opacity: 1;
2138
+ background-color: rgb(82 93 96 / var(--tw-bg-opacity));
2139
+ }
2127
2140
  .hover\:tw-bg-info-100:hover {
2128
2141
  --tw-bg-opacity: 1;
2129
2142
  background-color: rgb(207 234 251 / var(--tw-bg-opacity));
@@ -2240,6 +2253,18 @@ video {
2240
2253
  outline: 2px solid transparent;
2241
2254
  outline-offset: 2px;
2242
2255
  }
2256
+ .focus-visible\:tw-ring-2:focus-visible {
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
+ .focus-visible\:tw-ring-primary-500:focus-visible {
2262
+ --tw-ring-opacity: 1;
2263
+ --tw-ring-color: rgb(17 151 235 / var(--tw-ring-opacity));
2264
+ }
2265
+ .focus-visible\:tw-ring-offset-2:focus-visible {
2266
+ --tw-ring-offset-width: 2px;
2267
+ }
2243
2268
  .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));
package/index.js CHANGED
@@ -22,6 +22,7 @@ export { default as WebsiteContextualUpgradeModal } from './src/experiences/comp
22
22
  export { WEBSITE_UPGRADE_CONTEXT_TYPES } from './src/experiences/models/websiteContextualModel';
23
23
 
24
24
  export { setSharedLibLocaleAsync, tr } from './src/useSharedLibTranslate';
25
+ export { useVoiceToText } from './src/useVoiceToText';
25
26
 
26
27
  export { default as Button } from './src/atoms/components/Button/Button.vue';
27
28
  export { default as ButtonGroup } from './src/atoms/components/ButtonGroup/ButtonGroup.vue';
@@ -59,4 +60,5 @@ export { default as Select } from './src/atoms/components/Select/Select.vue';
59
60
  export { default as NumberStepper } from './src/atoms/components/NumberStepper/NumberStepper.vue';
60
61
  export { default as CopyToClipboardText } from './src/atoms/components/CopyToClipboardText/CopyToClipboardText.vue';
61
62
  export { default as SparkleIcon } from './src/atoms/components/SparkleIcon/SparkleIcon.vue';
63
+ export { default as VoiceToTextButton } from './src/atoms/components/VoiceToTextButton/VoiceToTextButton.vue';
62
64
  export { default as SideNavigationPanel } from './src/experiences/components/SideNavigationPanel/SideNavigationPanel.vue';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@designcrowd/fe-shared-lib",
3
- "version": "1.7.1",
3
+ "version": "1.8.1",
4
4
  "scripts": {
5
5
  "start": "run-p storybook watch:translation",
6
6
  "build": "npm run build:css --production",
@@ -71,6 +71,8 @@
71
71
  "postcss-import": "16.0.0",
72
72
  "postcss-nested": "6.0.1",
73
73
  "prettier": "3.2.4",
74
+ "react": "^19.2.5",
75
+ "react-dom": "^19.2.5",
74
76
  "storybook": "9.0.4",
75
77
  "stylelint": "16.2.1",
76
78
  "stylelint-config-standard": "36.0.0",
@@ -216,6 +216,7 @@ export const IconSample = () => {
216
216
  { name: 'media' },
217
217
  { name: 'search' },
218
218
  { name: 'secure' },
219
+ { name: 'select-all' },
219
220
  { name: 'send' },
220
221
  { name: 'services' },
221
222
  { name: 'settings' },
@@ -237,6 +237,7 @@ import IconLinkInBioFilled from './icons/link-in-bio-filled.vue';
237
237
  import IconMedia from './icons/media.vue';
238
238
  import IconMinusCircleLight from './icons/minus-circle-light.vue';
239
239
  import IconMinus from './icons/minus.vue';
240
+ import IconMicrophone from './icons/microphone.vue';
240
241
  import IconMobile from './icons/mobile.vue';
241
242
  import IconOther from './icons/other.vue';
242
243
  import IconPageButtons from './icons/page-buttons.vue';
@@ -638,6 +639,7 @@ export default {
638
639
  IconContactMessage,
639
640
  IconMinus,
640
641
  IconMinusCircleLight,
642
+ IconMicrophone,
641
643
  IconMobile,
642
644
  IconMug,
643
645
  IconOther,
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <path
3
+ d="M8 1a2 2 0 0 0-2 2v4a2 2 0 1 0 4 0V3a2 2 0 0 0-2-2zM4.5 7a.5.5 0 0 1 .5.5V8a3 3 0 1 0 6 0v-.5a.5.5 0 0 1 1 0V8a4 4 0 0 1-3.5 3.97V14h2a.5.5 0 0 1 0 1h-5a.5.5 0 0 1 0-1h2v-2.03A4 4 0 0 1 4 8v-.5a.5.5 0 0 1 .5-.5z"
4
+ />
5
+ </template>
@@ -1,7 +1,15 @@
1
1
  <template>
2
- <g>
3
- <rect x="0.75" y="0.75" width="14.5" height="14.5" rx="1.25" fill="none" stroke="currentColor" stroke-width="1.5" stroke-dasharray="4 4"/>
4
- <path fill-rule="evenodd" clip-rule="evenodd" d="M4.5 8.5V4.5H8.5V5.80003H10V4C10 3.44772 9.55228 3 9 3H4C3.44772 3 3 3.44772 3 4V9C3 9.55228 3.44772 10 4 10H5.80005V8.5H4.5Z"/>
5
- <rect x="6" y="6" width="7" height="7" rx="1" fill="none" stroke="currentColor" stroke-width="1.5"/>
2
+ <g clip-path="url(#clip0_3437_2353)">
3
+ <path
4
+ d="M13.9163 12.0003C13.9163 11.5862 14.2523 11.2505 14.6663 11.2503C15.0806 11.2503 15.4163 11.5861 15.4163 12.0003C15.4163 12.5718 15.4227 13.0046 15.3226 13.3783C15.0683 14.3273 14.3273 15.0683 13.3783 15.3226C13.0046 15.4227 12.5718 15.4163 12.0003 15.4163C11.5861 15.4163 11.2503 15.0806 11.2503 14.6663C11.2505 14.2523 11.5862 13.9163 12.0003 13.9163C12.6683 13.9163 12.8557 13.9105 12.9906 13.8743C13.4217 13.7587 13.7587 13.4217 13.8743 12.9906C13.9105 12.8557 13.9163 12.6683 13.9163 12.0003ZM1.32943 11.2503C1.74344 11.2475 2.08126 11.5805 2.08431 11.9945C2.08796 12.5202 2.10485 12.8174 2.14974 13.0257C2.2144 13.3254 2.44543 13.6173 2.76595 13.7806C2.93554 13.867 3.19601 13.9097 4.00521 13.9154C4.41941 13.9182 4.7532 14.257 4.75033 14.6712C4.74719 15.0852 4.40851 15.4182 3.99447 15.4154C3.2509 15.4102 2.62318 15.3905 2.08529 15.1165C1.4157 14.7754 0.855501 14.1374 0.68392 13.3421C0.601897 12.9618 0.587871 12.5175 0.584311 12.0052C0.581435 11.591 0.915226 11.2532 1.32943 11.2503ZM9.33333 13.6986C9.74751 13.6986 10.0833 14.0344 10.0833 14.4486C10.0833 14.8628 9.74755 15.1986 9.33333 15.1986H6.66634C6.25228 15.1984 5.91634 14.8627 5.91634 14.4486C5.9164 14.0345 6.25232 13.6987 6.66634 13.6986H9.33333ZM0.583334 9.33333V6.66634C0.58351 6.25228 0.919229 5.91634 1.33333 5.91634C1.74744 5.91634 2.08316 6.25228 2.08333 6.66634V9.33333C2.08333 9.74755 1.74755 10.0833 1.33333 10.0833C0.91912 10.0833 0.583334 9.74755 0.583334 9.33333ZM13.9163 9.33333V6.66634C13.9165 6.25239 14.2524 5.91652 14.6663 5.91634C15.0804 5.91634 15.4162 6.25228 15.4163 6.66634V9.33333C15.4163 9.74755 15.0806 10.0833 14.6663 10.0833C14.2523 10.0832 13.9163 9.74744 13.9163 9.33333ZM0.583334 4.00033C0.583334 3.42863 0.576938 2.99517 0.677084 2.62142C0.931395 1.67255 1.67255 0.931395 2.62142 0.677084C2.99517 0.576938 3.42863 0.583334 4.00033 0.583334C4.41439 0.58351 4.75033 0.919229 4.75033 1.33333C4.75033 1.74744 4.41439 2.08316 4.00033 2.08333C3.33234 2.08333 3.145 2.09019 3.01009 2.1263C2.57873 2.24189 2.24189 2.57873 2.1263 3.01009C2.09019 3.145 2.08333 3.33234 2.08333 4.00033C2.08316 4.41439 1.74744 4.75033 1.33333 4.75033C0.919229 4.75033 0.58351 4.41439 0.583334 4.00033ZM13.9163 4.00033C13.9163 3.33261 13.9104 3.14498 13.8743 3.01009C13.7588 2.57887 13.4217 2.242 12.9906 2.1263C12.8557 2.09016 12.6683 2.08334 12.0003 2.08333C11.5861 2.08333 11.2503 1.74755 11.2503 1.33333C11.2503 0.91912 11.5861 0.583334 12.0003 0.583334C12.5718 0.583332 13.0046 0.576996 13.3783 0.677084C14.3272 0.931347 15.0682 1.67253 15.3226 2.62142C15.4227 2.99517 15.4163 3.42863 15.4163 4.00033C15.4162 4.41439 15.0804 4.75033 14.6663 4.75033C14.2524 4.75015 13.9165 4.41428 13.9163 4.00033ZM9.33333 0.583334C9.74755 0.583334 10.0833 0.91912 10.0833 1.33333C10.0833 1.74755 9.74755 2.08333 9.33333 2.08333H6.66634C6.25228 2.08316 5.91634 1.74744 5.91634 1.33333C5.91634 0.919229 6.25228 0.58351 6.66634 0.583334H9.33333Z"
5
+ />
6
+ <path
7
+ d="M10.25 6.59961C10.25 6.30744 10.2498 6.13298 10.2393 6.00391C10.2294 5.88384 10.2143 5.87034 10.2227 5.88672C10.1987 5.83968 10.1603 5.80131 10.1133 5.77734C10.1297 5.78569 10.1162 5.77058 9.99609 5.76074C9.86702 5.7502 9.69256 5.75 9.40039 5.75H6.59961C6.30744 5.75 6.13298 5.7502 6.00391 5.76074C5.88384 5.77058 5.87034 5.78569 5.88672 5.77734C5.83968 5.80131 5.80131 5.83968 5.77734 5.88672C5.78569 5.87034 5.77058 5.88384 5.76074 6.00391C5.7502 6.13298 5.75 6.30744 5.75 6.59961V9.40039C5.75 9.69256 5.7502 9.86702 5.76074 9.99609C5.77058 10.1162 5.78569 10.1297 5.77734 10.1133C5.80131 10.1603 5.83968 10.1987 5.88672 10.2227C5.87034 10.2143 5.88384 10.2294 6.00391 10.2393C6.13298 10.2498 6.30744 10.25 6.59961 10.25H9.40039C9.69256 10.25 9.86702 10.2498 9.99609 10.2393C10.1162 10.2294 10.1297 10.2143 10.1133 10.2227C10.1603 10.1987 10.1987 10.1603 10.2227 10.1133C10.2143 10.1297 10.2294 10.1162 10.2393 9.99609C10.2498 9.86702 10.25 9.69256 10.25 9.40039V6.59961ZM11.75 9.40039C11.75 9.66789 11.7501 9.91389 11.7334 10.1182C11.716 10.3312 11.6769 10.5647 11.5596 10.7949C11.3918 11.124 11.124 11.3918 10.7949 11.5596C10.5647 11.6769 10.3312 11.716 10.1182 11.7334C9.91389 11.7501 9.66789 11.75 9.40039 11.75H6.59961C6.33211 11.75 6.08611 11.7501 5.88184 11.7334C5.66879 11.716 5.43527 11.6769 5.20508 11.5596C4.87597 11.3918 4.60818 11.124 4.44043 10.7949C4.32314 10.5647 4.28403 10.3312 4.2666 10.1182C4.24991 9.91389 4.25 9.66789 4.25 9.40039V6.59961C4.25 6.33211 4.24991 6.08611 4.2666 5.88184C4.28403 5.66879 4.32314 5.43527 4.44043 5.20508C4.60818 4.87597 4.87597 4.60818 5.20508 4.44043C5.43527 4.32314 5.66879 4.28403 5.88184 4.2666C6.08611 4.24991 6.33211 4.25 6.59961 4.25H9.40039C9.66789 4.25 9.91389 4.24991 10.1182 4.2666C10.3312 4.28403 10.5647 4.32314 10.7949 4.44043C11.124 4.60818 11.3918 4.87597 11.5596 5.20508C11.6769 5.43527 11.716 5.66879 11.7334 5.88184C11.7501 6.08611 11.75 6.33211 11.75 6.59961V9.40039Z"
8
+ />
6
9
  </g>
10
+ <defs>
11
+ <clipPath id="clip0_3437_2353">
12
+ <rect width="16" height="16" fill="white" />
13
+ </clipPath>
14
+ </defs>
7
15
  </template>
@@ -0,0 +1,242 @@
1
+ import VoiceToTextButton from './VoiceToTextButton.vue';
2
+
3
+ export default {
4
+ title: 'Components/VoiceToTextButton',
5
+ component: VoiceToTextButton,
6
+ };
7
+
8
+ export const PromptInputDemo = () => ({
9
+ components: { VoiceToTextButton },
10
+ data() {
11
+ return {
12
+ transcript: '',
13
+ isListening: false,
14
+ error: null,
15
+ };
16
+ },
17
+ template: `
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
24
+ v-model="transcript"
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"
28
+ />
29
+ <VoiceToTextButton
30
+ variant="dark"
31
+ size="md"
32
+ @on-transcript="transcript = $event"
33
+ @on-interim-transcript="transcript = $event"
34
+ @on-start="isListening = true; error = null"
35
+ @on-stop="isListening = false"
36
+ @on-error="error = $event"
37
+ />
38
+ <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">
39
+ <svg xmlns="http://www.w3.org/2000/svg" class="tw-w-5 tw-h-5" viewBox="0 0 20 20" fill="currentColor">
40
+ <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" />
41
+ </svg>
42
+ </button>
43
+ </div>
44
+
45
+ <div class="tw-mt-4 tw-text-sm tw-h-6">
46
+ <p v-if="isListening" class="tw-text-error-500 tw-font-medium">
47
+ Recording... speak now
48
+ </p>
49
+ <p v-else-if="error" class="tw-text-error-400">
50
+ {{ error }}
51
+ </p>
52
+ </div>
53
+ </div>
54
+ `,
55
+ });
56
+
57
+ PromptInputDemo.story = {
58
+ name: 'Dark - Prompt Input',
59
+ };
60
+
61
+ export const DarkVariantStates = () => ({
62
+ components: { VoiceToTextButton },
63
+ template: `
64
+ <div class="tw-p-8" style="background: #1a1a2e;">
65
+ <h3 class="tw-text-white tw-text-lg tw-font-semibold tw-mb-6">Dark Variant - All States</h3>
66
+
67
+ <div class="tw-flex tw-gap-8 tw-items-start">
68
+ <div class="tw-text-center">
69
+ <div class="tw-mb-2 tw-p-4 tw-bg-grayscale-800 tw-rounded-lg tw-inline-block">
70
+ <VoiceToTextButton variant="dark" size="sm" />
71
+ </div>
72
+ <p class="tw-text-grayscale-400 tw-text-xs">Small</p>
73
+ </div>
74
+
75
+ <div class="tw-text-center">
76
+ <div class="tw-mb-2 tw-p-4 tw-bg-grayscale-800 tw-rounded-lg tw-inline-block">
77
+ <VoiceToTextButton variant="dark" size="md" />
78
+ </div>
79
+ <p class="tw-text-grayscale-400 tw-text-xs">Medium (default)</p>
80
+ </div>
81
+
82
+ <div class="tw-text-center">
83
+ <div class="tw-mb-2 tw-p-4 tw-bg-grayscale-800 tw-rounded-lg tw-inline-block">
84
+ <VoiceToTextButton variant="dark" size="lg" />
85
+ </div>
86
+ <p class="tw-text-grayscale-400 tw-text-xs">Large</p>
87
+ </div>
88
+
89
+ <div class="tw-text-center">
90
+ <div class="tw-mb-2 tw-p-4 tw-bg-grayscale-800 tw-rounded-lg tw-inline-block">
91
+ <VoiceToTextButton variant="dark" :disabled="true" />
92
+ </div>
93
+ <p class="tw-text-grayscale-400 tw-text-xs">Disabled</p>
94
+ </div>
95
+ </div>
96
+
97
+ <p class="tw-text-grayscale-500 tw-text-sm tw-mt-6">
98
+ Click any button to see the recording state with grey circle indicator
99
+ </p>
100
+ </div>
101
+ `,
102
+ });
103
+
104
+ DarkVariantStates.story = {
105
+ name: 'Dark - Variant States',
106
+ };
107
+
108
+ export const LightInputDemo = () => ({
109
+ components: { VoiceToTextButton },
110
+ data() {
111
+ return {
112
+ transcript: '',
113
+ isListening: false,
114
+ error: null,
115
+ };
116
+ },
117
+ template: `
118
+ <div class="tw-min-h-[400px] tw-p-8 tw-flex tw-flex-col tw-items-center tw-justify-center tw-bg-white">
119
+ <h1 class="tw-text-grayscale-800 tw-text-3xl tw-font-bold tw-mb-2 tw-text-center">Search</h1>
120
+ <p class="tw-text-grayscale-600 tw-mb-8 tw-text-center">Find what you're looking for</p>
121
+
122
+ <div class="tw-w-full tw-max-w-xl tw-bg-grayscale-100 tw-rounded-full tw-px-6 tw-py-3 tw-flex tw-items-center tw-gap-3 tw-border tw-border-grayscale-300">
123
+ <input
124
+ v-model="transcript"
125
+ type="text"
126
+ placeholder="Type to search..."
127
+ class="tw-flex-1 tw-bg-transparent tw-border-none tw-text-grayscale-800 tw-placeholder-grayscale-500 focus:tw-outline-none tw-text-base"
128
+ />
129
+ <VoiceToTextButton
130
+ variant="light"
131
+ size="md"
132
+ @on-transcript="transcript = $event"
133
+ @on-interim-transcript="transcript = $event"
134
+ @on-start="isListening = true; error = null"
135
+ @on-stop="isListening = false"
136
+ @on-error="error = $event"
137
+ />
138
+ </div>
139
+
140
+ <div class="tw-mt-4 tw-text-sm tw-h-6">
141
+ <p v-if="isListening" class="tw-text-error-500 tw-font-medium">
142
+ Recording... speak now
143
+ </p>
144
+ <p v-else-if="error" class="tw-text-error-400">
145
+ {{ error }}
146
+ </p>
147
+ </div>
148
+ </div>
149
+ `,
150
+ });
151
+
152
+ LightInputDemo.story = {
153
+ name: 'Light - Search Input',
154
+ };
155
+
156
+ export const LightVariantStates = () => ({
157
+ components: { VoiceToTextButton },
158
+ template: `
159
+ <div class="tw-p-8 tw-bg-white">
160
+ <h3 class="tw-text-grayscale-800 tw-text-lg tw-font-semibold tw-mb-6">Light Variant - All States</h3>
161
+
162
+ <div class="tw-flex tw-gap-8 tw-items-start">
163
+ <div class="tw-text-center">
164
+ <div class="tw-mb-2 tw-p-4 tw-bg-grayscale-100 tw-rounded-lg tw-inline-block">
165
+ <VoiceToTextButton variant="light" size="sm" />
166
+ </div>
167
+ <p class="tw-text-grayscale-600 tw-text-xs">Small</p>
168
+ </div>
169
+
170
+ <div class="tw-text-center">
171
+ <div class="tw-mb-2 tw-p-4 tw-bg-grayscale-100 tw-rounded-lg tw-inline-block">
172
+ <VoiceToTextButton variant="light" size="md" />
173
+ </div>
174
+ <p class="tw-text-grayscale-600 tw-text-xs">Medium (default)</p>
175
+ </div>
176
+
177
+ <div class="tw-text-center">
178
+ <div class="tw-mb-2 tw-p-4 tw-bg-grayscale-100 tw-rounded-lg tw-inline-block">
179
+ <VoiceToTextButton variant="light" size="lg" />
180
+ </div>
181
+ <p class="tw-text-grayscale-600 tw-text-xs">Large</p>
182
+ </div>
183
+
184
+ <div class="tw-text-center">
185
+ <div class="tw-mb-2 tw-p-4 tw-bg-grayscale-100 tw-rounded-lg tw-inline-block">
186
+ <VoiceToTextButton variant="light" :disabled="true" />
187
+ </div>
188
+ <p class="tw-text-grayscale-600 tw-text-xs">Disabled</p>
189
+ </div>
190
+ </div>
191
+
192
+ <p class="tw-text-grayscale-500 tw-text-sm tw-mt-6">
193
+ Click any button to see the recording state with grey circle indicator
194
+ </p>
195
+ </div>
196
+ `,
197
+ });
198
+
199
+ LightVariantStates.story = {
200
+ name: 'Light - Variant States',
201
+ };
202
+
203
+ export const SideBySide = () => ({
204
+ components: { VoiceToTextButton },
205
+ template: `
206
+ <div class="tw-flex tw-min-h-[300px]">
207
+ <div class="tw-flex-1 tw-p-8 tw-flex tw-flex-col tw-items-center tw-justify-center" style="background: #1a1a2e;">
208
+ <h3 class="tw-text-white tw-text-lg tw-font-semibold tw-mb-6">Dark Variant</h3>
209
+ <div class="tw-flex tw-gap-4 tw-items-center">
210
+ <div class="tw-p-3 tw-bg-grayscale-800 tw-rounded-lg">
211
+ <VoiceToTextButton variant="dark" size="sm" />
212
+ </div>
213
+ <div class="tw-p-3 tw-bg-grayscale-800 tw-rounded-lg">
214
+ <VoiceToTextButton variant="dark" size="md" />
215
+ </div>
216
+ <div class="tw-p-3 tw-bg-grayscale-800 tw-rounded-lg">
217
+ <VoiceToTextButton variant="dark" size="lg" />
218
+ </div>
219
+ </div>
220
+ </div>
221
+
222
+ <div class="tw-flex-1 tw-p-8 tw-flex tw-flex-col tw-items-center tw-justify-center tw-bg-white">
223
+ <h3 class="tw-text-grayscale-800 tw-text-lg tw-font-semibold tw-mb-6">Light Variant</h3>
224
+ <div class="tw-flex tw-gap-4 tw-items-center">
225
+ <div class="tw-p-3 tw-bg-grayscale-100 tw-rounded-lg">
226
+ <VoiceToTextButton variant="light" size="sm" />
227
+ </div>
228
+ <div class="tw-p-3 tw-bg-grayscale-100 tw-rounded-lg">
229
+ <VoiceToTextButton variant="light" size="md" />
230
+ </div>
231
+ <div class="tw-p-3 tw-bg-grayscale-100 tw-rounded-lg">
232
+ <VoiceToTextButton variant="light" size="lg" />
233
+ </div>
234
+ </div>
235
+ </div>
236
+ </div>
237
+ `,
238
+ });
239
+
240
+ SideBySide.story = {
241
+ name: 'Side by Side Comparison',
242
+ };