Skip to content

Commit 30c1bee

Browse files
authored
feat(Icons): migrate SDK icons to Phosphor icon set (#3075)
### 🎯 Goal Migrate all SDK icons to the new Phosphor-based icon set from the design system, replacing legacy SVGs with consistent, standardized assets. Use Line (stroke-based) variants for controllable stroke weight. Remove unused icon exports to reduce bundle size. Resolves [REACT-936](https://linear.app/stream/issue/REACT-936/complete-sdk-icon-migration-to-phosphor-icons) ### 🛠 Implementation details **Icon SVG replacements (77 Line + 11 other):** - Switched to **Line variants** (stroke-based, 20×20 viewBox) for 77 icons, giving a consistent `strokeWidth="1.5"` that can be adjusted via attribute rather than being baked into path geometry - `BaseIcon` default viewBox updated from `0 0 16 16` → `0 0 20 20` to match Line icons - 8 legacy icons without Line matches get `{ viewBox: '0 0 16 16' }` override - Stroke-based paths get `fill='none'` to prevent CSS `fill: currentColor` from filling outlines - Fill variants (`play-fill`, `message-bubble-fill`, etc.) strip `fill="black"` to inherit `currentColor` - `IconGiphy` updated separately in its own file (brand colors preserved, hardcoded `viewBox='0 0 16 16'`) **Icon constant renames (55 total):** Key renames: `IconTrashBin→IconDelete`, `IconPaperPlane→IconSend`, `IconCrossMedium→IconXmark`, `IconMicrophone→IconVoice`, `IconBookmark→IconSave`, `IconBubbles→IconMessageBubbles`, `IconBubble2ChatMessage→IconMessageBubble`, `IconBubbleText6ChatMessage→IconThread`, `IconLoadingCircle→IconLoading`, `IconPlaySolid→IconPlayFill`, `IconPause→IconPauseFill` Old names preserved as `// was:` comments for traceability. Icons with name collisions (e.g. multiple checkmark variants mapping to `checkmark`) keep their original const name but receive the updated SVG. **CSS class name updates:** Renamed constants change the auto-derived CSS classes (via `toIconClass`). Updated all SCSS selectors accordingly (e.g. `.str-chat__icon--microphone` → `.str-chat__icon--voice`). **Unchanged icons (7):** Icons used in code but not in the mapping are annotated with `// no new icon mapping`: `IconArrowDown`, `IconArrowRight`, `IconExclamationTriangle`, `IconEyeOpen`, `IconBubbleText6SolidChatMessage`. Plus `IconLayoutAlignLeft` and `IconThunder` which had Line matches and were switched. **Removed unused icons (71):** The following icon exports were removed as they had zero references anywhere in the SDK or examples: `IconApiAggregate`, `IconApples`, `IconArrowsRepeatLeftRight`, `IconAtSolid`, `IconAccount` (was `IconPeopleCircle`), `IconBrowserAISparkle`, `IconBubble3Solid`, `IconBubbleAnnotation2ChatMessage`, `IconBubbleWideSparkleChatMessage`, `IconCalendar1`, `IconCallCancel`, `IconCar1`, `IconCat`, `IconCheckmark2Small`, `IconChevronGrabberVerticalSelector`, `IconChevronTop`, `IconCircleCheck`, `IconCircleQuestionmark`, `IconCircleQuestionmarkFilled`, `IconClockSolid`, `IconCode`, `IconCodeBrackets`, `IconCodeEditorInsert`, `IconCompass`, `IconCreditCard2Billing`, `IconDotsGrid1x3Vertical`, `IconEditBigSolid`, `IconEmojiAdd` (was `IconEmojiAddReaction`), `IconEmojiSad`, `IconExclamationTriangleFill` (was `IconExclamationTriangle1`), `IconExport` (was `IconShareRedirectLink`), `IconFilledCircleInfoTooltip`, `IconFilter1`, `IconGauge`, `IconGoogle`, `IconHashtagChannel`, `IconHeart2`, `IconHistory`, `IconInvite`, `IconLayoutGrid1`, `IconLimits`, `IconLineChart3`, `IconLock`, `IconMention` (was `IconAt`), `IconNewspaper2`, `IconOrganization`, `IconPaperPlaneTopRight`, `IconParagraphsText`, `IconPencil`, `IconPeople2`, `IconPeopleCopy`, `IconPeopleEditUserRights`, `IconPersona`, `IconPresentation` (was `IconLayersBehind`), `IconSearchText`, `IconSettingsSliderVer`, `IconShapesPlusCloseSquareCircle`, `IconShapesTriangleSquareCircle`, `IconShield`, `IconSpreadsheet` (was `IconTable`), `IconSquareCircleTopRightFeeds`, `IconStopFill` (was `IconStop`), `IconTeam`, `IconTennis`, `IconTextToImageURLEnrichment`, `IconTrending4`, `IconUnlock` (was `IconUnlocked`), `IconUsers`, `IconVoiceAndVideo`, `IconVoiceHigh`, `IconWebhook` This reduces `icons.tsx` from 130 to 59 exports. ### 🎨 UI Changes All icon visuals change from the legacy set to Phosphor Line icons with 1.5px stroke weight. `BaseIcon` default viewBox is now `0 0 20 20`. No layout or sizing changes — icons still use `1em` sizing via CSS and `currentColor` for theming.
1 parent becee7b commit 30c1bee

File tree

76 files changed

+1334
-1231
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+1334
-1231
lines changed

examples/vite/src/AppSettings/ActionsMenu/NotificationPromptDialog.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ import {
88
IconArrowRight,
99
Button,
1010
DialogAnchor,
11-
IconArrowRotateRightLeftRepeatRefresh,
11+
IconRefresh,
1212
IconArrowUp,
13-
IconCheckmark2,
14-
IconCircleInfoTooltip,
13+
IconCheckmark,
14+
IconInfo,
1515
IconClock,
16-
IconCrossMedium,
17-
IconExclamationCircle,
16+
IconXmark,
17+
IconExclamationMark,
1818
IconExclamationTriangle,
1919
IconPlusSmall,
2020
NumericInput,
@@ -50,10 +50,10 @@ const clamp = (value: number, min: number, max: number) => {
5050
const severityIcons: Partial<
5151
Record<NotificationSeverity, React.ComponentType<{ className?: string }>>
5252
> = {
53-
error: IconExclamationCircle,
54-
info: IconCircleInfoTooltip,
55-
loading: IconArrowRotateRightLeftRepeatRefresh,
56-
success: IconCheckmark2,
53+
error: IconExclamationMark,
54+
info: IconInfo,
55+
loading: IconRefresh,
56+
success: IconCheckmark,
5757
warning: IconExclamationTriangle,
5858
};
5959

@@ -148,7 +148,7 @@ const NotificationChipList = ({
148148
size='xs'
149149
variant='secondary'
150150
>
151-
<IconCrossMedium />
151+
<IconXmark />
152152
</Button>
153153
</div>
154154
);

examples/vite/src/AppSettings/AppSettings.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import {
33
ChatViewSelectorButton,
44
GlobalModal,
55
IconBubble3ChatMessage,
6-
IconBellNotification,
7-
IconEmojiSmile,
6+
IconBell,
7+
IconEmoji,
88
IconLightBulbSimple,
99
IconSettingsGear2,
1010
} from 'stream-chat-react';
@@ -18,9 +18,9 @@ import { appSettingsStore, useAppSettingsState } from './state';
1818
type TabId = 'notifications' | 'reactions' | 'sidebar';
1919

2020
const tabConfig: { Icon: ComponentType; id: TabId; title: string }[] = [
21-
{ Icon: IconBellNotification, id: 'notifications', title: 'Notifications' },
21+
{ Icon: IconBell, id: 'notifications', title: 'Notifications' },
2222
{ Icon: IconBubble3ChatMessage, id: 'sidebar', title: 'Sidebar' },
23-
{ Icon: IconEmojiSmile, id: 'reactions', title: 'Reactions' },
23+
{ Icon: IconEmoji, id: 'reactions', title: 'Reactions' },
2424
];
2525

2626
const SidebarThemeToggle = ({ iconOnly = true }: { iconOnly?: boolean }) => {

src/components/Attachment/Geolocation.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import React from 'react';
55
import type { Coords, SharedLocationResponse } from 'stream-chat';
66
import { useChatContext, useTranslationContext } from '../../context';
77
import { ExternalLinkIcon } from './icons';
8-
import { IconMapPin } from '../Icons';
8+
import { IconLocation } from '../Icons';
99
import { Button } from '../Button';
1010

1111
export type GeolocationMapProps = Coords;
@@ -105,7 +105,7 @@ const DefaultGeolocationAttachmentMapPlaceholder = ({
105105
className='str-chat__message-attachment-geolocation__placeholder'
106106
data-testid='geolocation-attachment-map-placeholder'
107107
>
108-
<IconMapPin />
108+
<IconLocation />
109109
<a
110110
className='str-chat__message-attachment-geolocation__placeholder-link'
111111
href={`https://maps.google.com?q=${[location.latitude, location.longitude].join()}`}

src/components/Attachment/LinkPreview/Card.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { useChannelStateContext } from '../../../context/ChannelStateContext';
66
import type { Attachment } from 'stream-chat';
77
import type { RenderAttachmentProps } from '../utils';
88
import type { Dimensions } from '../../../types/types';
9-
import { IconChainLink } from '../../Icons';
9+
import { IconLink } from '../../Icons';
1010
import { UnableToRenderCard } from './UnableToRenderCard';
1111
import clsx from 'clsx';
1212

@@ -74,7 +74,7 @@ const CardContent = (props: CardContentProps) => {
7474
className='str-chat__message-attachment-card--source-link'
7575
data-testid='card-source-link'
7676
>
77-
<IconChainLink />
77+
<IconLink />
7878
<div className='str-chat__message-attachment-card--url'>{url}</div>
7979
</div>
8080
)}

src/components/Attachment/LinkPreview/CardAudio.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { useStateStore } from '../../../store';
44
import { PlayButton } from '../../Button';
55
import type { AudioProps } from '../Audio';
66
import React from 'react';
7-
import { IconChainLink } from '../../Icons';
7+
import { IconLink } from '../../Icons';
88
import { SafeAnchor } from '../../SafeAnchor';
99
import type { CardProps } from './Card';
1010

@@ -26,7 +26,7 @@ const SourceLink = ({
2626
className='str-chat__message-attachment-card--source-link'
2727
data-testid='card-source-link'
2828
>
29-
<IconChainLink />
29+
<IconLink />
3030
<SafeAnchor
3131
className='str-chat__message-attachment-card--url'
3232
href={url}

src/components/Attachment/ModalGallery.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { Gallery as DefaultGallery, GalleryUI } from '../Gallery';
88
import { LoadingIndicator } from '../Loading';
99
import { GlobalModal } from '../Modal';
1010
import { useComponentContext, useTranslationContext } from '../../context';
11-
import { IconArrowRotateClockwise } from '../Icons';
11+
import { IconRetry } from '../Icons';
1212
import { VideoThumbnail } from '../VideoPlayer/VideoThumbnail';
1313

1414
const MAX_VISIBLE_THUMBNAILS = 4;
@@ -216,7 +216,7 @@ const ThumbnailButton = ({
216216
data-testid='str-chat__modal-gallery__image-load-failed-overlay'
217217
>
218218
<div className='str-chat__modal-gallery__image-retry-indicator'>
219-
<IconArrowRotateClockwise />
219+
<IconRetry />
220220
</div>
221221
</div>
222222
)}

0 commit comments

Comments
 (0)