mirror of
https://ghproxy.com/https://github.com/StreakingMan/solvable-sheep-game
synced 2025-05-24 06:09:42 +08:00
chore: 提示面板封装
This commit is contained in:
parent
557a6a705a
commit
84fa8483d9
|
@ -9,4 +9,7 @@ module.exports = {
|
||||||
'stylelint-config-standard-scss',
|
'stylelint-config-standard-scss',
|
||||||
'stylelint-config-prettier-scss',
|
'stylelint-config-prettier-scss',
|
||||||
],
|
],
|
||||||
|
rules: {
|
||||||
|
'selector-class-pattern': '^[a-z][a-zA-Z0-9]+$',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
63
src/components/FixedAnimateScalePanel.module.scss
Normal file
63
src/components/FixedAnimateScalePanel.module.scss
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
.panel {
|
||||||
|
position: fixed;
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
border-radius: 18px;
|
||||||
|
transition: 0.3s;
|
||||||
|
padding: 16px;
|
||||||
|
background-color: rgb(0 0 0/ 50%);
|
||||||
|
color: white;
|
||||||
|
overflow: hidden;
|
||||||
|
backdrop-filter: blur(8px);
|
||||||
|
box-sizing: border-box;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 14px;
|
||||||
|
|
||||||
|
> * {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.leftBottom {
|
||||||
|
left: 8px;
|
||||||
|
bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.closeBtn {
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: rgb(0 0 0/20%);
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
transform: scale(0);
|
||||||
|
color: white;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.open {
|
||||||
|
height: 100px;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: default;
|
||||||
|
z-index: 5 !important;
|
||||||
|
|
||||||
|
@media screen and (max-width: 500px) {
|
||||||
|
width: calc(100% - 16px);
|
||||||
|
}
|
||||||
|
@media screen and (min-width: 501px) {
|
||||||
|
width: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
|
> * {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.closeBtn {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
48
src/components/FixedAnimateScalePanel.tsx
Normal file
48
src/components/FixedAnimateScalePanel.tsx
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
import React, { FC, ReactNode, useState } from 'react';
|
||||||
|
import style from './FixedAnimateScalePanel.module.scss';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
export const FixedAnimateScalePanel: FC<{
|
||||||
|
children: ReactNode;
|
||||||
|
className?: string;
|
||||||
|
openClassName?: string;
|
||||||
|
closeClassName?: string;
|
||||||
|
initOpen?: boolean;
|
||||||
|
}> = ({
|
||||||
|
children,
|
||||||
|
className,
|
||||||
|
openClassName,
|
||||||
|
closeClassName,
|
||||||
|
initOpen = false,
|
||||||
|
}) => {
|
||||||
|
const [open, setOpen] = useState<boolean>(initOpen);
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
onClick={() => !open && setOpen(true)}
|
||||||
|
className={classNames(
|
||||||
|
style.panel,
|
||||||
|
open && style.open,
|
||||||
|
className,
|
||||||
|
open ? openClassName : closeClassName
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
<div className={style.closeBtn} onClick={() => setOpen(false)}>
|
||||||
|
<svg
|
||||||
|
width="13"
|
||||||
|
height="14"
|
||||||
|
viewBox="0 0 13 14"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
clipRule="evenodd"
|
||||||
|
d="M4.9498 7.04945L0 11.9993L1.41421 13.4135L6.36401 8.46367L11.3138 13.4135L12.728 11.9993L7.77823 7.04945L12.7279 2.09976L11.3137 0.685547L6.36401 5.63524L1.41432 0.685547L0.0001055 2.09976L4.9498 7.04945Z"
|
||||||
|
fill="#888888"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
|
@ -1,24 +1,9 @@
|
||||||
/* 可封装 */
|
|
||||||
.info {
|
.info {
|
||||||
position: fixed;
|
|
||||||
left: 8px;
|
left: 8px;
|
||||||
bottom: 8px;
|
bottom: 8px;
|
||||||
transition: 0.3s;
|
|
||||||
padding: 16px;
|
|
||||||
width: 36px;
|
|
||||||
height: 36px;
|
|
||||||
border-radius: 18px;
|
|
||||||
background: rgb(0 0 0/ 50%);
|
|
||||||
color: white;
|
|
||||||
overflow: hidden;
|
|
||||||
backdrop-filter: blur(8px);
|
|
||||||
box-sizing: border-box;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 14px;
|
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
opacity: 0;
|
|
||||||
transition: 0.6s;
|
transition: 0.6s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,41 +18,12 @@
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
transition: 0.2s;
|
transition: 0.2s;
|
||||||
}
|
|
||||||
|
|
||||||
.close {
|
|
||||||
position: absolute;
|
|
||||||
border-radius: 8px;
|
|
||||||
background-color: rgb(0 0 0/20%);
|
|
||||||
width: 36px;
|
|
||||||
height: 36px;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
line-height: 36px;
|
|
||||||
text-align: center;
|
|
||||||
transform: scale(0);
|
|
||||||
color: white;
|
|
||||||
cursor: pointer;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.open {
|
|
||||||
height: 100px;
|
|
||||||
border-radius: 8px;
|
|
||||||
|
|
||||||
@media screen and (max-width: 500px) {
|
|
||||||
width: calc(100% - 70px);
|
|
||||||
}
|
|
||||||
@media screen and (min-width: 501px) {
|
|
||||||
width: 500px;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.close {
|
&.open {
|
||||||
transform: scale(1);
|
@media screen and (max-width: 500px) {
|
||||||
|
width: calc(100% - 70px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
import React, { CSSProperties, FC, useState } from 'react';
|
import React, { FC } from 'react';
|
||||||
import style from './Info.module.scss';
|
import style from './Info.module.scss';
|
||||||
import classNames from 'classnames';
|
import { FixedAnimateScalePanel } from './FixedAnimateScalePanel';
|
||||||
export const Info: FC = () => {
|
export const Info: FC = () => {
|
||||||
const [open, setOpen] = useState(false);
|
|
||||||
return (
|
return (
|
||||||
<div
|
<FixedAnimateScalePanel
|
||||||
onClick={() => !open && setOpen(true)}
|
className={style.info}
|
||||||
className={classNames(style.info, open && style.open)}
|
openClassName={style.open}
|
||||||
>
|
>
|
||||||
<div className={style.icon}>i</div>
|
<div className={style.icon}>i</div>
|
||||||
<p>
|
<p>
|
||||||
|
@ -16,11 +15,27 @@ export const Info: FC = () => {
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
洛天依,言和原创《普通DISCO》
|
普通DISCO(言洛版)
|
||||||
|
</a>
|
||||||
|
、
|
||||||
|
<a
|
||||||
|
href="https://music.163.com/#/song?id=135022"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
贫民百万歌星
|
||||||
|
</a>
|
||||||
|
、
|
||||||
|
<a
|
||||||
|
href="https://y.qq.com/n/ryqq/songDetail/0020Nusb3QJGn9"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
只因你太美
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
玩法来源➡️羊了个羊➡️
|
玩法来源-{'>'}羊了个羊-{'>'}
|
||||||
<a
|
<a
|
||||||
href="https://play.google.com/store/apps/details?id=tile.master.connect.matching.game"
|
href="https://play.google.com/store/apps/details?id=tile.master.connect.matching.game"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
@ -28,11 +43,16 @@ export const Info: FC = () => {
|
||||||
>
|
>
|
||||||
3 Tiles
|
3 Tiles
|
||||||
</a>
|
</a>
|
||||||
|
-{'>'}
|
||||||
|
<a
|
||||||
|
href="https://www.bilibili.com/video/BV1zT411N7RT"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
中国龙
|
||||||
|
</a>
|
||||||
</p>
|
</p>
|
||||||
<p>仅供交流,禁止商用</p>
|
<p>仅供交流,禁止商用</p>
|
||||||
<div className={style.close} onClick={() => setOpen(false)}>
|
</FixedAnimateScalePanel>
|
||||||
X
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,14 +12,9 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.info {
|
.personalInfo {
|
||||||
position: fixed;
|
|
||||||
right: 8px;
|
right: 8px;
|
||||||
top: 8px;
|
top: 8px;
|
||||||
padding: 4px;
|
|
||||||
width: 36px;
|
|
||||||
height: 36px;
|
|
||||||
border-radius: 18px;
|
|
||||||
animation: gradient 4s ease infinite;
|
animation: gradient 4s ease infinite;
|
||||||
background-image: linear-gradient(
|
background-image: linear-gradient(
|
||||||
-45deg,
|
-45deg,
|
||||||
|
@ -30,12 +25,8 @@
|
||||||
);
|
);
|
||||||
background-size: 400% 400%;
|
background-size: 400% 400%;
|
||||||
background-position: 0 0;
|
background-position: 0 0;
|
||||||
box-sizing: border-box;
|
|
||||||
transition: 0.4s;
|
transition: 0.4s;
|
||||||
backdrop-filter: blur(8px);
|
|
||||||
z-index: 9;
|
z-index: 9;
|
||||||
overflow: hidden;
|
|
||||||
color: white;
|
|
||||||
|
|
||||||
* {
|
* {
|
||||||
transition: 0.6s;
|
transition: 0.6s;
|
||||||
|
@ -47,28 +38,13 @@
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
}
|
}
|
||||||
|
|
||||||
.close {
|
|
||||||
position: absolute;
|
|
||||||
border-radius: 8px;
|
|
||||||
background-color: rgb(0 0 0/20%);
|
|
||||||
width: 36px;
|
|
||||||
height: 36px;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
line-height: 36px;
|
|
||||||
text-align: center;
|
|
||||||
transform: scale(0);
|
|
||||||
color: white;
|
|
||||||
cursor: pointer;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.github {
|
.github {
|
||||||
&Icon {
|
&Icon {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 6px;
|
right: 6px;
|
||||||
top: 6px;
|
top: 6px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
opacity: 1 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
&Link {
|
&Link {
|
||||||
|
@ -93,18 +69,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&.open {
|
&.open {
|
||||||
height: 100px;
|
|
||||||
border-radius: 8px;
|
|
||||||
|
|
||||||
@media screen and (max-width: 500px) {
|
@media screen and (max-width: 500px) {
|
||||||
width: calc(100% - 16px);
|
width: calc(100% - 60px) !important;
|
||||||
}
|
|
||||||
@media screen and (min-width: 501px) {
|
|
||||||
width: 500px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.close {
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.github {
|
.github {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React, { FC, useState } from 'react';
|
import React, { FC, useState } from 'react';
|
||||||
import style from './PersonalInfo.module.scss';
|
import style from './PersonalInfo.module.scss';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import { FixedAnimateScalePanel } from './FixedAnimateScalePanel';
|
||||||
|
|
||||||
const GithubIcon: FC = () => {
|
const GithubIcon: FC = () => {
|
||||||
return (
|
return (
|
||||||
|
@ -63,19 +64,15 @@ export const BiliBiliLink: FC = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PersonalInfo: FC = () => {
|
export const PersonalInfo: FC = () => {
|
||||||
const [open, setOpen] = useState(false);
|
|
||||||
return (
|
return (
|
||||||
<div
|
<FixedAnimateScalePanel
|
||||||
onClick={() => !open && setOpen(true)}
|
className={style.personalInfo}
|
||||||
className={classNames(style.info, open && style.open)}
|
openClassName={style.open}
|
||||||
>
|
>
|
||||||
<GithubIcon />
|
<GithubIcon />
|
||||||
<GithubLink />
|
<GithubLink />
|
||||||
<BiliBiliIcon />
|
<BiliBiliIcon />
|
||||||
<BiliBiliLink />
|
<BiliBiliLink />
|
||||||
<div className={style.close} onClick={() => setOpen(false)}>
|
</FixedAnimateScalePanel>
|
||||||
X
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user