Skip to content

Commit 9682e3d

Browse files
authored
feat: social links (#149)
* feat: more socialLinks * feat: hidden social links component * feat: social links text mode * feat: social links img mode * feat: separate social component * feat: social links usage * fix: social links gap
1 parent 729a693 commit 9682e3d

File tree

13 files changed

+528
-92
lines changed

13 files changed

+528
-92
lines changed

docs/.island/config.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,13 @@ export default defineConfig({
6767
socialLinks: [
6868
{
6969
icon: 'github',
70-
link: 'https://github.com/sanyuan0704/island'
70+
mode: 'link',
71+
content: 'https://github.com/sanyuan0704/island'
72+
},
73+
{
74+
icon: 'discord',
75+
mode: 'link',
76+
content: 'https://discord.gg/Nvy4YSerjM'
7177
}
7278
],
7379

docs/en/guide/navbar.md

+60-2
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,9 @@ export default defineConfig({
102102

103103
## Social Links
104104

105-
You can add social links to the navbar:
105+
You can add social links to the navbar, such as `github`link, `twitter` link and so on.
106+
107+
Social links support three modes: `link mode` `text mode` `img mode`, for example:
106108

107109
```js
108110
import { defineConfig } from 'islandjs';
@@ -112,13 +114,69 @@ export default defineConfig({
112114
socialLinks: [
113115
{
114116
icon: 'github',
115-
link: 'https://github.com/sanyuan0704/island.js'
117+
mode: 'link',
118+
content: 'https://github.com/sanyuan0704/island.js'
119+
},
120+
{
121+
icon: 'wechat',
122+
mode: 'text',
123+
content: 'wechat ID xxx'
124+
},
125+
{
126+
icon: 'qq',
127+
mode: 'img',
128+
content: '/qrcode.png'
116129
}
117130
]
118131
}
119132
});
120133
```
121134

135+
- for `link mode`, click the icon will jump to preset link.
136+
- for `text mode`, hover the icon will show a popper, which contain the preset content.
137+
- for `img mode`, hover the icon will show a popper, which contain the preset image. Need to be aware that, the image should put in the `public` folder.
138+
139+
Social links support the following icons:
140+
141+
```ts
142+
export type SocialLinkIcon =
143+
| 'discord'
144+
| 'facebook'
145+
| 'github'
146+
| 'instagram'
147+
| 'linkedin'
148+
| 'slack'
149+
| 'twitter'
150+
| 'youtube'
151+
| 'weixin'
152+
| 'qq'
153+
| 'juejin'
154+
| 'zhihu'
155+
| 'bilibili'
156+
| 'weibo'
157+
| { svg: string };
158+
```
159+
160+
If you want to use other icon, you can pass in an object that have the `svg` key, for example:
161+
162+
```js
163+
import { defineConfig } from 'islandjs';
164+
165+
export default defineConfig({
166+
themeConfig: {
167+
socialLinks: [
168+
{
169+
icon: {
170+
svg: 'svg content'
171+
},
172+
mode: 'link',
173+
content: 'https://github.com/sanyuan0704/island.js'
174+
},
175+
]
176+
}
177+
});
178+
```
179+
122180
## Translations
123181

124182
When you set `themeConfig.locales`, the navbar will automatically adds the menu group about translations. See details in [I18n](/en/guide/i18n).

docs/zh/guide/navbar.md

+59-2
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ export default defineConfig({
102102

103103
## 相关链接
104104

105-
你可以通过如下的配置添加相关链接,比如 `github` 链接、`twitter` 链接等:
105+
你可以通过如下的配置添加相关链接,比如 `github` 链接、`twitter` 链接等。
106+
相关链接支持三种模式:`链接模式link` `文本模式text` `图片模式img`,相关例子如下:
106107

107108
```js
108109
import { defineConfig } from 'islandjs';
@@ -112,13 +113,69 @@ export default defineConfig({
112113
socialLinks: [
113114
{
114115
icon: 'github',
115-
link: 'https://github.com/sanyuan0704/island.js'
116+
mode: 'link',
117+
content: 'https://github.com/sanyuan0704/island.js'
118+
},
119+
{
120+
icon: 'wechat',
121+
mode: 'text',
122+
content: '微信号xxx'
123+
},
124+
{
125+
icon: 'qq',
126+
mode: 'img',
127+
content: '/qrcode.png'
116128
}
117129
]
118130
}
119131
});
120132
```
121133

134+
-`link`模式时,点击icon即可跳转链接
135+
-`text`模式时,鼠标移到icon上会显示弹框,弹框内容是输入的文本
136+
-`img`模式时,鼠标移到icon上会显示弹框,弹框内容是指定的图片,需要注意的是,图片需要放在`public`目录下
137+
138+
相关链接支持以下几种图片,通过icon属性来选择:
139+
140+
```ts
141+
export type SocialLinkIcon =
142+
| 'discord'
143+
| 'facebook'
144+
| 'github'
145+
| 'instagram'
146+
| 'linkedin'
147+
| 'slack'
148+
| 'twitter'
149+
| 'youtube'
150+
| 'weixin'
151+
| 'qq'
152+
| 'juejin'
153+
| 'zhihu'
154+
| 'bilibili'
155+
| 'weibo'
156+
| { svg: string };
157+
```
158+
159+
如果需要自定义icon,可以通过传入一个带有`svg属性`的对象,svg的值为自定义图标内容即可,比如:
160+
161+
```js
162+
import { defineConfig } from 'islandjs';
163+
164+
export default defineConfig({
165+
themeConfig: {
166+
socialLinks: [
167+
{
168+
icon: {
169+
svg: 'svg图标内容'
170+
},
171+
mode: 'link',
172+
content: 'https://github.com/sanyuan0704/island.js'
173+
},
174+
]
175+
}
176+
});
177+
```
178+
122179
## 国际化
123180

124181
当你配置了 `themeConfig.locales` 之后,导航栏会自动带上语言切换的菜单,你可以通过查看 [i18n](/zh/guide/i18n) 文档了解更多。

packages/island/src/shared/types/default-theme.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,8 @@ export namespace DefaultTheme {
186186

187187
export interface SocialLink {
188188
icon: SocialLinkIcon;
189-
link: string;
189+
mode: 'link' | 'text' | 'img';
190+
content: string;
190191
}
191192

192193
export type SocialLinkIcon =
@@ -198,6 +199,12 @@ export namespace DefaultTheme {
198199
| 'slack'
199200
| 'twitter'
200201
| 'youtube'
202+
| 'weixin'
203+
| 'qq'
204+
| 'juejin'
205+
| 'zhihu'
206+
| 'bilibili'
207+
| 'weibo'
201208
| { svg: string };
202209

203210
// footer --------------------------------------------------------------------

packages/island/src/theme-default/components/Nav/index.module.scss

+12
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,15 @@
6262
.container :deep(*) {
6363
pointer-events: all;
6464
}
65+
66+
.social-links-icon {
67+
width: 20px;
68+
height: 100%;
69+
display: flex;
70+
fill: currentColor;
71+
color: var(--island-c-text-2);
72+
73+
&:hover {
74+
color: var(--island-c-text-1);
75+
}
76+
}

packages/island/src/theme-default/components/Nav/index.tsx

+2-46
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,16 @@ import { Search } from '@search-box';
55
import { usePageData } from '@client';
66
import { NavMenuSingleItem } from './NavMenuSingleItem';
77
import { NavMenuGroup, NavMenuGroupItem } from './NavMenuGroup';
8+
import { SocialLinks } from '../SocialLinks';
89
import { useLocaleSiteData, useSidebarData } from '../../logic';
910
import { DefaultTheme } from 'shared/types';
10-
import GithubSvg from '../../assets/github.svg';
1111
import { useLocation } from 'react-router-dom';
1212
import { NavHamburger } from '../NavHambmger';
1313

1414
export interface NavProps {
1515
beforeNavTitle?: React.ReactNode;
1616
afterNavTitle?: React.ReactNode;
1717
}
18-
const IconMap = {
19-
github: GithubSvg
20-
};
21-
2218
const NavBarTitle = ({ title }: { title: string }) => {
2319
return (
2420
<div
@@ -63,46 +59,6 @@ const NavTranslations = ({
6359
);
6460
};
6561

66-
const NavSocialLinks = ({
67-
socialLinks
68-
}: {
69-
socialLinks: DefaultTheme.SocialLink[];
70-
}) => {
71-
return (
72-
<div
73-
className="social-links"
74-
flex=""
75-
items-center=""
76-
before="menu-item-before"
77-
>
78-
<div
79-
flex=""
80-
items-center=""
81-
w="9"
82-
h="9"
83-
transition="color duration-300"
84-
color="hover:brand"
85-
>
86-
{socialLinks.map((item) => {
87-
const IconComp = IconMap[item.icon as keyof typeof IconMap];
88-
return (
89-
<a
90-
key={item.link}
91-
href={item.link}
92-
target="_blank"
93-
rel="noopener noreferrer"
94-
w="5"
95-
h="5"
96-
>
97-
<IconComp fill="currentColor" />
98-
</a>
99-
);
100-
})}
101-
</div>
102-
</div>
103-
);
104-
};
105-
10662
export function Nav(props: NavProps & ComponentPropsWithIsland) {
10763
const { beforeNavTitle, afterNavTitle } = props;
10864
const { siteData, pageType } = usePageData();
@@ -166,7 +122,7 @@ export function Nav(props: NavProps & ComponentPropsWithIsland) {
166122
<NavTranslations translationMenuData={translationMenuData!} />
167123
)}
168124
{hasAppearanceSwitch && <NavAppearance />}
169-
{hasSocialLinks && <NavSocialLinks socialLinks={socialLinks} />}
125+
{hasSocialLinks && <SocialLinks __island socialLinks={socialLinks} />}
170126
</div>
171127
);
172128
};

packages/island/src/theme-default/components/NavScreen/index.tsx

+2-40
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
NavScreenMenuGroupItem
88
} from '../NavScreenMenuGroup/NavScreenMenuGroup';
99
import { NavMenuSingleItem } from '../Nav/NavMenuSingleItem';
10+
import { SocialLinks } from '../SocialLinks';
1011
import { SwitchAppearance } from '../SwitchAppearance/index';
1112
import Translator from '../../assets/translator.svg';
1213
import GithubSvg from '../../assets/github.svg';
@@ -42,45 +43,6 @@ const NavScreenTranslations = ({
4243
</div>
4344
);
4445
};
45-
const NavScreenSocialLinks = ({
46-
socialLinks
47-
}: {
48-
socialLinks: DefaultTheme.SocialLink[];
49-
}) => {
50-
return (
51-
<div
52-
className="social-links"
53-
flex=""
54-
items-center=""
55-
before="menu-item-before"
56-
>
57-
<div
58-
flex=""
59-
items-center=""
60-
w="9"
61-
h="9"
62-
transition="color duration-300"
63-
color="hover:brand"
64-
>
65-
{socialLinks.map((item) => {
66-
const IconComp = IconMap[item.icon as keyof typeof IconMap];
67-
return (
68-
<a
69-
key={item.link}
70-
href={item.link}
71-
target="_blank"
72-
rel="noopener noreferrer"
73-
w="5"
74-
h="5"
75-
>
76-
<IconComp fill="currentColor" />
77-
</a>
78-
);
79-
})}
80-
</div>
81-
</div>
82-
);
83-
};
8446

8547
export function NavScreen(props: Props) {
8648
const { isScreenOpen, localeData, siteData, pathname } = props;
@@ -160,7 +122,7 @@ export function NavScreen(props: Props) {
160122
items-center="center"
161123
>
162124
{hasAppearanceSwitch && <NavScreenAppearance />}
163-
{hasSocialLinks && <NavScreenSocialLinks socialLinks={socialLinks} />}
125+
{hasSocialLinks && <SocialLinks __island socialLinks={socialLinks} />}
164126
</div>
165127
{hasMultiLanguage && (
166128
<NavScreenTranslations translationMenuData={translationMenuData!} />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { LinkContent } from './LinkContent';
2+
import { DefaultTheme } from 'shared/types';
3+
4+
interface IHiddenLinksProps {
5+
links: DefaultTheme.SocialLink[];
6+
}
7+
8+
export const HiddenLinks = (props: IHiddenLinksProps) => {
9+
const { links } = props;
10+
11+
return (
12+
<div
13+
absolute=""
14+
pos="top-13 right-0"
15+
z="1"
16+
p="3"
17+
w="32"
18+
border-1=""
19+
rounded="xl"
20+
bg="bg-default"
21+
style={{
22+
boxShadow: 'var(--island-shadow-3)',
23+
marginRight: '-2px'
24+
}}
25+
flex="~ wrap"
26+
gap="4"
27+
>
28+
{links.map((item) => (
29+
<LinkContent
30+
key={item.icon}
31+
link={item}
32+
popperStyle={{ top: '1.25rem' }}
33+
/>
34+
))}
35+
</div>
36+
);
37+
};

0 commit comments

Comments
 (0)