refactor(styling): Remove Tailwind (#253)
* refactor(css): replace Tailwind classes with MUI sx * chore(deps): remove classnames * refactor(css): inline link baseline style * feat(css): use modern-normalize * chore(deps): remove tailwind * refactor(css): inline all Sass files * chore(deps): remove sass
This commit is contained in:
parent
72526ebbbb
commit
6c434f84ab
1044
package-lock.json
generated
1044
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -19,13 +19,13 @@
|
||||
"@types/react": "^18.2.66",
|
||||
"@types/react-dom": "^18.2.22",
|
||||
"buffer": "^6.0.3",
|
||||
"classnames": "^2.3.1",
|
||||
"detectincognitojs": "^1.1.2",
|
||||
"fast-memoize": "^2.5.2",
|
||||
"file-saver": "^2.0.5",
|
||||
"fun-animal-names": "^0.1.1",
|
||||
"idb-chunk-store": "^1.0.1",
|
||||
"localforage": "^1.10.0",
|
||||
"modern-normalize": "^2.0.0",
|
||||
"mui-markdown": "^0.5.5",
|
||||
"querystring": "^0.2.1",
|
||||
"react": "^18.2.0",
|
||||
@ -113,13 +113,10 @@
|
||||
"mprocs": "^0.6.4",
|
||||
"nodemon": "^3.0.1",
|
||||
"parcel": "^2.10.0",
|
||||
"postcss": "^8.4.31",
|
||||
"prettier": "^3.2.5",
|
||||
"pretty-quick": "^4.0.0",
|
||||
"process": "^0.11.10",
|
||||
"sass": "^1.69.5",
|
||||
"serve": "^14.1.2",
|
||||
"tailwindcss": "^3.1.8",
|
||||
"url": "^0.11.0",
|
||||
"util": "^0.12.5",
|
||||
"vite": "^5.0.13",
|
||||
|
@ -1,6 +0,0 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
import { HTMLAttributes, useRef, useEffect, useState, useContext } from 'react'
|
||||
import cx from 'classnames'
|
||||
import Box from '@mui/material/Box'
|
||||
import useTheme from '@mui/material/styles/useTheme'
|
||||
|
||||
@ -12,11 +11,7 @@ export interface ChatTranscriptProps extends HTMLAttributes<HTMLDivElement> {
|
||||
userId: string
|
||||
}
|
||||
|
||||
export const ChatTranscript = ({
|
||||
className,
|
||||
messageLog,
|
||||
userId,
|
||||
}: ChatTranscriptProps) => {
|
||||
export const ChatTranscript = ({ messageLog, userId }: ChatTranscriptProps) => {
|
||||
const { showRoomControls } = useContext(ShellContext)
|
||||
const theme = useTheme()
|
||||
const boxRef = useRef<HTMLDivElement>(null)
|
||||
@ -66,11 +61,13 @@ export const ChatTranscript = ({
|
||||
return (
|
||||
<Box
|
||||
ref={boxRef}
|
||||
className={cx('ChatTranscript', className)}
|
||||
className="ChatTranscript"
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
py: transcriptMinPadding,
|
||||
flexGrow: 1,
|
||||
overflow: 'auto',
|
||||
pb: transcriptMinPadding,
|
||||
pt: showRoomControls ? theme.spacing(10) : theme.spacing(2),
|
||||
px: `max(${transcriptPaddingX}, ${transcriptMinPadding})`,
|
||||
transition: `padding-top ${theme.transitions.duration.short}ms ${theme.transitions.easing.easeInOut}`,
|
||||
|
9
src/components/Elements/index.tsx
Normal file
9
src/components/Elements/index.tsx
Normal file
@ -0,0 +1,9 @@
|
||||
import styled from '@mui/material/styles/styled'
|
||||
|
||||
// NOTE: These components are defined to enable raw DOM elements to be styled
|
||||
// with MUI's sx prop.
|
||||
// @see https://mui.com/system/styled/
|
||||
// @see https://mui.com/system/getting-started/the-sx-prop/
|
||||
export const Form = styled('form')({})
|
||||
export const Input = styled('input')({})
|
||||
export const Main = styled('main')({})
|
@ -1,3 +0,0 @@
|
||||
.Message
|
||||
pre
|
||||
overflow: auto
|
@ -5,20 +5,10 @@ import Box from '@mui/material/Box'
|
||||
import Tooltip from '@mui/material/Tooltip'
|
||||
import Typography, { TypographyProps } from '@mui/material/Typography'
|
||||
import Link, { LinkProps } from '@mui/material/Link'
|
||||
import styled from '@mui/material/styles/styled'
|
||||
import { materialDark } from 'react-syntax-highlighter/dist/esm/styles/prism'
|
||||
|
||||
// These imports need to be ts-ignored to prevent spurious errors that look
|
||||
// like this:
|
||||
//
|
||||
// Module 'react-markdown' cannot be imported using this construct. The
|
||||
// specifier only resolves to an ES module, which cannot be imported
|
||||
// synchronously. Use dynamic import instead. (tsserver 1471)
|
||||
//
|
||||
// @ts-ignore
|
||||
import Markdown from 'react-markdown'
|
||||
// @ts-ignore
|
||||
import { CodeProps } from 'react-markdown/lib/ast-to-react'
|
||||
// @ts-ignore
|
||||
import remarkGfm from 'remark-gfm'
|
||||
|
||||
import {
|
||||
@ -32,7 +22,7 @@ import { CopyableBlock } from 'components/CopyableBlock/CopyableBlock'
|
||||
|
||||
import { InlineMedia } from './InlineMedia'
|
||||
|
||||
import './Message.sass'
|
||||
const StyledMarkdown = styled(Markdown)({})
|
||||
|
||||
export interface MessageProps {
|
||||
message: IMessage | I_InlineMedia
|
||||
@ -154,13 +144,26 @@ export const Message = ({ message, showAuthor, userId }: MessageProps) => {
|
||||
) : isYouTubeLink(message) ? (
|
||||
<YouTube videoId={getYouTubeVideoId(message.text)} />
|
||||
) : (
|
||||
<Markdown
|
||||
<StyledMarkdown
|
||||
components={componentMap}
|
||||
remarkPlugins={[remarkGfm]}
|
||||
linkTarget="_blank"
|
||||
sx={{
|
||||
'& pre': {
|
||||
overflow: 'auto',
|
||||
},
|
||||
'& ol': {
|
||||
pl: 2,
|
||||
listStyleType: 'decimal',
|
||||
},
|
||||
'& ul': {
|
||||
pl: 2,
|
||||
listStyleType: 'disc',
|
||||
},
|
||||
}}
|
||||
>
|
||||
{message.text}
|
||||
</Markdown>
|
||||
</StyledMarkdown>
|
||||
)}
|
||||
</Box>
|
||||
</Tooltip>
|
||||
|
@ -14,7 +14,7 @@ import ArrowUpward from '@mui/icons-material/ArrowUpward'
|
||||
|
||||
import { messageCharacterSizeLimit } from 'config/messaging'
|
||||
import { SettingsContext } from 'contexts/SettingsContext'
|
||||
import classNames from 'classnames'
|
||||
import { Form } from 'components/Elements'
|
||||
|
||||
interface MessageFormProps {
|
||||
onMessageSubmit: (message: string) => void
|
||||
@ -76,12 +76,17 @@ export const MessageForm = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<form
|
||||
<Form
|
||||
onSubmit={handleMessageSubmit}
|
||||
className={classNames({
|
||||
'pt-4 px-4': showActiveTypingStatus,
|
||||
'p-4': !showActiveTypingStatus,
|
||||
})}
|
||||
sx={{
|
||||
...(showActiveTypingStatus && {
|
||||
pt: 2,
|
||||
px: 2,
|
||||
}),
|
||||
...(!showActiveTypingStatus && {
|
||||
p: 2,
|
||||
}),
|
||||
}}
|
||||
>
|
||||
<Stack direction="row" spacing={2}>
|
||||
<FormControl fullWidth>
|
||||
@ -110,6 +115,6 @@ export const MessageForm = ({
|
||||
<ArrowUpward />
|
||||
</Fab>
|
||||
</Stack>
|
||||
</form>
|
||||
</Form>
|
||||
)
|
||||
}
|
||||
|
@ -157,11 +157,7 @@ export function Room({
|
||||
height: landscape ? '100%' : '40%',
|
||||
}}
|
||||
>
|
||||
<ChatTranscript
|
||||
messageLog={messageLog}
|
||||
userId={userId}
|
||||
className="grow overflow-auto"
|
||||
/>
|
||||
<ChatTranscript messageLog={messageLog} userId={userId} />
|
||||
<Divider />
|
||||
<Box>
|
||||
<MessageForm
|
||||
|
@ -8,6 +8,8 @@ import CircularProgress from '@mui/material/CircularProgress'
|
||||
import { RoomContext } from 'contexts/RoomContext'
|
||||
import { PeerRoom } from 'lib/PeerRoom'
|
||||
|
||||
import { Input } from 'components/Elements'
|
||||
|
||||
import { useRoomFileShare } from './useRoomFileShare'
|
||||
import { MediaButton } from './MediaButton'
|
||||
|
||||
@ -73,12 +75,12 @@ export function RoomFileUploadControls({
|
||||
px: 1,
|
||||
}}
|
||||
>
|
||||
<input
|
||||
<Input
|
||||
multiple
|
||||
ref={fileInputRef}
|
||||
type="file"
|
||||
id="file-upload"
|
||||
className="hidden"
|
||||
sx={{ display: 'none' }}
|
||||
onChange={handleFileSelect}
|
||||
/>
|
||||
<Tooltip
|
||||
|
@ -1,3 +0,0 @@
|
||||
.PeerDownloadFileButton
|
||||
.MuiCircularProgress-circle
|
||||
transition: none !important
|
@ -10,7 +10,6 @@ import { fileTransfer } from 'lib/FileTransfer'
|
||||
import { Peer } from 'models/chat'
|
||||
import { ShellContext } from 'contexts/ShellContext'
|
||||
|
||||
import './PeerDownloadFileButton.sass'
|
||||
import { usePeerNameDisplay } from 'components/PeerNameDisplay/usePeerNameDisplay'
|
||||
|
||||
interface PeerDownloadFileButtonProps {
|
||||
@ -65,6 +64,9 @@ export const PeerDownloadFileButton = ({
|
||||
<CircularProgress
|
||||
variant={downloadProgress === null ? 'indeterminate' : 'determinate'}
|
||||
value={downloadProgress === null ? undefined : downloadProgress}
|
||||
sx={{
|
||||
transition: 'none',
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<Tooltip
|
||||
|
20
src/index.css
Normal file
20
src/index.css
Normal file
@ -0,0 +1,20 @@
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
blockquote,
|
||||
dl,
|
||||
dd,
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
hr,
|
||||
figure,
|
||||
p,
|
||||
pre {
|
||||
margin: 0;
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
@tailwind base
|
||||
@tailwind components
|
||||
@tailwind utilities
|
||||
|
||||
ol
|
||||
@apply pl-4 list-decimal
|
||||
|
||||
ul
|
||||
@apply pl-4 list-disc
|
@ -2,7 +2,8 @@ import './polyfills'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import 'typeface-roboto'
|
||||
|
||||
import './index.sass'
|
||||
import 'modern-normalize/modern-normalize.css'
|
||||
import './index.css'
|
||||
|
||||
import { ThemeProvider, createTheme } from '@mui/material/styles'
|
||||
import { PrismAsyncLight as SyntaxHighlighter } from 'react-syntax-highlighter'
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { useContext, useEffect } from 'react'
|
||||
import MuiMarkdown from 'mui-markdown'
|
||||
import Box from '@mui/material/Box'
|
||||
import useTheme from '@mui/material/styles/useTheme'
|
||||
|
||||
import { ShellContext } from 'contexts/ShellContext'
|
||||
import {
|
||||
@ -8,8 +9,6 @@ import {
|
||||
messageCharacterSizeLimit,
|
||||
} from 'config/messaging'
|
||||
|
||||
import './index.sass'
|
||||
|
||||
const messageTranscriptSizeLimitFormatted = Intl.NumberFormat().format(
|
||||
messageTranscriptSizeLimit
|
||||
)
|
||||
@ -20,13 +19,24 @@ const messageCharacterSizeLimitFormatted = Intl.NumberFormat().format(
|
||||
|
||||
export const About = () => {
|
||||
const { setTitle } = useContext(ShellContext)
|
||||
const theme = useTheme()
|
||||
|
||||
useEffect(() => {
|
||||
setTitle('About')
|
||||
}, [setTitle])
|
||||
|
||||
return (
|
||||
<Box className="About max-w-3xl mx-auto p-4">
|
||||
<Box
|
||||
className="About"
|
||||
sx={{
|
||||
p: 2,
|
||||
mx: 'auto',
|
||||
maxWidth: theme.breakpoints.values.md,
|
||||
'& p': {
|
||||
mb: 2,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<MuiMarkdown>
|
||||
{`
|
||||
### User Guide
|
||||
|
@ -1,3 +0,0 @@
|
||||
.About
|
||||
p
|
||||
@apply mb-4
|
@ -1,20 +1,30 @@
|
||||
import { useContext, useEffect } from 'react'
|
||||
import Box from '@mui/material/Box'
|
||||
import MuiMarkdown from 'mui-markdown'
|
||||
import useTheme from '@mui/material/styles/useTheme'
|
||||
|
||||
import { ShellContext } from 'contexts/ShellContext'
|
||||
|
||||
import './index.sass'
|
||||
|
||||
export const Disclaimer = () => {
|
||||
const { setTitle } = useContext(ShellContext)
|
||||
const theme = useTheme()
|
||||
|
||||
useEffect(() => {
|
||||
setTitle('Disclaimer')
|
||||
}, [setTitle])
|
||||
|
||||
return (
|
||||
<Box className="Disclaimer max-w-3xl mx-auto p-4">
|
||||
<Box
|
||||
className="Disclaimer"
|
||||
sx={{
|
||||
p: 2,
|
||||
mx: 'auto',
|
||||
maxWidth: theme.breakpoints.values.md,
|
||||
'& p': {
|
||||
mb: 2,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<MuiMarkdown>
|
||||
{`
|
||||
### Interpretation and Definitions
|
||||
|
@ -1,6 +0,0 @@
|
||||
.Disclaimer
|
||||
ul
|
||||
@apply my-4
|
||||
|
||||
p
|
||||
@apply mb-4
|
@ -10,22 +10,28 @@ import IconButton from '@mui/material/IconButton'
|
||||
import MuiLink from '@mui/material/Link'
|
||||
import GitHubIcon from '@mui/icons-material/GitHub'
|
||||
import Cached from '@mui/icons-material/Cached'
|
||||
import useTheme from '@mui/material/styles/useTheme'
|
||||
import styled from '@mui/material/styles/styled'
|
||||
|
||||
import { v4 as uuid } from 'uuid'
|
||||
|
||||
import { routes } from 'config/routes'
|
||||
import { ShellContext } from 'contexts/ShellContext'
|
||||
import { PeerNameDisplay } from 'components/PeerNameDisplay'
|
||||
import { Form, Main } from 'components/Elements'
|
||||
import Logo from 'img/logo.svg?react'
|
||||
|
||||
import { EmbedCodeDialog } from './EmbedCodeDialog'
|
||||
|
||||
const StyledLogo = styled(Logo)({})
|
||||
|
||||
interface HomeProps {
|
||||
userId: string
|
||||
}
|
||||
|
||||
export function Home({ userId }: HomeProps) {
|
||||
const { setTitle } = useContext(ShellContext)
|
||||
const theme = useTheme()
|
||||
const [roomName, setRoomName] = useState(uuid())
|
||||
const [showEmbedCode, setShowEmbedCode] = useState(false)
|
||||
const navigate = useNavigate()
|
||||
@ -63,11 +69,29 @@ export function Home({ userId }: HomeProps) {
|
||||
|
||||
return (
|
||||
<Box className="Home">
|
||||
<main className="mt-6 px-4 max-w-3xl text-center mx-auto">
|
||||
<Main
|
||||
sx={{
|
||||
maxWidth: theme.breakpoints.values.md,
|
||||
mt: 3,
|
||||
mx: 'auto',
|
||||
px: 2,
|
||||
textAlign: 'center',
|
||||
}}
|
||||
>
|
||||
<Link to={routes.ABOUT}>
|
||||
<Logo className="px-1 pb-4 mx-auto max-w-md" />
|
||||
<StyledLogo
|
||||
sx={{
|
||||
px: 0.5,
|
||||
pb: 2,
|
||||
mx: 'auto',
|
||||
maxWidth: theme.breakpoints.values.sm,
|
||||
}}
|
||||
/>
|
||||
</Link>
|
||||
<form onSubmit={handleFormSubmit} className="max-w-xl mx-auto">
|
||||
<Form
|
||||
onSubmit={handleFormSubmit}
|
||||
sx={{ maxWidth: theme.breakpoints.values.sm, mx: 'auto' }}
|
||||
>
|
||||
<Typography sx={{ mb: 2 }}>
|
||||
Your username:{' '}
|
||||
<PeerNameDisplay paragraph={false} sx={{ fontWeight: 'bold' }}>
|
||||
@ -135,10 +159,17 @@ export function Home({ userId }: HomeProps) {
|
||||
Get embed code
|
||||
</Button>
|
||||
</Box>
|
||||
</form>
|
||||
</main>
|
||||
</Form>
|
||||
</Main>
|
||||
<Divider sx={{ my: 2 }} />
|
||||
<Box className="max-w-3xl text-center mx-auto px-4">
|
||||
<Box
|
||||
sx={{
|
||||
maxWidth: theme.breakpoints.values.sm,
|
||||
mx: 'auto',
|
||||
textAlign: 'center',
|
||||
px: 2,
|
||||
}}
|
||||
>
|
||||
<Typography variant="body1">
|
||||
This is a free communication tool that is designed for simplicity,
|
||||
privacy, and security. All interaction between you and your online
|
||||
@ -171,7 +202,7 @@ export function Home({ userId }: HomeProps) {
|
||||
</IconButton>
|
||||
</MuiLink>
|
||||
</Box>
|
||||
<Typography variant="body1" sx={{ textAlign: 'center' }}>
|
||||
<Typography variant="body1" sx={{ textAlign: 'center', mb: 1 }}>
|
||||
Licensed under{' '}
|
||||
<MuiLink
|
||||
href="https://github.com/jeremyckahn/chitchatter/blob/develop/LICENSE"
|
||||
|
@ -118,7 +118,7 @@ export const Settings = ({ userId }: SettingsProps) => {
|
||||
const areNotificationsAvailable = notification.permission === 'granted'
|
||||
|
||||
return (
|
||||
<Box className="max-w-3xl mx-auto p-4">
|
||||
<Box sx={{ p: 2, mx: 'auto', maxWidth: theme.breakpoints.values.md }}>
|
||||
<Typography
|
||||
variant="h2"
|
||||
sx={{
|
||||
|
@ -1,8 +0,0 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: ['./src/**/*.{js,jsx,ts,tsx}'],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [],
|
||||
}
|
Loading…
Reference in New Issue
Block a user