Skip to content

Commit f1aff60

Browse files
committed
update icons and types
1 parent 45e1b85 commit f1aff60

File tree

5 files changed

+95
-93
lines changed

5 files changed

+95
-93
lines changed

blocks/case-studies/card/case-studies-card.tsx

Lines changed: 38 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,9 @@
1-
// TypeScript React
21
import React from 'react';
32
import cn from 'classnames';
43
import styles from './case-studies-card.module.css';
4+
import { AndroidIcon, AppleIcon, ServerIcon, ComputerIcon, GlobusIcon } from '@rescui/icons';
5+
import { CaseStudyItem, CaseStudyType, isExternalCaseStudy, Platform } from '../case-studies';
56

6-
type Platform =
7-
| 'android'
8-
| 'ios'
9-
| 'desktop'
10-
| 'frontend'
11-
| 'backend'
12-
| 'compose-multi-platform';
13-
14-
type CaseType = 'multiplatform' | 'server-side';
15-
16-
type Media =
17-
| { type: 'youtube'; url: string }
18-
| { type: 'image'; path: string };
19-
20-
interface Signature {
21-
// markdown allowed (e.g., **Name Surname**, Role)
22-
line1: string;
23-
// plain text
24-
line2: string;
25-
}
26-
27-
export interface CaseCardItem {
28-
logos?: [string] | [string, string]; // 0–2 logos, local paths or filenames
29-
description: string; // markdown-enabled text
30-
signature?: Signature;
31-
readMoreUrl?: string; // "Read the full story →"
32-
exploreUrl?: string; // "Explore the stories"
33-
type: CaseType;
34-
platforms?: Platform[]; // platform icons row
35-
media?: Media; // youtube or local image
36-
/** Optional: mark case as selected for the home page */
37-
featuredOnHome?: boolean;
38-
}
397

408
/**
419
* Resolve asset path from YAML:
@@ -44,8 +12,6 @@ export interface CaseCardItem {
4412
*/
4513
const resolveAssetPath = (v?: string) => {
4614
if (!v) return '';
47-
const lower = v.toLowerCase();
48-
if (lower.startsWith('http://') || lower.startsWith('https://') || v.startsWith('/')) return v;
4915
return `/images/case-studies/${v}`;
5016
};
5117

@@ -72,27 +38,46 @@ const mdToHtml = (md: string) => {
7238
return withLinks;
7339
};
7440

