spoko-design-system 1.0.0 → 1.1.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.
Files changed (38) hide show
  1. package/.astro/data-store.json +1 -1
  2. package/.astro/settings.json +1 -1
  3. package/.claude/settings.local.json +11 -1
  4. package/.github/workflows/code-quality.yml +51 -0
  5. package/.github/workflows/sonarcloud.yml +51 -0
  6. package/.prettierignore +15 -0
  7. package/.prettierrc +25 -0
  8. package/.vscode/extensions.json +0 -1
  9. package/.vscode/settings.json +0 -4
  10. package/CHANGELOG.md +14 -0
  11. package/README.md +19 -3
  12. package/astro.config.mjs +0 -2
  13. package/eslint.config.js +64 -0
  14. package/icon.config.ts +32 -2
  15. package/package.json +14 -9
  16. package/sonar-project.properties +19 -0
  17. package/src/components/Category/CategoriesCarousel.astro +2 -3
  18. package/src/components/Category/CategoryDetails.astro +4 -5
  19. package/src/components/Faq.astro +1 -2
  20. package/src/components/Header/Header.astro +33 -33
  21. package/src/components/Headline.vue +24 -4
  22. package/src/components/Product/ProductLink.astro +7 -12
  23. package/src/components/ProductTile.astro +1 -2
  24. package/src/layouts/Layout.astro +0 -3
  25. package/src/layouts/MainLayout.astro +0 -3
  26. package/src/pages/components/buttons.mdx +0 -1
  27. package/src/pages/components/hand-drive.mdx +0 -27
  28. package/src/pages/index.astro +170 -39
  29. package/src/utils/category/getMainCategoryList.ts +8 -17
  30. package/src/utils/product/getPriceFormatted.ts +6 -9
  31. package/src/utils/product/getProductChecklist.ts +1 -2
  32. package/src/utils/text/formatLocaleNumber.ts +2 -3
  33. package/uno-config/index.ts +13 -19
  34. package/.astro/icon.d.ts +0 -11909
  35. package/astro-i18next.config.mjs +0 -18
  36. package/astro-i18next.config.ts +0 -11
  37. package/public/locales/en/translation.json +0 -13
  38. package/public/locales/pl/translation.json +0 -13
@@ -69,32 +69,32 @@ import Search from "astro-pagefind/components/Search";
69
69
  @apply font-textlight text-base;
70
70
  }
71
71
 
