Add Tailwind CSS (#425)

* Install and configure tailwind

* Fix style issues
This commit is contained in:
Misode
2023-10-02 23:38:18 +02:00
committed by GitHub
parent 427294ad3b
commit f71e44f91b
24 changed files with 1025 additions and 138 deletions

1059
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -55,11 +55,14 @@
"@types/seedrandom": "^2.4.28", "@types/seedrandom": "^2.4.28",
"@typescript-eslint/eslint-plugin": "^5.28.0", "@typescript-eslint/eslint-plugin": "^5.28.0",
"@typescript-eslint/parser": "^5.28.0", "@typescript-eslint/parser": "^5.28.0",
"autoprefixer": "^10.4.16",
"eslint": "^8.17.0", "eslint": "^8.17.0",
"fast-glob": "^3.2.11", "fast-glob": "^3.2.11",
"postcss": "^8.4.31",
"preact": "^10.8.0", "preact": "^10.8.0",
"preact-router": "^3.2.1", "preact-router": "^3.2.1",
"rollup-plugin-visualizer": "^5.6.0", "rollup-plugin-visualizer": "^5.6.0",
"tailwindcss": "^3.3.3",
"typescript": "^4.7.3", "typescript": "^4.7.3",
"vite": "^3.2.7", "vite": "^3.2.7",
"vite-plugin-static-copy": "^0.12.0" "vite-plugin-static-copy": "^0.12.0"

6
postcss.config.js Normal file
View File

@@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

View File

@@ -1,5 +1,6 @@
import { render } from 'preact' import { render } from 'preact'
import '../styles/global.css' import '../styles/global.css'
import '../styles/main.css'
import '../styles/nodes.css' import '../styles/nodes.css'
import { App } from './App.js' import { App } from './App.js'
import { LocaleProvider, ProjectProvider, StoreProvider, ThemeProvider, TitleProvider, VersionProvider } from './contexts/index.js' import { LocaleProvider, ProjectProvider, StoreProvider, ThemeProvider, TitleProvider, VersionProvider } from './contexts/index.js'

View File

@@ -10,7 +10,7 @@ export function Card({ title, overlay, link, children }: Props) {
const content = <> const content = <>
{overlay && <span class="card-overlay">{overlay}</span>} {overlay && <span class="card-overlay">{overlay}</span>}
<div class="card-content"> <div class="card-content">
{title && <h3 class="card-title">{title}</h3>} {title && <h3 class="card-title font-bold text-[1.17em]">{title}</h3>}
{children} {children}
</div> </div>
</> </>

View File

@@ -23,7 +23,7 @@ export function Header() {
return <header> return <header>
<div class="title"> <div class="title">
<Link class="home-link" href="/" aria-label={locale('home')} data-cy="home-link">{Icons.home}</Link> <Link class="home-link" href="/" aria-label={locale('home')} data-cy="home-link">{Icons.home}</Link>
<h1>{title}</h1> <h1 class="font-bold">{title}</h1>
{gen && <BtnMenu icon="chevron_down" tooltip={locale('switch_generator')} data-cy="generator-switcher"> {gen && <BtnMenu icon="chevron_down" tooltip={locale('switch_generator')} data-cy="generator-switcher">
{config.generators {config.generators
.filter(g => g.tags?.[0] === gen?.tags?.[0] && checkVersion(version, g.minVersion)) .filter(g => g.tags?.[0] === gen?.tags?.[0] && checkVersion(version, g.minVersion))

View File

@@ -25,7 +25,7 @@ export function ToolCard({ title, desc, link, icon, titleIcon }: Props) {
} }
function ToolHead({ title, titleIcon }: Pick<Props, 'title' | 'titleIcon'>) { function ToolHead({ title, titleIcon }: Pick<Props, 'title' | 'titleIcon'>) {
return <h3> return <h3 class="text-[1.17em]">
{title} {title}
{titleIcon && (titleIcon in Octicon ? (Octicon as any)[titleIcon] : (Icons as any)[titleIcon])} {titleIcon && (titleIcon in Octicon ? (Octicon as any)[titleIcon] : (Icons as any)[titleIcon])}
</h3> </h3>

View File

@@ -12,7 +12,7 @@ interface Props {
export function ToolGroup({ title, titleIcon, link, children }: Props) { export function ToolGroup({ title, titleIcon, link, children }: Props) {
return <div class="tool-group"> return <div class="tool-group">
{link === undefined {link === undefined
? <div class="tool-card"><h3>{title}</h3></div> ? <div class="tool-card"><h3 class="text-[1.17em]">{title}</h3></div>
: <ToolCard {...{ title, titleIcon, link}} /> : <ToolCard {...{ title, titleIcon, link}} />
} }
{children && <div class="tool-body"> {children && <div class="tool-body">

View File

@@ -9,7 +9,7 @@ export function WhatsNewEntry({ item }: EntryProps) {
return <article class="whats-new-entry"> return <article class="whats-new-entry">
<a href={item.url} target="_blank"> <a href={item.url} target="_blank">
<WhatsNewTime item={item} /> <WhatsNewTime item={item} />
<h2>{item.title}</h2> <h2 class="font-bold text-[27px]">{item.title}</h2>
</a> </a>
<div class="guide-content" dangerouslySetInnerHTML={{ __html: marked(item.body) }} /> <div class="guide-content" dangerouslySetInnerHTML={{ __html: marked(item.body) }} />
</article> </article>

View File

@@ -14,7 +14,7 @@ export function Changelog({}: Props) {
return <main> return <main>
{error && <ErrorPanel error={error} />} {error && <ErrorPanel error={error} />}
<div class="container changelog"> <div class="legacy-container changelog">
<ChangelogList changes={changes} defaultOrder="desc" limit={100} navigation={( <ChangelogList changes={changes} defaultOrder="desc" limit={100} navigation={(
<BtnLink link="/versions/" icon="three_bars" label={locale('versions.all')} /> <BtnLink link="/versions/" icon="three_bars" label={locale('versions.all')} />
)} /> )} />

View File

@@ -82,7 +82,7 @@ export function Customized({}: Props) {
}, [model, version]) }, [model, version])
return <main> return <main>
<div class="container customized"> <div class="legacy-container customized">
<div class="tabs tabs-sticky"> <div class="tabs tabs-sticky">
<span class={tab === 'basic' ? 'selected' : ''} onClick={() => setTab('basic')}>{locale('customized.basic')}</span> <span class={tab === 'basic' ? 'selected' : ''} onClick={() => setTab('basic')}>{locale('customized.basic')}</span>
<span class={tab === 'structures' ? 'selected' : ''} onClick={() => setTab('structures')}>{locale('customized.structures')}</span> <span class={tab === 'structures' ? 'selected' : ''} onClick={() => setTab('structures')}>{locale('customized.structures')}</span>

View File

@@ -9,7 +9,7 @@ export function Generators({}: Props) {
useTitle(locale('title.generators')) useTitle(locale('title.generators'))
return <main> return <main>
<div class="container"> <div class="legacy-container">
<GeneratorList predicate={gen => !gen.partner} /> <GeneratorList predicate={gen => !gen.partner} />
</div> </div>
<Footer /> <Footer />

View File

@@ -3,12 +3,12 @@ import json from 'highlight.js/lib/languages/json'
import { marked } from 'marked' import { marked } from 'marked'
import { route } from 'preact-router' import { route } from 'preact-router'
import { useCallback, useEffect, useMemo, useState } from 'preact/hooks' import { useCallback, useEffect, useMemo, useState } from 'preact/hooks'
import { Ad, Badge, Btn, Footer, Giscus, Icons, Octicon, VersionSwitcher } from '../components/index.js'
import config from '../Config.js' import config from '../Config.js'
import { parseFrontMatter, versionContent } from '../Utils.js'
import { Ad, Badge, Btn, Footer, Giscus, Icons, Octicon, VersionSwitcher } from '../components/index.js'
import { useLocale, useTitle, useVersion } from '../contexts/index.js' import { useLocale, useTitle, useVersion } from '../contexts/index.js'
import { useActiveTimeout, useAsync, useHash } from '../hooks/index.js' import { useActiveTimeout, useAsync, useHash } from '../hooks/index.js'
import type { VersionId } from '../services/index.js' import type { VersionId } from '../services/index.js'
import { parseFrontMatter, versionContent } from '../Utils.js'
const HASH = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M6.368 1.01a.75.75 0 01.623.859L6.57 4.5h3.98l.46-2.868a.75.75 0 011.48.237L12.07 4.5h2.18a.75.75 0 010 1.5h-2.42l-.64 4h2.56a.75.75 0 010 1.5h-2.8l-.46 2.869a.75.75 0 01-1.48-.237l.42-2.632H5.45l-.46 2.869a.75.75 0 01-1.48-.237l.42-2.632H1.75a.75.75 0 010-1.5h2.42l.64-4H2.25a.75.75 0 010-1.5h2.8l.46-2.868a.75.75 0 01.858-.622zM9.67 10l.64-4H6.33l-.64 4h3.98z"></path></svg>' const HASH = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M6.368 1.01a.75.75 0 01.623.859L6.57 4.5h3.98l.46-2.868a.75.75 0 011.48.237L12.07 4.5h2.18a.75.75 0 010 1.5h-2.42l-.64 4h2.56a.75.75 0 010 1.5h-2.8l-.46 2.869a.75.75 0 01-1.48-.237l.42-2.632H5.45l-.46 2.869a.75.75 0 01-1.48-.237l.42-2.632H1.75a.75.75 0 010-1.5h2.42l.64-4H2.25a.75.75 0 010-1.5h2.8l.46-2.868a.75.75 0 01.858-.622zM9.67 10l.64-4H6.33l-.64 4h3.98z"></path></svg>'
@@ -172,7 +172,7 @@ export function Guide({ id }: Props) {
const [largeWidth] = useState(window.innerWidth > 600) const [largeWidth] = useState(window.innerWidth > 600)
return <main> return <main>
<div class="container guide"> <div class="legacy-container guide">
<div class="navigation"> <div class="navigation">
<a class="btn btn-link" href="/guides/"> <a class="btn btn-link" href="/guides/">
{Octicon.arrow_left} {Octicon.arrow_left}

View File

@@ -41,7 +41,7 @@ export function Guides({}: Props) {
}, [versionedGuides, search, activeTags]) }, [versionedGuides, search, activeTags])
return <main> return <main>
<div class="container guides"> <div class="legacy-container guides">
<div class="navigation"> <div class="navigation">
<TextInput class="btn btn-input query-search" placeholder={locale('guides.search')} value={search} onChange={setSearch} /> <TextInput class="btn btn-input query-search" placeholder={locale('guides.search')} value={search} onChange={setSearch} />
<VersionSwitcher value={versionFilter ? version : undefined} onChange={v => {changeVersion(v); setVersionFiler(true)}} hasAny onAny={() => setVersionFiler(false)} /> <VersionSwitcher value={versionFilter ? version : undefined} onChange={v => {changeVersion(v); setVersionFiler(true)}} hasAny onAny={() => setVersionFiler(false)} />

View File

@@ -22,7 +22,7 @@ export function Home({}: Props) {
const smallScreen = useMediaQuery('(max-width: 580px)') const smallScreen = useMediaQuery('(max-width: 580px)')
return <main> return <main>
<div class="container"> <div class="legacy-container">
<MinecraftWikiBanner /> <MinecraftWikiBanner />
<div class="card-group"> <div class="card-group">
<div class="card-column"> <div class="card-column">

View File

@@ -9,7 +9,7 @@ export function Partners({}: Props) {
useTitle(locale('title.partners')) useTitle(locale('title.partners'))
return <main> return <main>
<div class="container"> <div class="legacy-container">
<GeneratorList predicate={gen => gen.partner !== undefined} /> <GeneratorList predicate={gen => gen.partner !== undefined} />
</div> </div>
<Footer donate={false} /> <Footer donate={false} />

View File

@@ -27,7 +27,7 @@ export function Versions({}: Props) {
return <main> return <main>
{error && <ErrorPanel error={error} />} {error && <ErrorPanel error={error} />}
<div class="container"> <div class="legacy-container">
{selectedId ? <> {selectedId ? <>
<div class="navigation"> <div class="navigation">
<BtnLink link="/versions/" icon="three_bars" label={locale('versions.all')} /> <BtnLink link="/versions/" icon="three_bars" label={locale('versions.all')} />

View File

@@ -29,7 +29,7 @@ export function WhatsNew({}: Props) {
}, [items, storeTime]) }, [items, storeTime])
return <main> return <main>
<div class="container whats-new"> <div class="legacy-container whats-new">
<p>{locale('whats_new.description')}</p> <p>{locale('whats_new.description')}</p>
{error && <ErrorPanel error={error} />} {error && <ErrorPanel error={error} />}
{items?.map(item => <WhatsNewEntry item={item} />)} {items?.map(item => <WhatsNewEntry item={item} />)}

View File

@@ -9,7 +9,7 @@ export function Worldgen({}: Props) {
useTitle(locale('title.worldgen')) useTitle(locale('title.worldgen'))
return <main> return <main>
<div class="container worldgen"> <div class="legacy-container worldgen">
<div class="card-group"> <div class="card-group">
<ToolGroup title={locale('generators.popular')}> <ToolGroup title={locale('generators.popular')}>
<GeneratorCard minimal id="dimension" /> <GeneratorCard minimal id="dimension" />

View File

@@ -278,10 +278,10 @@ const renderHtml: RenderHook = {
if (node.optional()) { if (node.optional()) {
if (value === undefined) { if (value === undefined) {
const onExpand = () => path.set(DataModel.wrapLists(node.default())) const onExpand = () => path.set(DataModel.wrapLists(node.default()))
suffix = <button class="collapse closed tooltipped tip-se" aria-label={localize(lang, 'expand')} onClick={onExpand}>{Octicon.plus_circle}</button> suffix = <button class="node-collapse closed tooltipped tip-se" aria-label={localize(lang, 'expand')} onClick={onExpand}>{Octicon.plus_circle}</button>
} else { } else {
const onCollapse = () => path.set(undefined) const onCollapse = () => path.set(undefined)
suffix = <button class="collapse open tooltipped tip-se" aria-label={localize(lang, 'remove')} onClick={onCollapse}>{Octicon.trashcan}</button> suffix = <button class="node-collapse open tooltipped tip-se" aria-label={localize(lang, 'remove')} onClick={onCollapse}>{Octicon.trashcan}</button>
} }
} }
const context = path.getContext().join('.') const context = path.getContext().join('.')

View File

@@ -126,12 +126,6 @@
} }
} }
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
::selection { ::selection {
background-color: var(--selection); background-color: var(--selection);
} }
@@ -1444,7 +1438,7 @@ main.has-project {
box-shadow: none; box-shadow: none;
} }
.container { .legacy-container {
padding: 16px; padding: 16px;
max-width: 960px; max-width: 960px;
margin: 0 auto; margin: 0 auto;
@@ -2421,8 +2415,8 @@ hr {
background-color: var(--background-1); background-color: var(--background-1);
border: 3px solid var(--text-1); border: 3px solid var(--text-1);
border-radius: 10px; border-radius: 10px;
width: 10px; width: 16px;
height: 10px; height: 16px;
} }
.whats-new-entry > a { .whats-new-entry > a {
@@ -2650,6 +2644,7 @@ hr {
padding: 8px 16px; padding: 8px 16px;
line-height: 1.2; line-height: 1.2;
font-size: 90%; font-size: 90%;
list-style-type: decimal;
} }
.guide-content { .guide-content {

15
src/styles/main.css Normal file
View File

@@ -0,0 +1,15 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
html {
line-height: normal;
}
a {
text-decoration: underline;
}
input::placeholder {
color: rgb(117, 117, 117);
}

View File

@@ -165,7 +165,7 @@
background-color: var(--node-background-input); background-color: var(--node-background-input);
} }
.object-node > .node-header > .collapse { .object-node > .node-header > .node-collapse {
cursor: pointer; cursor: pointer;
} }
@@ -215,40 +215,37 @@ button:not([disabled]).selected:hover {
background-color: var(--node-selected-hover); background-color: var(--node-selected-hover);
} }
.collapse svg { .node-collapse svg {
fill: var(--node-text); fill: var(--node-text);
} }
.collapse.closed, .node-collapse.closed,
button.add { button.add {
background-color: var(--node-add); background-color: var(--node-add);
border-color: var(--node-add-border); border-color: var(--node-add-border);
} }
.collapse:not([disabled]).closed:hover, .node-collapse:not([disabled]).closed:hover,
button:not([disabled]).add:hover { button:not([disabled]).add:hover {
background-color: var(--node-add-hover); background-color: var(--node-add-hover);
} }
.collapse.open, .node-collapse.open,
button.remove { button.remove {
background-color: var(--node-remove); background-color: var(--node-remove);
border-color: var(--node-remove-border); border-color: var(--node-remove-border);
} }
.collapse:not([disabled]).open:hover, .node-collapse:not([disabled]).open:hover,
button:not([disabled]).remove:hover { button:not([disabled]).remove:hover {
background-color: var(--node-remove-hover); background-color: var(--node-remove-hover);
} }
.node-header > button svg { .node-header > button svg {
display: inline-block;
position: relative;
top: 2px;
fill: var(--node-text); fill: var(--node-text);
} }
.node-header > button.collapse:last-child, .node-header > button.node-collapse:last-child,
.node-header > button.add:last-child { .node-header > button.add:last-child {
border-top-right-radius: 6px; border-top-right-radius: 6px;
border-bottom-right-radius: 6px; border-bottom-right-radius: 6px;

11
tailwind.config.js Normal file
View File

@@ -0,0 +1,11 @@
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./index.html",
"./src/app/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}