spoko-design-system 1.9.0 → 1.9.2

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.
Files changed (86) hide show
  1. package/.claude/settings.json +1 -1
  2. package/.husky/pre-commit +17 -1
  3. package/.prettierrc +8 -4
  4. package/CHANGELOG.md +35 -0
  5. package/index.ts +8 -2
  6. package/package.json +4 -3
  7. package/src/components/Badge.vue +1 -4
  8. package/src/components/Badges.vue +1 -4
  9. package/src/components/Breadcrumbs.vue +10 -44
  10. package/src/components/Button.vue +1 -5
  11. package/src/components/ButtonCopy.astro +2 -7
  12. package/src/components/ButtonCopy.vue +2 -9
  13. package/src/components/Card.astro +1 -4
  14. package/src/components/Category/CategoriesCarousel.astro +3 -11
  15. package/src/components/Category/CategoryDetails.astro +7 -32
  16. package/src/components/Category/CategoryLink.vue +1 -5
  17. package/src/components/Category/CategorySidebarToggler.vue +1 -5
  18. package/src/components/Category/CategoryTile.astro +2 -9
  19. package/src/components/Category/CategoryViewToggler.astro +3 -16
  20. package/src/components/Copyright.astro +1 -4
  21. package/src/components/Date.astro +1 -4
  22. package/src/components/Faq.astro +1 -5
  23. package/src/components/FaqItem.astro +3 -14
  24. package/src/components/FeaturesList.vue +2 -9
  25. package/src/components/FuckRussia.vue +9 -36
  26. package/src/components/HandDrive.astro +2 -12
  27. package/src/components/Header/Header.astro +3 -14
  28. package/src/components/Header/SkipToContent.astro +1 -5
  29. package/src/components/Input.vue +19 -31
  30. package/src/components/Jumbotron/index.astro +7 -41
  31. package/src/components/Jumbotron/variants/Default.astro +2 -17
  32. package/src/components/Jumbotron/variants/Hero.astro +3 -17
  33. package/src/components/Jumbotron/variants/Post.astro +3 -13
  34. package/src/components/Jumbotron/variants/PostSplit.astro +3 -13
  35. package/src/components/Jumbotron.astro +3 -12
  36. package/src/components/LanguageSuggestion.astro +3 -14
  37. package/src/components/MainColors.vue +7 -25
  38. package/src/components/MainInput.vue +2 -1
  39. package/src/components/Modal.astro +43 -41
  40. package/src/components/PageContent.astro +1 -4
  41. package/src/components/PartNumber.vue +1 -4
  42. package/src/components/PostHeader.astro +3 -13
  43. package/src/components/PrCode.vue +2 -2
  44. package/src/components/Product/ProductButton.vue +1 -4
  45. package/src/components/Product/ProductDetailName.vue +1 -4
  46. package/src/components/Product/ProductDetails.vue +19 -65
  47. package/src/components/Product/ProductDoc.vue +1 -4
  48. package/src/components/Product/ProductEngine.astro +67 -0
  49. package/src/components/Product/ProductEngineType.vue +1 -4
  50. package/src/components/Product/ProductEngines.astro +43 -0
  51. package/src/components/Product/ProductLink.astro +8 -32
  52. package/src/components/Product/ProductLink.vue +8 -36
  53. package/src/components/Product/ProductLinkInfo.astro +4 -19
  54. package/src/components/Product/ProductModel.vue +3 -5
  55. package/src/components/Product/ProductModels.vue +2 -10
  56. package/src/components/Product/ProductNumber.astro +6 -26
  57. package/src/components/Product/ProductPositions.vue +1 -5
  58. package/src/components/ProductCodes.vue +6 -14
  59. package/src/components/ProductDetailName.vue +2 -7
  60. package/src/components/ProductDetailsList.vue +7 -33
  61. package/src/components/ProductTile.astro +3 -13
  62. package/src/components/ReloadPrompt.astro +1 -5
  63. package/src/components/SlimBanner.vue +10 -15
  64. package/src/components/Table.vue +3 -15
  65. package/src/components/Translations.vue +1 -4
  66. package/src/components/layout/CallToAction.astro +2 -7
  67. package/src/components/layout/Container.astro +1 -3
  68. package/src/components/layout/Header.astro +2 -12
  69. package/src/layouts/Layout.astro +2 -9
  70. package/src/layouts/MainLayout.astro +4 -17
  71. package/src/layouts/partials/HeadCommon.astro +7 -24
  72. package/src/layouts/partials/HeadSEO.astro +12 -48
  73. package/src/pages/components/icons.astro +1 -4
  74. package/src/pages/components/product-engine.mdx +75 -31
  75. package/src/pages/core/typography.astro +2 -6
  76. package/src/pages/index.astro +16 -63
  77. package/src/scripts/tooltips.ts +33 -28
  78. package/src/styles/main.css +4 -0
  79. package/src/styles/tippy-theme.css +4 -2
  80. package/src/utils/product/getEngineTooltipContent.ts +158 -0
  81. package/src/utils/product/getPriceFormatted.ts +2 -6
  82. package/src/utils/product/useFormatProductNumber.ts +1 -4
  83. package/src/utils/seo/getShorterDescription.ts +1 -4
  84. package/uno-config/index.ts +1 -1
  85. package/src/components/Product/ProductEngine.vue +0 -240
  86. package/src/components/Product/ProductEngines.vue +0 -116