72
- .pagefind-ui__search-input {
73
- height: 40px !important;
72
+ .pagefind-ui .pagefind-ui__search-input {
73
+ height: 40px;
74
74
  border: 0;
75
- @apply rounded-none sm:rounded-3xl h-10 w-full;
75
+ @apply rounded-none sm:rounded-3xl w-full;
76
76
  }
77
77
 
78
- .pagefind-ui__result-excerpt,
79
- .pagefind-ui__button {
80
- font-size: 14px !important;
78
+ .pagefind-ui .pagefind-ui__result-excerpt,
79
+ .pagefind-ui .pagefind-ui__button {
80
+ font-size: 14px;
81
81
  }
82
82
 
83
- .pagefind-ui__filter-name {
84
- font-size: 12px !important;
83
+ .pagefind-ui .pagefind-ui__filter-name {
84
+ font-size: 12px;
85
85
  }
86
86
 
87
- .pagefind-ui__drawer:not(.pagefind-ui__hidden) {
87
+ .pagefind-ui .pagefind-ui__drawer:not(.pagefind-ui__hidden) {
88
88
  @apply p-4;
89
89
  }
90
90
 
91
- .pagefind-ui__result-link {
91
+ .pagefind-ui .pagefind-ui__result-link {
92
92
  color: var(--pagefind-ui-primary);
93
93
  font-family: vw_headlight;
94
94
  font-size: 1rem;
95
95
  }
96
96
 
97
- .pagefind-ui__result-link::before {
97
+ .pagefind-ui .pagefind-ui__result-link::before {
98
98
  top: 0;
99
99
  bottom: 0;
100
100
  left: 0;
@@ -103,107 +103,107 @@ import Search from "astro-pagefind/components/Search";
103
103
  position: absolute;
104
104
  }
105
105
 
106
- .pagefind-ui__result-excerpt {
106
+ .pagefind-ui .pagefind-ui__result-excerpt {
107
107
  color: var(--pagefind-ui-text);
108
108
  order: 3;
109
109
  }
110
110
 
111
- .pagefind-ui__drawer {
111
+ .pagefind-ui .pagefind-ui__drawer {
112
112
  @apply bg-white md:fixed shadow-lg rounded-b-lg border-t border-t-transparent overflow-auto top-17 md:max-w-[calc(100vw-10%)] max-h-[calc(100vh-10%)] gap-[30px];
113
113
  }
114
114
 
115
- .pagefind-ui__search-clear {
115
+ .pagefind-ui .pagefind-ui__search-clear {
116
116
  height: 38px;
117
117
  top: 0;
118
118
  @apply sm:rounded-3xl;
119
119
  }
120
120
 
121
- .pagefind-ui__search-input {
121
+ .pagefind-ui .pagefind-ui__search-input {
122
122
  font-size: 1rem;
123
123
  font-weight: 400;
124
124
  padding: 0 2.5rem 2px;
125
125
  }
126
126
 
127
- .pagefind-ui__form::before {
127
+ .pagefind-ui .pagefind-ui__form::before {
128
128
  top: 14px;
129
129
  left: 16px;
130
130
  width: 14px;
131
131
  height: 14px;
132
132
  }
133
133
 
134
- .pagefind-ui__result {
134
+ .pagefind-ui .pagefind-ui__result {
135
135
  padding: 0.875rem 0;
136
136
  gap: 1rem;
137
137
  @apply relative;
138
138
  }
139
139
 
140
- .pagefind-ui__filter-block {
140
+ .pagefind-ui .pagefind-ui__filter-block {
141
141
  padding: 0.875rem 0;
142
142
  border-width: 1px;
143
143
  }
144
144
 
145
- .pagefind-ui__filter-group {
145
+ .pagefind-ui .pagefind-ui__filter-group {
146
146
  gap: 0.5rem;
147
147
  padding-top: 0.875rem;
148
148
  }
149
149
 
150
- .pagefind-ui__filter-value {
150
+ .pagefind-ui .pagefind-ui__filter-value {
151
151
  gap: 10px;
152
152
  }
153
153
 
154
- .pagefind-ui__filter-checkbox {
154
+ .pagefind-ui .pagefind-ui__filter-checkbox {
155
155
  border-radius: 3px;
156
156
  margin-top: 1px;
157
157
  min-width: calc(16px * var(--pagefind-ui-scale));
158
158
  }
159
159
 
160
- .pagefind-ui__result-image {
160
+ .pagefind-ui .pagefind-ui__result-image {
161
161
  @apply drop-shadow-sm w-full h-full object-contain rounded-none;
162
162
  }
163
163
 
164
- .pagefind-ui__filter-panel {
164
+ .pagefind-ui .pagefind-ui__filter-panel {
165
165
  @apply hidden;
166
166
  }
167
167
 
168
- .pagefind-ui__filter-label {
168
+ .pagefind-ui .pagefind-ui__filter-label {
169
169
  font-size: 0.9rem;
170
170
  }
171
171
 
172
- .pagefind-ui__button {
172
+ .pagefind-ui .pagefind-ui__button {
173
173
  font-weight: 400;
174
174
  height: 40px;
175
175
  }
176
176
 
177
- .pagefind-ui__result-tag {
177
+ .pagefind-ui .pagefind-ui__result-tag {
178
178
  background: inherit;
179
179
  padding: 0;
180
180
  color: #9ca3af;
181
181
  }
182
182
 
183
- .pagefind-ui__result-thumb {
183
+ .pagefind-ui .pagefind-ui__result-thumb {
184
184
  max-width: 120px;
185
185
  }
186
186
 
187
- .pagefind-ui__result-tags {
187
+ .pagefind-ui .pagefind-ui__result-tags {
188
188
  margin-top: 0.4rem;
189
189
  order: 2;
190
190
  }
191
191
 
192
- .pagefind-ui__filter-name::after {
192
+ .pagefind-ui .pagefind-ui__filter-name::after {
193
193
  color: var(--pagefind-ui-primary);
194
194
  }
195
195
 
196
- .pagefind-ui__result-title {
196
+ .pagefind-ui .pagefind-ui__result-title {
197
197
  font-size: inherit;
198
198
  line-height: 1;
199
199
  }
200
200
 
201
- .pagefind-ui__filter-panel,
202
- .pagefind-ui__results-area {
201
+ .pagefind-ui .pagefind-ui__filter-panel,
202
+ .pagefind-ui .pagefind-ui__results-area {
203
203
  margin-top: 0;
204
204
  }
205
205
 
206
- .pagefind-ui__message {
206
+ .pagefind-ui .pagefind-ui__message {
207
207
  padding: 0.875rem 0;
208
208
  }
209
209
 
@@ -23,7 +23,7 @@ const props = defineProps({
23
23
  default: 'regular'
24
24
  },
25
25
  underline: {
26
- type: Boolean,
26
+ type: [Boolean, String] as PropType<boolean | 'center'>,
27
27
  required: false,
28
28
  default: false
29
29
  }
@@ -61,8 +61,8 @@ const typographyClass = getTypographyClass()
61
61
  </script>
62
62
 
63
63
  <template>
64
- <component :is="props.as" class="mb-2.5 flex sm:block md:flex items-center leading-none"
65
- :class="`${typographyClass} ${props.textSize ? `text-${props.textSize}` : 'text-xl'} ${props.underline ? 'headline--underline' : ''}`">
64
+ <component :is="props.as" class="mb-2.5 leading-none"
65
+ :class="`${typographyClass} ${props.textSize ? `text-${props.textSize}` : 'text-xl'} ${props.underline === true ? 'headline--underline' : ''} ${props.underline === 'center' ? 'headline--underline-center block text-center' : 'flex sm:block md:flex items-center'}`">
66
66
  <slot />
67
67
  </component>
68
68
  </template>
@@ -82,7 +82,27 @@ const typographyClass = getTypographyClass()
82
82
  @apply content-empty absolute left-0 bottom-px h-px;
83
83
  width: 95%;
84
84
  max-width: 255px;
85
- background-color: #64748b
85
+ background-color: #64748b;
86
+ }
87
+ }
88
+
89
+ .headline--underline-center {
90
+ @apply relative pb-4;
91
+
92
+ &:before {
93
+ @apply content-empty absolute left-1/2 bottom-px h-px;
94
+ width: 95%;
95
+ max-width: 255px;
96
+ background-color: #64748b;
97
+ transform: translateX(-50%);
98
+ }
99
+
100
+ &:after {
101
+ @apply content-empty absolute bottom-0;
102
+ height: 3px;
103
+ width: 55px;
104
+ background-color: var(--clr-primary-400);
105
+ left: calc(50% - min(47.5%, 127.5px));
86
106
  }
87
107
  }
88
108
  </style>
@@ -27,7 +27,6 @@ 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 i18next, { t } from "i18next";
31
30
  import { ProductImage, ProductNumber, removeSemicolon, getPriceFormatted } from "spoko-design-system";
32
31
 
33
32
  // Użycie productObject jeśli przekazane, inaczej pobranie produktu na podstawie productId
@@ -40,18 +39,14 @@ const thumb = product ? (
40
39
  : await getImageUrl(product.photo || "", `'ProductLink' ${product.number}`)
41
40
  ) : "";
42
41
 
43
- // Tłumaczenie nazwy produktu jeśli dostępne
44
- const productTranslation = i18next.exists(`parts.${product?.number}.name`)
45
- ? null
46
- : productId ? await getProductTranslation(productId, product?.number || "") : null;
42
+ // Product translation removed - using English only
43
+ const productTranslation = productId ? await getProductTranslation(productId, product?.number || "") : null;
47
44
 
48
- // const productName = product ? (
49
- // isShopProduct
50
- // ? (locale === "pl" ? product.name_pl : product.name_en)
51
- // : productTranslation?.name || t(`parts.${product.number}.name`)
52
- // ) : "";
53
-
54
- const productName = product.name || 'NO NAME';
45
+ const productName = product ? (
46
+ isShopProduct
47
+ ? product.name_en || product.name
48
+ : productTranslation?.name || product.name
49
+ ) : 'NO NAME';
55
50
 
56
51
  const nameFormatted = removeSemicolon(productName.toString());
57
52
  ---
@@ -2,7 +2,6 @@
2
2
  const { productObject, locale, index } = Astro.props;
3
3
  import Image from "./Image.astro"
4
4
  import ProductNumber from "./Product/ProductNumber.astro"
5
- import { t } from "i18next";
6
5
  ---
7
6
 
8
7
  { productObject &&
@@ -36,7 +35,7 @@ import { t } from "i18next";
36
35
  { productObject.name }
37
36
  </a>
38
37
 
39
- <ProductNumber productNumber={productObject.number} copyDisabled={false} buttonTexts={{ copy: t('copy'), copied: t('copied') }} />
38
+ <ProductNumber productNumber={productObject.number} copyDisabled={false} buttonTexts={{ copy: 'Copy', copied: 'Copied' }} />
40
39
 
41
40
  { index !== null &&
42
41
  ( <meta itemprop="position" content={String(index)} />
@@ -3,11 +3,8 @@ import HeadCommon from "./partials/HeadCommon.astro";
3
3
  import FooterCommon from "./partials/FooterCommon.astro";
4
4
  import HeadSEO from "../layouts/partials/HeadSEO.astro";
5
5
  import * as CONFIG from "../config";
6
- import { t, changeLanguage } from "i18next";
7
6
  import "../styles/main.css";
8
7
  import Copyright from "../components/Copyright.astro";
9
- const locale = "en";
10
- changeLanguage(locale);
11
8
  const { content = {} } = Astro.props;
12
9
  const canonicalURL = new URL(Astro.url.pathname, Astro.site).toString();
13
10
  ---
@@ -5,11 +5,8 @@ import Header from "../components/Header/Header.astro";
5
5
  import PageContent from "../components/PageContent.astro";
6
6
  import LeftSidebar from "../components/LeftSidebar.astro";
7
7
  import * as CONFIG from "../config";
8
- import { t, changeLanguage } from "i18next";
9
8
  import "../styles/main.css";
10
9
  import Copyright from "../components/Copyright.astro";
11
- const locale = "en";
12
- changeLanguage(locale);
13
10
  const { content = {} } = Astro.props;
14
11
  const currentPage = Astro.url.pathname;
15
12
  const canonicalURL = new URL(Astro.url.pathname, Astro.site).toString();
@@ -5,7 +5,6 @@ layout: "../../layouts/MainLayout.astro"
5
5
  import Button from '../../components/Button.vue'
6
6
  import ButtonCopy from '../../components/ButtonCopy.astro'
7
7
  import { Icon } from 'astro-icon/components';
8
- import { t } from "i18next";
9
8
 
10
9
  # All buttons
11
10
 
@@ -68,33 +68,6 @@ import HandDrive from 'spoko-design-system/src/components/HandDrive.astro'
68
68
  />
69
69
  ```
70
70
 
71
- ## API Integration
72
-
73
- The component is designed to work seamlessly with API data:
74
-
75
- ```js
76
- // API Response Format
77
- {
78
- "hand_drive": 1, // Original number (legacy)
79
- "hand_drive_type": "lhd", // Clean string value
80
- "hand_drive_text": "Left-Hand Drive" // Translated text
81
- }
82
-
83
- // Component Usage
84
- <HandDrive
85
- handDrive={partData.hand_drive_type}
86
- text={partData.hand_drive_text}
87
- />
88
- ```
89
-
90
- ### API Call Example
91
- ```js
92
- const response = await fetch('/api/parts/6R106150282V?locale=en&with_translations=1');
93
- const partData = await response.json();
94
-
95
- // partData.hand_drive_type = "lhd"
96
- // partData.hand_drive_text = "Left-Hand Drive"
97
- ```
98
71
 
99
72
  ## Design Principles
100
73
 
@@ -1,5 +1,4 @@
1
1
  ---
2
- import { changeLanguage } from "i18next";
3
2
  import { Icon } from "astro-icon/components";
4
3
  import { SITE } from "../config";
5
4
  import Jumbotron from "../components/Jumbotron.astro";
@@ -14,19 +13,19 @@ const navItems = [
14
13
  title: "Core",
15
14
  description: "Base colors, typography, shadows etc.",
16
15
  url: "/core/introduction",
17
- icon: "ant-design:cluster-outlined",
16
+ icon: "streamline-freehand-color:database",
18
17
  },
19
18
  {
20
19
  title: "Components",
21
20
  description: "The building blocks for our UI.",
22
21
  url: "/components/buttons",
23
- icon: "ant-design:build-twotone",
22
+ icon: "streamline-freehand-color:module-building-blocks",
24
23
  },
25
24
  {
26
25
  title: "Patterns",
27
26
  description: "Common patterns for building interfaces.",
28
27
  url: "/patterns/introduction",
29
- icon: "ant-design:audit-outlined",
28
+ icon: "streamline-freehand-color:layouts-array-1",
30
29
  },
31
30
  ];
32
31
  ---
@@ -75,6 +74,69 @@ const navItems = [
75
74
  }
76
75
  </div>
77
76
  </nav>
77
+
78
+ <!-- Features Section -->
79
+ <section class="py-16 px-4 max-w-5xl mx-auto">
80
+ <div class="text-center mb-12">
81
+ <Headline as="h2" textSize="3xl" underline="center" class="text-gray-900 mb-6">
82
+ Why Spoko Design System?
83
+ </Headline>
84
+ <p class="text-lg text-gray-600 max-w-2xl mx-auto">
85
+ A modern, comprehensive design system built with Astro and Vue, featuring consistent components and patterns for rapid development.
86
+ </p>
87
+ </div>
88
+
89
+ <div class="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
90
+ <div class="text-center p-6 bg-white rounded-lg shadow-sm border border-gray-100">
91
+ <Headline as="h3" textSize="xl" underline={false} class="mb-3 text-gray-900 flex items-center justify-center">
92
+ <Icon name="simple-icons:astro" aria-hidden="true" class="text-3xl text-blue-400 mr-3" />
93
+ Astro-Powered
94
+ </Headline>
95
+ <p class="text-gray-600">Built with <a href="https://astro.build/" target="_blank" rel="noopener noreferrer" class="text-blue-600 hover:text-blue-800 underline transition-colors">Astro</a> for lightning-fast performance and seamless integration with modern frameworks.</p>
96
+ </div>
97
+
98
+ <div class="text-center p-6 bg-white rounded-lg shadow-sm border border-gray-100">
99
+ <Headline as="h3" textSize="xl" underline={false} class="mb-3 text-gray-900 flex items-center justify-center">
100
+ <Icon name="streamline-freehand-color:data-transfer-document-module" aria-hidden="true" class="text-3xl text-blue-400 mr-3" />
101
+ Rich Components
102
+ </Headline>
103
+ <p class="text-gray-600">20+ production-ready components including buttons, modals, carousels, and specialized automotive elements.</p>
104
+ </div>
105
+
106
+ <div class="text-center p-6 bg-white rounded-lg shadow-sm border border-gray-100">
107
+ <Headline as="h3" textSize="xl" underline={false} class="mb-3 text-gray-900 flex items-center justify-center">
108
+ <Icon name="vscode-icons:file-type-unocss" aria-hidden="true" class="text-3xl text-blue-400 mr-3" />
109
+ UnoCSS Styling
110
+ </Headline>
111
+ <p class="text-gray-600">Atomic CSS approach with <a href="https://unocss.dev/" target="_blank" rel="noopener noreferrer" class="text-blue-600 hover:text-blue-800 underline transition-colors">UnoCSS</a> for flexible, maintainable styling and consistent design tokens.</p>
112
+ </div>
113
+
114
+ <div class="text-center p-6 bg-white rounded-lg shadow-sm border border-gray-100">
115
+ <Headline as="h3" textSize="xl" underline={false} class="mb-3 text-gray-900 flex items-center justify-center">
116
+ <Icon name="vscode-icons:file-type-vue" aria-hidden="true" class="text-3xl text-blue-400 mr-3" />
117
+ Vue Integration
118
+ </Headline>
119
+ <p class="text-gray-600">Seamless <a href="https://vuejs.org/" target="_blank" rel="noopener noreferrer" class="text-blue-600 hover:text-blue-800 underline transition-colors">Vue 3</a> component integration with TypeScript support for interactive elements.</p>
120
+ </div>
121
+
122
+ <div class="text-center p-6 bg-white rounded-lg shadow-sm border border-gray-100">
123
+ <Headline as="h3" textSize="xl" underline={false} class="mb-3 text-gray-900 flex items-center justify-center">
124
+ <Icon name="streamline-freehand-color:design-process-drawing-board" aria-hidden="true" class="text-3xl text-blue-400 mr-3" />
125
+ Design Patterns
126
+ </Headline>
127
+ <p class="text-gray-600">Proven patterns and layouts for common use cases, from landing pages to product catalogs.</p>
128
+ </div>
129
+
130
+ <div class="text-center p-6 bg-white rounded-lg shadow-sm border border-gray-100">
131
+ <Headline as="h3" textSize="xl" underline={false} class="mb-3 text-gray-900 flex items-center justify-center">
132
+ <Icon name="streamline-freehand-color:app-window-source-code" aria-hidden="true" class="text-3xl text-blue-400 mr-3" />
133
+ Developer Ready
134
+ </Headline>
135
+ <p class="text-gray-600">Complete documentation, TypeScript support, and easy npm installation for quick project setup.</p>
136
+ </div>
137
+ </div>
138
+ </section>
139
+
78
140
  <div
79
141
  class="mt-12 py-20 bg-blue-darker bg-vw text-white flex items-center justify-center relative"
80
142
  >
@@ -86,44 +148,113 @@ const navItems = [
86
148
  </Quote>
87
149
  </div>
88
150
 
89
- <div class="px-4 grid lg:grid-cols-2 gap-4 md:gap-10 max-w-5xl mx-auto text-center py-12 md:px-0">
90
-
91
- <div>
92
- <Headline underline as="div" class="mx-auto text-gray-900" textSize="3xl">Download:</Headline>
93
- <div class="grid grid-flow-col gap-4 auto-cols-max text-6xl mb-12">
94
- <a href="https://www.npmjs.com/package/spoko-design-system" rel="noopener" title="npm page" class="hover:text-accent-light">
95
- <Icon name="mdi:npm"/>
96
- </a>
97
- <a href="https://github.com/polo-blue/sds" rel="noopener" title="Github Page" class="hover:text-accent-light">
98
- <Icon name="mdi:github"/>
99
- </a>
151
+ <!-- Download & Examples Section -->
152
+ <section class="py-16 px-4 max-w-6xl mx-auto">
153
+ <div class="grid lg:grid-cols-2 gap-8 md:gap-12">
154
+
155
+ <!-- Download Section -->
156
+ <div class="text-center">
157
+ <Headline underline as="h2" class="text-gray-900 mb-8" textSize="3xl">
158
+ <Icon name="streamline-freehand-color:archive-box" aria-hidden="true" class="text-3xl text-blue-400 mr-3" />
159
+ Get Started
160
+ </Headline>
161
+
162
+ <!-- Installation Commands -->
163
+ <div class="bg-gray-900 rounded-lg p-6 mb-6 text-left space-y-4">
164
+ <div>
165
+ <p class="text-gray-400 text-sm mb-2">Install via npm:</p>
166
+ <code class="text-green-400 font-mono text-lg">npm install spoko-design-system</code>
167
+ </div>
168
+ <div>
169
+ <p class="text-gray-400 text-sm mb-2">Or with pnpm (recommended):</p>
170
+ <code class="text-blue-400 font-mono text-lg">pnpm add spoko-design-system</code>
171
+ </div>
172
+ </div>
173
+
174
+ <!-- Download Links -->
175
+ <div class="flex justify-center gap-6 mb-6">
176
+ <a href="https://www.npmjs.com/package/spoko-design-system"
177
+ target="_blank"
178
+ rel="noopener noreferrer"
179
+ class="flex items-center gap-3 bg-red-600 hover:bg-red-700 text-white px-6 py-3 rounded-lg transition-colors">
180
+ <Icon name="mdi:npm" class="text-3xl" />
181
+ <span class="font-semibold">npm Package</span>
182
+ </a>
183
+ <a href="https://github.com/polo-blue/sds"
184
+ target="_blank"
185
+ rel="noopener noreferrer"
186
+ class="flex items-center gap-3 bg-gray-800 hover:bg-gray-900 text-white px-6 py-3 rounded-lg transition-colors">
187
+ <Icon name="mdi:github" class="text-2xl" />
188
+ <span class="font-semibold">Source Code</span>
189
+ </a>
190
+ </div>
191
+
192
+ <p class="text-gray-600 text-sm">
193
+ TypeScript support included • Complete documentation • Production ready
194
+ </p>
100
195
  </div>
101
- </div>
102
-
103
-
104
- <div>
105
- <Headline underline as="div" class="mx-auto text-gray-900" textSize="3xl">Examples:</Headline>
106
- <ul class="flex flex-wrap text-2xl pt-6 lg:(py-4 gap-4) text-left justify-center lg:justify-start w-full">
107
- <li class="leading-5 me-6 mb-4 lg:mb-0 flex-shrink-0">
108
- <a href="https://catalog.polo.blue" class="example-link whitespace-nowrap" target="_blank"> catalog.polo.blue</a>
109
- </li>
110
- <li class="leading-5 me-6 mb-4 lg:mb-0 flex-shrink-0">
111
- <a href="https://polo.blue" class="example-link whitespace-nowrap" target="_blank"> polo.blue</a>
112
- </li>
113
- <li class="leading-5 me-6 mb-4 lg:mb-0 flex-shrink-0">
114
- <a href="https://spoko.space" class="example-link whitespace-nowrap" target="_blank"> spoko.space</a>
115
- </li>
116
- <li class="leading-5 me-6 mb-4 lg:mb-0 flex-shrink-0">
117
- <a href="https://sale.polo.blue/" class="example-link whitespace-nowrap" target="_blank">sale.polo.blue</a>
118
- </li>
119
- <li class="leading-5 me-6 mb-4 lg:mb-0 flex-shrink-0">
120
- <a href="https://polo6r.pl" class="example-link whitespace-nowrap" target="_blank">polo6r.pl</a>
121
- </li>
122
- </ul>
123
- </div>
124
196
 
197
+ <!-- Examples Section -->
198
+ <div class="text-center">
199
+ <Headline underline as="h2" class="text-gray-900 mb-8" textSize="3xl">
200
+ <Icon name="streamline-freehand-color:app-window-source-code" aria-hidden="true" class="text-3xl text-blue-400 mr-3" />
201
+ Live Examples
202
+ </Headline>
125
203
 
126
- </div>
204
+ <!-- Example Sites Grid -->
205
+ <div class="grid gap-4 mb-6">
206
+ <a href="https://catalog.polo.blue"
207
+ target="_blank"
208
+ rel="noopener noreferrer"
209
+ class="flex items-center justify-between p-4 bg-white border border-gray-200 rounded-lg hover:border-blue-400 hover:shadow-md transition-all group">
210
+ <div class="text-left">
211
+ <h4 class="font-semibold text-gray-900 group-hover:text-blue-600">catalog.polo.blue</h4>
212
+ <p class="text-sm text-gray-600">Car parts catalog</p>
213
+ </div>
214
+ <Icon name="lucide:link" class="text-gray-400 group-hover:text-blue-400" />
215
+ </a>
216
+
217
+ <a href="https://polo.blue"
218
+ target="_blank"
219
+ rel="noopener noreferrer"
220
+ class="flex items-center justify-between p-4 bg-white border border-gray-200 rounded-lg hover:border-blue-400 hover:shadow-md transition-all group">
221
+ <div class="text-left">
222
+ <h4 class="font-semibold text-gray-900 group-hover:text-blue-600">polo.blue</h4>
223
+ <p class="text-sm text-gray-600">Polo 6R DIY workshop & guides</p>
224
+ </div>
225
+ <Icon name="lucide:link" class="text-gray-400 group-hover:text-blue-400" />
226
+ </a>
227
+
228
+ <a href="https://sale.polo.blue/"
229
+ target="_blank"
230
+ rel="noopener noreferrer"
231
+ class="flex items-center justify-between p-4 bg-white border border-gray-200 rounded-lg hover:border-blue-400 hover:shadow-md transition-all group">
232
+ <div class="text-left">
233
+ <h4 class="font-semibold text-gray-900 group-hover:text-blue-600">sale.polo.blue</h4>
234
+ <p class="text-sm text-gray-600">Used car parts marketplace</p>
235
+ </div>
236
+ <Icon name="lucide:link" class="text-gray-400 group-hover:text-blue-400" />
237
+ </a>
238
+
239
+ <a href="https://polo6r.pl"
240
+ target="_blank"
241
+ rel="noopener noreferrer"
242
+ class="flex items-center justify-between p-4 bg-white border border-gray-200 rounded-lg hover:border-blue-400 hover:shadow-md transition-all group">
243
+ <div class="text-left">
244
+ <h4 class="font-semibold text-gray-900 group-hover:text-blue-600">polo6r.pl</h4>
245
+ <p class="text-sm text-gray-600">Polo V Manual</p>
246
+ </div>
247
+ <Icon name="lucide:link" class="text-gray-400 group-hover:text-blue-400" />
248
+ </a>
249
+ </div>
250
+
251
+ <p class="text-gray-600 text-sm">
252
+ See the design system in action across different project types
253
+ </p>
254
+ </div>
255
+
256
+ </div>
257
+ </section>
127
258
  </div>
128
259
  <script is:inline></script>
129
260
  </Layout>
@@ -1,31 +1,22 @@
1
1
  import type { CatObject } from "@types/index";
2
2
 
3
- import i18next, { t } from "i18next";
4
3
  import { getApiCategories } from "@utils/api/getCategories";
5
4
  import { getSortedCategories } from "@utils/category/getSortedCategories";
6
5
 
7
6
  // Retrieve main categories:
8
7
  export const getMainCategoryList = async (locale: string = 'en'): Promise<CatObject[]> => {
9
- // Set the selected language
10
- await i18next.changeLanguage(locale);
11
-
12
8
  // Fetch categories from API
13
9
  const categories = await getApiCategories();
14
10
 
15
- // Map categories with translations
16
- const translatedCategories = categories.map((category) => {
17
- const name = t(`cat.${category.slug}.name`);
18
- const desc = i18next.exists(`cat.${category.slug}.desc`)
19
- ? t(`cat.${category.slug}.desc`)
20
- : '';
21
-
22
- if (!desc) {
23
- console.warn('No category description', category.slug, i18next.language);
24
- }
25
-
26
- return { ...category, name, desc };
11
+ // Use category data directly (English only)
12
+ const processedCategories = categories.map((category) => {
13
+ return {
14
+ ...category,
15
+ name: category.name || category.slug,
16
+ desc: category.desc || ''
17
+ };
27
18
  });
28
19
 
29
20
  // Sort and return processed categories
30
- return translatedCategories.sort(getSortedCategories);
21
+ return processedCategories.sort(getSortedCategories);
31
22
  };
@@ -1,15 +1,12 @@
1
- import i18next from "i18next";
2
-
3
1
  export const getPriceFormatted = (product: any) => {
4
- if (i18next.language === 'en') {
5
- return new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(product.price_eur, )
6
- }
7
- if (i18next.language === 'pl') {
8
- return new Intl.NumberFormat('pl-PL', { style: 'currency', currency: 'PLN' }).format(product.price_pln, )
2
+ // Default to EUR formatting for English-only design system
3
+ if (product.price_eur) {
4
+ return new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(product.price_eur)
9
5
  }
10
- else {
11
- return 'no price'
6
+ if (product.price_pln) {
7
+ return new Intl.NumberFormat('pl-PL', { style: 'currency', currency: 'PLN' }).format(product.price_pln)
12
8
  }
9
+ return 'no price'
13
10
  }
14
11
 
15
12