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
@@ -10,11 +10,9 @@ const props = defineProps({
10
10
  });
11
11
  </script>
12
12
  <template>
13
- <strong
14
- class="product-model"
15
- :data-pagefind-filter="`model:${props.carModel.name}`"
16
- >{{ props.carModel.name }}</strong
17
- >
13
+ <strong class="product-model" :data-pagefind-filter="`model:${props.carModel.name}`">
14
+ {{ props.carModel.name }}
15
+ </strong>
18
16
  </template>
19
17
  <style>
20
18
  .product-model:not(:last-child) {
@@ -11,16 +11,8 @@ const props = defineProps({
11
11
  </script>
12
12
 
13
13
  <template>
14
- <div
15
- inline-flex
16
- flex-wrap
17
- max-w-max
18
- >
19
- <span
20
- v-for="(modelId, index) in props.modelIds"
21
- :key="index"
22
- class="product-model block"
23
- >
14
+ <div inline-flex flex-wrap max-w-max>
15
+ <span v-for="(modelId, index) in props.modelIds" :key="index" class="product-model block">
24
16
  <ProductModel :id="modelId" />
25
17
  </span>
26
18
  </div>
@@ -15,9 +15,7 @@ const {
15
15
  const { formattedNumbers: formatted } = useFormatProductNumber(productNumber);
16
16
 
17
17
  // Define classes dynamically
18
- const classNames = ['product-number', big ? 'text-4.5' : 'number-big', customClass]
19
- .filter(Boolean)
20
- .join(' ');
18
+ const classNames = ['product-number', big ? 'text-4.5' : 'number-big', customClass].filter(Boolean).join(' ');
21
19
 
22
20
  const trackingClass = small ? 'tracking-wide' : 'tracking-tight';
23
21
 
@@ -29,37 +27,19 @@ const FormattedWrapper = isPdp ? 'h3' : 'div';
29
27
  {
30
28
  productNumber && formatted && (
31
29
  <div class={classNames}>
32
- <div
33
- class={['p-number', small ? 'w-full' : ''].join(' ')}
34
- itemprop="identifier"
35
- >
36
- <ProductWrapper
37
- id={productNumber}
38
- class="product-code"
39
- >
30
+ <div class={['p-number', small ? 'w-full' : ''].join(' ')} itemprop="identifier">
31
+ <ProductWrapper id={productNumber} class="product-code">
40
32
  {productNumber}
41
33
  </ProductWrapper>
42
34
 
43
- {big && (
44
- <ButtonCopy
45
- productNumber={productNumber}
46
- texts={buttonTexts}
47
- tooltipClasses=""
48
- />
49
- )}
35
+ {big && <ButtonCopy productNumber={productNumber} texts={buttonTexts} tooltipClasses="" />}
50
36
  </div>
51
37
 
52
38
  <div class={['code-formatted', trackingClass].join(' ')}>
53
- <div
54
- class="relative inset-0"
55
- data-pagefind-ignore
56
- >
39
+ <div class="relative inset-0" data-pagefind-ignore>
57
40
  {formatted.dot}
58
41
  </div>
59
- <div
60
- class="absolute inset-0"
61
- data-pagefind-ignore
62
- >
42
+ <div class="absolute inset-0" data-pagefind-ignore>
63
43
  {formatted.dash}
64
44
  </div>
65
45
  <FormattedWrapper class="number-secondary">{formatted.standard}</FormattedWrapper>
@@ -16,11 +16,7 @@ const props = defineProps({
16
16
  </script>
17
17
 
18
18
  <template>
19
- <span
20
- v-for="position in props.positions"
21
- :key="position.sort"
22
- class="product-position"
23
- >
19
+ <span v-for="position in props.positions" :key="position.sort" class="product-position">
24
20
  {{ position.name }}
25
21
  </span>
26
22
  </template>
@@ -10,7 +10,7 @@ interface PrCodeObject {
10
10
  variant_category?: string;
11
11
  }
12
12
 
13
- const props = defineProps({
13
+ defineProps({
14
14
  prcodes: {
15
15
  type: Array as PropType<PrCodeObject[]>,
16
16
  default: () => [],
@@ -33,11 +33,11 @@ const variantCategoryMap: Record<string, string> = {
33
33
  '0NH': 'GTI',
34
34
  '1ZR': 'GTI',
35
35
  // WRC
36
- 'E5M': 'WRC',
36
+ E5M: 'WRC',
37
37
  '1KD': 'WRC',
38
38
  '1ZP': 'WRC',
39
39
  '2JQ': 'WRC',
40
- 'TA2': 'WRC',
40
+ TA2: 'WRC',
41
41
  // CROSS
42
42
  '2JK': 'CROSS',
43
43
  // BLUEGT
@@ -56,17 +56,9 @@ const getVariantCategory = (code: string, fallback?: string): string | undefined
56
56
  </script>
57
57
 
58
58
  <template>
59
- <span
60
- v-for="(prcode, index) in prcodes"
61
- :key="prcode?.id || index"
62
- class="not-last:mr-1"
63
- >
59
+ <span v-for="(prcode, index) in prcodes" :key="prcode?.id || index" class="not-last:mr-1">
64
60
  <template v-if="prcode?.code">
65
- <PrCode
66
- v-if="!prcode.code.includes('+')"
67
- :prcode="prcode"
68
- :isPdp="isPdp"
69
- />
61
+ <PrCode v-if="!prcode.code.includes('+')" :prcode="prcode" :isPdp="isPdp" />
70
62
  <span v-else class="inline-flex items-center gap-1">
71
63
  <template v-for="(code, idx) in prcode.code.split('+')" :key="idx">
72
64
  <span v-if="idx > 0" class="text-sm opacity-75">+</span>
@@ -75,7 +67,7 @@ const getVariantCategory = (code: string, fallback?: string): string | undefined
75
67
  code: code.trim(),
76
68
  group: prcode.group,
77
69
  description: null,
78
- variant_category: getVariantCategory(code.trim(), prcode.variant_category)
70
+ variant_category: getVariantCategory(code.trim(), prcode.variant_category),
79
71
  }"
80
72
  :isPdp="isPdp"
81
73
  />
@@ -3,9 +3,7 @@ import { PropType } from 'vue';
3
3
 
4
4
  const props = defineProps({
5
5
  as: {
6
- type: String as PropType<
7
- 'th' | 'td' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' | 'div' | 'span'
8
- >,
6
+ type: String as PropType<'th' | 'td' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' | 'div' | 'span'>,
9
7
  default: 'div',
10
8
  required: true,
11
9
  },
@@ -23,10 +21,7 @@ const props = defineProps({
23
21
  </script>
24
22
 
25
23
  <template>
26
- <component
27
- :is="props.as"
28
- class="font-bold detail-name w-full sm:w-50 flex 2xl:w-64"
29
- >
24
+ <component :is="props.as" class="font-bold detail-name w-full sm:w-50 flex 2xl:w-64">
30
25
  <span :class="styles && styles.length ? styles : 'mt-auto'">
31
26
  <b class="bg-white z-1 colon-after pr-1">{{ props.text }}</b>
32
27
  </span>
@@ -84,22 +84,11 @@ const validatedItems = computed(() => {
84
84
  <col class="details-table-col" />
85
85
  </colgroup>
86
86
  <tbody>
87
- <tr
88
- v-for="(row, index) in validatedItems"
89
- :key="index"
90
- class="details-table-row"
91
- >
92
- <ProductDetailName
93
- as="th"
94
- :text="getHeaderText(row)"
95
- class="details-table-header"
96
- />
87
+ <tr v-for="(row, index) in validatedItems" :key="index" class="details-table-row">
88
+ <ProductDetailName as="th" :text="getHeaderText(row)" class="details-table-header" />
97
89
 
98
90
  <!-- Links Array -->
99
- <td
100
- v-if="isLinksArray(row)"
101
- class="details-table-cell"
102
- >
91
+ <td v-if="isLinksArray(row)" class="details-table-cell">
103
92
  <ul class="list-none p-0 m-0">
104
93
  <li
105
94
  v-for="(link, linkIndex) in row.value as Link[]"
@@ -112,12 +101,7 @@ const validatedItems = computed(() => {
112
101
  'leading-none inline-block mr-2 w-4 min-w-4 h-4 text-gray-400',
113
102
  ]"
114
103
  />
115
- <a
116
- :href="link.url"
117
- target="_blank"
118
- rel="noopener noreferrer"
119
- class="link-primary"
120
- >
104
+ <a :href="link.url" target="_blank" rel="noopener noreferrer" class="link-primary">
121
105
  {{ link.anchor }}
122
106
  </a>
123
107
  </li>
@@ -125,10 +109,7 @@ const validatedItems = computed(() => {
125
109
  </td>
126
110
 
127
111
  <!-- Generic String Array -->
128
- <td
129
- v-else-if="isGenericArray(row)"
130
- class="details-table-cell"
131
- >
112
+ <td v-else-if="isGenericArray(row)" class="details-table-cell">
132
113
  <ul class="list-none p-0 m-0">
133
114
  <li
134
115
  v-for="(item, itemIndex) in row.value as string[]"
@@ -142,17 +123,10 @@ const validatedItems = computed(() => {
142
123
  </td>
143
124
 
144
125
  <!-- HTML Value -->
145
- <td
146
- v-else-if="isHtmlValue(row.value)"
147
- class="details-table-cell"
148
- v-html="row.value"
149
- />
126
+ <td v-else-if="isHtmlValue(row.value)" class="details-table-cell" v-html="row.value" />
150
127
 
151
128
  <!-- Slot or Default Value -->
152
- <slot
153
- v-else
154
- :name="row.id"
155
- >
129
+ <slot v-else :name="row.id">
156
130
  <td class="details-table-cell">
157
131
  {{ row.value }}
158
132
  </td>
@@ -19,11 +19,7 @@ import ProductNumber from './Product/ProductNumber.astro';
19
19
  }}
20
20
  />
21
21
  ) : (
22
- <img
23
- src="/1x1.png"
24
- class="bg-gray-100/70"
25
- alt={productObject.name}
26
- />
22
+ <img src="/1x1.png" class="bg-gray-100/70" alt={productObject.name} />
27
23
  )}
28
24
  </div>
29
25
 
@@ -45,14 +41,8 @@ import ProductNumber from './Product/ProductNumber.astro';
45
41
 
46
42
  {index !== null && (
47
43
  <>
48
- <meta
49
- itemprop="position"
50
- content={String(index)}
51
- />
52
- <meta
53
- itemprop="name"
54
- content={productObject.name}
55
- />
44
+ <meta itemprop="position" content={String(index)} />
45
+ <meta itemprop="name" content={productObject.name} />
56
46
  </>
57
47
  )}
58
48
  </div>
@@ -1,9 +1,5 @@
1
1
  <script src="./../pwa.ts"></script>
2
- <div
3
- id="pwa-toast"
4
- role="alert"
5
- aria-labelledby="toast-message"
6
- >
2
+ <div id="pwa-toast" role="alert" aria-labelledby="toast-message">
7
3
  <div class="message">
8
4
  <span id="toast-message"></span>
9
5
  </div>
@@ -1,11 +1,13 @@
1
1
  <script lang="ts" setup>
2
+ /* global localStorage */
2
3
  import { ref, onMounted } from 'vue';
3
4
 
4
5
  const props = defineProps({
5
6
  // Primary state (visible by default)
6
7
  message: {
7
8
  type: String,
8
- default: 'We stand with our friends and colleagues in Ukraine. To support Ukraine in their time of need visit',
9
+ default:
10
+ 'We stand with our friends and colleagues in Ukraine. To support Ukraine in their time of need visit',
9
11
  },
10
12
  linkText: {
11
13
  type: String,
@@ -51,7 +53,8 @@ const props = defineProps({
51
53
  },
52
54
  iconClass: {
53
55
  type: String,
54
- default: 'inline-block text-4xl w-6 h-3.5 min-w-[1.25rem] mr-3 bg-gradient-to-b stops-[#0057b7_50%,50%,#ffd700_100%]',
56
+ default:
57
+ 'inline-block text-4xl w-6 h-3.5 min-w-[1.25rem] mr-3 bg-gradient-to-b stops-[#0057b7_50%,50%,#ffd700_100%]',
55
58
  },
56
59
 
57
60
  // LocalStorage persistence
@@ -90,7 +93,7 @@ onMounted(() => {
90
93
  // Still valid, keep hidden
91
94
  isHidden.value = true;
92
95
  }
93
- } catch (e) {
96
+ } catch {
94
97
  // Invalid data, remove it
95
98
  localStorage.removeItem(props.storageKey);
96
99
  }
@@ -109,9 +112,8 @@ const closePermanently = () => {
109
112
  const data = {
110
113
  closed: true,
111
114
  timestamp: new Date().getTime(),
112
- expires: props.expirationDays > 0
113
- ? new Date().getTime() + (props.expirationDays * 24 * 60 * 60 * 1000)
114
- : null,
115
+ expires:
116
+ props.expirationDays > 0 ? new Date().getTime() + props.expirationDays * 24 * 60 * 60 * 1000 : null,
115
117
  };
116
118
  localStorage.setItem(props.storageKey, JSON.stringify(data));
117
119
  }
@@ -120,16 +122,9 @@ const closePermanently = () => {
120
122
 
121
123
  <template>
122
124
  <template v-if="!isHidden">
123
- <div
124
- v-if="isShow"
125
- data-pagefind-ignore
126
- class="slimbanner"
127
- >
125
+ <div v-if="isShow" data-pagefind-ignore class="slimbanner">
128
126
  <slot name="icon">
129
- <span
130
- v-if="props.showIcon"
131
- :class="props.iconClass"
132
- />
127
+ <span v-if="props.showIcon" :class="props.iconClass" />
133
128
  </slot>
134
129
 
135
130
  <span class="leading-none inline-flex">
@@ -14,26 +14,14 @@ const capitalizeFirstLetter = (text: string) => {
14
14
  <table class="table-auto text-left border bg-white shadow-md">
15
15
  <thead class="bg-gray-500 text-white">
16
16
  <tr class="border">
17
- <th
18
- v-for="(thead, index) in theads"
19
- :key="index"
20
- class="px-4 py-2 font-semibold"
21
- >
17
+ <th v-for="(thead, index) in theads" :key="index" class="px-4 py-2 font-semibold">
22
18
  {{ capitalizeFirstLetter(thead) }}
23
19
  </th>
24
20
  </tr>
25
21
  </thead>
26
22
  <tbody>
27
- <tr
28
- v-for="(row, index) in props.data"
29
- :key="index"
30
- class="border"
31
- >
32
- <td
33
- v-for="key in Object.keys(row)"
34
- :key="key"
35
- class="px-4 py-2"
36
- >
23
+ <tr v-for="(row, index) in props.data" :key="index" class="border">
24
+ <td v-for="key in Object.keys(row)" :key="key" class="px-4 py-2">
37
25
  {{ row[key] }}
38
26
  </td>
39
27
  </tr>
@@ -18,10 +18,7 @@ const props = defineProps({
18
18
  </script>
19
19
 
20
20
  <template>
21
- <div
22
- v-if="props.translations !== null && props.translations.uri"
23
- data-pagefind-ignore
24
- >
21
+ <div v-if="props.translations !== null && props.translations.uri" data-pagefind-ignore>
25
22
  <a
26
23
  aria-label="Change language"
27
24
  type="button"
@@ -24,10 +24,7 @@ const hasDescriptionSlotContent = Astro.slots.has('description');
24
24
  >
25
25
  <div class="flex-shrink-0 hidden md:block">
26
26
  <slot name="icon">
27
- <span
28
- i-ph:sparkle-thin
29
- class="mr-1 text-8 md:text-10 text-brand-secondary"
30
- ></span>
27
+ <span i-ph:sparkle-thin class="mr-1 text-8 md:text-10 text-brand-secondary"></span>
31
28
  </slot>
32
29
  </div>
33
30
  <div class="flex-1 text-center md:text-left">
@@ -39,9 +36,7 @@ const hasDescriptionSlotContent = Astro.slots.has('description');
39
36
  {
40
37
  (propDescription || hasDescriptionSlotContent) && (
41
38
  <p class="text-blue-darker mt-1">
42
- <slot name="description">
43
- {propDescription || 'Domyślny opis, który zachęca do działania.'}
44
- </slot>
39
+ <slot name="description">{propDescription || 'Domyślny opis, który zachęca do działania.'}</slot>
45
40
  </p>
46
41
  )
47
42
  }
@@ -2,8 +2,6 @@
2
2
  const { class: className, isFullWidth } = Astro.props;
3
3
  ---
4
4
 
5
- <div
6
- class:list={[`${isFullWidth ? 'max-w-full' : 'max-w-screen-xl'} mx-auto px-5 py-4`, className]}
7
- >
5
+ <div class:list={[`${isFullWidth ? 'max-w-full' : 'max-w-screen-xl'} mx-auto px-5 py-4`, className]}>
8
6
  <slot />
9
7
  </div>
@@ -30,10 +30,7 @@ const navItemsLeft = [
30
30
  <slot name="logo" />
31
31
 
32
32
  <div class="hidden sm:block sm:ml-6">
33
- <div
34
- class="flex space-x-4"
35
- itemprop="hasPart"
36
- >
33
+ <div class="flex space-x-4" itemprop="hasPart">
37
34
  {
38
35
  navItemsLeft.map(({ title, description, url }) => (
39
36
  <a
@@ -60,14 +57,7 @@ const navItemsLeft = [
60
57
  itemscope
61
58
  itemtype="http://schema.org/SiteNavigationElement"
62
59
  >
63
- <a
64
- class="icon-btn mx-2"
65
- title=""
66
- aria-label=""
67
- href="#"
68
- itemprop="url"
69
- data-astro-reload
70
- >
60
+ <a class="icon-btn mx-2" title="" aria-label="" href="#" itemprop="url" data-astro-reload>
71
61
  <Icon name="carbon:language" />
72
62
  </a>
73
63
  </div>
@@ -9,17 +9,10 @@ const { content = {} } = Astro.props;
9
9
  const canonicalURL = new URL(Astro.url.pathname, Astro.site).toString();
10
10
  ---
11
11
 
12
- <html
13
- dir={content.dir ?? 'ltr'}
14
- lang={content.lang ?? 'en-us'}
15
- class="initial"
16
- >
12
+ <html dir={content.dir ?? 'ltr'} lang={content.lang ?? 'en-us'} class="initial">
17
13
  <head>
18
14
  <HeadCommon />
19
- <HeadSEO
20
- {content}
21
- canonicalURL={canonicalURL}
22
- />
15
+ <HeadSEO {content} canonicalURL={canonicalURL} />
23
16
  <title>
24
17
  {content.title ? `${content.title} 🚀 ${CONFIG.SITE.title}` : CONFIG.SITE.title}
25
18
  </title>
@@ -25,17 +25,10 @@ const canonicalURL = new URL(Astro.url.pathname, Astro.site).toString();
25
25
  import '../scripts/tooltips.ts';
26
26
  </script>
27
27
 
28
- <html
29
- dir={content.dir ?? 'ltr'}
30
- lang={content.lang ?? 'en-us'}
31
- class="initial"
32
- >
28
+ <html dir={content.dir ?? 'ltr'} lang={content.lang ?? 'en-us'} class="initial">
33
29
  <head>
34
30
  <HeadCommon />
35
- <HeadSEO
36
- content={content}
37
- canonicalURL={canonicalURL}
38
- />
31
+ <HeadSEO content={content} canonicalURL={canonicalURL} />
39
32
  <title>
40
33
  {content.title ? `${content.title} 🚀 ${CONFIG.SITE.title}` : CONFIG.SITE.title}
41
34
  </title>
@@ -48,18 +41,12 @@ const canonicalURL = new URL(Astro.url.pathname, Astro.site).toString();
48
41
 
49
42
  <div class="flex bg-white z-10 mb-11 relative">
50
43
  <div class="sticky top-0 flex lg:(h-screen w-64) z-50">
51
- <div
52
- class="mr-auto"
53
- transition:name="sidebar"
54
- >
44
+ <div class="mr-auto" transition:name="sidebar">
55
45
  <LeftSidebar currentPage={currentPage} />
56
46
  </div>
57
47
  </div>
58
48
  <main class="pb-4 px-4 sm:px-8 col-auto sm:(pb-32) overflow-auto w-full">
59
- <PageContent
60
- content={content}
61
- transition:name="content"
62
- >
49
+ <PageContent content={content} transition:name="content">
63
50
  <slot />
64
51
  </PageContent>
65
52
  </main>
@@ -5,26 +5,12 @@ import { pwaInfo } from 'virtual:pwa-info';
5
5
 
6
6
  <!-- Global Metadata -->
7
7
  <meta charset="utf-8" />
8
- <meta
9
- name="viewport"
10
- content="width=device-width"
11
- />
12
-
13
- <link
14
- rel="icon"
15
- type="image/svg+xml"
16
- href="/favicon.svg"
17
- />
18
- <link
19
- rel="alternate icon"
20
- type="image/x-icon"
21
- href="/favicon.ico"
22
- />
23
-
24
- <link
25
- rel="sitemap"
26
- href="/sitemap-index.xml"
27
- />
8
+ <meta name="viewport" content="width=device-width" />
9
+
10
+ <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
11
+ <link rel="alternate icon" type="image/x-icon" href="/favicon.ico" />
12
+
13
+ <link rel="sitemap" href="/sitemap-index.xml" />
28
14
 
29
15
  <!-- Preload Fonts -->
30
16
  <!-- <link rel="preconnect" href="https://fonts.googleapis.com" />
@@ -32,10 +18,7 @@ import { pwaInfo } from 'virtual:pwa-info';
32
18
  <link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital@0;1&display=swap" rel="stylesheet" /> -->
33
19
 
34
20
  <!-- Scrollable a11y code helper -->
35
- <script
36
- src="/make-scrollable-code-focusable.js"
37
- is:inline
38
- ></script>
21
+ <script src="/make-scrollable-code-focusable.js" is:inline></script>
39
22
 
40
23
  <!-- This is intentionally inlined to avoid FOUC -->
41
24
  <script is:inline>
@@ -13,65 +13,29 @@ const imageAlt = content?.image?.alt ?? OPEN_GRAPH.image.alt;
13
13
  ---
14
14
 
15
15
  <!-- Page Metadata -->
16
- <link
17
- rel="canonical"
18
- href={canonicalURL}
19
- />
16
+ <link rel="canonical" href={canonicalURL} />
20
17
 
21
18
  <!-- OpenGraph Tags -->
22
- <meta
23
- property="og:title"
24
- content={formattedContentTitle}
25
- />
26
- <meta
27
- property="og:type"
28
- content="article"
29
- />
30
- <meta
31
- property="og:url"
32
- content={canonicalURL}
33
- />
34
- <meta
35
- property="og:locale"
36
- content={content.ogLocale ?? SITE.defaultLanguage}
37
- />
19
+ <meta property="og:title" content={formattedContentTitle} />
20
+ <meta property="og:type" content="article" />
21
+ <meta property="og:url" content={canonicalURL} />
22
+ <meta property="og:locale" content={content.ogLocale ?? SITE.defaultLanguage} />
38
23
  <!-- <meta property="og:image" content={canonicalImageSrc} /> -->
39
- <meta
40
- property="og:image:alt"
41
- content={imageAlt}
42
- />
24
+ <meta property="og:image:alt" content={imageAlt} />
43
25
  <meta
44
26
  name="description"
45
27
  property="og:description"
46
28
  content={content.description ? content.description : SITE.description}
47
29
  />
48
- <meta
49
- property="og:site_name"
50
- content={SITE.title}
51
- />
30
+ <meta property="og:site_name" content={SITE.title} />
52
31
 
53
32
  <!-- Twitter Tags -->
54
- <meta
55
- name="twitter:card"
56
- content="summary_large_image"
57
- />
58
- <meta
59
- name="twitter:site"
60
- content={OPEN_GRAPH.twitter}
61
- />
62
- <meta
63
- name="twitter:title"
64
- content={formattedContentTitle}
65
- />
66
- <meta
67
- name="twitter:description"
68
- content={content.description ? content.description : SITE.description}
69
- />
33
+ <meta name="twitter:card" content="summary_large_image" />
34
+ <meta name="twitter:site" content={OPEN_GRAPH.twitter} />
35
+ <meta name="twitter:title" content={formattedContentTitle} />
36
+ <meta name="twitter:description" content={content.description ? content.description : SITE.description} />
70
37
  <!-- <meta name="twitter:image" content={canonicalImageSrc} /> -->
71
- <meta
72
- name="twitter:image:alt"
73
- content={imageAlt}
74
- />
38
+ <meta name="twitter:image:alt" content={imageAlt} />
75
39
 
76
40
  <!--
77
41
  TODO: Add json+ld data, maybe https://schema.org/APIReference makes sense?
@@ -57,10 +57,7 @@ const sortedIconCollections = Object.entries(ICONS)
57
57
  >
58
58
  <div class="flex flex-col items-center">
59
59
  <div class="p-4 bg-gray-50 rounded-lg mb-2 w-full flex justify-center items-center min-h-[64px]">
60
- <Icon
61
- name={`${name}:${iconName}`}
62
- class="text-3xl text-blue-medium"
63
- />
60
+ <Icon name={`${name}:${iconName}`} class="text-3xl text-blue-medium" />
64
61
  </div>
65
62
  <code class="text-sm text-gray-600 text-center break-all">
66
63
  {name}:{iconName}