Skip to content

Commit 57adcb5

Browse files
authored
feat: add github button in navigation (#194)
1 parent 7515055 commit 57adcb5

File tree

7 files changed

+131
-0
lines changed

7 files changed

+131
-0
lines changed

package-lock.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
"dependencies": {
4949
"@gravity-ui/i18n": "^1.0.0",
5050
"bem-cn-lite": "^4.0.0",
51+
"github-buttons": "2.23.0",
5152
"lodash": "^4.17.21",
5253
"react-player": "^2.9.0",
5354
"react-slick": "^0.28.1",

src/containers/PageConstructor/__stories__/data.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,12 @@
308308
}
309309
],
310310
"rightItems": [
311+
{
312+
"type": "github-button",
313+
"text": "Star",
314+
"label": "Star @gravity-ui/page-constructor on GitHub",
315+
"url": "https://github.com/gravity-ui/page-constructor"
316+
},
311317
{
312318
"type": "link",
313319
"text": "Link",

src/models/navigation.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export enum NavigationItemType {
66
Dropdown = 'dropdown',
77
Button = 'button',
88
Social = 'social',
9+
GithubButton = 'github-button',
910
}
1011

1112
export interface NavigationItemBase {
@@ -14,6 +15,27 @@ export interface NavigationItemBase {
1415
url?: string;
1516
}
1617

18+
export enum NavigationGithubButtonIcon {
19+
heart = 'octicon-heart',
20+
eye = 'octicon-eye',
21+
star = 'octicon-star',
22+
fork = 'octicon-repo-forked',
23+
issue = 'octicon-issue-opened',
24+
comment = 'octicon-comment-discussion',
25+
download = 'octicon-download',
26+
package = 'octicon-package',
27+
template = 'octicon-repo-template',
28+
play = 'octicon-play',
29+
}
30+
31+
export interface NavigationGithubButton extends Omit<NavigationItemBase, 'icon'> {
32+
type: NavigationItemType.GithubButton;
33+
url: string;
34+
label?: string;
35+
icon?: keyof typeof NavigationGithubButtonIcon;
36+
size?: string;
37+
}
38+
1739
export interface NavigationLinkItem extends Omit<NavigationItemBase, 'url'> {
1840
type: NavigationItemType.Link;
1941
url: string;

src/navigation/components/NavigationItem/NavigationItem.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {BlockIdContext} from '../../../context/blockIdContext';
77
import {NavigationButton} from './components/NavigationButton/NavigationButton';
88
import {NavigationDropdown} from './components/NavigationDropdown/NavigationDropdown';
99
import {NavigationLink} from './components/NavigationLink/NavigationLink';
10+
import {GithubButton} from './components/GithubButton/GithubButton';
1011

1112
const ANALYTICS_ID = 'navigation';
1213

@@ -24,6 +25,7 @@ const NavigationItemsMap: Record<NavigationItemType, React.ComponentType<any>> =
2425
[NavigationItemType.Social]: SocialIcon,
2526
[NavigationItemType.Dropdown]: NavigationDropdown,
2627
[NavigationItemType.Link]: NavigationLink,
28+
[NavigationItemType.GithubButton]: GithubButton,
2729
};
2830

2931
const NavigationItem: React.FC<NavigationItemProps> = ({data, className, ...props}) => {
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
@import '../../../../../../styles/variables';
2+
@import '../../mixins';
3+
4+
$block: '.#{$ns}github-button';
5+
6+
#{$block} {
7+
@include navigation-item-display();
8+
9+
display: flex;
10+
align-items: center;
11+
height: 100%;
12+
13+
span {
14+
display: flex;
15+
flex-direction: column;
16+
justify-content: center;
17+
}
18+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import React, {useRef, useEffect} from 'react';
2+
3+
import {block} from '../../../../../utils';
4+
5+
import {NavigationItemProps} from '../../NavigationItem';
6+
import {NavigationGithubButton, NavigationGithubButtonIcon} from '../../../../../models';
7+
8+
import './GithubButton.scss';
9+
10+
const b = block('github-button');
11+
12+
type NavigationGithubButtonProps = NavigationItemProps & NavigationGithubButton;
13+
14+
const DEFAULT_LABEL = 'Stars on GitHub';
15+
16+
/* More information about github-buttons in https://buttons.github.io/ */
17+
export const GithubButton = ({
18+
text,
19+
url,
20+
className,
21+
label,
22+
size,
23+
icon,
24+
}: NavigationGithubButtonProps) => {
25+
const containerRef = useRef<HTMLSpanElement>(null);
26+
const linkRef = useRef<HTMLAnchorElement>(null);
27+
28+
useEffect(() => {
29+
const paint = () => {
30+
if (containerRef.current) {
31+
const githubButton = containerRef.current.appendChild(
32+
document.createElement('span'),
33+
);
34+
import(/* webpackMode: "eager" */ 'github-buttons').then(({render}) => {
35+
if (linkRef.current !== null) {
36+
render(githubButton.appendChild(linkRef.current), (el) => {
37+
try {
38+
if (githubButton.parentNode) {
39+
githubButton.parentNode.replaceChild(el, githubButton);
40+
}
41+
} catch (_) {}
42+
});
43+
}
44+
});
45+
}
46+
};
47+
48+
const reset = () => {
49+
if (containerRef?.current?.lastChild && linkRef.current) {
50+
containerRef.current.replaceChild(linkRef.current, containerRef.current.lastChild);
51+
}
52+
};
53+
54+
paint();
55+
56+
return () => {
57+
reset();
58+
};
59+
}, []);
60+
61+
return (
62+
<div className={b(null, className)}>
63+
<span ref={containerRef}>
64+
<a
65+
href={url}
66+
ref={linkRef}
67+
data-show-count="true"
68+
aria-label={label || DEFAULT_LABEL}
69+
{...(icon && {'data-icon': NavigationGithubButtonIcon[icon]})}
70+
{...(size && {'data-size': size})}
71+
>
72+
{text}
73+
</a>
74+
</span>
75+
</div>
76+
);
77+
};

0 commit comments

Comments
 (0)