@designcrowd/fe-shared-lib 1.4.7 → 1.4.8-promocardv0
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/dist/css/tailwind-brandCrowd.css +0 -6
- package/dist/css/tailwind-brandPage.css +0 -6
- package/dist/css/tailwind-crazyDomains.css +0 -6
- package/dist/css/tailwind-designCom.css +0 -6
- package/dist/css/tailwind-designCrowd.css +0 -6
- package/index.js +1 -1
- package/package.json +2 -1
- package/public/css/tailwind-brandCrowd.css +2479 -0
- package/public/css/tailwind-brandPage.css +2163 -0
- package/public/css/tailwind-crazyDomains.css +2479 -0
- package/public/css/tailwind-designCom.css +2479 -0
- package/public/css/tailwind-designCrowd.css +2479 -0
- package/src/atoms/components/Carousel/Carousel.fixtures.js +18 -0
- package/src/atoms/components/Carousel/carousel.stories.js +448 -179
- package/src/atoms/components/PromoCard/PromoCard.stories.ts +265 -0
- package/src/atoms/components/PromoCard/PromoCard.vue +89 -0
- package/tailwind.config.js +7 -8
- package/src/atoms/components/SparkleIcon/SparkleIcon.stories.js +0 -182
- package/src/atoms/components/SparkleIcon/SparkleIcon.vue +0 -105
- package/src/atoms/components/SparkleIcon/assets/animations/state-01.svg +0 -5
- package/src/atoms/components/SparkleIcon/assets/animations/state-02.svg +0 -5
- package/src/atoms/components/SparkleIcon/assets/animations/state-03.svg +0 -5
- package/src/atoms/components/SparkleIcon/assets/animations/state-04.svg +0 -5
- package/src/atoms/components/SparkleIcon/assets/animations/state-05.svg +0 -5
- package/src/atoms/components/SparkleIcon/assets/animations/state-06.svg +0 -5
- package/src/atoms/components/SparkleIcon/assets/animations/state-07.svg +0 -5
- package/src/atoms/components/SparkleIcon/assets/animations/state-08.svg +0 -5
- package/src/atoms/components/SparkleIcon/assets/sparkle.svg +0 -3
- package/src/atoms/components/SparkleIcon/index.ts +0 -3
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import PromoCard from './PromoCard.vue';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
title: 'Components/PromoCard',
|
|
5
|
+
component: PromoCard,
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const Standard = {
|
|
9
|
+
render: (args) => {
|
|
10
|
+
return {
|
|
11
|
+
components: {
|
|
12
|
+
PromoCard,
|
|
13
|
+
},
|
|
14
|
+
setup() {
|
|
15
|
+
return { args };
|
|
16
|
+
},
|
|
17
|
+
template: `
|
|
18
|
+
<PromoCard
|
|
19
|
+
v-bind="args"
|
|
20
|
+
@button-clicked="handleButtonClick"
|
|
21
|
+
/>
|
|
22
|
+
`,
|
|
23
|
+
methods: {
|
|
24
|
+
handleButtonClick() {
|
|
25
|
+
console.log('Button clicked!');
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
},
|
|
30
|
+
args: {
|
|
31
|
+
title: 'Special Offer',
|
|
32
|
+
description: 'Get 20% off your next purchase. Limited time offer!',
|
|
33
|
+
imageUrl: 'https://bcassetcdn.com/assets/images/promo/brandpage-design-support.png',
|
|
34
|
+
altText: 'Promotional image',
|
|
35
|
+
buttonLabel: 'Learn More',
|
|
36
|
+
horizontalLayout: false,
|
|
37
|
+
scaleImageDown: false,
|
|
38
|
+
imageWidthFull: false,
|
|
39
|
+
shouldShowImageOnTop: false,
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const HorizontalLayout = {
|
|
44
|
+
render: (args) => {
|
|
45
|
+
return {
|
|
46
|
+
components: {
|
|
47
|
+
PromoCard,
|
|
48
|
+
},
|
|
49
|
+
setup() {
|
|
50
|
+
return { args };
|
|
51
|
+
},
|
|
52
|
+
template: `
|
|
53
|
+
<PromoCard
|
|
54
|
+
v-bind="args"
|
|
55
|
+
@button-clicked="handleButtonClick"
|
|
56
|
+
/>
|
|
57
|
+
`,
|
|
58
|
+
methods: {
|
|
59
|
+
handleButtonClick() {
|
|
60
|
+
console.log('Button clicked!');
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
},
|
|
65
|
+
args: {
|
|
66
|
+
title: 'Premium Package',
|
|
67
|
+
description: 'Upgrade to premium and unlock exclusive features today.',
|
|
68
|
+
imageUrl: 'https://bcassetcdn.com/assets/images/promo/brandpage-design-support.png',
|
|
69
|
+
altText: 'Premium package image',
|
|
70
|
+
buttonLabel: 'Upgrade Now',
|
|
71
|
+
horizontalLayout: true,
|
|
72
|
+
scaleImageDown: false,
|
|
73
|
+
imageWidthFull: false,
|
|
74
|
+
shouldShowImageOnTop: false,
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export const ImageOnTop = {
|
|
79
|
+
render: (args) => {
|
|
80
|
+
return {
|
|
81
|
+
components: {
|
|
82
|
+
PromoCard,
|
|
83
|
+
},
|
|
84
|
+
setup() {
|
|
85
|
+
return { args };
|
|
86
|
+
},
|
|
87
|
+
template: `
|
|
88
|
+
<PromoCard
|
|
89
|
+
v-bind="args"
|
|
90
|
+
@button-clicked="handleButtonClick"
|
|
91
|
+
/>
|
|
92
|
+
`,
|
|
93
|
+
methods: {
|
|
94
|
+
handleButtonClick() {
|
|
95
|
+
console.log('Button clicked!');
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
},
|
|
100
|
+
args: {
|
|
101
|
+
title: 'Mobile Friendly',
|
|
102
|
+
description: 'This layout works great on mobile devices with the image displayed on top.',
|
|
103
|
+
imageUrl: 'https://bcassetcdn.com/assets/images/promo/brandpage-design-support.png',
|
|
104
|
+
altText: 'Mobile friendly layout',
|
|
105
|
+
buttonLabel: 'Try It',
|
|
106
|
+
horizontalLayout: false,
|
|
107
|
+
scaleImageDown: false,
|
|
108
|
+
imageWidthFull: false,
|
|
109
|
+
shouldShowImageOnTop: true,
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
export const ScaledDownImage = {
|
|
114
|
+
render: (args) => {
|
|
115
|
+
return {
|
|
116
|
+
components: {
|
|
117
|
+
PromoCard,
|
|
118
|
+
},
|
|
119
|
+
setup() {
|
|
120
|
+
return { args };
|
|
121
|
+
},
|
|
122
|
+
template: `
|
|
123
|
+
<PromoCard
|
|
124
|
+
v-bind="args"
|
|
125
|
+
@button-clicked="handleButtonClick"
|
|
126
|
+
/>
|
|
127
|
+
`,
|
|
128
|
+
methods: {
|
|
129
|
+
handleButtonClick() {
|
|
130
|
+
console.log('Button clicked!');
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
},
|
|
135
|
+
args: {
|
|
136
|
+
title: 'Logo Showcase',
|
|
137
|
+
description: 'Display your logo with proper spacing and scaling.',
|
|
138
|
+
imageUrl: 'https://via.placeholder.com/120x120',
|
|
139
|
+
altText: 'Logo showcase',
|
|
140
|
+
buttonLabel: 'View More',
|
|
141
|
+
horizontalLayout: false,
|
|
142
|
+
scaleImageDown: true,
|
|
143
|
+
imageWidthFull: false,
|
|
144
|
+
shouldShowImageOnTop: false,
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
export const FullWidthImage = {
|
|
149
|
+
render: (args) => {
|
|
150
|
+
return {
|
|
151
|
+
components: {
|
|
152
|
+
PromoCard,
|
|
153
|
+
},
|
|
154
|
+
setup() {
|
|
155
|
+
return { args };
|
|
156
|
+
},
|
|
157
|
+
template: `
|
|
158
|
+
<PromoCard
|
|
159
|
+
v-bind="args"
|
|
160
|
+
@button-clicked="handleButtonClick"
|
|
161
|
+
/>
|
|
162
|
+
`,
|
|
163
|
+
methods: {
|
|
164
|
+
handleButtonClick() {
|
|
165
|
+
console.log('Button clicked!');
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
},
|
|
170
|
+
args: {
|
|
171
|
+
title: 'Full Width Banner',
|
|
172
|
+
description: 'Images that stretch to fill the available space.',
|
|
173
|
+
imageUrl: 'https://bcassetcdn.com/assets/images/promo/brandpage-design-support.png',
|
|
174
|
+
altText: 'Full width banner',
|
|
175
|
+
buttonLabel: 'Explore',
|
|
176
|
+
horizontalLayout: false,
|
|
177
|
+
scaleImageDown: false,
|
|
178
|
+
imageWidthFull: true,
|
|
179
|
+
shouldShowImageOnTop: false,
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
export const AllOptions = {
|
|
184
|
+
render: (args) => {
|
|
185
|
+
return {
|
|
186
|
+
components: {
|
|
187
|
+
PromoCard,
|
|
188
|
+
},
|
|
189
|
+
setup() {
|
|
190
|
+
return { args };
|
|
191
|
+
},
|
|
192
|
+
template: `
|
|
193
|
+
<div class="tw-space-y-4">
|
|
194
|
+
<div>
|
|
195
|
+
<h3 class="tw-mb-2 tw-font-bold">Standard Layout</h3>
|
|
196
|
+
<PromoCard
|
|
197
|
+
title="Standard Promo"
|
|
198
|
+
description="This is the default vertical layout with image on the left."
|
|
199
|
+
imageUrl="https://bcassetcdn.com/assets/images/promo/brandpage-design-support.png"
|
|
200
|
+
altText="Standard layout"
|
|
201
|
+
buttonLabel="Click Me"
|
|
202
|
+
@button-clicked="handleButtonClick"
|
|
203
|
+
/>
|
|
204
|
+
</div>
|
|
205
|
+
|
|
206
|
+
<div>
|
|
207
|
+
<h3 class="tw-mb-2 tw-font-bold">Horizontal Layout</h3>
|
|
208
|
+
<PromoCard
|
|
209
|
+
title="Horizontal Promo"
|
|
210
|
+
description="This layout is better for desktop with content side by side."
|
|
211
|
+
imageUrl="https://bcassetcdn.com/assets/images/promo/brandpage-design-support.png"
|
|
212
|
+
altText="Horizontal layout"
|
|
213
|
+
buttonLabel="Click Me"
|
|
214
|
+
:horizontal-layout="true"
|
|
215
|
+
@button-clicked="handleButtonClick"
|
|
216
|
+
/>
|
|
217
|
+
</div>
|
|
218
|
+
|
|
219
|
+
<div>
|
|
220
|
+
<h3 class="tw-mb-2 tw-font-bold">Image On Top</h3>
|
|
221
|
+
<PromoCard
|
|
222
|
+
title="Mobile Optimized"
|
|
223
|
+
description="Perfect for mobile views with image stacked on top."
|
|
224
|
+
imageUrl="https://bcassetcdn.com/assets/images/promo/brandpage-design-support.png"
|
|
225
|
+
altText="Image on top"
|
|
226
|
+
buttonLabel="Click Me"
|
|
227
|
+
:should-show-image-on-top="true"
|
|
228
|
+
@button-clicked="handleButtonClick"
|
|
229
|
+
/>
|
|
230
|
+
</div>
|
|
231
|
+
</div>
|
|
232
|
+
`,
|
|
233
|
+
methods: {
|
|
234
|
+
handleButtonClick() {
|
|
235
|
+
console.log('Button clicked!');
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
};
|
|
239
|
+
},
|
|
240
|
+
args: {},
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
Standard.story = {
|
|
244
|
+
name: 'PromoCard - Standard',
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
HorizontalLayout.story = {
|
|
248
|
+
name: 'PromoCard - Horizontal Layout',
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
ImageOnTop.story = {
|
|
252
|
+
name: 'PromoCard - Image On Top',
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
ScaledDownImage.story = {
|
|
256
|
+
name: 'PromoCard - Scaled Down Image',
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
FullWidthImage.story = {
|
|
260
|
+
name: 'PromoCard - Full Width Image',
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
AllOptions.story = {
|
|
264
|
+
name: 'PromoCard - All Variants',
|
|
265
|
+
};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="tw-flex" :class="shouldShowImageOnTop ? 'tw-flex-col' : 'tw-flex-row'">
|
|
3
|
+
<div
|
|
4
|
+
class="tw-flex tw-justify-center tw-items-center tw-bg-grayscale-400 tw-w-60 tw-p-1 dcom-rounded-tl dcom-rounded-bl"
|
|
5
|
+
:class="{
|
|
6
|
+
'tw-w-full tw-px-8 md:tw-px-12 lg:tw-px-20 tw-py-4': shouldShowImageOnTop,
|
|
7
|
+
'tw-px-4': !shouldShowImageOnTop,
|
|
8
|
+
}"
|
|
9
|
+
>
|
|
10
|
+
<img :src="imageUrl" :alt="altText" />
|
|
11
|
+
</div>
|
|
12
|
+
<div
|
|
13
|
+
class="tw-flex tw-bg-white tw-w-full tw-p-4 tw-grow dcom-rounded-tr dcom-rounded-br tw-flex-col tw-justify-between"
|
|
14
|
+
:class="{
|
|
15
|
+
'lg:tw-flex-row lg:tw-items-center lg:tw-justify-normal': horizontalLayout,
|
|
16
|
+
}"
|
|
17
|
+
>
|
|
18
|
+
<div class="tw-text-left tw-overflow-hidden tw-text-ellipsis" :class="lineClampStyle">
|
|
19
|
+
<div class="tw-font-bold tw-text-black tw-mb-0.5">
|
|
20
|
+
{{ title }}
|
|
21
|
+
</div>
|
|
22
|
+
<p>
|
|
23
|
+
{{ description }}
|
|
24
|
+
</p>
|
|
25
|
+
</div>
|
|
26
|
+
<Button
|
|
27
|
+
variant="primary"
|
|
28
|
+
size="small"
|
|
29
|
+
:full-width="!horizontalLayout"
|
|
30
|
+
class="tw-text-left tw-mt-4"
|
|
31
|
+
:class="horizontalLayout ? 'tw-w-full tw-mr-2 md:tw-mt-0 md:tw-w-auto' : ''"
|
|
32
|
+
:label="buttonLabel"
|
|
33
|
+
@on-click="buttonClicked"
|
|
34
|
+
/>
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
</template>
|
|
38
|
+
<script>
|
|
39
|
+
import Button from '../Button/Button.vue';
|
|
40
|
+
|
|
41
|
+
export default {
|
|
42
|
+
components: { Button },
|
|
43
|
+
props: {
|
|
44
|
+
title: {
|
|
45
|
+
type: String,
|
|
46
|
+
required: true,
|
|
47
|
+
},
|
|
48
|
+
description: {
|
|
49
|
+
type: String,
|
|
50
|
+
required: true,
|
|
51
|
+
},
|
|
52
|
+
imageUrl: { type: String, required: true },
|
|
53
|
+
altText: { type: String, default: '' },
|
|
54
|
+
buttonLabel: {
|
|
55
|
+
type: String,
|
|
56
|
+
required: true,
|
|
57
|
+
},
|
|
58
|
+
horizontalLayout: {
|
|
59
|
+
type: Boolean,
|
|
60
|
+
default: false,
|
|
61
|
+
},
|
|
62
|
+
shouldShowImageOnTop: {
|
|
63
|
+
type: Boolean,
|
|
64
|
+
default: false,
|
|
65
|
+
},
|
|
66
|
+
textLineClamp: {
|
|
67
|
+
type: Number,
|
|
68
|
+
default: 0, // 0 is infinite
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
computed: {
|
|
72
|
+
shouldUseHorizontalLayout() {
|
|
73
|
+
// when in desktop view, display horizontal mode
|
|
74
|
+
return this.horizontalLayout;
|
|
75
|
+
},
|
|
76
|
+
lineClampStyle() {
|
|
77
|
+
if (this.textLineClamp > 0) {
|
|
78
|
+
return `tw-line-clamp-${this.textLineClamp}`;
|
|
79
|
+
}
|
|
80
|
+
return 'tw-line-clamp-none';
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
methods: {
|
|
84
|
+
buttonClicked() {
|
|
85
|
+
this.$emit('button-clicked');
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
</script>
|
package/tailwind.config.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
const bcTheme = require(
|
|
2
|
-
const bpTheme = require(
|
|
3
|
-
const dcTheme = require(
|
|
4
|
-
const cdTheme = require(
|
|
5
|
-
const dcomTheme = require(
|
|
6
|
-
const viewports = require(
|
|
1
|
+
const bcTheme = require('./src/themes/bc');
|
|
2
|
+
const bpTheme = require('./src/themes/bp');
|
|
3
|
+
const dcTheme = require('./src/themes/dc');
|
|
4
|
+
const cdTheme = require('./src/themes/cd');
|
|
5
|
+
const dcomTheme = require('./src/themes/dcom');
|
|
6
|
+
const viewports = require('./src/viewports');
|
|
7
7
|
|
|
8
8
|
const designSystemConfig = {
|
|
9
9
|
themes: {
|
|
@@ -20,7 +20,7 @@ const theme = designSystemConfig.themes[process.env.tailwindTheme]; // use the e
|
|
|
20
20
|
module.exports = {
|
|
21
21
|
prefix: 'tw-',
|
|
22
22
|
content: ['./src/**/components/**/*.vue'],
|
|
23
|
-
safelist: [{ pattern: /^!tw-p-/ }, { pattern: /^tw-overflow-y-auto$/ }],
|
|
23
|
+
safelist: [{ pattern: /^!tw-p-/ }, { pattern: /^tw-overflow-y-auto$/ }, { pattern: /^tw-line-clamp-/ }],
|
|
24
24
|
theme: {
|
|
25
25
|
...theme,
|
|
26
26
|
extend: {
|
|
@@ -34,4 +34,3 @@ module.exports = {
|
|
|
34
34
|
preflight: true,
|
|
35
35
|
},
|
|
36
36
|
};
|
|
37
|
-
|
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
import SparkleIcon from './SparkleIcon.vue';
|
|
2
|
-
|
|
3
|
-
export default {
|
|
4
|
-
title: 'Components/SparkleIcon',
|
|
5
|
-
component: SparkleIcon,
|
|
6
|
-
argTypes: {
|
|
7
|
-
animated: {
|
|
8
|
-
control: 'boolean',
|
|
9
|
-
description: 'Whether the sparkle icon should animate',
|
|
10
|
-
defaultValue: false,
|
|
11
|
-
},
|
|
12
|
-
size: {
|
|
13
|
-
control: { type: 'select' },
|
|
14
|
-
options: ['sm', 'md', 'lg', 12, 16, 20, 24, 32, 48],
|
|
15
|
-
description: 'Size of the icon (predefined or custom number)',
|
|
16
|
-
defaultValue: 'md',
|
|
17
|
-
},
|
|
18
|
-
},
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
// Default story
|
|
22
|
-
export const Default = (args) => ({
|
|
23
|
-
components: { SparkleIcon },
|
|
24
|
-
setup() {
|
|
25
|
-
return { args };
|
|
26
|
-
},
|
|
27
|
-
template: '<SparkleIcon v-bind="args" />',
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
Default.args = {
|
|
31
|
-
animated: false,
|
|
32
|
-
size: 'md',
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
// Static icon story
|
|
36
|
-
export const Static = () => ({
|
|
37
|
-
components: { SparkleIcon },
|
|
38
|
-
template: `
|
|
39
|
-
<div class="tw-flex tw-gap-4 tw-items-center">
|
|
40
|
-
<SparkleIcon size="sm" />
|
|
41
|
-
<SparkleIcon size="md" />
|
|
42
|
-
<SparkleIcon size="lg" />
|
|
43
|
-
</div>
|
|
44
|
-
`,
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
Static.story = {
|
|
48
|
-
name: 'Static Sizes',
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
// Animated icon story
|
|
52
|
-
export const Animated = () => ({
|
|
53
|
-
components: { SparkleIcon },
|
|
54
|
-
template: `
|
|
55
|
-
<div class="tw-flex tw-gap-4 tw-items-center">
|
|
56
|
-
<SparkleIcon :animated="true" size="sm" />
|
|
57
|
-
<SparkleIcon :animated="true" size="md" />
|
|
58
|
-
<SparkleIcon :animated="true" size="lg" />
|
|
59
|
-
</div>
|
|
60
|
-
`,
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
Animated.story = {
|
|
64
|
-
name: 'Animated Sizes',
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
// Custom sizes story
|
|
68
|
-
export const CustomSizes = () => ({
|
|
69
|
-
components: { SparkleIcon },
|
|
70
|
-
template: `
|
|
71
|
-
<div class="tw-flex tw-gap-4 tw-items-center">
|
|
72
|
-
<SparkleIcon :size="12" />
|
|
73
|
-
<SparkleIcon :size="16" />
|
|
74
|
-
<SparkleIcon :size="20" />
|
|
75
|
-
<SparkleIcon :size="24" />
|
|
76
|
-
<SparkleIcon :size="32" />
|
|
77
|
-
<SparkleIcon :size="48" />
|
|
78
|
-
</div>
|
|
79
|
-
`,
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
CustomSizes.story = {
|
|
83
|
-
name: 'Custom Number Sizes',
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
// Interactive toggle story
|
|
87
|
-
export const Interactive = () => ({
|
|
88
|
-
components: { SparkleIcon },
|
|
89
|
-
data() {
|
|
90
|
-
return {
|
|
91
|
-
isAnimated: false,
|
|
92
|
-
};
|
|
93
|
-
},
|
|
94
|
-
template: `
|
|
95
|
-
<div class="tw-flex tw-flex-col tw-gap-4">
|
|
96
|
-
<div class="tw-flex tw-items-center tw-gap-4">
|
|
97
|
-
<SparkleIcon :animated="isAnimated" size="lg" />
|
|
98
|
-
<button
|
|
99
|
-
class="tw-px-4 tw-py-2 tw-bg-primary-500 tw-text-white tw-rounded hover:tw-bg-blue-600"
|
|
100
|
-
@click="isAnimated = !isAnimated"
|
|
101
|
-
>
|
|
102
|
-
{{ isAnimated ? 'Stop Animation' : 'Start Animation' }}
|
|
103
|
-
</button>
|
|
104
|
-
</div>
|
|
105
|
-
<p class="tw-text-sm tw-text-gray-600">
|
|
106
|
-
Click the button to toggle animation
|
|
107
|
-
</p>
|
|
108
|
-
</div>
|
|
109
|
-
`,
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
Interactive.story = {
|
|
113
|
-
name: 'Interactive Toggle',
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
// All variations showcase
|
|
117
|
-
export const Showcase = () => ({
|
|
118
|
-
components: { SparkleIcon },
|
|
119
|
-
template: `
|
|
120
|
-
<div class="tw-p-6">
|
|
121
|
-
<h3 class="tw-text-lg tw-font-bold tw-mb-4">Sparkle Icon Showcase</h3>
|
|
122
|
-
|
|
123
|
-
<div class="tw-mb-6">
|
|
124
|
-
<h4 class="tw-text-md tw-font-semibold tw-mb-2">Static Icons</h4>
|
|
125
|
-
<div class="tw-flex tw-gap-4 tw-items-center tw-p-4 tw-bg-gray-100 tw-rounded">
|
|
126
|
-
<div class="tw-text-center">
|
|
127
|
-
<SparkleIcon size="sm" />
|
|
128
|
-
<p class="tw-text-xs tw-mt-1">Small (12px)</p>
|
|
129
|
-
</div>
|
|
130
|
-
<div class="tw-text-center">
|
|
131
|
-
<SparkleIcon size="md" />
|
|
132
|
-
<p class="tw-text-xs tw-mt-1">Medium (16px)</p>
|
|
133
|
-
</div>
|
|
134
|
-
<div class="tw-text-center">
|
|
135
|
-
<SparkleIcon size="lg" />
|
|
136
|
-
<p class="tw-text-xs tw-mt-1">Large (20px)</p>
|
|
137
|
-
</div>
|
|
138
|
-
</div>
|
|
139
|
-
</div>
|
|
140
|
-
|
|
141
|
-
<div class="tw-mb-6">
|
|
142
|
-
<h4 class="tw-text-md tw-font-semibold tw-mb-2">Animated Icons</h4>
|
|
143
|
-
<div class="tw-flex tw-gap-4 tw-items-center tw-p-4 tw-bg-gray-100 tw-rounded">
|
|
144
|
-
<div class="tw-text-center">
|
|
145
|
-
<SparkleIcon :animated="true" size="sm" />
|
|
146
|
-
<p class="tw-text-xs tw-mt-1">Small (12px)</p>
|
|
147
|
-
</div>
|
|
148
|
-
<div class="tw-text-center">
|
|
149
|
-
<SparkleIcon :animated="true" size="md" />
|
|
150
|
-
<p class="tw-text-xs tw-mt-1">Medium (16px)</p>
|
|
151
|
-
</div>
|
|
152
|
-
<div class="tw-text-center">
|
|
153
|
-
<SparkleIcon :animated="true" size="lg" />
|
|
154
|
-
<p class="tw-text-xs tw-mt-1">Large (20px)</p>
|
|
155
|
-
</div>
|
|
156
|
-
</div>
|
|
157
|
-
</div>
|
|
158
|
-
|
|
159
|
-
<div>
|
|
160
|
-
<h4 class="tw-text-md tw-font-semibold tw-mb-2">Custom Sizes</h4>
|
|
161
|
-
<div class="tw-flex tw-gap-4 tw-items-center tw-p-4 tw-bg-gray-100 tw-rounded">
|
|
162
|
-
<div class="tw-text-center">
|
|
163
|
-
<SparkleIcon :animated="true" :size="24" />
|
|
164
|
-
<p class="tw-text-xs tw-mt-1">24px</p>
|
|
165
|
-
</div>
|
|
166
|
-
<div class="tw-text-center">
|
|
167
|
-
<SparkleIcon :animated="true" :size="32" />
|
|
168
|
-
<p class="tw-text-xs tw-mt-1">32px</p>
|
|
169
|
-
</div>
|
|
170
|
-
<div class="tw-text-center">
|
|
171
|
-
<SparkleIcon :animated="true" :size="48" />
|
|
172
|
-
<p class="tw-text-xs tw-mt-1">48px</p>
|
|
173
|
-
</div>
|
|
174
|
-
</div>
|
|
175
|
-
</div>
|
|
176
|
-
</div>
|
|
177
|
-
`,
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
Showcase.story = {
|
|
181
|
-
name: 'Complete Showcase',
|
|
182
|
-
};
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<img :src="currentIcon" alt="AI" class="tw-flex-shrink-0" :style="sizeStyle" />
|
|
3
|
-
</template>
|
|
4
|
-
|
|
5
|
-
<script setup lang="ts">
|
|
6
|
-
import { ref, computed, watch, onUnmounted } from 'vue';
|
|
7
|
-
import sparkleIcon from './assets/sparkle.svg';
|
|
8
|
-
import sparkleState01 from './assets/animations/state-01.svg';
|
|
9
|
-
import sparkleState02 from './assets/animations/state-02.svg';
|
|
10
|
-
import sparkleState03 from './assets/animations/state-03.svg';
|
|
11
|
-
import sparkleState04 from './assets/animations/state-04.svg';
|
|
12
|
-
import sparkleState05 from './assets/animations/state-05.svg';
|
|
13
|
-
import sparkleState06 from './assets/animations/state-06.svg';
|
|
14
|
-
import sparkleState07 from './assets/animations/state-07.svg';
|
|
15
|
-
import sparkleState08 from './assets/animations/state-08.svg';
|
|
16
|
-
|
|
17
|
-
interface SparkleIconProps {
|
|
18
|
-
animated?: boolean;
|
|
19
|
-
size?: 'sm' | 'md' | 'lg' | number;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const props = withDefaults(defineProps<SparkleIconProps>(), {
|
|
23
|
-
animated: false,
|
|
24
|
-
size: 'md',
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
// Size mapping
|
|
28
|
-
const sizeMap = {
|
|
29
|
-
sm: 12,
|
|
30
|
-
md: 16,
|
|
31
|
-
lg: 20,
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
// Computed style for size
|
|
35
|
-
const sizeStyle = computed(() => {
|
|
36
|
-
const sizeValue = typeof props.size === 'number' ? props.size : sizeMap[props.size];
|
|
37
|
-
|
|
38
|
-
return {
|
|
39
|
-
width: `${sizeValue}px`,
|
|
40
|
-
height: `${sizeValue}px`,
|
|
41
|
-
};
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
// Animation frames
|
|
45
|
-
const sparkleFrames = [
|
|
46
|
-
sparkleState01,
|
|
47
|
-
sparkleState02,
|
|
48
|
-
sparkleState03,
|
|
49
|
-
sparkleState04,
|
|
50
|
-
sparkleState05,
|
|
51
|
-
sparkleState06,
|
|
52
|
-
sparkleState07,
|
|
53
|
-
sparkleState08,
|
|
54
|
-
];
|
|
55
|
-
|
|
56
|
-
const currentFrame = ref(0);
|
|
57
|
-
let animationInterval: number | null = null;
|
|
58
|
-
|
|
59
|
-
// Computed property to return either static or animated icon
|
|
60
|
-
const currentIcon = computed(() => {
|
|
61
|
-
if (props.animated) {
|
|
62
|
-
return sparkleFrames[currentFrame.value];
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return sparkleIcon;
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
// Start animation
|
|
69
|
-
const startAnimation = () => {
|
|
70
|
-
if (animationInterval) return;
|
|
71
|
-
|
|
72
|
-
currentFrame.value = 0;
|
|
73
|
-
animationInterval = window.setInterval(() => {
|
|
74
|
-
currentFrame.value = (currentFrame.value + 1) % sparkleFrames.length;
|
|
75
|
-
}, 100); // Change frame every 100ms
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
// Stop animation
|
|
79
|
-
const stopAnimation = () => {
|
|
80
|
-
if (animationInterval) {
|
|
81
|
-
clearInterval(animationInterval);
|
|
82
|
-
animationInterval = null;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
currentFrame.value = 0;
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
// Watch animated prop to control animation
|
|
89
|
-
watch(
|
|
90
|
-
() => props.animated,
|
|
91
|
-
(isAnimated) => {
|
|
92
|
-
if (isAnimated) {
|
|
93
|
-
startAnimation();
|
|
94
|
-
} else {
|
|
95
|
-
stopAnimation();
|
|
96
|
-
}
|
|
97
|
-
},
|
|
98
|
-
{ immediate: true },
|
|
99
|
-
);
|
|
100
|
-
|
|
101
|
-
// Cleanup on unmount
|
|
102
|
-
onUnmounted(() => {
|
|
103
|
-
stopAnimation();
|
|
104
|
-
});
|
|
105
|
-
</script>
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
-
<path d="M12.5 10C12.5 9.80469 12.4121 9.6582 12.2363 9.56055L8.95508 7.91992L7.28516 4.60938C7.20703 4.45312 7.07031 4.375 6.875 4.375C6.67969 4.375 6.54297 4.45312 6.46484 4.60938L4.79492 7.91992L1.51367 9.56055C1.33789 9.6582 1.25 9.80469 1.25 10C1.25 10.1953 1.33789 10.332 1.51367 10.4102L4.79492 12.0508L6.46484 15.3613C6.54297 15.5371 6.67969 15.625 6.875 15.625C7.07031 15.625 7.20703 15.5371 7.28516 15.3613L8.95508 12.0508L12.2363 10.4102C12.4121 10.332 12.5 10.1953 12.5 10Z" fill="#3F59F6"/>
|
|
3
|
-
<path d="M11.5625 5.3125C11.5625 5.3776 11.5885 5.42318 11.6406 5.44922L12.8125 5.9375L13.3008 7.10938C13.3268 7.16146 13.3724 7.1875 13.4375 7.1875C13.5026 7.1875 13.5482 7.16146 13.5742 7.10938L14.0625 5.9375L15.2344 5.44922C15.2865 5.42318 15.3125 5.3776 15.3125 5.3125C15.3125 5.2474 15.2865 5.20182 15.2344 5.17578L14.0625 4.6875L13.5742 3.51562C13.5482 3.46354 13.5026 3.4375 13.4375 3.4375C13.3724 3.4375 13.3268 3.46354 13.3008 3.51562L12.8125 4.6875L11.6406 5.17578C11.5885 5.20182 11.5625 5.2474 11.5625 5.3125Z" fill="#3F59F6"/>
|
|
4
|
-
<path d="M15.3125 14.6875C15.3125 14.6224 15.2865 14.5768 15.2344 14.5508L14.0625 14.0625L13.5742 12.8906C13.5482 12.8385 13.5026 12.8125 13.4375 12.8125C13.3724 12.8125 13.3268 12.8385 13.3008 12.8906L12.8125 14.0625L11.6406 14.5508C11.5885 14.5768 11.5625 14.6224 11.5625 14.6875C11.5625 14.7526 11.5885 14.7982 11.6406 14.8242L12.8125 15.3125L13.3008 16.4844C13.3268 16.5365 13.3724 16.5625 13.4375 16.5625C13.5026 16.5625 13.5482 16.5365 13.5742 16.4844L14.0625 15.3125L15.2344 14.8242C15.2865 14.7982 15.3125 14.7526 15.3125 14.6875Z" fill="#3F59F6"/>
|
|
5
|
-
</svg>
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
-
<path d="M13.125 10C13.125 9.78299 13.0273 9.62023 12.832 9.51172L9.1862 7.6888L7.33073 4.01042C7.24392 3.83681 7.09201 3.75 6.875 3.75C6.65799 3.75 6.50608 3.83681 6.41927 4.01042L4.5638 7.6888L0.917969 9.51172C0.722656 9.62023 0.625 9.78299 0.625 10C0.625 10.217 0.722656 10.3689 0.917969 10.4557L4.5638 12.2786L6.41927 15.957C6.50608 16.1523 6.65799 16.25 6.875 16.25C7.09201 16.25 7.24392 16.1523 7.33073 15.957L9.1862 12.2786L12.832 10.4557C13.0273 10.3689 13.125 10.217 13.125 10Z" fill="#3F59F6"/>
|
|
3
|
-
<path d="M12.5 5.3125C12.5 5.34505 12.513 5.36784 12.5391 5.38086L13.125 5.625L13.3691 6.21094C13.3822 6.23698 13.4049 6.25 13.4375 6.25C13.4701 6.25 13.4928 6.23698 13.5059 6.21094L13.75 5.625L14.3359 5.38086C14.362 5.36784 14.375 5.34505 14.375 5.3125C14.375 5.27995 14.362 5.25716 14.3359 5.24414L13.75 5L13.5059 4.41406C13.4928 4.38802 13.4701 4.375 13.4375 4.375C13.4049 4.375 13.3822 4.38802 13.3691 4.41406L13.125 5L12.5391 5.24414C12.513 5.25716 12.5 5.27995 12.5 5.3125Z" fill="#3F59F6"/>
|
|
4
|
-
<path d="M14.375 14.6875C14.375 14.6549 14.362 14.6322 14.3359 14.6191L13.75 14.375L13.5059 13.7891C13.4928 13.763 13.4701 13.75 13.4375 13.75C13.4049 13.75 13.3822 13.763 13.3691 13.7891L13.125 14.375L12.5391 14.6191C12.513 14.6322 12.5 14.6549 12.5 14.6875C12.5 14.7201 12.513 14.7428 12.5391 14.7559L13.125 15L13.3691 15.5859C13.3822 15.612 13.4049 15.625 13.4375 15.625C13.4701 15.625 13.4928 15.612 13.5059 15.5859L13.75 15L14.3359 14.7559C14.362 14.7428 14.375 14.7201 14.375 14.6875Z" fill="#3F59F6"/>
|
|
5
|
-
</svg>
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
-
<path d="M12.5 10C12.5 9.80469 12.4121 9.6582 12.2363 9.56055L8.95508 7.91992L7.28516 4.60938C7.20703 4.45312 7.07031 4.375 6.875 4.375C6.67969 4.375 6.54297 4.45312 6.46484 4.60938L4.79492 7.91992L1.51367 9.56055C1.33789 9.6582 1.25 9.80469 1.25 10C1.25 10.1953 1.33789 10.332 1.51367 10.4102L4.79492 12.0508L6.46484 15.3613C6.54297 15.5371 6.67969 15.625 6.875 15.625C7.07031 15.625 7.20703 15.5371 7.28516 15.3613L8.95508 12.0508L12.2363 10.4102C12.4121 10.332 12.5 10.1953 12.5 10Z" fill="#3F59F6"/>
|
|
3
|
-
<path d="M11.5625 5.3125C11.5625 5.3776 11.5885 5.42318 11.6406 5.44922L12.8125 5.9375L13.3008 7.10938C13.3268 7.16146 13.3724 7.1875 13.4375 7.1875C13.5026 7.1875 13.5482 7.16146 13.5742 7.10938L14.0625 5.9375L15.2344 5.44922C15.2865 5.42318 15.3125 5.3776 15.3125 5.3125C15.3125 5.2474 15.2865 5.20182 15.2344 5.17578L14.0625 4.6875L13.5742 3.51562C13.5482 3.46354 13.5026 3.4375 13.4375 3.4375C13.3724 3.4375 13.3268 3.46354 13.3008 3.51562L12.8125 4.6875L11.6406 5.17578C11.5885 5.20182 11.5625 5.2474 11.5625 5.3125Z" fill="#3F59F6"/>
|
|
4
|
-
<path d="M15.3125 14.6875C15.3125 14.6224 15.2865 14.5768 15.2344 14.5508L14.0625 14.0625L13.5742 12.8906C13.5482 12.8385 13.5026 12.8125 13.4375 12.8125C13.3724 12.8125 13.3268 12.8385 13.3008 12.8906L12.8125 14.0625L11.6406 14.5508C11.5885 14.5768 11.5625 14.6224 11.5625 14.6875C11.5625 14.7526 11.5885 14.7982 11.6406 14.8242L12.8125 15.3125L13.3008 16.4844C13.3268 16.5365 13.3724 16.5625 13.4375 16.5625C13.5026 16.5625 13.5482 16.5365 13.5742 16.4844L14.0625 15.3125L15.2344 14.8242C15.2865 14.7982 15.3125 14.7526 15.3125 14.6875Z" fill="#3F59F6"/>
|
|
5
|
-
</svg>
|