refactor: style with tailwind

This commit is contained in:
Tristan Yang
2022-12-30 14:39:25 +08:00
parent fbde6f3d92
commit 4a973ee07a
11 changed files with 41 additions and 264 deletions
-43
View File
@@ -1,43 +0,0 @@
import { useState, useEffect, memo, SyntheticEvent, FC, ImgHTMLAttributes } from "react";
import { getInitials, getInitialsAvatar } from "../utils";
interface Props extends ImgHTMLAttributes<HTMLImageElement> {
// className?: string;
// alt?: string;
// src?: string;
name?: string;
type?: "user" | "channel";
}
const Avatar: FC<Props> = ({ src = "", name = "Deleted User", type = "user", ...rest }) => {
const [url, setUrl] = useState("");
const handleError = (err: SyntheticEvent<HTMLImageElement>) => {
console.error("load avatar error", err);
const tmp = getInitialsAvatar({
initials: getInitials(name),
background: type == "channel" ? "#EAECF0" : undefined,
foreground: type == "channel" ? "#475467" : undefined
});
setUrl(tmp);
};
useEffect(() => {
if (!src) {
const tmp = getInitialsAvatar({
initials: getInitials(name),
background: type == "channel" ? "#EAECF0" : undefined,
foreground: type == "channel" ? "#475467" : undefined
});
setUrl(tmp);
} else {
setUrl(src);
}
}, [src, name]);
if (!url) return null;
return <img src={url} onError={handleError} {...rest} />;
};
export default memo(Avatar, (prev, next) => {
return prev.src == next.src;
});
+3 -27
View File
@@ -1,36 +1,12 @@
import styled from "styled-components";
import { FC } from "react";
const StyledDivider = styled.hr`
display: block;
position: relative;
border: 0;
border-top: 1px solid #e3e5e8;
margin: 25px 0;
overflow: visible;
&:before {
background: #fff;
padding: 2px 4px;
position: absolute;
left: 50%;
top: 50%;
transform: translate3d(-50%, -50%, 0);
content: attr(data-content);
font-style: normal;
font-weight: 600;
font-size: 12px;
line-height: 18px;
color: #78787c;
}
`;
interface Props {
content: string;
}
const Divider: FC<Props> = ({ content }) => {
if (!content) return null;
return <StyledDivider data-content={content}></StyledDivider>;
return <div className="relative border-none h-[1px] bg-[#e3e5e8] my-6 overflow-visible">
<span className="p-1 absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 text-xs text-gray-500 font-semibold bg-white">{content}</span>
</div>;
};
export default Divider;
+4 -21
View File
@@ -1,21 +1,4 @@
import { FC, ReactEventHandler, useState } from "react";
import styled from "styled-components";
const Styled = styled.div`
height: 100%;
display: flex;
justify-content: center;
align-items: center;
.err {
padding: 18px;
/* font-weight: bold; */
font-size: 16px;
color: #999;
}
audio {
width: 100%;
}
`;
interface Props {
url: string;
@@ -31,13 +14,13 @@ const Audio: FC<Props> = ({ url }) => {
if (!url) return null;
return (
<Styled>
<div className="flex items-center justify-center h-full">
{err ? (
<div className="err">Unable to play this audio</div>
<div className="p-[18px] text-base text-gray-500">Unable to play this audio</div>
) : (
<audio controls src={url} onError={handleError} />
<audio className="w-full" controls src={url} onError={handleError} />
)}
</Styled>
</div>
);
};
+1 -13
View File
@@ -1,16 +1,4 @@
import { useState, useEffect, FC } from "react";
import styled from "styled-components";
const Styled = styled.div`
height: 218px;
padding: 15px 15px 0 15px;
line-height: 1.4;
overflow: scroll;
white-space: pre-wrap;
word-break: break-all;
background-color: #000;
color: #eee;
`;
interface Props {
url: string;
@@ -29,7 +17,7 @@ const Code: FC<Props> = ({ url }) => {
}, [url]);
if (!content) return null;
return <Styled>{content}</Styled>;
return <div className="h-[218px] p-[15px] pb-0 bg-black text-white overflow-scroll whitespace-pre-wrap break-all leading-snug">{content}</div>;
};
export default Code;
+3 -16
View File
@@ -1,27 +1,14 @@
import React, { FC } from "react";
import styled from "styled-components";
const Styled = styled.div`
height: 218px;
overflow: hidden;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
`;
interface Props {
url: string;
alt?: string;
}
const Image: FC<Props> = ({ url, alt }) => {
if (!url) return null;
return (
<Styled>
<img src={url} alt={alt} />
</Styled>
<div className="h-[218px] overflow-hidden">
<img className="w-full h-full object-cover" src={url} alt={alt} />
</div>
);
};
+3 -23
View File
@@ -1,34 +1,14 @@
import styled from "styled-components";
import { FC } from "react";
const Styled = styled.div`
padding: 8px;
/* height: 218px; */
overflow: hidden;
embed {
width: 100%;
height: 100%;
}
`;
interface Props {
url: string;
}
const Pdf: FC<Props> = ({ url }) => {
// const [content, setContent] = useState("");
// const [pageNumber, setPageNumber] = useState(1);
// const [numPages, setNumPages] = useState(null);
// const onDocumentLoadSuccess = ({ numPages }) => {
// setNumPages(numPages);
// };
return (
<Styled>
<embed src={url} type="application/pdf" />
{/* <Document file={url} onLoadSuccess={onDocumentLoadSuccess}>
<Page pageNumber={pageNumber} />
</Document> */}
</Styled>
<div className="p-2 overflow-hidden">
<embed className="w-full h-full" src={url} type="application/pdf" />
</div>
);
};
+3 -14
View File
@@ -1,24 +1,13 @@
import React, { FC } from "react";
import styled from "styled-components";
const Styled = styled.div`
height: 218px;
video {
width: 100%;
height: 100%;
object-fit: cover;
}
`;
interface Props {
url: string;
}
const Video: FC<Props> = ({ url }) => {
return (
<Styled>
<video controls src={url} />
</Styled>
<div className="h-[218px]">
<video className="w-full h-full object-cover" controls src={url} />
</div>
);
};
+3 -18
View File
@@ -1,19 +1,4 @@
import { FC } from "react";
import styled from "styled-components";
const Styled = styled.div`
background: #ecfdff;
border-radius: 4px;
height: 8px;
overflow: hidden;
.progress {
transition: all 0.25s ease;
height: 8px;
background: #088ab2;
border-radius: 4px;
}
`;
interface Props {
value: number;
width?: string;
@@ -21,9 +6,9 @@ interface Props {
const Progress: FC<Props> = ({ value, width = "100%" }) => {
return (
<Styled style={{ width }}>
<div className="progress" style={{ width: `${value}%` }}></div>
</Styled>
<div className="bg-[#ecfdff] rounded h-2 overflow-hidden" style={{ width }}>
<div className="h-2 bg-[#088ab2] rounded transition-all" style={{ width: `${value}%` }}></div>
</div>
);
};
+4 -27
View File
@@ -1,4 +1,3 @@
import styled from "styled-components";
import InviteByEmail from "./InviteByEmail";
import AddMembers from "./AddMembers";
import CloseIcon from "../../../assets/icons/close.svg";
@@ -7,28 +6,6 @@ import { useAppSelector } from "../../../app/store";
import { FC } from "react";
import { useTranslation } from "react-i18next";
const Styled = styled.div`
display: flex;
flex-direction: column;
background: #fff;
box-shadow: 0 25px 50px rgba(31, 41, 55, 0.25);
border-radius: var(--br);
padding: 16px;
min-width: 408px;
> .title {
display: flex;
align-items: center;
justify-content: space-between;
font-style: normal;
font-weight: 600;
font-size: 18px;
line-height: 28px;
color: #374151;
.close {
cursor: pointer;
}
}
`;
interface Props {
type?: "server" | "channel";
@@ -48,14 +25,14 @@ const InviteModal: FC<Props> = ({ type = "server", cid, title = "", closeModal }
const finalTitle = type == "server" ? server.name : `#${title || channel?.name}`;
return (
<Modal>
<Styled>
<h2 className="title">
<div className="flex flex-col bg-white rounded-lg p-4 min-w-[408px]">
<h2 className="flex items-center justify-between text-lg text-gray-700 ">
{t("invite_title", { name: finalTitle })}
<CloseIcon className="close" onClick={closeModal} />
<CloseIcon className="cursor-pointer" onClick={closeModal} />
</h2>
{!channel?.is_public && <AddMembers cid={cid} closeModal={closeModal} />}
<InviteByEmail cid={channel?.is_public ? undefined : cid} />
</Styled>
</div>
</Modal>
);
};
+17 -62
View File
@@ -1,4 +1,3 @@
import styled from "styled-components";
import { NavLink, useLocation } from "react-router-dom";
import Tippy from "@tippyjs/react";
import addIcon from "../../assets/icons/add.svg?url";
@@ -7,50 +6,6 @@ import AddEntriesMenu from "./AddEntriesMenu";
import { useAppSelector } from "../../app/store";
import { useTranslation } from "react-i18next";
const StyledWrapper = styled.div`
min-height: 56px;
position: relative;
padding: 10px 16px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
.server {
display: flex;
align-items: center;
gap: 8px;
.logo {
width: 32px;
height: 32px;
img {
width: 100%;
height: 100%;
object-fit: cover;
border-radius: 50%;
}
}
.info {
display: flex;
flex-direction: column;
gap: 4px;
.name {
font-weight: 700;
font-size: 14px;
line-height: 100%;
color: #374151;
}
.desc {
font-weight: 400;
font-size: 12px;
line-height: 100%;
color: #78787c;
}
}
}
.add {
cursor: pointer;
}
`;
type Props = {
readonly?: boolean;
};
@@ -67,42 +22,42 @@ export default function Server({ readonly = false }: Props) {
const { name, description, logo } = server;
if (readonly)
return (
<StyledWrapper>
<div className="server">
<div className="logo">
<img alt={`${name} logo`} src={logo} />
<div className="relative flex items-center justify-between gap-2 px-4 py-2">
<div className="flex items-center gap-2">
<div className="w-8 h-8">
<img alt={`${name} logo`} className="w-full h-full object-cover rounded-full" src={logo} />
</div>
<div className="info">
<h3 className="name" title={description}>
<div className="flex flex-col gap-1">
<h3 className="text-sm text-gray-600" title={description}>
{name}
</h3>
<span className="desc">{userCount} {t("members")}</span>
<span className="text-xs text-gray-500">{userCount} {t("members")}</span>
</div>
</div>
</div>
</StyledWrapper>
);
return (
<StyledWrapper>
<div className="relative flex items-center justify-between gap-2 px-4 py-2">
<NavLink to={`/setting?f=${pathname}`}>
<div className="server">
<div className="logo">
<img alt={`${name} logo`} src={logo} />
<div className="flex items-center gap-2">
<div className="w-8 h-8">
<img alt={`${name} logo`} className="w-full h-full object-cover rounded-full" src={logo} />
</div>
<div className="info">
<h3 className="name" title={description}>
<div className="flex flex-col gap-1">
<h3 className="text-sm text-gray-600 font-bold" title={description}>
{name}
</h3>
<span className="desc">{userCount} {t("members")}</span>
<span className="text-xs text-gray-500">{userCount} {t("members")}</span>
</div>
</div>
</NavLink>
<Tooltip tip={t("more")} placement="bottom">
<Tippy interactive placement="bottom-end" trigger="click" content={<AddEntriesMenu />}>
<img src={addIcon} alt="add icon" className="add" />
<img src={addIcon} alt="add icon" className="cursor-pointer" />
</Tippy>
</Tooltip>
</StyledWrapper>
</div>
);
}