75-
const badgeText: Record<CaseType, string> = {
41+
const badgeText: Record<CaseStudyType, string> = {
7642
'multiplatform': 'Kotlin Multiplatform',
77-
'server-side': 'Server-side',
43+
'server-side': 'Server-side'
7844
};
7945

80-
const badgeClass: Record<CaseType, string> = {
46+
const badgeClass: Record<CaseStudyType, string> = {
8147
'multiplatform': 'badgeMultiplatform',
82-
'server-side': 'badgeServerSide',
48+
'server-side': 'badgeServerSide'
8349
};
8450

8551
// Platform icon path builder. If you keep icons in (for example) /images/platforms/*.svg,
8652
// they’ll be resolved automatically by key. If an icon is missing, we still render the label.
87-
const platformIconPath = (p: Platform) => `/images/platforms/${p}.svg`;
53+
const getPlatformIcon = (p: Platform) => {
54+
switch (p) {
55+
case 'android':
56+
return <AndroidIcon/>;
57+
case 'ios':
58+
return <AppleIcon/>;
59+
case 'desktop':
60+
return <ComputerIcon/>;
61+
case 'frontend':
62+
return <GlobusIcon/>;
63+
case 'backend':
64+
return <ServerIcon/>;
65+
case 'compose-multiplatform':
66+
return <img className={styles.platformIcon} src={'/images/platforms/compose-multiplatform.svg'}
67+
alt="Compose Multiplatform icon"
68+
onError={(e) => hideBrokenIcon(e.currentTarget)} />;
69+
default:
70+
return null;
71+
}
72+
};
8873

8974
type Props = {
90-
item: CaseCardItem;
75+
item: CaseStudyItem;
9176
className?: string;
9277
};
9378

9479
export const CaseStudyCard: React.FC<Props> = ({ item, className }) => {
95-
const logos = item.logos ?? [];
80+
const logos = item.logo ?? [];
9681
const logoSrc1 = resolveAssetPath(logos[0]);
9782
const logoSrc2 = resolveAssetPath(logos[1]);
9883

@@ -142,13 +127,11 @@ export const CaseStudyCard: React.FC<Props> = ({ item, className }) => {
142127
</div>
143128
)}
144129

145-
{/* Description (markdown) */}
146130
<div
147131
className={styles.description}
148132
dangerouslySetInnerHTML={{ __html: mdToHtml(item.description) }}
149133
/>
150134

151-
{/* Signature (optional) */}
152135
{item.signature && (
153136
<div className={styles.signature}>
154137
<div
@@ -163,43 +146,33 @@ export const CaseStudyCard: React.FC<Props> = ({ item, className }) => {
163146
{item.platforms && item.platforms.length > 0 && (
164147
<div className={styles.platforms} aria-label="Platforms">
165148
{item.platforms.map((p) => {
166-
const iconSrc = platformIconPath(p);
149+
const iconSrc = getPlatformIcon(p);
167150
// We render icon + label; if icon path 404s, the label remains visible
168151
return (
169152
<span key={p} className={styles.platform}>
170-
<img className={styles.platformIcon} src={iconSrc} alt={`${p} icon`} onError={(e) => hideBrokenIcon(e.currentTarget)} />
153+
<>
154+
{getPlatformIcon(p)}
155+
</>
171156
<span className={styles.platformLabel}>{humanizePlatform(p)}</span>
172157
</span>
173158
);
174159
})}
175160
</div>
176161
)}
177-
178-
{/* Actions */}
179-
{(item.readMoreUrl || item.exploreUrl) && (
162+
{(isExternalCaseStudy(item)) ? (
180163
<div className={styles.actions}>
181-
{item.readMoreUrl && (
182-
<a
183-
className={styles.link}
184-
href={item.readMoreUrl}
185-
target="_blank"
186-
rel="noopener noreferrer"
187-
>
188-
Read the full story →
189-
</a>
190-
)}
191-
{item.exploreUrl && (
164+
{item.externalLink && (
192165
<a
193166
className={styles.button}
194-
href={item.exploreUrl}
167+
href={item.externalLink}
195168
target="_blank"
196169
rel="noopener noreferrer"
197170
>
198-
Explore the stories
171+
{item.externalLinkText || 'Read the full story'}
199172
</a>
200173
)}
201174
</div>
202-
)}
175+
) : null}
203176
</article>
204177
);
205178
};
@@ -247,7 +220,7 @@ function hideBrokenIcon(img: HTMLImageElement) {
247220
*/
248221
function humanizePlatform(p: Platform): string {
249222
switch (p) {
250-
case 'compose-multi-platform':
223+
case 'compose-multiplatform':
251224
return 'Compose Multiplatform';
252225
case 'frontend':
253226
return 'Frontend';
Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,62 @@
1+
export type CaseStudyType = 'multiplatform' | 'server-side';
2+
3+
type CaseStudyDestination = 'internal' | 'external';
4+
15
export type Platform =
26
| 'android'
37
| 'ios'
48
| 'desktop'
59
| 'frontend'
610
| 'backend'
7-
| 'compose-multi-platform';
8-
9-
type CaseType = 'multiplatform' | 'server-side';
10-
11-
type Media =
12-
| { type: 'youtube'; url: string }
13-
| { type: 'image'; path: string };
11+
| 'compose-multiplatform';
1412

15-
interface Signature {
16-
// line1 — markdown (e.g., **Name Surname**, Role)
13+
type Signature = {
1714
line1: string;
18-
// line2 — plain text
1915
line2: string;
2016
}
2117

22-
interface CaseCardItem {
23-
// 0–2 logos: single or pair (for KMP + Compose special card)
24-
logos?: [string] | [string, string];
25-
// markdown-enabled description
18+
type YoutubeMedia = {
19+
type: 'youtube';
20+
url: string;
21+
};
22+
23+
type ImageMedia = {
24+
type: 'image';
25+
path: string;
26+
};
27+
28+
type Media = YoutubeMedia | ImageMedia;
29+
30+
interface CaseStudyItemBase {
31+
id: string;
32+
type: CaseStudyType;
2633
description: string;
34+
destination: CaseStudyDestination;
35+
logo?: string[];
2736
signature?: Signature;
28-
// "Read the full story →"
29-
readMoreUrl?: string;
30-
// "Explore the stories"
31-
exploreUrl?: string;
32-
caseType: CaseType;
3337
platforms?: Platform[];
3438
media?: Media;
35-
/** Optional: selected for the home page */
36-
featuredOnHome?: boolean;
39+
featuredOnMainPage?: boolean;
40+
slug?: string;
41+
externalLinkText?: string;
42+
}
43+
44+
export interface ExternalDestinationCaseStudyItem extends CaseStudyItemBase {
45+
destination: 'external';
46+
// required when destination === 'external'
47+
externalLink: string;
48+
}
49+
50+
export interface InternalDestinationCaseStudyItem extends CaseStudyItemBase {
51+
destination: 'internal';
52+
// required when destination === 'internal'
53+
pageContentPath: string;
54+
}
55+
56+
export type CaseStudyItem =
57+
| ExternalDestinationCaseStudyItem
58+
| InternalDestinationCaseStudyItem;
59+
60+
export function isExternalCaseStudy(item: CaseStudyItem): item is ExternalDestinationCaseStudyItem {
61+
return item.destination === 'external';
3762
}

blocks/case-studies/filter/case-studies-filter.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,9 @@ export const CaseStudiesFilter: React.FC = () => {
7878
onChange={() => toggleCodeShared(opt.id)}
7979
mode="classic"
8080
size="m"
81-
/>
81+
>
82+
{opt.label}
83+
</Checkbox>
8284
);
8385
})}
8486
</div>
@@ -98,7 +100,9 @@ export const CaseStudiesFilter: React.FC = () => {
98100
onChange={() => toggleUiTech(opt.id)}
99101
mode="classic"
100102
size="m"
101-
/>
103+
>
104+
{opt.label}
105+
</Checkbox>
102106
);
103107
})}
104108
</div>

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"@rescui/colors": "^0.1.6",
1919
"@rescui/dropdown-menu": "^0.6.1",
2020
"@rescui/focus-manager": "^0.1.4",
21-
"@rescui/icons": "^0.16.13",
21+
"@rescui/icons": "^1.5.0",
2222
"@rescui/input": "^0.8.2",
2323
"@rescui/menu": "0.9.4",
2424
"@rescui/switcher": "^0.5.1",

yarn.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1840,10 +1840,10 @@
18401840
classnames "^2.2.6"
18411841
core-js "^3.9.1"
18421842

1843-
"@rescui/icons@^0.16.13":
1844-
version "0.16.13"
1845-
resolved "https://registry.yarnpkg.com/@rescui/icons/-/icons-0.16.13.tgz#e1a64bd98d83bd8815035a3aa56ec67ecaead95e"
1846-
integrity sha512-ik1ZE0QNFM6Kfk8hs3GSmHMvcLLTu/Pxzi5aAy4Z5uIrnKxqXf5k3AlbKZVWS/pneeKLSWhheztcjUVtjidv+g==
1843+
"@rescui/icons@^1.5.0":
1844+
version "1.6.0"
1845+
resolved "https://registry.yarnpkg.com/@rescui/icons/-/icons-1.6.0.tgz#3bf7fbda19e0690e70cb254c583bf958a4af78f2"
1846+
integrity sha512-O5+ElCJ4I0tx1wSy6M7IdOuTvIjJLWL/3wNJ0LANu2jfi95cVhbMrxfvZewhOimS6/QgZXqJ7aPn2iCgagrySQ==
18471847
dependencies:
18481848
"@babel/runtime-corejs3" "^7.26.0"
18491849
classnames "^2.2.6"

0 commit comments

Comments
 (0)