@designcrowd/fe-shared-lib 1.5.26 → 1.5.27-ENG-3954

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@designcrowd/fe-shared-lib",
3
- "version": "1.5.26",
3
+ "version": "1.5.27-ENG-3954",
4
4
  "scripts": {
5
5
  "start": "run-p storybook watch:translation",
6
6
  "build": "npm run build:css --production",
@@ -1,15 +1,14 @@
1
1
  <template>
2
2
  <button
3
3
  v-if="!url"
4
- class="tw-font-sans tw-border-2 tw-font-bold tw-text-grayscale-800 tw-uppercase tw-border-solid tw-transition-colors tw-duration-300"
4
+ class="tw-font-sans tw-font-bold tw-text-grayscale-800 tw-uppercase tw-border-solid tw-transition-colors tw-duration-300"
5
5
  :class="[
6
6
  classes,
7
7
  computedClasses,
8
8
  {
9
9
  'no-rounded-l': !rounded && !roundedLeft,
10
10
  'no-rounded-r': !rounded && !roundedRight,
11
- 'tw-cursor-pointer tw-bg-grayscale-300 tw-border-grayscale-300 hover:tw-border-grayscale-500 hover:tw-bg-grayscale-500':
12
- !disabled,
11
+ 'tw-cursor-pointer tw-bg-grayscale-300 hover:tw-bg-grayscale-500': !disabled,
13
12
  'tw-bg-grayscale-100 tw-border-grayscale-300 tw-cursor-not-allowed': disabled,
14
13
  },
15
14
  ]"
@@ -23,16 +22,15 @@
23
22
  <a
24
23
  v-else
25
24
  :href="computedUrl"
26
- class="tw-justify-center tw-font-sans tw-inline-flex tw-border-2 tw-font-bold tw-text-grayscale-800 tw-uppercase tw-border-solid tw-transition-colors tw-duration-300 tw-no-underline"
25
+ class="tw-justify-center tw-font-sans tw-inline-flex tw-font-bold tw-text-grayscale-800 hover:tw-text-grayscale-800 tw-uppercase tw-border-solid tw-transition-colors tw-duration-300 tw-no-underline"
27
26
  :class="[
28
27
  classes,
29
28
  computedClasses,
30
29
  {
31
30
  'no-rounded-l': !rounded && !roundedLeft,
32
31
  'no-rounded-r': !rounded && !roundedRight,
33
- 'tw-cursor-pointer tw-bg-grayscale-300 tw-border-grayscale-300 hover:tw-border-grayscale-500 hover:tw-bg-grayscale-500':
34
- !disabled,
35
- 'tw-bg-grayscale-100 tw-border-grayscale-100 tw-cursor-not-allowed': disabled,
32
+ 'tw-cursor-pointer tw-bg-grayscale-300 hover:tw-bg-grayscale-500': !disabled,
33
+ 'tw-bg-grayscale-100 tw-cursor-not-allowed': disabled,
36
34
  },
37
35
  ]"
38
36
  :download="download"
