Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 166 additions & 2 deletions src/components/TopicTypeIcon.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
<template>
<div
class="TopicTypeIcon"
:class="{ 'navigator-icon': true, 'colorful-navigator-icon': shouldUseColorfulIcons && hasSymbolText }"
:style="styles"
:data-color-variant="colorVariant"
:data-symbol-text="symbolText"
>
<OverridableAsset
v-if="imageOverride"
Expand Down Expand Up @@ -110,6 +113,10 @@ export default {
type: Boolean,
default: false,
},
enableColorfulIcons: {
type: Boolean,
default: true,
},
imageOverride: {
type: Object,
default: null,
Expand All @@ -124,6 +131,57 @@ export default {
icon: ({ normalisedType }) => TopicTypeIcons[normalisedType] || CollectionIcon,
iconProps: ({ normalisedType }) => TopicTypeProps[normalisedType] || {},
color: ({ normalisedType }) => HeroColorsMap[normalisedType],
shouldUseColorfulIcons() {
return this.enableColorfulIcons;
},
/**
* Returns the symbol text to display in colorful icon mode.
* Only symbols with explicit text definitions (from TopicTypeProps) are colorized.
* Decorative icons (articles, collections, etc.) remain unchanged.
*/
symbolText() {
if (!this.shouldUseColorfulIcons) return null;

const props = this.iconProps;
if (props.symbol) {
return props.symbol;
}
if (props.first && props.second) {
return props.first + props.second;
}

return '';
},
hasSymbolText() {
return this.symbolText && this.symbolText.length > 0;
},
/**
* Determines the background color variant based on the symbol text.
* Color mapping follows Apple's SF Symbols conventions.
*/
colorVariant() {
if (!this.shouldUseColorfulIcons || !this.hasSymbolText) return null;

const text = this.symbolText.toUpperCase();

// Purple: Structures, Classes, Protocols
if (['S', 'C', 'PR'].includes(text)) return 'purple';

// Blue: Methods
if (text === 'M') return 'blue';

// Mint: Properties
if (text === 'P') return 'mint';

// Orange: Types, Enums
if (['T', 'E'].includes(text)) return 'orange';

// Red: Macros
if (text === '#') return 'red';

// Green: Default
return 'green';
},
styles: ({
color,
withColors,
Expand All @@ -132,14 +190,77 @@ export default {
};
</script>

<style scoped lang='scss'>
<style lang='scss'>
@import 'docc-render/styles/_core.scss';

/**
* Colorful Navigator Icons
*
* Provides colorful, rounded icon badges for symbol types in the navigator.
* Inspired by Xcode's documentation rendering and SF Symbols design language.
*
* Features:
* - System font fallback for SF Pro Rounded
* - Color variants based on symbol type (purple, blue, mint, orange, red, green)
* - Automatic light/dark mode color adjustment
* - Only applied to symbols with text (classes, structs, methods, etc.)
* - Decorative icons (articles, collections) remain unchanged
*/

// System font with SF Pro Rounded fallback
@font-face {
font-family: 'SF Pro Rounded';
src: local('SF Pro Rounded'), local('SF Pro Display');
font-weight: bold;
font-style: normal;
}

// Color palette for colorful icons
:root {
// Light mode colors
--systemOrange-light: #ff9500;
--systemPurple-light: #cc54da;
--systemBlue-light: #0f7dfa;
--systemMint-light: #00c1d9;
--systemRed-light: #ec4425;
--systemGreen-light: #34c759;

// Dark mode colors
--systemOrange-dark: #ff9f0a;
--systemPurple-dark: #bf5af2;
--systemBlue-dark: #0a84ff;
--systemMint-dark: #27c7d6;
--systemRed-dark: #ff453a;
--systemGreen-dark: #30d158;

// Active colors (default to light mode)
--systemOrange: var(--systemOrange-light);
--systemPurple: var(--systemPurple-light);
--systemBlue: var(--systemBlue-light);
--systemMint: var(--systemMint-light);
--systemRed: var(--systemRed-light);
--systemGreen: var(--systemGreen-light);
}

// Switch to dark mode colors
@media (prefers-color-scheme: dark) {
:root {
--systemOrange: var(--systemOrange-dark);
--systemPurple: var(--systemPurple-dark);
--systemBlue: var(--systemBlue-dark);
--systemMint: var(--systemMint-dark);
--systemRed: var(--systemRed-dark);
--systemGreen: var(--systemGreen-dark);
}
}
</style>

<style scoped lang='scss'>

.TopicTypeIcon {
width: 1em;
height: 1em;
flex: 0 0 auto;
// use the `--icon-color` if `withColors` is true, otherwise just use gray.
color: var(--icon-color, var(--color-figure-gray-secondary));

:deep(picture) {
Expand All @@ -151,5 +272,48 @@ export default {
width: 100%;
height: 100%;
}

/**
* Colorful icon badge styling
* Applied only to symbols with text (classes, structs, methods, etc.)
*/
&.colorful-navigator-icon {
width: 18px;
min-width: 18px;
height: 18px;
padding: 2px 4px;
border-radius: 4px;
background-color: var(--systemGreen);

display: inline-flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
vertical-align: middle;

font-family: 'SF Pro Rounded', 'SF Pro Display', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
font-weight: 700;
font-size: 12px;
line-height: 1;
color: white;

// Hide the original SVG icon
svg {
display: none;
}

// Display symbol text via pseudo-element
&::after {
content: attr(data-symbol-text);
}

// Color variants based on symbol type
&[data-color-variant="purple"] { background-color: var(--systemPurple); }
&[data-color-variant="blue"] { background-color: var(--systemBlue); }
&[data-color-variant="mint"] { background-color: var(--systemMint); }
&[data-color-variant="orange"] { background-color: var(--systemOrange); }
&[data-color-variant="red"] { background-color: var(--systemRed); }
&[data-color-variant="green"] { background-color: var(--systemGreen); }
}
}
</style>