@@ -1,47 +1,20 @@
1
1
  <template>
2
- <div
3
- class="relative flex"
4
- title="FUCK PUTIN! FUCK RUZZIA!"
5
- >
6
- <div
7
- i-mdi:tank
8
- class="inline-block bg-ukraine mr-1 mt-0.5"
9
- />
10
- <div
11
- i-mdi:tank
12
- class="inline-block bg-ukraine mr-1 mt-0.5"
13
- />
14
- <div
15
- i-mdi:tank
16
- class="inline-block bg-ukraine mr-5 mt-0.5"
17
- />
2
+ <div class="relative flex" title="FUCK PUTIN! FUCK RUZZIA!">
3
+ <div i-mdi:tank class="inline-block bg-ukraine mr-1 mt-0.5" />
4
+ <div i-mdi:tank class="inline-block bg-ukraine mr-1 mt-0.5" />
5
+ <div i-mdi:tank class="inline-block bg-ukraine mr-5 mt-0.5" />
18
6
  <div class="relative">
19
- <div
20
- class="inline-block absolute"
21
- i-noto-v1:flag-for-flag-russia
22
- />
23
- <div
24
- i-emojione:fire
25
- class="inline-block absolute -mt-1 animate-ping animate-pulseR"
26
- />
7
+ <div class="inline-block absolute" i-noto-v1:flag-for-flag-russia />
8
+ <div i-emojione:fire class="inline-block absolute -mt-1 animate-ping animate-pulseR" />
27
9
  </div>
28
10
  <div class="absolute left-0 animate-bull animate-bull--1 -mt-1">
29
- <div
30
- i-mdi:bullet
31
- class="rotate-90 inline-block bg-yellow"
32
- />
11
+ <div i-mdi:bullet class="rotate-90 inline-block bg-yellow" />
33
12
  </div>
34
13
  <div class="absolute left-0 animate-bull animate-bull animate-bull--2 -mt-1">
35
- <div
36
- i-mdi:bullet
37
- class="rotate-90 inline-block bg-yellow"
38
- />
14
+ <div i-mdi:bullet class="rotate-90 inline-block bg-yellow" />
39
15
  </div>
40
16
  <div class="absolute left-0 animate-bull animate-bull--3 -mt-1">
41
- <div
42
- i-mdi:bullet
43
- class="rotate-90 inline-block bg-yellow"
44
- />
17
+ <div i-mdi:bullet class="rotate-90 inline-block bg-yellow" />
45
18
  </div>
46
19
  </div>
47
20
  </template>