@@ -14,12 +14,8 @@ export const IconSample = () => {
14
14
  return {
15
15
  sizes: ['xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl', '4xl'],
16
16
  icons: [
17
- { name: 'websites-upgrade-to-add-page' },
18
- { name: 'websites-upgrade-to-contact-form' },
19
- { name: 'websites-upgrade-to-remove-watermark' },
20
- { name: 'websites-upgrade-to-publish' },
21
- { name: 'websites-upgrade-to-videos' },
22
- { name: 'websites-upgrade-to-maps' },
17
+ { name: 'crown' },
18
+ { name: 'crown-alt' },
23
19
  { name: 'add-page' },
24
20
  { name: 'ai' },
25
21
  { name: 'arrow-down' },
@@ -387,7 +383,6 @@ export const IconSample = () => {
387
383
  <div class="tw-grid tw-grid-cols-8 tw-gap-4 tw-items-center" style="grid-template-columns: repeat(8, minmax(0, 1fr));">
388
384
  <Icon
389
385
  v-for="size in sizes"
390
- viewBox="0 0 96 96"
391
386
  :name="icon.name"
392
387
  :alt-text="icon.altText"
393
388
  :size="size"
@@ -50,12 +50,12 @@ import IconAttach from './icons/attach.vue';
50
50
  import IconAuthFacebookWhite from './icons/auth-facebook-white.vue';
51
51
  import IconAuthFacebook from './icons/auth-facebook.vue';
52
52
  import IconAuthGoogle from './icons/auth-google.vue';
53
- import IconBriefcase from './icons/briefcase.vue';
54
53
  import IconBackground from './icons/background.vue';
55
54
  import IconBannerCentered from './icons/banner-centered.vue';
56
55
  import IconBannerLeft from './icons/banner-left.vue';
57
56
  import IconBanner from './icons/banner.vue';
58
57
  import IconBcMast from './icons/bc-mast.vue';
58
+ import IconBriefcase from './icons/briefcase.vue';
59
59
  import IconBrush from './icons/brush.vue';
60
60
  import IconBusinessCardFilled from './icons/business-card-filled.vue';
61
61
  import IconBusiness from './icons/business.vue';
@@ -105,6 +105,8 @@ import IconCopy from './icons/copy.vue';
105
105
  import IconFilterCrazyDomains from './icons/crazy-domains/filter.vue';
106
106
  import IconGlobeCrazyDomains from './icons/crazy-domains/globe.vue';
107
107
  import IconHomeCrazyDomains from './icons/crazy-domains/home.vue';
108
+ import IconCrownAlt from './icons/crown-alt.vue';
109
+ import IconCrown from './icons/crown.vue';
108
110
  import IconDelete from './icons/delete.vue';
109
111
  import IconDesigns from './icons/designs.vue';
110
112
  import IconDesktop from './icons/desktop.vue';
@@ -222,11 +224,14 @@ import IconSocialInstagramCrazyDomains from './icons/crazy-domains/social-instag
222
224
  import IconSocialTwitterCrazyDomains from './icons/crazy-domains/social-twitter.vue';
223
225
  import IconSocialYoutubeCrazyDomains from './icons/crazy-domains/social-youtube.vue';
224
226
  import IconCrop from './icons/crop.vue';
227
+ import IconDigitalBusinessCardFilled from './icons/digital-business-card-filled.vue';
225
228
  import IconFormMessage from './icons/form-message.vue';
226
229
  import IconGodaddy from './icons/godaddy/logo.vue';
227
230
  import IconIconStyleCircleBg from './icons/icon-style-circle-bg.vue';
228
231
  import IconIconStyleNoBg from './icons/icon-style-no-bg.vue';
229
232
  import IconIconStyleSquareBg from './icons/icon-style-square-bg.vue';
233
+ import IconLinkInBioFilled from './icons/link-in-bio-filled.vue';
234
+ import IconMedia from './icons/media.vue';
230
235
  import IconMinusCircleLight from './icons/minus-circle-light.vue';
231
236
  import IconMinus from './icons/minus.vue';
232
237
  import IconMobile from './icons/mobile.vue';
@@ -254,9 +259,8 @@ import IconQuestion from './icons/question.vue';
254
259
  import IconQuote from './icons/quote.vue';
255
260
  import IconReload from './icons/reload.vue';
256
261
  import IconReorderable from './icons/reorderable.vue';
257
- import IconResize from './icons/resize.vue';
258
- import IconMedia from './icons/media.vue';
259
262
  import IconRequestPayment from './icons/request-payment.vue';
263
+ import IconResize from './icons/resize.vue';
260
264
  import IconSearch from './icons/search.vue';
261
265
  import IconSecure from './icons/secure.vue';
262
266
  import IconSend from './icons/send.vue';
@@ -265,7 +269,6 @@ import IconSettings from './icons/settings.vue';
265
269
  import IconShare from './icons/share.vue';
266
270
  import IconShieldTick from './icons/shield-tick.vue';
267
271
  import IconShop from './icons/shop.vue';
268
- import IconStop from './icons/stop.vue';
269
272
  import IconSms from './icons/sms.vue';
270
273
  import IconSocialFacebookColor from './icons/social-facebook-color.vue';
271
274
  import IconSocialFacebook from './icons/social-facebook.vue';
@@ -277,6 +280,7 @@ import IconSocialTwitterColor from './icons/social-twitter-color.vue';
277
280
  import IconStarFilled from './icons/star-filled.vue';
278
281
  import IconStarHollow from './icons/star-hollow.vue';
279
282
  import IconSticker from './icons/sticker.vue';
283
+ import IconStop from './icons/stop.vue';
280
284
  import IconStyles from './icons/styles.vue';
281
285
  import IconSubmit from './icons/submit.vue';
282
286
  import IconTemplates from './icons/templates.vue';
@@ -304,8 +308,6 @@ import IconWatchlistFilled from './icons/watchlist-filled.vue';
304
308
  import IconWatchlistHollowAlt from './icons/watchlist-hollow-alt.vue';
305
309
  import IconWatchlistHollow from './icons/watchlist-hollow.vue';
306
310
  import IconWebsiteFilled from './icons/website-filled.vue';
307
- import IconDigitalBusinessCardFilled from './icons/digital-business-card-filled.vue';
308
- import IconLinkInBioFilled from './icons/link-in-bio-filled.vue';
309
311
  import IconWebsite from './icons/website.vue';
310
312
  import IconWholesale from './icons/wholesale.vue';
311
313
  import IconZoomIn from './icons/zoom-in.vue';
@@ -327,6 +329,7 @@ import IconShape from './icons/shape.vue';
327
329
  // New icons copied from dcom
328
330
  import IconAnnotateHeart from './icons/annotate-heart.vue';
329
331
  import IconAward from './icons/award.vue';
332
+ import IconBezierCurveOutline from './icons/bezier-curve-outline.vue';
330
333
  import IconBezierCurve from './icons/bezier-curve.vue';
331
334
  import IconBrowser from './icons/browser.vue';
332
335
  import IconCardVertical from './icons/card-vertical.vue';
@@ -336,12 +339,11 @@ import IconHeadphones from './icons/headphones.vue';
336
339
  import IconImage from './icons/image.vue';
337
340
  import IconLightning from './icons/lightning.vue';
338
341
  import IconLogo from './icons/logo.vue';
339
- import IconPen from './icons/pen.vue';
342
+ import IconPaletteOutline from './icons/palette-outline.vue';
340
343
  import IconPenOutline from './icons/pen-outline.vue';
341
344
  import IconPenSparkle from './icons/pen-sparkle.vue';
345
+ import IconPen from './icons/pen.vue';
342
346
  import IconSparkleSquare from './icons/sparkle-square.vue';
343
- import IconBezierCurveOutline from './icons/bezier-curve-outline.vue';
344
- import IconPaletteOutline from './icons/palette-outline.vue';
345
347
 
346
348
  // Maker Icons
347
349
  import IconMakerAlignCenter from './icons/maker/align-center.vue';
@@ -422,18 +424,18 @@ import IconFlipVertical from './icons/flip-vertical.vue';
422
424
  import IconVolumeMuted from './icons/volume-muted.vue';
423
425
  import IconVolume from './icons/volume.vue';
424
426
 
425
- import IconFile from './icons/file.vue';
426
- import IconPenTool from './icons/pen-tool.vue';
427
- import IconClipboardCheck from './icons/clipboard-check.vue';
428
427
  import IconBadge from './icons/badge.vue';
429
428
  import IconCalculator from './icons/calculator.vue';
429
+ import IconClipboardCheck from './icons/clipboard-check.vue';
430
+ import IconFile from './icons/file.vue';
431
+ import IconPenTool from './icons/pen-tool.vue';
430
432
  import IconWebsitesUpgradeToAddPage from './icons/websites/upgrade-to-add-page.vue';
431
433
  import IconWebsitesUpgradeToContactForm from './icons/websites/upgrade-to-contact-form.vue';
432
- import IconWebsitesUpgradeToRemoveWatermark from './icons/websites/upgrade-to-remove-watermark.vue';
434
+ import IconWebsitesUpgradeToGoogleAd from './icons/websites/upgrade-to-google-ad.vue';
435
+ import IconWebsitesUpgradeToMaps from './icons/websites/upgrade-to-maps.vue';
433
436
  import IconWebsitesUpgradeToPublish from './icons/websites/upgrade-to-publish.vue';
437
+ import IconWebsitesUpgradeToRemoveWatermark from './icons/websites/upgrade-to-remove-watermark.vue';
434
438
  import IconWebsitesUpgradeToVideos from './icons/websites/upgrade-to-videos.vue';
435
- import IconWebsitesUpgradeToMaps from './icons/websites/upgrade-to-maps.vue';
436
- import IconWebsitesUpgradeToGoogleAd from './icons/websites/upgrade-to-google-ad.vue';
437
439
 
438
440
  import IconGroup from './icons/group.vue';
439
441
  import IconPremiumContent from './icons/premium-content.vue';
@@ -506,6 +508,7 @@ export default {
506
508
  IconColumn2,
507
509
  IconColumn3,
508
510
  IconColumn4,
511
+ IconCrownAlt,
509
512
  IconCopy,
510
513
  IconDelete,
511
514
  IconDesigns,
@@ -612,6 +615,7 @@ export default {
612
615
  IconDisplayStyleContact5,
613
616
  IconDisplayStyleContact6,
614
617
  IconLetterheadFilled,
618
+ IconCrown,
615
619
  IconLink,
616
620
  IconLocation,
617
621
  IconLock,
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <path
3
+ d="M12.55 12.125C12.6521 12.125 12.7323 12.1536 12.7906 12.2109C12.8635 12.2826 12.9 12.3685 12.9 12.4688V13.1562C12.9 13.2565 12.8635 13.3353 12.7906 13.3926C12.7323 13.4642 12.6521 13.5 12.55 13.5H3.45C3.34792 13.5 3.26042 13.4642 3.1875 13.3926C3.12917 13.3353 3.1 13.2565 3.1 13.1562V12.4688C3.1 12.3685 3.12917 12.2826 3.1875 12.2109C3.26042 12.1536 3.34792 12.125 3.45 12.125H12.55ZM13.2063 5.55078C13.4104 5.35026 13.6583 5.25 13.95 5.25C14.2417 5.25 14.4896 5.35026 14.6938 5.55078C14.8979 5.7513 15 5.99479 15 6.28125C15 6.56771 14.8979 6.8112 14.6938 7.01172C14.4896 7.21224 14.2417 7.3125 13.95 7.3125C13.9062 7.3125 13.8479 7.30534 13.775 7.29102L12.2 11.4375H3.8L2.225 7.29102C2.15208 7.30534 2.09375 7.3125 2.05 7.3125C1.75833 7.3125 1.51042 7.21224 1.30625 7.01172C1.10208 6.8112 1 6.56771 1 6.28125C1 5.99479 1.10208 5.7513 1.30625 5.55078C1.51042 5.35026 1.75833 5.25 2.05 5.25C2.34167 5.25 2.58958 5.35026 2.79375 5.55078C2.99792 5.7513 3.1 5.99479 3.1 6.28125C3.1 6.42448 3.07083 6.56771 3.0125 6.71094L4.5875 7.63477C4.74792 7.73503 4.92292 7.76367 5.1125 7.7207C5.31667 7.66341 5.4625 7.55599 5.55 7.39844L7.34375 4.32617C7.08125 4.11133 6.95 3.84635 6.95 3.53125C6.95 3.24479 7.05208 3.0013 7.25625 2.80078C7.46042 2.60026 7.70833 2.5 8 2.5C8.29167 2.5 8.53958 2.60026 8.74375 2.80078C8.94792 3.0013 9.05 3.24479 9.05 3.53125C9.05 3.84635 8.91875 4.11133 8.65625 4.32617L10.45 7.39844C10.5375 7.55599 10.676 7.66341 10.8656 7.7207C11.0552 7.76367 11.2375 7.73503 11.4125 7.63477L12.9875 6.71094C12.9292 6.56771 12.9 6.42448 12.9 6.28125C12.9 5.99479 13.0021 5.7513 13.2063 5.55078Z"
4
+ />
5
+ </template>
@@ -0,0 +1,6 @@
1
+ <template>
2
+ <path
3
+ d="M12.55 12.125C12.6521 12.125 12.7323 12.1536 12.7906 12.2109C12.8635 12.2826 12.9 12.3685 12.9 12.4688V13.1562C12.9 13.2565 12.8635 13.3353 12.7906 13.3926C12.7323 13.4642 12.6521 13.5 12.55 13.5H3.45C3.34792 13.5 3.26042 13.4642 3.1875 13.3926C3.12917 13.3353 3.1 13.2565 3.1 13.1562V12.4688C3.1 12.3685 3.12917 12.2826 3.1875 12.2109C3.26042 12.1536 3.34792 12.125 3.45 12.125H12.55ZM13.2063 5.55078C13.4104 5.35026 13.6583 5.25 13.95 5.25C14.2417 5.25 14.4896 5.35026 14.6938 5.55078C14.8979 5.7513 15 5.99479 15 6.28125C15 6.56771 14.8979 6.8112 14.6938 7.01172C14.4896 7.21224 14.2417 7.3125 13.95 7.3125C13.9062 7.3125 13.8479 7.30534 13.775 7.29102L12.2 11.4375H3.8L2.225 7.29102C2.15208 7.30534 2.09375 7.3125 2.05 7.3125C1.75833 7.3125 1.51042 7.21224 1.30625 7.01172C1.10208 6.8112 1 6.56771 1 6.28125C1 5.99479 1.10208 5.7513 1.30625 5.55078C1.51042 5.35026 1.75833 5.25 2.05 5.25C2.34167 5.25 2.58958 5.35026 2.79375 5.55078C2.99792 5.7513 3.1 5.99479 3.1 6.28125C3.1 6.42448 3.07083 6.56771 3.0125 6.71094L4.5875 7.63477C4.74792 7.73503 4.92292 7.76367 5.1125 7.7207C5.31667 7.66341 5.4625 7.55599 5.55 7.39844L7.34375 4.32617C7.08125 4.11133 6.95 3.84635 6.95 3.53125C6.95 3.24479 7.05208 3.0013 7.25625 2.80078C7.46042 2.60026 7.70833 2.5 8 2.5C8.29167 2.5 8.53958 2.60026 8.74375 2.80078C8.94792 3.0013 9.05 3.24479 9.05 3.53125C9.05 3.84635 8.91875 4.11133 8.65625 4.32617L10.45 7.39844C10.5375 7.55599 10.676 7.66341 10.8656 7.7207C11.0552 7.76367 11.2375 7.73503 11.4125 7.63477L12.9875 6.71094C12.9292 6.56771 12.9 6.42448 12.9 6.28125C12.9 5.99479 13.0021 5.7513 13.2063 5.55078Z"
4
+ fill="#E3A008"
5
+ />
6
+ </template>
@@ -0,0 +1,62 @@
1
+ <template>
2
+ <component :is="componentTag" class="menu-item" :class="variantClasses" v-bind="componentAttrs" @click="handleClick">
3
+ <Icon v-if="icon" :name="icon" :size="iconSize" />
4
+ <span>{{ label }}</span>
5
+ </component>
6
+ </template>
7
+
8
+ <script setup lang="ts">
9
+ import { computed } from 'vue';
10
+ import Icon from '../../../atoms/components/Icon/Icon.vue';
11
+
12
+ type MenuCtaVariant = 'primary' | 'secondary' | 'empty';
13
+
14
+ interface MenuCtaProps {
15
+ label: string;
16
+ variant?: MenuCtaVariant;
17
+ icon?: string;
18
+ iconSize?: 'sm' | 'md' | 'lg';
19
+ url?: string;
20
+ action?: () => void;
21
+ }
22
+
23
+ const props = withDefaults(defineProps<MenuCtaProps>(), {
24
+ variant: 'primary',
25
+ iconSize: 'sm',
26
+ });
27
+
28
+ const emit = defineEmits<{
29
+ click: [event: MouseEvent];
30
+ }>();
31
+
32
+ const componentTag = computed(() => (props.action ? 'button' : 'a'));
33
+
34
+ const componentAttrs = computed(() => (props.action ? {} : { href: props.url }));
35
+
36
+ const variantClasses = computed(() => {
37
+ switch (props.variant) {
38
+ case 'primary':
39
+ return 'tw-bg-primary-500 tw-text-white hover:tw-bg-primary-700';
40
+ case 'secondary':
41
+ return 'tw-justify-center tw-bg-secondary-500 tw-text-white hover:tw-bg-secondary-700';
42
+ case 'empty':
43
+ return 'tw-justify-center tw-text-grayscale-700 hover:tw-bg-gray-600 tw-text-center';
44
+ default:
45
+ return '';
46
+ }
47
+ });
48
+
49
+ const handleClick = (event: MouseEvent) => {
50
+ if (props.action) {
51
+ props.action();
52
+ }
53
+ emit('click', event);
54
+ };
55
+ </script>
56
+
57
+ <style scoped>
58
+ .menu-item {
59
+ @apply tw-p-2 tw-flex tw-gap-2 tw-items-center tw-rounded-lg tw-font-normal tw-cursor-pointer;
60
+ height: 36px;
61
+ }
62
+ </style>
@@ -0,0 +1,47 @@
1
+ <template>
2
+ <component
3
+ :is="componentTag"
4
+ class="menu-item"
5
+ :class="{ 'tw-bg-grayscale-400': isActive, 'hover:tw-bg-grayscale-300': !isActive }"
6
+ v-bind="componentAttrs"
7
+ @click="handleClick"
8
+ >
9
+ <Icon class="icon" :name="icon" size="sm" />
10
+ <span class="tw-text-md tw-font-medium tw-text-grayscale-700">{{ label }}</span>
11
+ </component>
12
+ </template>
13
+
14
+ <script setup lang="ts">
15
+ import { computed } from 'vue';
16
+ import Icon from '../../../atoms/components/Icon/Icon.vue';
17
+
18
+ type IMenuItem = {
19
+ label: string;
20
+ url?: string;
21
+ action?: () => void;
22
+ icon: string;
23
+ isActive: boolean;
24
+ };
25
+
26
+ const props = defineProps<IMenuItem>();
27
+
28
+ const componentTag = computed(() => (props.action ? 'button' : 'a'));
29
+
30
+ const componentAttrs = computed(() => (props.action ? {} : { href: props.url }));
31
+
32
+ const handleClick = () => {
33
+ if (props.action) {
34
+ props.action();
35
+ }
36
+ };
37
+ </script>
38
+
39
+ <style scoped>
40
+ .menu-item {
41
+ @apply tw-p-2 tw-mb-1 tw-flex tw-gap-2 tw-items-center tw-rounded-lg tw-cursor-pointer;
42
+ height: 36px;
43
+ }
44
+ .icon svg {
45
+ color: var(--text-secondary, rgba(61, 61, 61, 1));
46
+ }
47
+ </style>
@@ -0,0 +1,219 @@
1
+ import SideNavigationPanel from './SideNavigationPanel.vue';
2
+
3
+ export default {
4
+ title: 'Experiences/SideNavigationPanel',
5
+ component: SideNavigationPanel,
6
+ argTypes: {
7
+ menuItems: {
8
+ control: 'object',
9
+ description: 'Array of menu items with label, url, icon, and isActive properties',
10
+ },
11
+ createNewDesignCta: {
12
+ control: 'object',
13
+ description: 'CTA object for "Create New Design" button with url property',
14
+ },
15
+ upgradeCta: {
16
+ control: 'object',
17
+ description: 'CTA object for "Upgrade" button with url property',
18
+ },
19
+ rateCta: {
20
+ control: 'object',
21
+ description: 'CTA object for "Rate Design.com" button with action property',
22
+ },
23
+ },
24
+ parameters: {
25
+ layout: 'fullscreen',
26
+ },
27
+ };
28
+
29
+ // Default menu items representing a typical navigation structure
30
+ const defaultMenuItems = [
31
+ { label: 'Logos', icon: 'star-hollow', url: '#logos', isActive: true, action: undefined },
32
+ { label: 'Designs', icon: 'designs', url: '#designs', isActive: false, action: undefined },
33
+ { label: 'Printing', icon: 'printing', url: '#printing', isActive: false, action: undefined },
34
+ { label: 'Websites', icon: 'website', url: '#websites', isActive: false, action: undefined },
35
+ { label: 'Domains', icon: 'globe', url: '#domains', isActive: false, action: undefined },
36
+ { label: 'Settings', icon: 'settings', url: '#settings', isActive: false, action: undefined },
37
+ ];
38
+
39
+ const defaultCreateNewDesignCta = {
40
+ url: '#create-new-design',
41
+ };
42
+
43
+ const defaultUpgradeCta = {
44
+ url: '#upgrade',
45
+ };
46
+
47
+ const defaultRateCta = {
48
+ action: () => console.log('Rate Design.com clicked'),
49
+ };
50
+
51
+ const Template = (args) => ({
52
+ components: { SideNavigationPanel },
53
+ setup() {
54
+ return { args };
55
+ },
56
+ template: `
57
+ <div style="width: 100vw; height: 100vh; display: flex;">
58
+ <SideNavigationPanel v-bind="args" />
59
+ <div style="flex: 1; padding: 2rem; background: white;">
60
+ <h1 style="font-size: 2rem; margin-bottom: 1rem;">Content Area</h1>
61
+ <p>This is where your main content would appear. The side navigation panel is on the left.</p>
62
+ <p style="margin-top: 1rem;">Click on the menu items to see the active state change (in a real app).</p>
63
+ </div>
64
+ </div>
65
+ `,
66
+ });
67
+
68
+ export const Default = Template.bind({});
69
+ Default.args = {
70
+ menuItems: defaultMenuItems,
71
+ createNewDesignCta: defaultCreateNewDesignCta,
72
+ upgradeCta: defaultUpgradeCta,
73
+ rateCta: defaultRateCta,
74
+ };
75
+ Default.parameters = {
76
+ docs: {
77
+ description: {
78
+ story: 'Default side navigation panel with all CTAs and the first menu item active.',
79
+ },
80
+ },
81
+ };
82
+
83
+ export const DesignsActive = Template.bind({});
84
+ DesignsActive.args = {
85
+ menuItems: [
86
+ { label: 'Logos', icon: 'star-hollow', url: '#logos', isActive: false, action: undefined },
87
+ { label: 'Designs', icon: 'designs', url: '#designs', isActive: true, action: undefined },
88
+ { label: 'Printing', icon: 'printing', url: '#printing', isActive: false, action: undefined },
89
+ { label: 'Websites', icon: 'website', url: '#websites', isActive: false, action: undefined },
90
+ { label: 'Domains', icon: 'globe', url: '#domains', isActive: false, action: undefined },
91
+ { label: 'Settings', icon: 'settings', url: '#settings', isActive: false, action: undefined },
92
+ ],
93
+ createNewDesignCta: defaultCreateNewDesignCta,
94
+ upgradeCta: defaultUpgradeCta,
95
+ rateCta: defaultRateCta,
96
+ };
97
+ DesignsActive.parameters = {
98
+ docs: {
99
+ description: {
100
+ story: 'Side navigation panel with the "Designs" menu item active.',
101
+ },
102
+ },
103
+ };
104
+
105
+ export const SettingsActive = Template.bind({});
106
+ SettingsActive.args = {
107
+ menuItems: [
108
+ { label: 'Logos', icon: 'star-hollow', url: '#logos', isActive: false, action: undefined },
109
+ { label: 'Designs', icon: 'designs', url: '#designs', isActive: false, action: undefined },
110
+ { label: 'Printing', icon: 'printing', url: '#printing', isActive: false, action: undefined },
111
+ { label: 'Websites', icon: 'website', url: '#websites', isActive: false, action: undefined },
112
+ { label: 'Domains', icon: 'globe', url: '#domains', isActive: false, action: undefined },
113
+ { label: 'Settings', icon: 'settings', url: '#settings', isActive: true, action: undefined },
114
+ ],
115
+ createNewDesignCta: defaultCreateNewDesignCta,
116
+ upgradeCta: defaultUpgradeCta,
117
+ rateCta: defaultRateCta,
118
+ };
119
+ SettingsActive.parameters = {
120
+ docs: {
121
+ description: {
122
+ story: 'Side navigation panel with the "Settings" menu item active.',
123
+ },
124
+ },
125
+ };
126
+
127
+ export const NoActiveItem = Template.bind({});
128
+ NoActiveItem.args = {
129
+ menuItems: [
130
+ { label: 'Logos', icon: 'star-hollow', url: '#logos', isActive: false, action: undefined },
131
+ { label: 'Designs', icon: 'designs', url: '#designs', isActive: false, action: undefined },
132
+ { label: 'Printing', icon: 'printing', url: '#printing', isActive: false, action: undefined },
133
+ { label: 'Websites', icon: 'website', url: '#websites', isActive: false, action: undefined },
134
+ { label: 'Domains', icon: 'globe', url: '#domains', isActive: false, action: undefined },
135
+ { label: 'Settings', icon: 'settings', url: '#settings', isActive: false, action: undefined },
136
+ ],
137
+ createNewDesignCta: defaultCreateNewDesignCta,
138
+ upgradeCta: defaultUpgradeCta,
139
+ rateCta: defaultRateCta,
140
+ };
141
+ NoActiveItem.parameters = {
142
+ docs: {
143
+ description: {
144
+ story: 'Side navigation panel with no active menu item.',
145
+ },
146
+ },
147
+ };
148
+
149
+ export const WithActionBasedMenuItems = Template.bind({});
150
+ WithActionBasedMenuItems.args = {
151
+ menuItems: [
152
+ { label: 'Logos', icon: 'star-hollow', url: '#logos', isActive: true, action: undefined },
153
+ { label: 'Designs', icon: 'designs', url: '#designs', isActive: false, action: undefined },
154
+ {
155
+ label: 'Export Data',
156
+ icon: 'download',
157
+ url: undefined,
158
+ isActive: false,
159
+ action: () => console.log('Export data action triggered'),
160
+ },
161
+ { label: 'Websites', icon: 'website', url: '#websites', isActive: false, action: undefined },
162
+ { label: 'Settings', icon: 'settings', url: '#settings', isActive: false, action: undefined },
163
+ ],
164
+ createNewDesignCta: defaultCreateNewDesignCta,
165
+ upgradeCta: defaultUpgradeCta,
166
+ rateCta: defaultRateCta,
167
+ };
168
+ WithActionBasedMenuItems.parameters = {
169
+ docs: {
170
+ description: {
171
+ story:
172
+ 'Side navigation panel with an action-based menu item (Export Data) that triggers a function instead of navigation. Check console for action output.',
173
+ },
174
+ },
175
+ };
176
+
177
+ export const MinimalMenuItems = Template.bind({});
178
+ MinimalMenuItems.args = {
179
+ menuItems: [
180
+ { label: 'Dashboard', icon: 'star-hollow', url: '#dashboard', isActive: true, action: undefined },
181
+ { label: 'Projects', icon: 'designs', url: '#projects', isActive: false, action: undefined },
182
+ { label: 'Help', icon: 'help', url: '#help', isActive: false, action: undefined },
183
+ ],
184
+ createNewDesignCta: defaultCreateNewDesignCta,
185
+ upgradeCta: defaultUpgradeCta,
186
+ rateCta: defaultRateCta,
187
+ };
188
+ MinimalMenuItems.parameters = {
189
+ docs: {
190
+ description: {
191
+ story: 'Side navigation panel with a minimal set of menu items.',
192
+ },
193
+ },
194
+ };
195
+
196
+ export const ExtendedMenuItems = Template.bind({});
197
+ ExtendedMenuItems.args = {
198
+ menuItems: [
199
+ { label: 'Logos', icon: 'star-hollow', url: '#logos', isActive: false, action: undefined },
200
+ { label: 'Designs', icon: 'designs', url: '#designs', isActive: false, action: undefined },
201
+ { label: 'Printing', icon: 'printing', url: '#printing', isActive: false, action: undefined },
202
+ { label: 'Websites', icon: 'website', url: '#websites', isActive: true, action: undefined },
203
+ { label: 'Domains', icon: 'globe', url: '#domains', isActive: false, action: undefined },
204
+ { label: 'Marketing', icon: 'megaphone', url: '#marketing', isActive: false, action: undefined },
205
+ { label: 'Analytics', icon: 'chart', url: '#analytics', isActive: false, action: undefined },
206
+ { label: 'Billing', icon: 'creditcard', url: '#billing', isActive: false, action: undefined },
207
+ { label: 'Settings', icon: 'settings', url: '#settings', isActive: false, action: undefined },
208
+ ],
209
+ createNewDesignCta: defaultCreateNewDesignCta,
210
+ upgradeCta: defaultUpgradeCta,
211
+ rateCta: defaultRateCta,
212
+ };
213
+ ExtendedMenuItems.parameters = {
214
+ docs: {
215
+ description: {
216
+ story: 'Side navigation panel with an extended list of menu items to test scrolling behavior.',
217
+ },
218
+ },
219
+ };
@@ -0,0 +1,57 @@
1
+ <template>
2
+ <!-- Side Navigation Component following these figma designs: https://www.figma.com/design/UUZ56EQZbb1Ua9NBMm6Rt5/DCOM---My-Account-Left-Nav -->
3
+ <div class="sidebar">
4
+ <div class="menu tw-mb-4">
5
+ <MenuCta class="tw-mt-2 tw-mb-4" label="Create New Design" variant="primary" icon="plus" icon-size="xs" />
6
+ <div class="menuitemcontainer">
7
+ <MenuItem
8
+ v-for="item in menuItems"
9
+ :key="item.label"
10
+ :label="item.label"
11
+ :url="item.action ? '' : item.url"
12
+ :icon="item.icon"
13
+ :is-active="item.isActive"
14
+ />
15
+ </div>
16
+ </div>
17
+ <div class="ctas tw-flex tw-flex-col tw-gap-2">
18
+ <MenuCta label="Upgrade" variant="secondary" icon="crown" icon-size="sm" />
19
+ <MenuCta label="Rate Design.com" variant="empty" />
20
+ </div>
21
+ </div>
22
+ </template>
23
+ <script setup lang="ts">
24
+ import defineProps from 'vue';
25
+ import MenuCta from './MenuCta.vue';
26
+ import MenuItem from './MenuItem.vue';
27
+
28
+ type IMenuItem = {
29
+ label: string;
30
+ url: string | undefined;
31
+ action: Function | undefined; // might need to implement actions on menu items
32
+ icon: string;
33
+ isActive: Boolean;
34
+ };
35
+
36
+ const props = defineProps({
37
+ menuItems: {
38
+ type: Array<IMenuItem>,
39
+ required: true,
40
+ },
41
+ createNewDesignCta: {
42
+ type: Object,
43
+ required: true,
44
+ },
45
+ // ctaItems: {},
46
+ });
47
+ </script>
48
+ <style scoped>
49
+ .sidebar {
50
+ @apply tw-p-2 tw-flex tw-flex-col tw-h-full tw-justify-between tw-w-[14rem];
51
+ background-color: rgba(245, 245, 245, 1);
52
+ border-right: 1px rgba(227, 227, 227, 1) solid;
53
+ }
54
+ .ctas {
55
+ text-align: center;
56
+ }
57
+ </style>