diff --git a/src/blog/components/Latest.tsx b/src/blog/components/Latest.tsx
index 4fbafc0..4fa3016 100644
--- a/src/blog/components/Latest.tsx
+++ b/src/blog/components/Latest.tsx
@@ -1,99 +1,19 @@
import * as React from 'react';
-import Avatar from '@mui/material/Avatar';
-import AvatarGroup from '@mui/material/AvatarGroup';
import Box from '@mui/material/Box';
import Grid from '@mui/material/Grid';
import Typography from '@mui/material/Typography';
-import { styled } from '@mui/material/styles';
import NavigateNextRoundedIcon from '@mui/icons-material/NavigateNextRounded';
import CircularProgress from '@mui/material/CircularProgress';
import { LatestProps } from "../types/props";
+import { StyledTypography, TitleTypography } from "../types/styles";
+import { ArticleMeta } from "./ArticleMeta";
import Fade from '@mui/material/Fade';
-
-const StyledTypography = styled(Typography)({
- display: '-webkit-box',
- WebkitBoxOrient: 'vertical',
- WebkitLineClamp: 2,
- overflow: 'hidden',
- textOverflow: 'ellipsis',
-});
-
-const TitleTypography = styled(Typography)(({ theme }) => ({
- position: 'relative',
- textDecoration: 'none',
- '&:hover': { cursor: 'pointer' },
- '& .arrow': {
- visibility: 'hidden',
- position: 'absolute',
- right: 0,
- top: '50%',
- transform: 'translateY(-50%)',
- },
- '&:hover .arrow': {
- visibility: 'visible',
- opacity: 0.7,
- },
- '&:focus-visible': {
- outline: '3px solid',
- outlineColor: 'hsla(210, 98%, 48%, 0.5)',
- outlineOffset: '3px',
- borderRadius: '8px',
- },
- '&::before': {
- content: '""',
- position: 'absolute',
- width: 0,
- height: '1px',
- bottom: 0,
- left: 0,
- backgroundColor: (theme.vars || theme).palette.text.primary,
- opacity: 0.3,
- transition: 'width 0.3s ease, opacity 0.3s ease',
- },
- '&:hover::before': {
- width: '100%',
- },
-}));
-
-function Author({ authors }: { authors: { name: string; avatar: string }[] }) {
- return (
-
-
-
- {authors.map((author, index) => (
-
- ))}
-
-
- {authors.map((a) => a.name).join(', ')}
-
-
- Recently Updated
-
- );
-}
-
-export default function Latest({ articles, onSelectArticle, onLoadMore }: LatestProps) {
+export default function Latest({
+ articles,
+ onSelectArticle,
+ onLoadMore
+}: LatestProps) {
const [visibleCount, setVisibleCount] = React.useState(2);
const [loadingMore, setLoadingMore] = React.useState(false);
const [animating, setAnimating] = React.useState(false);
@@ -182,7 +102,7 @@ export default function Latest({ articles, onSelectArticle, onLoadMore }: Latest
{article.description}
-
+
diff --git a/src/blog/components/Login.tsx b/src/blog/components/Login.tsx
index 3c04765..6bba4cf 100644
--- a/src/blog/components/Login.tsx
+++ b/src/blog/components/Login.tsx
@@ -2,13 +2,12 @@ import * as React from 'react';
import { Box, TextField, Button, Typography, IconButton, CircularProgress, Link } from '@mui/material';
import ArrowBackRoundedIcon from '@mui/icons-material/ArrowBackRounded';
import { useAuth } from '../providers/Author';
+import { LoginProps } from '../types/props';
-interface LoginProps {
- onBack: () => void;
- onRegister: () => void;
-}
-
-export default function Login({ onBack, onRegister }: LoginProps) {
+export default function Login({
+ onBack,
+ onRegister
+}: LoginProps) {
const { login, loading, error, currentUser } = useAuth();
const [username, setUsername] = React.useState('');
const [password, setPassword] = React.useState('');
diff --git a/src/blog/components/MainContent.tsx b/src/blog/components/MainContent.tsx
index 288e797..e11e6d1 100644
--- a/src/blog/components/MainContent.tsx
+++ b/src/blog/components/MainContent.tsx
@@ -10,6 +10,7 @@ import SearchRoundedIcon from '@mui/icons-material/SearchRounded';
import RssFeedRoundedIcon from '@mui/icons-material/RssFeedRounded';
import { ArticleModel } from "../types/models";
+import { MainContentProps } from "../types/props";
import ArticleCardsGrid from "./ArticleCards/ArticleCardsGrid";
export function Search() {
@@ -36,10 +37,7 @@ export function Search() {
export default function MainContent({
articles,
onSelectArticle,
-}: {
- articles: ArticleModel[];
- onSelectArticle: (index: number) => void;
-}) {
+}: MainContentProps) {
const [visibleArticles, setVisibleArticles] = React.useState(articles);
const [activeTag, setActiveTag] = React.useState('all');
diff --git a/src/blog/components/Profile.tsx b/src/blog/components/Profile.tsx
index b149eb9..21b7e10 100644
--- a/src/blog/components/Profile.tsx
+++ b/src/blog/components/Profile.tsx
@@ -12,12 +12,11 @@ import ArrowBackRoundedIcon from '@mui/icons-material/ArrowBackRounded';
import { useAuth } from '../providers/Author';
import { useUpload } from "../providers/Upload";
import ImageUploadField from './ImageUploadField';
+import { ProfileProps } from '../types/props';
-interface ProfileProps {
- onBack: () => void;
-}
-
-export default function Profile({ onBack }: ProfileProps) {
+export default function Profile({
+ onBack
+}: ProfileProps) {
const { currentUser, loading, error, logout, updateProfile } = useAuth();
const { uploadFile } = useUpload();
const [formData, setFormData] = React.useState({
diff --git a/src/blog/components/Register.tsx b/src/blog/components/Register.tsx
index 9359516..58d9a5d 100644
--- a/src/blog/components/Register.tsx
+++ b/src/blog/components/Register.tsx
@@ -2,12 +2,11 @@ import * as React from 'react';
import { Box, TextField, Button, Typography, IconButton, CircularProgress, Alert, } from '@mui/material';
import ArrowBackRoundedIcon from '@mui/icons-material/ArrowBackRounded';
import { useAuth } from '../providers/Author';
+import { RegisterProps } from '../types/props';
-interface RegisterProps {
- onBack: () => void;
-}
-
-export default function Register({ onBack }: RegisterProps) {
+export default function Register({
+ onBack
+}: RegisterProps) {
const { register, loading, error, currentUser } = useAuth();
const [username, setUsername] = React.useState('');
const [password1, setPassword1] = React.useState('');
diff --git a/src/blog/types/props.ts b/src/blog/types/props.ts
index 365394d..549cccb 100644
--- a/src/blog/types/props.ts
+++ b/src/blog/types/props.ts
@@ -6,13 +6,30 @@ export interface LatestProps {
onLoadMore?: (offset: number, limit: number) => Promise; // optional async callback
}
+export interface LoginProps {
+ onBack: () => void;
+ onRegister: () => void;
+}
+
+export interface MainContentProps {
+ articles: ArticleModel[];
+ onSelectArticle: (index: number) => void;
+}
+
+export interface ProfileProps {
+ onBack: () => void;
+}
+
+export interface RegisterProps {
+ onBack: () => void;
+}
+
export interface ArticleViewProps {
article: ArticleModel;
onBack: () => void;
open_editor: () => void;
}
-
export interface ArticleEditorProps {
article?: ArticleModel | null;
onBack: () => void;
diff --git a/src/blog/types/styles.ts b/src/blog/types/styles.ts
index 148d7c9..ddfe1bb 100644
--- a/src/blog/types/styles.ts
+++ b/src/blog/types/styles.ts
@@ -37,4 +37,41 @@ export const StyledTypography = styled(Typography)({
WebkitLineClamp: 2,
overflow: 'hidden',
textOverflow: 'ellipsis',
-});
\ No newline at end of file
+});
+
+export const TitleTypography = styled(Typography)(({ theme }) => ({
+ position: 'relative',
+ textDecoration: 'none',
+ '&:hover': { cursor: 'pointer' },
+ '& .arrow': {
+ visibility: 'hidden',
+ position: 'absolute',
+ right: 0,
+ top: '50%',
+ transform: 'translateY(-50%)',
+ },
+ '&:hover .arrow': {
+ visibility: 'visible',
+ opacity: 0.7,
+ },
+ '&:focus-visible': {
+ outline: '3px solid',
+ outlineColor: 'hsla(210, 98%, 48%, 0.5)',
+ outlineOffset: '3px',
+ borderRadius: '8px',
+ },
+ '&::before': {
+ content: '""',
+ position: 'absolute',
+ width: 0,
+ height: '1px',
+ bottom: 0,
+ left: 0,
+ backgroundColor: (theme.vars || theme).palette.text.primary,
+ opacity: 0.3,
+ transition: 'width 0.3s ease, opacity 0.3s ease',
+ },
+ '&:hover::before': {
+ width: '100%',
+ },
+}));