@@ -28,11 +28,7 @@ if (!handDrive || (handDrive !== 'lhd' && handDrive !== 'rhd')) {
28
28
  const titleText = title || handDrive.toUpperCase();
29
29
  ---
30
30
 
31
- <div
32
- title={titleText}
33
- class="flex items-center"
34
- class:list={className}
35
- >
31
+ <div title={titleText} class="flex items-center" class:list={className}>
36
32
  <Image
37
33
  src={handDriveImage}
38
34
  alt={`${handDrive.toUpperCase()} hand drive`}
@@ -40,13 +36,7 @@ const titleText = title || handDrive.toUpperCase();
40
36
  height={34}
41
37
  class={handDrive}
42
38
  />
43
- {
44
- text && (
45
- <div class={`ml-2 ${biggerText ? 'text-sm md:text-base' : 'text-xxs md:text-xs'}`}>
46
- {text}
47
- </div>
48
- )
49
- }
39
+ {text && <div class={`ml-2 ${biggerText ? 'text-sm md:text-base' : 'text-xxs md:text-xs'}`}>{text}</div>}
50
40
  </div>
51
41
 
52
42
  <style>
@@ -7,10 +7,7 @@ import Search from 'astro-pagefind/components/Search';
7
7
 
8
8
  <header class="p-3 bg-blue-medium bg-opacity-10 backdrop-blur-md border-b text-slate-900">
9
9
  <SkipToContent />
10
- <nav
11
- title="Top Navigation"
12
- class="mx-auto flex justify-between items-center px-4"
13
- >
10
+ <nav title="Top Navigation" class="mx-auto flex justify-between items-center px-4">
14
11
  <div class="flex flex-nowrap">
15
12
  <MenuIcon class="w-4 h-4 text-gray-800 lg:hidden mr-4" />
16
13
  <a
@@ -39,11 +36,7 @@ import Search from 'astro-pagefind/components/Search';
39
36
  class="opacity-80 hover:opacity-100 hover:bg-slate-200 p-2 rounded-full transition-colors"
40
37
  href={'https://github.com/' + SITE.github}
41
38
  >
42
- <img
43
- class="h-7"
44
- src="/github.svg"
45
- alt="github logo"
46
- />
39
+ <img class="h-7" src="/github.svg" alt="github logo" />
47
40
  </a>
48
41
  )
49
42
  }
@@ -54,11 +47,7 @@ import Search from 'astro-pagefind/components/Search';
54
47
  class="opacity-80 hover:opacity-100 hover:bg-blue-50 p-2 rounded-full transition-colors"
55
48
  href={'https://linkedin.com/in/' + SITE.linkedin}
56
49
  >
57
- <img
58
- class="h-7"
59
- src="/linkedin.svg"
60
- alt="linkedin logo"
61
- />
50
+ <img class="h-7" src="/linkedin.svg" alt="linkedin logo" />
62
51
  </a>
63
52
  )
64
53
  }
@@ -1,5 +1 @@
1
- <a
2
- href="#article"
3
- class="sr-only focus:not-sr-only skiplink"
4
- ><span>Skip to Content</span></a
5
- >
1
+ <a href="#article" class="sr-only focus:not-sr-only skiplink"><span>Skip to Content</span></a>
@@ -1,4 +1,5 @@
1
1
  <script setup lang="ts">
2
+ /* global Event, HTMLInputElement, HTMLTextAreaElement, FocusEvent */
2
3
  import { computed, useAttrs } from 'vue';
3
4
 
