client: improve rendered post styling; length is 100% if uneditable
This commit is contained in:
parent
5b71fc6b27
commit
844ccded3c
7 changed files with 113 additions and 82 deletions
|
@ -24,3 +24,7 @@
|
|||
/* Override geist-ui styling */
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.textarea {
|
||||
height: 100%;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ type Props = {
|
|||
const Document = ({ remove, editable, title, content, setTitle, setContent, initialTab = 'edit' }: Props) => {
|
||||
const codeEditorRef = useRef<HTMLTextAreaElement>(null)
|
||||
const [tab, setTab] = useState(initialTab)
|
||||
const height = editable ? "500px" : '100%'
|
||||
|
||||
const handleTabChange = (newTab: string) => {
|
||||
if (newTab === 'edit') {
|
||||
|
@ -59,20 +60,23 @@ const Document = ({ remove, editable, title, content, setTitle, setContent, init
|
|||
<Tabs onChange={handleTabChange} initialValue={initialTab} hideDivider leftSpace={0}>
|
||||
<Tabs.Item label={editable ? "Edit" : "Raw"} value="edit">
|
||||
{/* <textarea className={styles.lineCounter} wrap='off' readOnly ref={lineNumberRef}>1.</textarea> */}
|
||||
<Textarea
|
||||
ref={codeEditorRef}
|
||||
placeholder="Type some contents..."
|
||||
value={content}
|
||||
onChange={(event) => setContent ? setContent(event.target.value) : null}
|
||||
width="100%"
|
||||
height="500px"
|
||||
disabled={!editable}
|
||||
resize="vertical"
|
||||
className={styles.textarea}
|
||||
/>
|
||||
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
||||
<Textarea
|
||||
ref={codeEditorRef}
|
||||
placeholder="Type some contents..."
|
||||
value={content}
|
||||
onChange={(event) => setContent ? setContent(event.target.value) : null}
|
||||
width="100%"
|
||||
disabled={!editable}
|
||||
// TODO: Textarea should grow to fill parent if height == 100%
|
||||
style={{ flex: 1, minHeight: 350 }}
|
||||
resize="vertical"
|
||||
className={styles.textarea}
|
||||
/>
|
||||
</div>
|
||||
</Tabs.Item>
|
||||
<Tabs.Item label="Preview" value="preview">
|
||||
<MarkdownPreview height={500} content={content} />
|
||||
<MarkdownPreview height={height} content={content} />
|
||||
</Tabs.Item>
|
||||
</Tabs>
|
||||
|
||||
|
|
|
@ -13,28 +13,27 @@
|
|||
|
||||
.mobile {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.controls {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 650px) {
|
||||
.tabs {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.controls {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
|
||||
.controls {
|
||||
flex: 1 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.controls :global(.menu-toggle) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-width: 40px;
|
||||
height: 40px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
|
|
|
@ -72,12 +72,12 @@ const Header = ({ changeTheme, theme }: DriftProps) => {
|
|||
condition: !isSignedIn
|
||||
},
|
||||
{
|
||||
name: "",
|
||||
name: isMobile ? "GitHub" : "",
|
||||
href: "https://github.com/maxleiter/drift",
|
||||
icon: <GitHubIcon />,
|
||||
condition: true
|
||||
}
|
||||
], [isSignedIn, router])
|
||||
], [isMobile, isSignedIn, router])
|
||||
|
||||
useEffect(() => {
|
||||
setSelectedTab(pages.find((page) => {
|
||||
|
@ -89,7 +89,7 @@ const Header = ({ changeTheme, theme }: DriftProps) => {
|
|||
|
||||
return (
|
||||
<Page.Header height={'var(--page-nav-height)'} margin={0} paddingBottom={0} paddingTop={"var(--gap)"}>
|
||||
{!isMobile && <div className={styles.tabs}>
|
||||
<div className={styles.tabs}>
|
||||
<Tabs
|
||||
value={selectedTab}
|
||||
leftSpace={0}
|
||||
|
@ -116,17 +116,14 @@ const Header = ({ changeTheme, theme }: DriftProps) => {
|
|||
else return null
|
||||
})}
|
||||
</Tabs>
|
||||
</div>}
|
||||
<div className="controls">
|
||||
{isMobile && (
|
||||
<Button
|
||||
className="menu-toggle"
|
||||
auto
|
||||
type="abort"
|
||||
onClick={() => setExpanded(!expanded)}>
|
||||
<MenuIcon size="1.125rem" />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
<div className={styles.controls}>
|
||||
<Button
|
||||
auto
|
||||
type="abort"
|
||||
onClick={() => setExpanded(!expanded)}>
|
||||
<MenuIcon size="1.125rem" />
|
||||
</Button>
|
||||
</div>
|
||||
{isMobile && expanded && (<div className={styles.mobile}>
|
||||
<ButtonGroup vertical>
|
||||
|
|
|
@ -1,15 +1,8 @@
|
|||
import { memo } from "react"
|
||||
import ReactMarkdown from "react-markdown"
|
||||
import remarkGfm from "remark-gfm"
|
||||
// @ts-ignore because of no types in remark-a11y-emoji
|
||||
import a11yEmoji from '@fec/remark-a11y-emoji';
|
||||
import styles from './preview.module.css'
|
||||
import ReactMarkdownPreview from "./react-markdown-preview"
|
||||
|
||||
const MarkdownPreview = ({ content, height }: { content?: string, height?: number | string }) => {
|
||||
{/* remarkGfm is github flavored markdown support, a11yEmoji wraps emojis in accessible spans for screen readers */ }
|
||||
return (<div style={{ height }}><ReactMarkdown className={styles.markdownPreview} remarkPlugins={[remarkGfm, a11yEmoji]} >
|
||||
{content || ""}
|
||||
</ReactMarkdown></div>)
|
||||
const MarkdownPreview = ({ content = '', height = 500 }: { content?: string, height?: number | string }) => {
|
||||
return (<ReactMarkdownPreview height={height} content={content} />)
|
||||
}
|
||||
|
||||
export default memo(MarkdownPreview)
|
||||
|
|
19
client/components/preview/react-markdown-preview.tsx
Normal file
19
client/components/preview/react-markdown-preview.tsx
Normal file
|
@ -0,0 +1,19 @@
|
|||
import ReactMarkdown from "react-markdown"
|
||||
import remarkGfm from "remark-gfm"
|
||||
|
||||
// @ts-ignore because of no types in remark-a11y-emoji
|
||||
import a11yEmoji from '@fec/remark-a11y-emoji';
|
||||
import styles from './preview.module.css'
|
||||
|
||||
type Props = {
|
||||
content: string | undefined
|
||||
height: number | string
|
||||
}
|
||||
|
||||
const ReactMarkdownPreview = ({ content, height }: Props) => {
|
||||
return (<div style={{ height }}><ReactMarkdown className={styles.markdownPreview} remarkPlugins={[remarkGfm, a11yEmoji]} >
|
||||
{content || ""}
|
||||
</ReactMarkdown></div>)
|
||||
}
|
||||
|
||||
export default ReactMarkdownPreview
|
|
@ -5,7 +5,54 @@ import { Page, Spacer } from '@geist-ui/core'
|
|||
import Header from '../components/header'
|
||||
import { ThemeProps } from './_app'
|
||||
import Document from '../components/document'
|
||||
const Home = ({ theme, changeTheme }: ThemeProps) => {
|
||||
|
||||
export function getStaticProps() {
|
||||
const introDoc = `# Welcome to Drift
|
||||
### Drift is a self-hostable clone of GitHub Gist.
|
||||
#### It is a simple way to share code and text snippets with your friends, with support for the following:
|
||||
|
||||
- Render GitHub Extended Markdown (including images)
|
||||
- User authentication
|
||||
- Private, public, and secret posts
|
||||
|
||||
If you want to signup, you can join at [/signup](/signup) as long as you have a passcode provided by the administrator (which you don't need for this demo).
|
||||
**This demo is on a memory-only database, so accounts and pastes can be deleted at any time.**
|
||||
You can find the source code on [GitHub](https://github.com/MaxLeiter/drift).
|
||||
|
||||
Drift was inspired by [this tweet](https://twitter.com/emilyst/status/1499858264346935297):
|
||||
> What is the absolute closest thing to GitHub Gist that can be self-hosted?
|
||||
In terms of design and functionality. Hosts images and markdown, rendered. Creates links that can be private or public. Uses/requires registration.
|
||||
I have looked at dozens of pastebin-like things.
|
||||
`
|
||||
const todoDoc =
|
||||
`#### In no particular order:
|
||||
|
||||
- Less JavaScript usage (it's currently required)
|
||||
- A non-Node backend
|
||||
- Hosting images
|
||||
- Password-protected posts
|
||||
- Administrator panel
|
||||
- Meta tags
|
||||
- User settings
|
||||
- Search
|
||||
- "Forking"
|
||||
- LaTeX
|
||||
- Syntax highlighting based on filename ending"`
|
||||
|
||||
return {
|
||||
props: {
|
||||
introContent: introDoc,
|
||||
todoContent: todoDoc,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type Props = ThemeProps & {
|
||||
introContent: string
|
||||
todoContent: string
|
||||
}
|
||||
|
||||
const Home = ({ theme, changeTheme, introContent, todoContent }: Props) => {
|
||||
return (
|
||||
<Page className={styles.container} width="100%">
|
||||
<Head>
|
||||
|
@ -16,49 +63,17 @@ const Home = ({ theme, changeTheme }: ThemeProps) => {
|
|||
<Page.Header>
|
||||
<Header theme={theme} changeTheme={changeTheme} />
|
||||
</Page.Header>
|
||||
<Page.Content width={"var(--main-content-width)"} margin="auto">
|
||||
<Page.Content width={"var(--main-content-width)"} margin="auto" paddingTop={"var(--gap)"}>
|
||||
<Document
|
||||
editable={false}
|
||||
content={
|
||||
`# Welcome to Drift
|
||||
### Drift is a self-hostable clone of GitHub Gist.
|
||||
#### It is a simple way to share code and text snippets with your friends, with support for the following:
|
||||
|
||||
- Render GitHub Extended Markdown (including images)
|
||||
- User authentication
|
||||
- Private, public, and secret posts
|
||||
|
||||
If you want to signup, you can join at [/signup](/signup) as long as you have a passcode provided by the administrator (which you don't need for this demo).
|
||||
**This demo is on a memory-only database, so accounts and pastes can be deleted at any time.**
|
||||
You can find the source code on [GitHub](https://github.com/MaxLeiter/drift).
|
||||
|
||||
Drift was inspired by [this tweet](https://twitter.com/emilyst/status/1499858264346935297):
|
||||
> What is the absolute closest thing to GitHub Gist that can be self-hosted?
|
||||
In terms of design and functionality. Hosts images and markdown, rendered. Creates links that can be private or public. Uses/requires registration.
|
||||
I have looked at dozens of pastebin-like things.
|
||||
|
||||
|
||||
`}
|
||||
content={introContent}
|
||||
title={`Welcome to Drift.md`}
|
||||
initialTab={`preview`}
|
||||
/>
|
||||
<Spacer height={1} />
|
||||
<Document
|
||||
editable={false}
|
||||
content={
|
||||
`#### In no particular order:
|
||||
|
||||
- [ ] Less JavaScript usage (it's currently required)
|
||||
- [ ] A non-Node backend
|
||||
- [ ] Hosting images
|
||||
- [ ] Password-protected posts
|
||||
- [ ] Administrator panel
|
||||
- [ ] Meta tags
|
||||
- [ ] User settings
|
||||
- [ ] Search
|
||||
- [ ] "Forking
|
||||
- [ ] LaTeX
|
||||
- [ ] Syntax highlighting based on filename ending"`}
|
||||
content={todoContent}
|
||||
title={`TODO.md`}
|
||||
initialTab={`preview`}
|
||||
/>
|
||||
|
|
Loading…
Reference in a new issue