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
@@ -84,31 +84,26 @@ const {
84
84
  }
85
85
  </style>
86
86
 
87
- {showTrigger && (
88
- <Button
89
- primary
90
- onclick={`window.${id}.showModal()`}
91
- >{open}</Button
92
- >
93
- )}
94
-
95
- <dialog
96
- id={id}
97
- class="p-6"
98
- >
87
+ {
88
+ showTrigger && (
89
+ <Button primary onclick={`window.${id}.showModal()`}>
90
+ {open}
91
+ </Button>
92
+ )
93
+ }
94
+
95
+ <dialog id={id} class="p-6">
99
96
  <div class="modal-header">
100
97
  {title && <h2 class="text-2xl font-bold pr-8">{title}</h2>}
101
98
  <slot name="header" />
102
99
 
103
- {showXButton && (
104
- <form method="dialog" class="inline">
105
- <button
106
- class="modal-close-x"
107
- aria-label="Close"
108
- type="submit"
109
- />
110
- </form>
111
- )}
100
+ {
101
+ showXButton && (
102
+ <form method="dialog" class="inline">
103
+ <button class="modal-close-x" aria-label="Close" type="submit" />
104
+ </form>
105
+ )
106
+ }
112
107
  </div>
113
108
 
114
109
  <div class="modal-content">