4
5
  interface InputProps {
@@ -30,7 +31,7 @@ const props = withDefaults(defineProps<InputProps>(), {
30
31
  error: false,
31
32
  success: false,
32
33
  size: 'md',
33
- class: ''
34
+ class: '',
34
35
  });
35
36
 
36
37
  const emit = defineEmits(['update:modelValue', 'input', 'focus', 'blur']);
@@ -45,7 +46,7 @@ const wrapperClass = computed(() => `relative input-wrapper-${props.variant}`);
45
46
  const inputClass = computed(() => {
46
47
  // Base classes
47
48
  const classes = ['input-base', `input-${props.variant}`];
48
-
49
+
49
50
  // Focus and placeholder behavior - using direct arbitrary selectors
50
51
  classes.push('[&:focus~label]:text-blue-light');
51
52
  classes.push('[&:focus~label]:dark:text-blue-lightest');
@@ -53,7 +54,7 @@ const inputClass = computed(() => {
53
54
  classes.push('[&:placeholder-shown~label]:scale-100');
54
55
  classes.push('[&:placeholder-shown~label]:translate-y-0');
55
56
  classes.push('[&:not(:placeholder-shown)~label]:scale-75');
56
-
57
+
57
58
  // Variant-specific behaviors
58
59
  if (props.variant === 'standard') {
59
60
  classes.push('[&:focus~label]:-translate-y-6');
@@ -63,14 +64,14 @@ const inputClass = computed(() => {
63
64
  classes.push('[&:focus~label]:-translate-y-4');
64
65
  classes.push('[&:not(:placeholder-shown)~label]:-translate-y-4');
65
66
  }
66
-
67
+
67
68
  // Additional classes
68
69
  if (props.size) classes.push(`input-${props.size}`);
69
70
  if (props.type === 'textarea') classes.push('input-textarea');
70
71
  if (props.error) classes.push('input-error');
71
72
  else if (props.success) classes.push('input-success');
72
73
  if (props.class) classes.push(props.class);
73
-
74
+
74
75
  return classes.join(' ');
75
76
  });
76
77
 
@@ -78,7 +79,7 @@ const inputClass = computed(() => {
78
79
  const labelClass = computed(() => {
79
80
  // Base classes
80
81
  const classes = ['input-label-base', `input-label-${props.variant}`];
81
-
82
+
82
83
  // Explicitly add transform for initial state to ensure consistency
83
84
  if (props.variant === 'standard') {
84
85
  // Start in position and let focus/content move it
@@ -87,12 +88,12 @@ const labelClass = computed(() => {
87
88
  // Start in position and let focus/content move it
88
89
  classes.push('translate-y-0');
89
90
  }
90
-
91
+
91
92
  // Additional classes
92
93
  if (props.size) classes.push(`input-label-${props.size}`);
93
94
  if (props.error) classes.push('input-label-error');
94
95
  else if (props.success) classes.push('input-label-success');
95
-
96
+
96
97
  return classes.join(' ');
97
98
  });
98
99
 
@@ -125,7 +126,7 @@ const handleBlur = (event: FocusEvent) => emit('blur', event);
125
126
  @focus="handleFocus"
126
127
  @blur="handleBlur"
127
128
  />
128
-
129
+
129
130
  <!-- Input field -->
130
131
  <input
131
132
  v-else
@@ -140,35 +141,22 @@ const handleBlur = (event: FocusEvent) => emit('blur', event);
140
141
  @input="handleInput"
141
142
  @focus="handleFocus"
142
143
  @blur="handleBlur"
143
- >
144
-
144
+ />
145
+
145
146
  <!-- Label with guaranteed correct transform origin -->
146
- <label
147
- :for="id"
148
- :class="labelClass"
149
- style="transform-origin: top left;"
150
- >
147
+ <label :for="id" :class="labelClass" style="transform-origin: top left">
151
148
  {{ label }}
152
- <span
153
- v-if="required"
154
- class="text-red-500 ml-1"
155
- >*</span>
149
+ <span v-if="required" class="text-red-500 ml-1">*</span>
156
150
  </label>
157
-
151
+
158
152
  <!-- Error message -->
159
- <div
160
- v-if="error && typeof error === 'string'"
161
- class="input-error-message"
162
- >
153
+ <div v-if="error && typeof error === 'string'" class="input-error-message">
163
154
  {{ error }}
164
155
  </div>
165
-
156
+
166
157
  <!-- Success message -->
167
- <div
168
- v-if="success && typeof success === 'string'"
169
- class="input-success-message"
170
- >
158
+ <div v-if="success && typeof success === 'string'" class="input-success-message">
171
159
  {{ success }}
172
160
  </div>
173
161
  </div>
174
- </template>
162
+ </template>
@@ -64,55 +64,21 @@ const commonProps = {
64
64
 
65
65
  {
66
66
  variant === 'default' && (
67
- <DefaultVariant
68
- {...commonProps}
69
- small={small}
70
- >
71
- <slot
72
- name="intro"
73
- slot="intro"
74
- />
75
- <slot
76
- name="subtitle"
77
- slot="subtitle"
78
- />
79
- <slot
80
- name="cta-content"
81
- slot="cta-content"
82
- />
67
+ <DefaultVariant {...commonProps} small={small}>
68
+ <slot name="intro" slot="intro" />
69
+ <slot name="subtitle" slot="subtitle" />
70
+ <slot name="cta-content" slot="cta-content" />
83
71
  </DefaultVariant>
84
72
  )
85
73
  }
86
74
 
87
- {
88
- variant === 'hero' && (
89
- <HeroVariant
90
- {...commonProps}
91
- description={description}
92
- info={info}
93
- />
94
- )
95
- }
75
+ {variant === 'hero' && <HeroVariant {...commonProps} description={description} info={info} />}
96
76
 
97
- {
98
- variant === 'post' && (
99
- <PostVariant
100
- {...commonProps}
101
- author={author}
102
- date={date}
103
- categories={categories}
104
- />
105
- )
106
- }
77
+ {variant === 'post' && <PostVariant {...commonProps} author={author} date={date} categories={categories} />}
107
78
 
108
79
  {
109
80
  variant === 'post-split' && (
110
- <PostSplitVariant
111
- {...commonProps}
112
- author={author}
113
- date={date}
114
- categories={categories}
115
- />
81
+ <PostSplitVariant {...commonProps} author={author} date={date} categories={categories} />
116
82
  )
117
83
  }
118
84
 
@@ -8,13 +8,7 @@ interface Props {
8
8
  hasCtaContent: boolean;
9
9
  }
10
10
 
11
- const {
12
- title = '',
13
- small = false,
14
- hasIntroContent,
15
- hasSubtitleContent,
16
- hasCtaContent,
17
- } = Astro.props;
11
+ const { title = '', small = false, hasIntroContent, hasSubtitleContent, hasCtaContent } = Astro.props;
18
12
  ---
19
13
 
20
14
  <header
@@ -24,16 +18,7 @@ const {
24
18
  small ? 'jumbotron-container-small' : 'jumbotron-container-large', // wariant rozmiaru
25
19
  ]}
26
20
  >
27
- {
28
- hasIntroContent ? (
29
- <slot name="intro" />
30
- ) : (
31
- <h1
32
- class="jumbotron-title-default"
33
- set:html={title}
34
- />
35
- )
36
- }
21
+ {hasIntroContent ? <slot name="intro" /> : <h1 class="jumbotron-title-default" set:html={title} />}
37
22
 
38
23
  {hasSubtitleContent && <slot name="subtitle" />}
39
24
 
@@ -16,11 +16,7 @@ const { title = '', image, description, info, backgroundClass } = Astro.props;
16
16
  image && (
17
17
  <div class="absolute inset-0 w-full h-full">
18
18
  <div class="absolute inset-0 bg-gradient-to-r from-blue-900 to-transparent opacity-90 z-1" />
19
- <img
20
- class="w-full h-full object-cover"
21
- src={image}
22
- alt={title}
23
- />
19
+ <img class="w-full h-full object-cover" src={image} alt={title} />
24
20
  </div>
25
21
  )
26
22
  }
@@ -33,20 +29,10 @@ const { title = '', image, description, info, backgroundClass } = Astro.props;
33
29
  />
34
30
  {
35
31
  description && (
36
- <div
37
- class="mb-1 line-clamp-3 text-base sm:text-lg leading-none mt-4"
38
- set:html={description}
39
- />
40
- )
41
- }
42
- {
43
- info && (
44
- <div
45
- class="font-medium mb-4 line-clamp-1 text-base sm:text-lg mt-2"
46
- set:html={info}
47
- />
32
+ <div class="mb-1 line-clamp-3 text-base sm:text-lg leading-none mt-4" set:html={description} />
48
33
  )
49
34
  }
35
+ {info && <div class="font-medium mb-4 line-clamp-1 text-base sm:text-lg mt-2" set:html={info} />}
50
36
  </header>
51
37
  </div>
52
38
  </div>
@@ -41,10 +41,7 @@ const {
41
41
  {
42
42
  hasCategories && (
43
43
  <div class="order-1">
44
- <PostCategories
45
- categories={categories}
46
- lang={lang}
47
- />
44
+ <PostCategories categories={categories} lang={lang} />
48
45
  </div>
49
46
  )
50
47
  }
@@ -53,10 +50,7 @@ const {
53
50
  hasMetadata && (
54
51
  <div class="order-3 flex items-center text-gray-100">
55
52
  {author && (
56
- <span
57
- class="text-sm"
58
- title={author.firstName}
59
- >
53
+ <span class="text-sm" title={author.firstName}>
60
54
  {author.name}
61
55
  </span>
62
56
  )}
@@ -69,10 +63,6 @@ const {
69
63
  </div>
70
64
 
71
65
  <div class="featured-image-overlay">
72
- <img
73
- src={image}
74
- alt={title}
75
- class="w-full h-full object-cover block max-w-full"
76
- />
66
+ <img src={image} alt={title} class="w-full h-full object-cover block max-w-full" />
77
67
  </div>
78
68
  </header>
@@ -42,18 +42,12 @@ const cleanTitle = stripHtml(title);
42
42
  class="heading flex flex-wrap text-white relative items-center justify-center mt-auto w-full z-[2]"
43
43
  >
44
44
  <div class="jumbotron-split-content">
45
- <h1
46
- class="jumbotron-split-title"
47
- set:html={title}
48
- />
45
+ <h1 class="jumbotron-split-title" set:html={title} />
49
46
 
50
47
  {
51
48
  hasCategories && (
52
49
  <div class="jumbotron-categories">
53
- <PostCategories
54
- categories={categories}
55
- lang={lang}
56
- />
50
+ <PostCategories categories={categories} lang={lang} />
57
51
  </div>
58
52
  )
59
53
  }
@@ -62,11 +56,7 @@ const cleanTitle = stripHtml(title);
62
56
  hasMetadata && (
63
57
  <div class="jumbotron-split-meta">
64
58
  {author && (
65
- <span
66
- class="text-sm"
67
- title={author.firstName}
68
- data-pagefind-ignore
69
- >
59
+ <span class="text-sm" title={author.firstName} data-pagefind-ignore>
70
60
  {author.name}
71
61
  </span>
72
62
  )}
@@ -6,16 +6,7 @@ const props = Astro.props as Props;
6
6
  ---
7
7
 
8
8
  <BaseJumbotron {...props}>
9
- <slot
10
- name="intro"
11
- slot="intro"
12
- />
13
- <slot
14
- name="subtitle"
15
- slot="subtitle"
16
- />
17
- <slot
18
- name="cta-content"
19
- slot="cta-content"
20
- />
9
+ <slot name="intro" slot="intro" />
10
+ <slot name="subtitle" slot="subtitle" />
11
+ <slot name="cta-content" slot="cta-content" />
21
12
  </BaseJumbotron>
@@ -8,13 +8,7 @@ interface Props {
8
8
  showIcon?: boolean;
9
9
  }
10
10
 
11
- const {
12
- position = 'bottom',
13
- className = '',
14
- customPath,
15
- dismissTimeout,
16
- showIcon = true,
17
- } = Astro.props;
11
+ const { position = 'bottom', className = '', customPath, dismissTimeout, showIcon = true } = Astro.props;
18
12
 
19
13
  const currentLocale = Astro.currentLocale;
20
14
  const preferredLocale = Astro.preferredLocale;
@@ -33,10 +27,7 @@ const targetPath = customPath
33
27
  ]}
34
28
  role="alert"
35
29
  >
36
- <a
37
- href={targetPath}
38
- class="flex items-center gap-2 font-medium hover:underline"
39
- >
30
+ <a href={targetPath} class="flex items-center gap-2 font-medium hover:underline">
40
31
  {showIcon && <span class="material-icons-outlined text-sm">translate</span>}
41
32
  {new Intl.DisplayNames([preferredLocale], { type: 'language' }).of(preferredLocale)}
42
33
  </a>
@@ -51,9 +42,7 @@ const targetPath = customPath
51
42
 
52
43
  <script define:vars={{ currentLocale, preferredLocale, dismissTimeout }}>
53
44
  const shouldShow =
54
- preferredLocale &&
55
- preferredLocale !== currentLocale &&
56
- !localStorage.getItem('languageSuggestDenied');
45
+ preferredLocale && preferredLocale !== currentLocale && !localStorage.getItem('languageSuggestDenied');
57
46
 
58
47
  if (shouldShow) {
59
48
  const popup = document.getElementById('languageSuggestion');
@@ -1,4 +1,5 @@
1
1
  <script setup lang="ts">
2
+ /* global navigator, setTimeout */
2
3
  import { ref } from 'vue';
3
4
  import { colors } from './../../uno-config/theme/colors';
4
5
 
@@ -29,19 +30,12 @@ const getColorClass = (category: string, name: string) => {
29
30
 
30
31
  <template>
31
32
  <div class="flex flex-col space-y-12">
32
- <div
33
- v-for="[category, shades] in colorCategories"
34
- :key="category"
35
- >
33
+ <div v-for="[category, shades] in colorCategories" :key="category">
36
34
  <h3 class="capitalize text-xl font-bold mb-4">
37
35
  {{ category }}
38
36
  </h3>
39
37
  <div class="grid grid-cols-2 md:grid-cols-4 xl:grid-cols-5 gap-x-6 gap-y-10">
40
- <div
41
- v-for="(value, name) in shades"
42
- :key="name"
43
- class="group relative"
44
- >
38
+ <div v-for="(value, name) in shades" :key="name" class="group relative">
45
39
  <!-- Color Swatch -->
46
40
  <button
47
41
  class="w-full h-10 rounded-lg shadow-md transition-all duration-200 hover:shadow-xl hover:scale-105 cursor-pointer relative overflow-hidden"
@@ -73,14 +67,8 @@ const getColorClass = (category: string, name: string) => {
73
67
  :title="`Copy hex: ${value}`"
74
68
  @click="copyToClipboard(value, `${category}-${name}-hex`)"
75
69
  >
76
- <span
77
- v-if="copiedItem === `${category}-${name}-hex`"
78
- class="text-green-600"
79
- >✓</span>
80
- <span
81
- v-else
82
- class="uppercase text-xs"
83
- >{{ value }}</span>
70
+ <span v-if="copiedItem === `${category}-${name}-hex`" class="text-green-600">✓</span>
71
+ <span v-else class="uppercase text-xs">{{ value }}</span>
84
72
  </button>
85
73
 
86
74
  <!-- Copy Class Name (text-*) -->
@@ -89,10 +77,7 @@ const getColorClass = (category: string, name: string) => {
89
77
  :title="`Copy class: text-${getColorClass(category, name)}`"
90
78
  @click="copyToClipboard(`text-${getColorClass(category, name)}`, `${category}-${name}-class`)"
91
79
  >
92
- <span
93
- v-if="copiedItem === `${category}-${name}-class`"
94
- class="text-green-600"
95
- >✓</span>
80
+ <span v-if="copiedItem === `${category}-${name}-class`" class="text-green-600">✓</span>
96
81
  <span v-else>text-</span>
97
82
  </button>
98
83
 
@@ -102,10 +87,7 @@ const getColorClass = (category: string, name: string) => {
102
87
  :title="`Copy class: bg-${getColorClass(category, name)}`"
103
88
  @click="copyToClipboard(`bg-${getColorClass(category, name)}`, `${category}-${name}-bg`)"
104
89
  >
105
- <span
106
- v-if="copiedItem === `${category}-${name}-bg`"
107
- class="text-green-600"
108
- >✓</span>
90
+ <span v-if="copiedItem === `${category}-${name}-bg`" class="text-green-600">✓</span>
109
91
  <span v-else>bg-</span>
110
92
  </button>
111
93
  </div>
@@ -8,8 +8,9 @@ const props = defineProps<{
8
8
  <label class="group text-left w-full max-w-xs flex flex-col">
9
9
  <span
10
10
  class="group-hover:text-blue-medium ml-2 text-slate-600 text-sm group-focus-within:text-blue-medium"
11
- >{{ props.label }}</span
12
11
  >
12
+ {{ props.label }}
13
+ </span>
13
14
  <input
14
15
  class="group-hover:border-blue-lightest border px-4 py-2 transition-colors rounded-md w-full focus:ring focus:outline-none focus:border-blue-medium"
15
16
  type="text"