spoko-design-system 1.6.0 → 1.8.0

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.
@@ -0,0 +1,370 @@
1
+ ---
2
+ title: "ProductEngine"
3
+ layout: "../../layouts/MainLayout.astro"
4
+ ---
5
+ import ProductEngine from '../../components/Product/ProductEngine.vue'
6
+ import ProductEngines from '../../components/Product/ProductEngines.vue'
7
+
8
+ # ProductEngine
9
+
10
+ Engine codes with detailed tooltips showing specifications like power, displacement, dates, and more.
11
+
12
+ ## Single Engine Code
13
+
14
+ Display a single engine code with tooltip showing detailed engine information.
15
+
16
+ ### import:
17
+
18
+ ```js
19
+ import ProductEngine from 'spoko-design-system/src/components/Product/ProductEngine.vue'
20
+ ```
21
+
22
+ ### Basic Usage (New API Structure):
23
+
24
+ <div class="component-preview">
25
+ <div class="bg-white p-6 w-full flex gap-2">
26
+ <ProductEngine client:load engine={{
27
+ code: "CAYA",
28
+ name: "1.6 TDI",
29
+ serie: { value: "EA189", label: "Seria silnika" },
30
+ power: { kw: 55, ps: 75, ps_label: "KM", label: "Moc" },
31
+ displacement: { value: 1598, label: "Pojemność" },
32
+ euro: { value: 5, label: "Norma Euro" }
33
+ }} />
34
+ <ProductEngine client:load engine={{
35
+ code: "CAYB",
36
+ name: "1.6 TDI",
37
+ serie: { value: "EA189", label: "Seria silnika" },
38
+ power: { kw: 66, ps: 90, ps_label: "KM", label: "Moc" },
39
+ displacement: { value: 1598, label: "Pojemność" },
40
+ euro: { value: 5, label: "Norma Euro" }
41
+ }} />
42
+ </div>
43
+ </div>
44
+
45
+ ```vue
46
+ <!-- New API structure (with built-in translations) -->
47
+ <ProductEngine :engine="{
48
+ code: 'CAYA',
49
+ name: '1.6 TDI',
50
+ serie: { value: 'EA189', label: 'Seria silnika' },
51
+ power: { kw: 55, ps: 75, ps_label: 'KM', label: 'Moc' },
52
+ displacement: { value: 1598, label: 'Pojemność' },
53
+ euro: { value: 5, label: 'Norma Euro' }
54
+ }" />
55
+
56
+ <!-- Old API structure (backward compatible) -->
57
+ <ProductEngine
58
+ :engine="{ code: 'CAYA', name: '1.6 TDI', kw: 55, ps: 75, cc: 1598, serie: 3, euro: 5 }"
59
+ :translations="{ power: 'Moc', cc: 'Pojemność', euro: 'Euro', horsepowerUnit: 'KM' }"
60
+ />
61
+ ```
62
+
63
+ ### Special Engine Variants (Colored):
64
+
65
+ Engine codes for special editions are automatically color-coded:
66
+
67
+ <div class="component-preview">
68
+ <div class="bg-white p-6 w-full flex flex-wrap gap-3">
69
+ <div class="flex flex-col gap-1">
70
+ <small class="text-xs text-gray-500">GTI Engine (Red)</small>
71
+ <ProductEngine client:load engine={{
72
+ code: "CAVE",
73
+ name: "1.4 TSI",
74
+ power: { kw: 132, ps: 180, ps_label: "KM", label: "Moc" },
75
+ displacement: { value: 1390, label: "Pojemność" },
76
+ euro: { value: 5, label: "Norma Euro" }
77
+ }} />
78
+ </div>
79
+ <div class="flex flex-col gap-1">
80
+ <small class="text-xs text-gray-500">WRC Engine (Blue)</small>
81
+ <ProductEngine client:load engine={{
82
+ code: "CDLJ",
83
+ name: "1.6 TDI",
84
+ power: { kw: 165, ps: 220, ps_label: "KM", label: "Moc" },
85
+ displacement: { value: 1598, label: "Pojemność" },
86
+ euro: { value: 6, label: "Norma Euro" }
87
+ }} />
88
+ </div>
89
+ <div class="flex flex-col gap-1">
90
+ <small class="text-xs text-gray-500">Special Blue</small>
91
+ <ProductEngine client:load engine={{
92
+ code: "CPTA",
93
+ name: "1.0 TSI",
94
+ power: { kw: 70, ps: 95, ps_label: "KM", label: "Moc" },
95
+ displacement: { value: 999, label: "Pojemność" },
96
+ euro: { value: 6, label: "Norma Euro" }
97
+ }} />
98
+ </div>
99
+ </div>
100
+ </div>
101
+
102
+ ```vue
103
+ <!-- GTI Engine - Red -->
104
+ <ProductEngine :engine="{
105
+ code: 'CAVE',
106
+ name: '1.4 TSI',
107
+ power: { kw: 132, ps: 180, ps_label: 'KM', label: 'Moc' },
108
+ displacement: { value: 1390, label: 'Pojemność' },
109
+ euro: { value: 5, label: 'Norma Euro' }
110
+ }" />
111
+
112
+ <!-- WRC Engine - Blue -->
113
+ <ProductEngine :engine="{
114
+ code: 'CDLJ',
115
+ name: '1.6 TDI',
116
+ power: { kw: 165, ps: 220, ps_label: 'KM', label: 'Moc' },
117
+ displacement: { value: 1598, label: 'Pojemność' },
118
+ euro: { value: 6, label: 'Norma Euro' }
119
+ }" />
120
+ ```
121
+
122
+ ## Engine List
123
+
124
+ Display multiple engine codes from an array (from API response).
125
+
126
+ ### import:
127
+
128
+ ```js
129
+ import ProductEngines from 'spoko-design-system/src/components/Product/ProductEngines.vue'
130
+ ```
131
+
132
+ ### Usage:
133
+
134
+ <div class="component-preview">
135
+ <div class="bg-white p-6 w-full">
136
+ <ProductEngines client:load engines={[
137
+ {
138
+ id: 13,
139
+ code: "CAYA",
140
+ name: "1.6 TDI",
141
+ serie: { value: "EA189", label: "Seria silnika" },
142
+ power: { kw: 55, ps: 75, ps_label: "KM", label: "Moc" },
143
+ displacement: { value: 1598, label: "Pojemność" },
144
+ euro: { value: 5, label: "Norma Euro" }
145
+ },
146
+ {
147
+ id: 14,
148
+ code: "CAYB",
149
+ name: "1.6 TDI",
150
+ serie: { value: "EA189", label: "Seria silnika" },
151
+ power: { kw: 66, ps: 90, ps_label: "KM", label: "Moc" },
152
+ displacement: { value: 1598, label: "Pojemność" },
153
+ euro: { value: 5, label: "Norma Euro" }
154
+ },
155
+ {
156
+ id: 15,
157
+ code: "CAYC",
158
+ name: "1.6 TDI",
159
+ serie: { value: "EA189", label: "Seria silnika" },
160
+ power: { kw: 77, ps: 105, ps_label: "KM", label: "Moc" },
161
+ displacement: { value: 1598, label: "Pojemność" },
162
+ euro: { value: 5, label: "Norma Euro" }
163
+ },
164
+ ]} />
165
+ </div>
166
+ </div>
167
+
168
+ ```vue
169
+ <ProductEngines :engines="[
170
+ {
171
+ id: 13,
172
+ code: 'CAYA',
173
+ name: '1.6 TDI',
174
+ serie: { value: 'EA189', label: 'Seria silnika' },
175
+ power: { kw: 55, ps: 75, ps_label: 'KM', label: 'Moc' },
176
+ displacement: { value: 1598, label: 'Pojemność' },
177
+ euro: { value: 5, label: 'Norma Euro' }
178
+ },
179
+ {
180
+ id: 14,
181
+ code: 'CAYB',
182
+ name: '1.6 TDI',
183
+ serie: { value: 'EA189', label: 'Seria silnika' },
184
+ power: { kw: 66, ps: 90, ps_label: 'KM', label: 'Moc' },
185
+ displacement: { value: 1598, label: 'Pojemność' },
186
+ euro: { value: 5, label: 'Norma Euro' }
187
+ }
188
+ ]" />
189
+ ```
190
+
191
+ ### With API Data:
192
+
193
+ When using data from the API, pass the `part_engines` array directly. The component automatically extracts translations from the nested structure:
194
+
195
+ ```vue
196
+ <ProductEngines
197
+ :engines="product.part_engines"
198
+ :isPdp="true"
199
+ />
200
+ ```
201
+
202
+ **Note**: The new API structure includes labels and translations, so you no longer need to pass the `translations` prop. The component will use labels from the API (e.g., "Moc", "Pojemność", "KM").
203
+
204
+ ### API Response Structure:
205
+
206
+ ```json
207
+ {
208
+ "part_engines": [
209
+ {
210
+ "id": 13,
211
+ "code": "CAYA",
212
+ "name": "1.6 TDI",
213
+ "info": null,
214
+ "serie": {
215
+ "value": "EA189",
216
+ "label": "Seria silnika"
217
+ },
218
+ "type": {
219
+ "value": "diesel",
220
+ "translated": "Diesel",
221
+ "label": "Typ paliwa"
222
+ },
223
+ "power": {
224
+ "kw": 55,
225
+ "ps": 75,
226
+ "ps_label": "KM",
227
+ "label": "Moc"
228
+ },
229
+ "date": {
230
+ "value": "03/2009–05/2010",
231
+ "label": "Data produkcji"
232
+ },
233
+ "displacement": {
234
+ "value": 1598,
235
+ "label": "Pojemność"
236
+ },
237
+ "compression_ratio": {
238
+ "value": "16,5:1",
239
+ "label": "Stopień sprężania"
240
+ },
241
+ "valves": {
242
+ "value": 16,
243
+ "label": "Zawory"
244
+ },
245
+ "euro": {
246
+ "value": 5,
247
+ "formatted": "Norma Euro 5",
248
+ "label": "Norma Euro"
249
+ }
250
+ },
251
+ {
252
+ "id": 14,
253
+ "code": "CAYB",
254
+ "name": "1.6 TDI",
255
+ "info": null,
256
+ "serie": {
257
+ "value": "EA189",
258
+ "label": "Seria silnika"
259
+ },
260
+ "type": {
261
+ "value": "diesel",
262
+ "translated": "Diesel",
263
+ "label": "Typ paliwa"
264
+ },
265
+ "power": {
266
+ "kw": 66,
267
+ "ps": 90,
268
+ "ps_label": "KM",
269
+ "label": "Moc"
270
+ },
271
+ "date": {
272
+ "value": "03/2009–03/2014",
273
+ "label": "Data produkcji"
274
+ },
275
+ "displacement": {
276
+ "value": 1598,
277
+ "label": "Pojemność"
278
+ },
279
+ "compression_ratio": {
280
+ "value": "16,5:1",
281
+ "label": "Stopień sprężania"
282
+ },
283
+ "valves": {
284
+ "value": 16,
285
+ "label": "Zawory"
286
+ },
287
+ "euro": {
288
+ "value": 5,
289
+ "formatted": "Norma Euro 5",
290
+ "label": "Norma Euro"
291
+ }
292
+ }
293
+ ]
294
+ }
295
+ ```
296
+
297
+ ## Props
298
+
299
+ ### ProductEngine Props:
300
+
301
+ | Prop | Type | Required | Default | Description |
302
+ |------|------|----------|---------|-------------|
303
+ | `engine` | `Object` | Yes | - | Engine object with nested structure from API |
304
+ | `engine.code` | `String` | Yes | - | Engine code (e.g., "CAYA") |
305
+ | `engine.name` | `String` | No | - | Engine name (e.g., "1.6 TDI") |
306
+ | `engine.info` | `String` | No | - | Additional info shown in header |
307
+ | `engine.serie` | `Object` | No | - | Engine series object |
308
+ | `engine.serie.value` | `String` | No | - | Series value (e.g., "EA189", "EA288") |
309
+ | `engine.serie.label` | `String` | No | - | Series label (e.g., "Seria silnika") |
310
+ | `engine.power` | `Object` | No | - | Power object with kw, ps, labels |
311
+ | `engine.power.kw` | `Number` | No | - | Power in kilowatts |
312
+ | `engine.power.ps` | `Number` | No | - | Power in horsepower |
313
+ | `engine.power.ps_label` | `String` | No | - | Unit label (e.g., "KM", "PS") |
314
+ | `engine.power.label` | `String` | No | - | Power label (e.g., "Moc") |
315
+ | `engine.displacement` | `Object` | No | - | Displacement object |
316
+ | `engine.displacement.value` | `Number` | No | - | Displacement in cm³ |
317
+ | `engine.displacement.label` | `String` | No | - | Label (e.g., "Pojemność") |
318
+ | `engine.euro` | `Object` | No | - | Euro standard object |
319
+ | `engine.euro.value` | `Number` | No | - | Euro standard number |
320
+ | `engine.euro.label` | `String` | No | - | Label (e.g., "Norma Euro") |
321
+ | `engine.euro.formatted` | `String` | No | - | Formatted string (e.g., "Norma Euro 5") |
322
+ | `showComma` | `Boolean` | No | `false` | Show comma after code (for lists) |
323
+ | `translations` | `Object` | No | API labels | Fallback translations (used only with old API) |
324
+
325
+ **Note**: The component supports both the new nested API structure (with built-in labels) and the old flat structure for backward compatibility.
326
+
327
+ ### ProductEngines Props:
328
+
329
+ | Prop | Type | Required | Default | Description |
330
+ |------|------|----------|---------|-------------|
331
+ | `engines` | `Array<Object>` | Yes | `[]` | Array of engine objects (new nested structure) |
332
+ | `isPdp` | `Boolean` | No | `false` | Product detail page styling |
333
+ | `translations` | `Object` | No | API labels | Fallback translations (used only with old API) |
334
+
335
+ ## Features
336
+
337
+ - ✅ **Rich Tooltips**: Shows detailed engine specifications on hover (Tippy.js)
338
+ - ✅ **API-Driven Translations**: Labels and units come directly from API
339
+ - ✅ **Multi-language**: Supports Polish (KM), German (PS), English (HP)
340
+ - ✅ **Two-Tone Design**: Dark blue header with light body for better hierarchy
341
+ - ✅ **Semantic Colors**: Automatic color coding for special engines (GTI, WRC, etc.)
342
+ - ✅ **Clean Layout**: Flexbox-based design with semantic CSS classes
343
+ - ✅ **Smart Data**: Only shows relevant fields (power, displacement, euro)
344
+ - ✅ **Auto-sorting**: Engines automatically sorted alphabetically by code
345
+ - ✅ **SEO-Friendly**: Static HTML enhanced with client-side tooltips
346
+ - ✅ **Backward Compatible**: Works with both new and old API structures
347
+ - ✅ **Touch Friendly**: Works on mobile devices
348
+
349
+ ## Engine Color Coding
350
+
351
+ Special engine codes are automatically color-coded:
352
+
353
+ | Engine Codes | Color | Description |
354
+ |--------------|-------|-------------|
355
+ | CAVE, CTHE, DAJA, DAYB | Red | GTI Performance engines |
356
+ | CDLJ | Blue | WRC/R Street engines |
357
+ | CPTA, CZEA | Light Blue | Special blue engines |
358
+
359
+ ## Notes
360
+
361
+ - Hover over any engine code to see full specifications in a detailed tooltip
362
+ - Tooltips use Tippy.js with custom two-tone SDS theme
363
+ - **New API structure**: Labels come from API (e.g., "Moc", "Pojemność", "KM")
364
+ - **No manual translations needed**: The API provides all labels and units
365
+ - The component automatically extracts series value from nested structure
366
+ - Date field is not shown in tooltips (only power, displacement, and euro)
367
+ - Missing data fields are gracefully hidden
368
+ - Commas between engine codes are automatically handled in lists
369
+ - **Backward compatible**: Still works with old flat API structure
370
+ - Tooltip has dark blue header (#001e50) with light gray body (#f3f4f6)
@@ -0,0 +1,46 @@
1
+ import tippy from 'tippy.js';
2
+ import 'tippy.js/dist/tippy.css';
3
+ import '../styles/tippy-theme.css';
4
+
5
+ /**
6
+ * Global Tooltip Initializer
7
+ * Automatically enhances all elements with data-tippy-content attribute
8
+ * Works with static HTML - perfect for SEO and Astro static pages
9
+ */
10
+
11
+ function initTooltips() {
12
+ // Destroy existing tooltips to avoid duplicates
13
+ document.querySelectorAll('[data-tippy-content]').forEach((el: any) => {
14
+ if (el._tippy) {
15
+ el._tippy.destroy();
16
+ }
17
+ });
18
+
19
+ // Initialize tooltips for all elements with data-tippy-content
20
+ tippy('[data-tippy-content]', {
21
+ theme: 'sds',
22
+ placement: 'top',
23
+ arrow: true,
24
+ animation: 'shift-away',
25
+ duration: [200, 150],
26
+ maxWidth: 280,
27
+ allowHTML: true, // Allow HTML content for rich tooltips
28
+ });
29
+ }
30
+
31
+ // Initialize on page load
32
+ if (typeof window !== 'undefined') {
33
+ // Initial load
34
+ document.addEventListener('DOMContentLoaded', () => {
35
+ initTooltips();
36
+ // Reinitialize after a short delay to catch Vue components
37
+ setTimeout(initTooltips, 100);
38
+ });
39
+
40
+ // Reinitialize on Astro page transitions (for View Transitions)
41
+ document.addEventListener('astro:page-load', () => {
42
+ initTooltips();
43
+ // Reinitialize after a short delay to catch Vue components
44
+ setTimeout(initTooltips, 100);
45
+ });
46
+ }
@@ -0,0 +1,131 @@
1
+ /*
2
+ * Custom Tippy.js Theme for SDS
3
+ * Matches the design system colors and styling
4
+ */
5
+
6
+ /* SDS Theme for Tippy */
7
+ .tippy-box[data-theme~='sds'] {
8
+ background-color: #f3f4f6 !important; /* neutral-lightest */
9
+ color: #1e293b !important; /* slate-darkest */
10
+ font-size: 0.75rem;
11
+ line-height: 1.5;
12
+ border-radius: 0.5rem;
13
+ box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
14
+ max-width: 280px;
15
+ border: 1px solid #e5e7eb; /* neutral-lighter */
16
+ }
17
+
18
+ .tippy-box[data-theme~='sds'][data-placement^='top'] > .tippy-arrow::before {
19
+ border-top-color: #f3f4f6;
20
+ }
21
+ .tippy-box[data-theme~='sds'][data-placement^='bottom'] > .tippy-arrow::before {
22
+ border-bottom-color: #f3f4f6;
23
+ }
24
+ .tippy-box[data-theme~='sds'][data-placement^='left'] > .tippy-arrow::before {
25
+ border-left-color: #f3f4f6;
26
+ }
27
+ .tippy-box[data-theme~='sds'][data-placement^='right'] > .tippy-arrow::before {
28
+ border-right-color: #f3f4f6;
29
+ }
30
+
31
+ /* Content styling */
32
+ .tippy-box[data-theme~='sds'] .tippy-content {
33
+ padding: 0.5rem 0.75rem;
34
+ background-color: transparent !important;
35
+ color: #1e293b !important; /* slate-darkest */
36
+ }
37
+
38
+ /* Remove padding for structured tooltips (with tooltip-header) */
39
+ .tippy-box[data-theme~='sds'] .tippy-content:has(.tooltip-header) {
40
+ padding: 0;
41
+ }
42
+
43
+ /* Force all child elements to inherit text color */
44
+ .tippy-box[data-theme~='sds'] * {
45
+ color: inherit;
46
+ }
47
+
48
+ /* Engine tooltip header - dark blue background */
49
+ .tippy-box[data-theme~='sds'] .tooltip-header {
50
+ display: flex;
51
+ align-items: center;
52
+ padding: 0.375rem 0.5rem;
53
+ background-color: #001e50;
54
+ border-radius: 0.5rem 0.5rem 0 0;
55
+ color: white;
56
+ }
57
+
58
+ .tippy-box[data-theme~='sds'] .tooltip-header strong {
59
+ font-weight: 600;
60
+ color: white;
61
+ }
62
+
63
+ .tippy-box[data-theme~='sds'] .tooltip-header .info {
64
+ font-weight: 300;
65
+ margin-left: 0.5rem;
66
+ color: rgba(255, 255, 255, 0.9);
67
+ }
68
+
69
+ .tippy-box[data-theme~='sds'] .tooltip-header .series-badge {
70
+ margin-left: auto;
71
+ font-weight: 400;
72
+ color: #00b0f0;
73
+ font-size: 0.75rem;
74
+ }
75
+
76
+ /* Engine tooltip specs */
77
+ .tippy-box[data-theme~='sds'] .tooltip-specs {
78
+ padding: 0.375rem 0.5rem;
79
+ }
80
+
81
+ .tippy-box[data-theme~='sds'] .tooltip-row {
82
+ display: flex;
83
+ justify-content: space-between;
84
+ align-items: center;
85
+ padding: 0.25rem 0;
86
+ border-bottom: 1px solid #e5e7eb;
87
+ }
88
+
89
+ .tippy-box[data-theme~='sds'] .tooltip-row:last-child {
90
+ border-bottom: none;
91
+ }
92
+
93
+ .tippy-box[data-theme~='sds'] .tooltip-label {
94
+ font-size: 0.7rem;
95
+ color: #64748B;
96
+ font-weight: 400;
97
+ }
98
+
99
+ .tippy-box[data-theme~='sds'] .tooltip-value {
100
+ font-size: 0.75rem;
101
+ color: #1e293b;
102
+ font-weight: 500;
103
+ margin-left: 1rem;
104
+ }
105
+
106
+ /* Engine tooltip table styling */
107
+ .tippy-box[data-theme~='sds'] table {
108
+ width: 100%;
109
+ margin-top: 0.25rem;
110
+ border-collapse: collapse;
111
+ color: white;
112
+ }
113
+
114
+ .tippy-box[data-theme~='sds'] th {
115
+ text-align: left;
116
+ padding: 0.125rem 0.5rem 0.125rem 0;
117
+ color: rgba(255, 255, 255, 0.7) !important;
118
+ font-weight: 400;
119
+ font-size: 0.7rem;
120
+ }
121
+
122
+ .tippy-box[data-theme~='sds'] td {
123
+ padding: 0.125rem 0;
124
+ font-weight: 500;
125
+ text-align: right;
126
+ color: white !important;
127
+ }
128
+
129
+ .tippy-box[data-theme~='sds'] strong {
130
+ font-weight: 600;
131
+ }
@@ -165,6 +165,8 @@ export function createSdsConfig(customConfig: CustomConfig = {}) {
165
165
  // All peer selectors from the list (needed for floating labels)
166
166
  ...peerSelectorClasses,
167
167
  ],
168
+ // Disable default extractors to prevent false positives from JavaScript code
169
+ extractorDefault: false,
168
170
  // Optimized extractors for static Astro builds
169
171
  extractors: [
170
172
  {
@@ -207,7 +209,7 @@ export function createSdsConfig(customConfig: CustomConfig = {}) {
207
209
  presetAttributify(),
208
210
  presetIcons({
209
211
  scale: 1.2,
210
- warn: true,
212
+ warn: true, // Show warnings for actual missing icons
211
213
  prefix: 'i-',
212
214
  extraProperties: {
213
215
  'display': 'inline-block',
@@ -7,7 +7,7 @@ import { breakpoints } from './../breakpoints';
7
7
 
8
8
  export const jumbotronShortcuts = [
9
9
  // Default variant
10
- ['jumbotron-header-base', 'relative mx-auto my-auto lg:w-full text-center py-8'],
10
+ ['jumbotron-header-base', 'relative mx-auto my-auto w-full text-center py-8'],
11
11
  ['jumbotron-container-small', 'md:min-h-xs sm:py-12 md:py-14 lg:py-16 xl:py-20'],
12
12
  ['jumbotron-container-large', 'md:min-h-md sm:py-16 md:py-20 lg:py-28 xl:py-32'],
13
13
  ['jumbotron-title-default', 'text-3xl headline-light text-white sm:(text-4xl pt-0) md:text-5xl lg:text-6xl'],