@@ -116,37 +111,44 @@ const {
116
111
  <slot />
117
112
  </div>
118
113
 
119
- {showActions && (
120
- <div class="modal-actions">
121
- <slot name="actions">
122
- <form method="dialog" class="contents">
123
- <Button>{cancelText}</Button>
124
- </form>
125
- <Button primary={confirmPrimary} onclick={`document.getElementById('${id}').dispatchEvent(new CustomEvent('confirm', { detail: { id: '${id}' } }))`}>
126
- {confirmText}
127
- </Button>
128
- </slot>
129
- </div>
130
- )}
131
-
132
- {!showActions && (
133
- <form method="dialog">
134
- <slot name="close" />
135
- </form>
136
- )}
114
+ {
115
+ showActions && (
116
+ <div class="modal-actions">
117
+ <slot name="actions">
118
+ <form method="dialog" class="contents">
119
+ <Button>{cancelText}</Button>
120
+ </form>
121
+ <Button
122
+ primary={confirmPrimary}
123
+ onclick={`document.getElementById('${id}').dispatchEvent(new CustomEvent('confirm', { detail: { id: '${id}' } }))`}
124
+ >
125
+ {confirmText}
126
+ </Button>
127
+ </slot>
128
+ </div>
129
+ )
130
+ }
131
+
132
+ {
133
+ !showActions && (
134
+ <form method="dialog">
135
+ <slot name="close" />
136
+ </form>
137
+ )
138
+ }
137
139
  </dialog>
138
140
 
139
141
  <script define:vars={{ id }}>
140
142
  // Close on backdrop click
141
143
  const dialog = document.getElementById(id);
142
- dialog?.addEventListener('click', (e) => {
144
+ dialog?.addEventListener('click', e => {
143
145
  if (e.target === dialog) {
144
146
  dialog.close();
145
147
  }
146
148
  });
147
149
 
148
150
  // Close on Escape key
149
- dialog?.addEventListener('keydown', (e) => {
151
+ dialog?.addEventListener('keydown', e => {
150
152
  if (e.key === 'Escape') {
151
153
  dialog.close();
152
154
  }
@@ -1,7 +1,4 @@
1
- <article
2
- id="article"
3
- class="content"
4
- >
1
+ <article id="article" class="content">
5
2
  <section class="main-section">
6
3
  <slot />
7
4
  </section>
@@ -21,10 +21,7 @@ const props = defineProps({
21
21
  </script>
22
22
 
23
23
  <template>
24
- <component
25
- :is="props.as"
26
- :class="props.class"
27
- >
24
+ <component :is="props.as" :class="props.class">
28
25
  {{ props.number }}
29
26
  </component>
30
27
  </template>
@@ -31,18 +31,11 @@ import Date from './Date.astro';
31
31
  >
32
32
  {title}
33
33
  </h1>
34
- <PostCategories
35
- categories={categories}
36
- lang={lang}
37
- />
34
+ <PostCategories categories={categories} lang={lang} />
38
35
  <div class="order-3 flex items-center text-gray-1 00">
39
36
  {
40
37
  author && (
41
- <span
42
- class="text-sm"
43
- title={author.firstName}
44
- data-pagefind-ignore
45
- >
38
+ <span class="text-sm" title={author.firstName} data-pagefind-ignore>
46
39
  {author.name}
47
40
  </span>
48
41
  )
@@ -53,10 +46,7 @@ import Date from './Date.astro';
53
46
  </div>
54
47
  </div>
55
48
  <div class="featured-image">
56
- <img
57
- src={image}
58
- alt={title}
59
- />
49
+ <img src={image} alt={title} />
60
50
  </div>
61
51
  </header>
62
52
 
@@ -13,7 +13,7 @@ interface PrCodeObject {
13
13
  variant_category?: string;
14
14
  }
15
15
 
16
- const props = defineProps({
16
+ defineProps({
17
17
  prcode: {
18
18
  type: Object as PropType<PrCodeObject>,
19
19
  required: true,
@@ -32,7 +32,7 @@ const props = defineProps({
32
32
  class="btn-prcode"
33
33
  :class="[
34
34
  prcode.variant_category ? `btn-prcode--variant-${prcode.variant_category.toLowerCase()}` : '',
35
- { 'btn-prcode--pdp': isPdp }
35
+ { 'btn-prcode--pdp': isPdp },
36
36
  ]"
37
37
  :data-tippy-content="prcode.description || undefined"
38
38
  >
@@ -9,10 +9,7 @@ const props = defineProps({
9
9
  </script>
10
10
 
11
11
  <template>
12
- <button
13
- class="product-button"
14
- :class="props.shadow ? 'drop-shadow hover:(drop-shadow-md)' : ''"
15
- >
12
+ <button class="product-button" :class="props.shadow ? 'drop-shadow hover:(drop-shadow-md)' : ''">
16
13
  <slot />
17
14
  </button>
18
15
  </template>
@@ -15,10 +15,7 @@ const props = defineProps({
15
15
 
16
16
  <template>
17
17
  <div class="font-bold detail-name w-full sm:w-50 flex">
18
- <span
19
- class="colon-after"
20
- :class="styles && styles.length ? styles : 'mt-auto'"
21
- >
18
+ <span class="colon-after" :class="styles && styles.length ? styles : 'mt-auto'">
22
19
  {{ props.text }}
23
20
  </span>
24
21
  </div>
@@ -30,28 +30,18 @@ const props = defineProps({
30
30
 
31
31
  <template>
32
32
  <div v-if="details && details.length">
33
- <template
34
- v-for="(detail, index) in details"
35
- :key="index"
36
- >
33
+ <template v-for="(detail, index) in details" :key="index">
37
34
  <!-- PDP PAGE - PRODUCT ROW -->
38
35
  <!-- <pre>{{ JSON.stringify(details) }}</pre> -->
39
36
  <li
40
37
  v-if="props.small"
41
38
  class="text-xs md:text-sm text-slate-darkest dark:text-neutral-light leading-tight font-textlight md:font-textregular"
42
39
  >
43
- <span
44
- v-if="detail.id"
45
- class="inline-block mr-1 items--0"
46
- >
40
+ <span v-if="detail.id" class="inline-block mr-1 items--0">
47
41
  {{ getTranslation(`detail.${detail.id}`) }}:
48
42
  </span>
49
43
 
50
- <span
51
- v-if="detail.translated"
52
- :class="detail.id ? 'font-semibold' : ''"
53
- class="items--1"
54
- >
44
+ <span v-if="detail.translated" :class="detail.id ? 'font-semibold' : ''" class="items--1">
55
45
  {{ detail.value }}
56
46
  </span>
57
47
 
@@ -59,26 +49,16 @@ const props = defineProps({
59
49
  v-else-if="detail.value !== undefined && detail.id === 'color' && detail.isArrayValue"
60
50
  class="items--2 inline-block"
61
51
  >
62
- <span
63
- v-for="(color, indexColor) in detail.value"
64
- :key="indexColor"
65
- class="comma"
66
- >
52
+ <span v-for="(color, indexColor) in detail.value" :key="indexColor" class="comma">
67
53
  {{ color['name'] }}
68
54
  </span>
69
55
  </div>
70
56
 
71
- <span
72
- v-else-if="detail.id !== 'paint-marks' && !detail.isArrayValue"
73
- class="items--3"
74
- >
57
+ <span v-else-if="detail.id !== 'paint-marks' && !detail.isArrayValue" class="items--3">
75
58
  {{ locale === 'en' ? String(detail.value).replace(/,/g, '.') : String(detail.value) }}
76
59
  </span>
77
60
 
78
- <span
79
- v-else-if="detail.id && detail.id === 'paint-marks'"
80
- class="items items--4"
81
- >
61
+ <span v-else-if="detail.id && detail.id === 'paint-marks'" class="items items--4">
82
62
  {{ detail.value }}
83
63
  <!-- <span v-for="(mark, index2) in JSON.parse(String(detail.value))" :key="index2" class="item">
84
64
  {{ mark[0] }} x <span>{{ getTranslation(`color.${mark[1]}`) }}</span>
@@ -91,14 +71,8 @@ const props = defineProps({
91
71
  class="text-sm mt-1 md:mt-4 mb-4 grid grid-cols-2 sm:(grid-cols-details-desktop grid-flow-col auto-cols-max) gap-4"
92
72
  >
93
73
  <!-- PRODUCT CARD -->
94
- <ProductDetailName
95
- v-if="detail.id"
96
- :text="getTranslation(`detail.${detail.id}`)"
97
- />
98
- <div
99
- v-if="detail.value"
100
- class="leading-4 flex items-end"
101
- >
74
+ <ProductDetailName v-if="detail.id" :text="getTranslation(`detail.${detail.id}`)" />
75
+ <div v-if="detail.value" class="leading-4 flex items-end">
102
76
  <span
103
77
  v-if="detail.translated && !detail.isArrayValue"
104
78
  :class="detail.id === 'light-function' ? 'whitespace-pre-line' : ''"
@@ -106,51 +80,31 @@ const props = defineProps({
106
80
  {{ getTranslation(`detail.value.${detail.value}`) }}
107
81
  </span>
108
82
 
109
- <span
110
- v-else-if="detail.id !== 'paint-marks' && !detail.isArrayValue"
111
- class=""
112
- >
83
+ <span v-else-if="detail.id !== 'paint-marks' && !detail.isArrayValue" class="">
113
84
  {{ detail.value }}
114
85
  </span>
115
86
 
116
87
  <span
117
88
  v-else-if="
118
- detail.value !== undefined &&
119
- detail.id === 'for-exterior-colour' &&
120
- detail.isArrayValue
89
+ detail.value !== undefined && detail.id === 'for-exterior-colour' && detail.isArrayValue
121
90
  "
122
91
  class=""
123
92
  >
124
- <div
125
- v-for="(color, indexColor) in JSON.parse(String(detail.value))"
126
- :key="indexColor"
127
- >
128
- <span class="font-mono">{{ color }}</span> -
93
+ <div v-for="(color, indexColor) in JSON.parse(String(detail.value))" :key="indexColor">
94
+ <span class="font-mono">{{ color }}</span>
95
+ -
129
96
  {{ getTranslation(`colorCodes.${color}`) }}
130
97
  </div>
131
98
  </span>
132
99
 
133
- <span
134
- v-else-if="detail.id && detail.id === 'paint-marks'"
135
- class="items"
136
- >
137
- <span
138
- v-for="(mark, markIndex) in JSON.parse(String(detail.value))"
139
- :key="markIndex"
140
- class="item"
141
- >
142
- {{ mark[0] }} x <span>{{ getTranslation(`color.${mark[1]}`) }}</span>
100
+ <span v-else-if="detail.id && detail.id === 'paint-marks'" class="items">
101
+ <span v-for="(mark, markIndex) in JSON.parse(String(detail.value))" :key="markIndex" class="item">
102
+ {{ mark[0] }} x
103
+ <span>{{ getTranslation(`color.${mark[1]}`) }}</span>
143
104
  </span>
144
105
  </span>
145
- <ul
146
- v-else-if="detail.id && detail.isArrayValue"
147
- class="items"
148
- >
149
- <li
150
- v-for="(d, index3) in JSON.parse(String(detail.value))"
151
- :key="index3"
152
- class="item"
153
- >
106
+ <ul v-else-if="detail.id && detail.isArrayValue" class="items">
107
+ <li v-for="(d, index3) in JSON.parse(String(detail.value))" :key="index3" class="item">
154
108
  · {{ d }}
155
109
  </li>
156
110
  </ul>
@@ -20,10 +20,7 @@ const props = defineProps({
20
20
  :title="props.file.path"
21
21
  class="flex items-center hover:underline underline-offset-2 hover:underline-1"
22
22
  >
23
- <div
24
- i-system-uicons-document-justified
25
- class="text-blue-lightest dark:text-accent-light"
26
- />
23
+ <div i-system-uicons-document-justified class="text-blue-lightest dark:text-accent-light" />
27
24
  <span>{{ props.file.name }}</span>
28
25
  </a>
29
26
  </li>
@@ -0,0 +1,67 @@
1
+ ---
2
+ import { getEngineTooltipContent } from '../../utils/product/getEngineTooltipContent';
3
+ import type { Engine, EngineTranslations } from '../../utils/product/getEngineTooltipContent';
4
+
5
+ /*
6
+ VAG group (VW/Audi/Skoda/Seat/Porsche/Bentley/Lamborghini/Ducati/Cupra/Scania/MAN) manufacturer Engine Code
7
+ Displays engine code with detailed tooltip showing: name, power, displacement, dates, etc.
8
+
9
+ SEO-friendly: Engine code is rendered in HTML, tooltips enhanced via delegation script
10
+ */
11
+
12
+ interface Props {
13
+ engine: Engine;
14
+ showComma?: boolean;
15
+ translations?: EngineTranslations;
16
+ }
17
+
18
+ const { engine, showComma = false, translations = {} } = Astro.props;
19
+
20
+ // Generate tooltip content for data attribute
21
+ const tooltipContent = getEngineTooltipContent(engine, translations);
22
+
23
+ // Escape quotes for HTML attribute
24
+ const tooltipContentEscaped = tooltipContent.replace(/"/g, '&quot;');
25
+ ---
26
+
27
+ <span
28
+ class="engine-code"
29
+ class:list={[`engine-code-${engine.code}`]}
30
+ data-tippy-content={tooltipContentEscaped}
31
+ >
32
+ {engine.code}{showComma && ','}
33
+ </span>
34
+
35
+ <style>
36
+ /* Engine Code Styles */
37
+ .engine-code {
38
+ @apply inline-block mr-1;
39
+ @apply underline decoration-dotted underline-offset-4 py-0.5;
40
+ @apply decoration-neutral-light cursor-default;
41
+ @apply transition-colors duration-200;
42
+ }
43
+
44
+ .engine-code:hover {
45
+ @apply decoration-blue-darker dark:decoration-blue-light;
46
+ }
47
+
48
+ /* Semantic Engine Code Colors */
49
+ /* GTI Engines - Red */
50
+ .engine-code-CAVE,
51
+ .engine-code-CTHE,
52
+ .engine-code-DAJA,
53
+ .engine-code-DAYB {
54
+ @apply text-red-600 dark:text-red-500;
55
+ }
56
+
57
+ /* WRC R Engine - Blue */
58
+ .engine-code-CDLJ {
59
+ @apply text-blue-600 dark:text-blue-500;
60
+ }
61
+
62
+ /* Special Blue Engines */
63
+ .engine-code-CPTA,
64
+ .engine-code-CZEA {
65
+ @apply text-blue-700 dark:text-blue-600;
66
+ }
67
+ </style>
@@ -15,10 +15,7 @@ const props = withDefaults(
15
15
  </script>
16
16
 
17
17
  <template>
18
- <ul
19
- v-if="props.engines.length"
20
- class="engine-types"
21
- >
18
+ <ul v-if="props.engines.length" class="engine-types">
22
19
  <li
23
20
  v-for="(engine, index) in props.engines"
24
21
  :key="engine.id"
@@ -0,0 +1,43 @@
1
+ ---
2
+ import ProductEngine from './ProductEngine.astro';
3
+ import type { Engine, EngineTranslations } from '../../utils/product/getEngineTooltipContent';
4
+
5
+ /*
6
+ ProductEngines wrapper component
7
+ Displays a list of engine codes with tooltips
8
+ SEO-friendly: All engine codes rendered in HTML, enhanced by global delegation script
9
+ */
10
+
11
+ interface Props {
12
+ engines: Engine[];
13
+ isPdp?: boolean;
14
+ translations?: EngineTranslations;
15
+ }
16
+
17
+ const { engines = [], translations = {} } = Astro.props;
18
+
19
+ // Sort engines by code
20
+ const sortedEngines = engines.length
21
+ ? [...engines].sort((a, b) => (a.code || '').localeCompare(b.code || ''))
22
+ : [];
23
+ ---
24
+
25
+ {
26
+ sortedEngines.length > 0 && (
27
+ <div class="engines-list inline-flex flex-wrap items-center gap-x-0.5">
28
+ {sortedEngines.map((engine, index) => (
29
+ <ProductEngine
30
+ engine={engine}
31
+ showComma={index !== sortedEngines.length - 1}
32
+ translations={translations}
33
+ />
34
+ ))}
35
+ </div>
36
+ )
37
+ }
38
+
39
+ <style>
40
+ .engines-list {
41
+ @apply leading-none;
42
+ }
43
+ </style>
@@ -27,12 +27,7 @@ import { getProductUrl } from '@utils/product/getProductUrl';
27
27
  import { getShopProductUrl } from '@utils/product/getShopProductUrl';
28
28
  import { getProductTranslation } from '@utils/product/getProductTranslation';
29
29
  import { getImageUrl } from '@utils/getImageUrl';
30
- import {
31
- ProductImage,
32
- ProductNumber,
33
- removeSemicolon,
34
- getPriceFormatted,
35
- } from 'spoko-design-system';
30
+ import { ProductImage, ProductNumber, removeSemicolon, getPriceFormatted } from 'spoko-design-system';
36
31
 
37
32
  // Użycie productObject jeśli przekazane, inaczej pobranie produktu na podstawie productId
38
33
  const product =
@@ -51,9 +46,7 @@ const thumb = product
51
46
  : '';
52
47
 
53
48
  // Product translation removed - using English only
54
- const productTranslation = productId
55
- ? await getProductTranslation(productId, product?.number || '')
56
- : null;
49
+ const productTranslation = productId ? await getProductTranslation(productId, product?.number || '') : null;
57
50
 
58
51
  const productName = product
59
52
  ? isShopProduct
@@ -67,9 +60,7 @@ const nameFormatted = removeSemicolon(productName.toString());
67
60
  {
68
61
  product && (
69
62
  <>
70
- <div
71
- class={bigTile ? 'product-link--big-tile' : 'product-thumb--plp product-thumb--carousel'}
72
- >
63
+ <div class={bigTile ? 'product-link--big-tile' : 'product-thumb--plp product-thumb--carousel'}>
73
64
  {product.photo !== null && thumb ? (
74
65
  <ProductImage
75
66
  imagesApiUrl="https://api.polo.blue"
@@ -82,11 +73,7 @@ const nameFormatted = removeSemicolon(productName.toString());
82
73
  }}
83
74
  />
84
75
  ) : (
85
- <img
86
- src="/1x1.png"
87
- class="bg-neutral-lightest/70"
88
- alt={productName}
89
- />
76
+ <img src="/1x1.png" class="bg-neutral-lightest/70" alt={productName} />
90
77
  )}
91
78
  </div>
92
79
 
@@ -98,30 +85,19 @@ const nameFormatted = removeSemicolon(productName.toString());
98
85
  <a
99
86
  class="product-link--url"
100
87
  href={
101
- isShopProduct
102
- ? getShopProductUrl(product.slug, locale)
103
- : getProductUrl(product.number, locale)
88
+ isShopProduct ? getShopProductUrl(product.slug, locale) : getProductUrl(product.number, locale)
104
89
  }
105
90
  itemprop="url"
106
91
  title={product.number}
107
92
  set:html={nameFormatted}
108
93
  />
109
94
 
110
- <ProductNumber
111
- productNumber={product.number}
112
- copyDisabled={true}
113
- />
95
+ <ProductNumber productNumber={product.number} copyDisabled={true} />
114
96
 
115
97
  {index !== null && (
116
98
  <>
117
- <meta
118
- itemprop="position"
119
- content={index.toString()}
120
- />
121
- <meta
122
- itemprop="name"
123
- content={nameFormatted}
124
- />
99
+ <meta itemprop="position" content={index.toString()} />
100
+ <meta itemprop="name" content={nameFormatted} />
125
101
  </>
126
102
  )}
127
103
  </div>
@@ -1,52 +1,24 @@
1
1
  <template>
2
- <div
3
- class="product-link"
4
- itemscope
5
- itemtype="https://schema.org/Product"
6
- >
7
- <div
8
- :class="[bigTile ? 'product-link--big-tile' : 'product-thumb--plp product-thumb--carousel']"
9
- >
2
+ <div class="product-link" itemscope itemtype="https://schema.org/Product">
3
+ <div :class="[bigTile ? 'product-link--big-tile' : 'product-thumb--plp product-thumb--carousel']">
10
4
  <!-- Slot na ProductImage z Astro -->
11
5
  <slot name="image">
12
- <img
13
- src="/1x1.png"
14
- class="bg-neutral-lightest/70"
15
- :alt="productName"
16
- />
6
+ <img src="/1x1.png" class="bg-neutral-lightest/70" :alt="productName" />
17
7
  </slot>
18
8
  </div>
19
9
 
20
10
  <div :class="[bigTile ? '' : 'sm:pl-4']">
21
- <p
22
- v-if="price"
23
- class="block mb-2 font-600 font-headbold text-5"
24
- >
11
+ <p v-if="price" class="block mb-2 font-600 font-headbold text-5">
25
12
  {{ price }}
26
13
  </p>
27
14
 
28
- <a
29
- class="product-link--url"
30
- :href="url"
31
- itemprop="url"
32
- :title="productNumber"
33
- v-html="nameFormatted"
34
- />
15
+ <a class="product-link--url" :href="url" itemprop="url" :title="productNumber" v-html="nameFormatted" />
35
16
 
36
- <ProductNumber
37
- :product-number="productNumber"
38
- :copy-disabled="true"
39
- />
17
+ <ProductNumber :product-number="productNumber" :copy-disabled="true" />
40
18
 
41
19
  <template v-if="index !== null">
42
- <meta
43
- itemprop="position"
44
- :content="index.toString()"
45
- />
46
- <meta
47
- itemprop="name"
48
- :content="nameFormatted"
49
- />
20
+ <meta itemprop="position" :content="index.toString()" />
21
+ <meta itemprop="name" :content="nameFormatted" />
50
22
  </template>
51
23
  </div>
52
24
  </div>
@@ -16,28 +16,13 @@ const { product, nameFormatted, price, url, index, bigTile } = Astro.props;
16
16
 
17
17
  <div class={`flex flex-col ${bigTile ? '' : 'sm:pl-4'}`}>
18
18
  {price && <p class="block mb-2 font-600 font-headbold text-5">{price}</p>}
19
- <a
20
- class="product-link--url"
21
- href={url}
22
- itemprop="url"
23
- title={product.number}
24
- set:html={nameFormatted}
25
- />
26
- <ProductNumber
27
- productNumber={product.number}
28
- copyDisabled={true}
29
- />
19
+ <a class="product-link--url" href={url} itemprop="url" title={product.number} set:html={nameFormatted} />
20
+ <ProductNumber productNumber={product.number} copyDisabled={true} />
30
21
  {
31
22
  index !== null && (
32
23
  <>
33
- <meta
34
- itemprop="position"
35
- content={index}
36
- />
37
- <meta
38
- itemprop="name"
39
- content={nameFormatted}
40
- />
24
+ <meta itemprop="position" content={index} />
25
+ <meta itemprop="name" content={nameFormatted} />
41
26
  </>
42
27
  )
43
28
  }