mirror of
https://github.com/Motschen/midnightdust-eu.git
synced 2025-12-16 18:45:10 +01:00
Add many interactive components
- Version selector for MidnightLib is now finally working - Added buttons to copy code from code blocks - Added color chooser in Puzzle wiki
This commit is contained in:
71
src/components/ColorPicker.astro
Normal file
71
src/components/ColorPicker.astro
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
---
|
||||||
|
interface Props {
|
||||||
|
includeHashtag?: boolean
|
||||||
|
}
|
||||||
|
const { includeHashtag } = Astro.props
|
||||||
|
import { Icon } from 'astro-icon/components'
|
||||||
|
---
|
||||||
|
|
||||||
|
<section class="my-6">
|
||||||
|
<div class="">
|
||||||
|
<p class="text-lg">Select a color below to get the hex code:</p>
|
||||||
|
<div class="flex">
|
||||||
|
<fieldset>
|
||||||
|
<input
|
||||||
|
type="color"
|
||||||
|
id="color-select"
|
||||||
|
class="h-16 w-48 hover:cursor-pointer rounded-xl border-neutral-900 dark:border-neutral-100 border-4"
|
||||||
|
/>
|
||||||
|
</fieldset>
|
||||||
|
<button
|
||||||
|
id="copy-button"
|
||||||
|
class="button has-icon color-secondary ml-3 rounded-md text-white hover:cursor-pointer appearance-none h-16">
|
||||||
|
<Icon id="copy-icon" name="ion:copy-outline" />
|
||||||
|
<Icon id="success-icon" name="ion:checkmark-outline" class="hidden" />
|
||||||
|
<p id="color-label">{includeHashtag ? '#' : ''}000000</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Get the 2 elements from above
|
||||||
|
const colorLabel = document.getElementById("color-label");
|
||||||
|
const colorSelect = document.getElementById("color-select");
|
||||||
|
const copyButton = document.getElementById("copy-button");
|
||||||
|
|
||||||
|
const copyIcon = document.getElementById("copy-icon");
|
||||||
|
const successIcon = document.getElementById("success-icon");
|
||||||
|
|
||||||
|
colorSelect?.addEventListener("change", async (e) => {
|
||||||
|
const {
|
||||||
|
target: { value }, // Returns the chosen color (already in hex format :D)
|
||||||
|
} = e;
|
||||||
|
if (colorLabel) colorLabel.innerText = colorLabel.innerText.startsWith('#') ? value : value.replace('#', '');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add event listener to copy the color to the clipboard
|
||||||
|
if (colorLabel) copyButton?.addEventListener('click', () => copyString(colorLabel.innerText, copyButton));
|
||||||
|
|
||||||
|
|
||||||
|
async function copyString(text: string, button: HTMLElement) {
|
||||||
|
await navigator.clipboard.writeText(text);
|
||||||
|
|
||||||
|
// visual feedback that task is completed
|
||||||
|
if (button) {
|
||||||
|
button.style.backgroundColor = "#"+text.replace('#', '');
|
||||||
|
button.style.borderColor = "#"+text.replace('#', '');
|
||||||
|
}
|
||||||
|
if (copyIcon) copyIcon.style.display = 'none';
|
||||||
|
if (successIcon) successIcon.style.display = 'initial';
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
if (button) {
|
||||||
|
button.style.backgroundColor = 'var(--secondary-100)';
|
||||||
|
button.style.borderColor = 'var(--secondary-100)';
|
||||||
|
}
|
||||||
|
if (copyIcon) copyIcon.style.display = 'initial';
|
||||||
|
if (successIcon) successIcon.style.display = 'none';
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
@@ -1,161 +1,68 @@
|
|||||||
---
|
---
|
||||||
import { loaderList, versionList, selectedLoader, selectedVersion, getResultingVersion } from '../js/modversion.js'
|
import { Icon } from 'astro-icon/components'
|
||||||
|
import { loaderList, versionList} from '../js/modversion.js'
|
||||||
---
|
---
|
||||||
|
|
||||||
<div id="version-dropdown">
|
<div id="version-dropdown">
|
||||||
<div class="container">
|
<div class="">
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
<label for="loader-selector" class="sr-only">Select the Modloader</label>
|
<label for="loader-selector" class="sr-only">Select the Modloader</label>
|
||||||
<select
|
<select
|
||||||
x-data="{
|
|
||||||
loader: localStorage.selectedLoader || 'fabric',
|
|
||||||
switchLoader: function (newValue) {
|
|
||||||
localStorage.selectedLoader = newValue;
|
|
||||||
console.log('New loader: ' + localStorage.selectedLoader);
|
|
||||||
},
|
|
||||||
}"
|
|
||||||
name="loader-selector"
|
name="loader-selector"
|
||||||
id="loader-selector"
|
id="loader-selector"
|
||||||
class="appearance-none cursor-pointer rounded-md pl-3 pr-2 py-1.5 dark:bg-stone-950 dark:text-white focus-visible:outline-none"
|
class="selector cursor-pointer rounded-md pl-3 pr-2 py-1.5 border-2 dark:border-green-300 dark:bg-neutral-800 dark:text-white focus-visible:outline-none"
|
||||||
x-model="loader"
|
aria-label="Choose the Modloader">
|
||||||
aria-label="Choose the Modloader"
|
|
||||||
@change="switchLoader($event.target.value)">
|
|
||||||
{ loaderList.map((loader) =>
|
{ loaderList.map((loader) =>
|
||||||
<option value={loader}>{loader.charAt(0).toUpperCase() + loader.slice(1)}</option>
|
<option value={loader}>{loader.charAt(0).toUpperCase() + loader.replace("neoforge", "NeoForge").slice(1)}</option>
|
||||||
)}
|
)}
|
||||||
</select>
|
</select>
|
||||||
<label for="version-selector" class="sr-only">Select the Version</label>
|
<label for="version-selector" class="sr-only">Select the Version</label>
|
||||||
<select
|
<select
|
||||||
x-data="{
|
|
||||||
version: localStorage.selectedVersion || '1.21.1',
|
|
||||||
switchVersion: function (newValue) {
|
|
||||||
localStorage.selectedVersion = newValue;
|
|
||||||
console.log('New version: ' + localStorage.selectedVersion);
|
|
||||||
console.log(getResultingVersion);
|
|
||||||
},
|
|
||||||
}"
|
|
||||||
name="version-selector"
|
name="version-selector"
|
||||||
id="version-selector"
|
id="version-selector"
|
||||||
class="appearance-none cursor-pointer rounded-md pl-3 pr-2 py-1.5 dark:bg-stone-950 dark:text-white focus-visible:outline-none"
|
class="selector cursor-pointer rounded-md ml-2 pl-3 pr-2 py-1.5 border-2 dark:border-green-300 dark:bg-neutral-800 dark:text-white focus-visible:outline-none"
|
||||||
x-model="version"
|
aria-label="Choose the Version">
|
||||||
aria-label="Choose the Version"
|
|
||||||
@change="switchVersion($event.target.value)">
|
|
||||||
{ versionList.map((version) =>
|
{ versionList.map((version) =>
|
||||||
<option value={version}>{version}</option>
|
<option value={version}>{version}</option>
|
||||||
)}
|
)}
|
||||||
|
<Icon name="ion:copy-outline"></Icon>
|
||||||
</select>
|
</select>
|
||||||
<label for="version-selector" x-text="">{}</label>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getResultingVersion, setGameVersion, setLoaderVersion } from "../js/modversion";
|
||||||
|
// Get the gradle.properties code block
|
||||||
|
const versionLabel = document.getElementById("midnightlib-version");
|
||||||
|
// Get the 2 selectors defined above
|
||||||
|
const loaderSelector = document.getElementById("loader-selector");
|
||||||
|
const versionSelector = document.getElementById("version-selector");
|
||||||
|
|
||||||
|
loaderSelector?.addEventListener("change", async (e) => {
|
||||||
|
const {
|
||||||
|
target: { value }, // Returns the current loader string
|
||||||
|
} = e;
|
||||||
|
|
||||||
|
setLoaderVersion(value);
|
||||||
|
if (versionLabel) versionLabel.innerText = `midnightlib_version = `+getResultingVersion();
|
||||||
|
});
|
||||||
|
versionSelector?.addEventListener("change", async (e) => {
|
||||||
|
const {
|
||||||
|
target: { value }, // Returns the current version string
|
||||||
|
} = e;
|
||||||
|
|
||||||
|
setGameVersion(value);
|
||||||
|
if (versionLabel) versionLabel.innerText = `midnightlib_version = `+getResultingVersion();
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
<style lang="scss" is:global>
|
<style lang="scss" is:global>
|
||||||
@use '../assets/scss/base/breakpoint' as *;
|
#loader-selector::after {
|
||||||
@use '../assets/scss/base/outline' as *;
|
content: "v";
|
||||||
|
}
|
||||||
#version-dropdown {
|
.selector:is(.darkmode *) {
|
||||||
> .container {
|
background-color: var(--dark-100);
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.wrapper {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wrapper {
|
|
||||||
> ul {
|
|
||||||
display: flex;
|
|
||||||
gap: 1.5rem;
|
|
||||||
list-style-type: none;
|
|
||||||
|
|
||||||
a,
|
|
||||||
button {
|
|
||||||
text-decoration: none;
|
|
||||||
font-size: 1.125rem;
|
|
||||||
line-height: 1.6875rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:hover,
|
|
||||||
a:focus,
|
|
||||||
.is-active,
|
|
||||||
.has-version-dropdown > button:hover,
|
|
||||||
.has-version-dropdown > button:focus {
|
|
||||||
text-decoration: underline;
|
|
||||||
text-decoration-thickness: 1px;
|
|
||||||
text-decoration-style: wavy;
|
|
||||||
text-underline-offset: 7px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.is-active {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.has-version-dropdown {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
> button {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.5rem;
|
|
||||||
padding: 0;
|
|
||||||
margin-top: -1px;
|
|
||||||
border: none;
|
|
||||||
color: var(--action-color);
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: var(--action-color-state);
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
border-color: var(--action-color-state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
content: '';
|
|
||||||
width: 0.85rem;
|
|
||||||
height: 0.75em;
|
|
||||||
margin-top: -0.25rem;
|
|
||||||
border-style: solid;
|
|
||||||
border-width: 0.2em 0.2em 0 0;
|
|
||||||
border-color: var(--action-color);
|
|
||||||
transform: rotate(135deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.show {
|
|
||||||
&::after {
|
|
||||||
margin-top: 0.25rem;
|
|
||||||
transform: rotate(-45deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
~ ul {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ul {
|
|
||||||
display: none;
|
|
||||||
position: absolute;
|
|
||||||
z-index: 100;
|
|
||||||
min-width: 260px;
|
|
||||||
top: 125%;
|
|
||||||
right: 0;
|
|
||||||
bottom: auto;
|
|
||||||
left: 0;
|
|
||||||
padding: 1rem;
|
|
||||||
background-color: var(--neutral-background);
|
|
||||||
border: 2px solid black;
|
|
||||||
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.15);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -3,6 +3,44 @@ import DefaultLayout from './DefaultLayout.astro'
|
|||||||
|
|
||||||
const { frontmatter } = Astro.props
|
const { frontmatter } = Astro.props
|
||||||
---
|
---
|
||||||
|
<!-- Copy Code Buttons based on: https://timneubauer.dev/blog/copy-code-button-in-astro/ -->
|
||||||
|
<script>
|
||||||
|
let copyButtonLabel = "Copy Code";
|
||||||
|
let codeBlocks = Array.from(document.querySelectorAll("pre"));
|
||||||
|
|
||||||
|
for (let codeBlock of codeBlocks) {
|
||||||
|
let wrapper = document.createElement("div");
|
||||||
|
wrapper.style.position = "relative";
|
||||||
|
|
||||||
|
let copyButton = document.createElement("button");
|
||||||
|
copyButton.className = "copy-code";
|
||||||
|
copyButton.innerHTML = copyButtonLabel;
|
||||||
|
|
||||||
|
codeBlock.setAttribute("tabindex", "0");
|
||||||
|
codeBlock.appendChild(copyButton);
|
||||||
|
// wrap codebock with relative parent element
|
||||||
|
if (codeBlock.parentNode) codeBlock.parentNode.insertBefore(wrapper, codeBlock);
|
||||||
|
wrapper.appendChild(codeBlock);
|
||||||
|
|
||||||
|
copyButton.addEventListener("click", async () => {
|
||||||
|
await copyCode(codeBlock, copyButton);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function copyCode(block, button) {
|
||||||
|
let code = block.querySelector("code");
|
||||||
|
let text = code.innerText;
|
||||||
|
|
||||||
|
await navigator.clipboard.writeText(text);
|
||||||
|
|
||||||
|
// visual feedback that task is completed
|
||||||
|
button.innerText = "Code Copied!";
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
button.innerText = copyButtonLabel;
|
||||||
|
}, 700);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<DefaultLayout title={frontmatter.title}>
|
<DefaultLayout title={frontmatter.title}>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
@@ -11,3 +49,35 @@ const { frontmatter } = Astro.props
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</DefaultLayout>
|
</DefaultLayout>
|
||||||
|
|
||||||
|
<style is:global>
|
||||||
|
.copy-code {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
background-color: var(--primary-300);
|
||||||
|
color: var(--neutral-100);
|
||||||
|
padding: 0.25rem 0.5rem;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
line-height: 1rem;
|
||||||
|
border: none;
|
||||||
|
border-top-right-radius: 0.35rem;
|
||||||
|
border-bottom-left-radius: 0.35rem;
|
||||||
|
box-shadow: -1px 1px 8px var(--primary-300);
|
||||||
|
}
|
||||||
|
.copy-code:is(.darkmode *) {
|
||||||
|
background-color: var(--secondary-100);
|
||||||
|
color: var(--dark-100);
|
||||||
|
box-shadow: -1px 1px 8px var(--secondary-100);
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-code:hover {
|
||||||
|
background-color: var(--primary-500);
|
||||||
|
box-shadow: -1px 1px 8px var(--primary-500);
|
||||||
|
}
|
||||||
|
.copy-code:hover:is(.darkmode *) {
|
||||||
|
background-color: var(--secondary-500);
|
||||||
|
box-shadow: -1px 1px 8px var(--secondary-500);
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -33,14 +33,13 @@ dependencies {
|
|||||||
```
|
```
|
||||||
### `gradle.properties`
|
### `gradle.properties`
|
||||||
<VersionDropdown></VersionDropdown>
|
<VersionDropdown></VersionDropdown>
|
||||||
{<pre><code className="language-java">midnightlib_version = {getResultingVersion()}</code></pre>}
|
{<pre><code className="language-java" id="midnightlib-version" >midnightlib_version = {getResultingVersion()}</code></pre>}
|
||||||
|
|
||||||
<Notification type="info">
|
<Notification type="info">
|
||||||
<Icon name="ion:information-circle-outline" />
|
<Icon name="ion:information-circle-outline" />
|
||||||
<p>
|
<p>
|
||||||
<strong>Info:</strong> You should always pick the version that suits your modloader and Minecraft version best.
|
<strong>Info:</strong> You should always pick the version that suits your modloader and Minecraft version best.
|
||||||
The version selector is currently still WIP.
|
The version selector is finally fully functional!
|
||||||
Find all available versions on [Modrinth](https://www.modrinth.com/mod/midnightlib/versions)
|
|
||||||
</p>
|
</p>
|
||||||
</Notification>
|
</Notification>
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ layout: ../../layouts/MarkdownLayout.astro
|
|||||||
title: Puzzle Wiki
|
title: Puzzle Wiki
|
||||||
---
|
---
|
||||||
|
|
||||||
|
import ColorPicker from '../../components/ColorPicker.astro'
|
||||||
import { Icon } from 'astro-icon/components'
|
import { Icon } from 'astro-icon/components'
|
||||||
import { Notification } from 'accessible-astro-components'
|
import { Notification } from 'accessible-astro-components'
|
||||||
|
|
||||||
@@ -51,7 +52,7 @@ screen.loading.blend=off
|
|||||||
|
|
||||||
### Entering the world of color
|
### Entering the world of color
|
||||||
The world would be a sad place without colors.
|
The world would be a sad place without colors.
|
||||||
That's why Puzzle allows you to customize them to your heart's content.
|
That's why Puzzle allows you to customize them to your heart's content!
|
||||||
Custom colors can be defined in the `assets/minecraft/optifine/color.properties` file.
|
Custom colors can be defined in the `assets/minecraft/optifine/color.properties` file.
|
||||||
|
|
||||||
```properties
|
```properties
|
||||||
@@ -69,11 +70,12 @@ screen.loading.bar=313244
|
|||||||
<Notification type="default">
|
<Notification type="default">
|
||||||
<Icon name="ion:information-circle-outline" />
|
<Icon name="ion:information-circle-outline" />
|
||||||
<p>
|
<p>
|
||||||
<strong>Info:</strong> Colors have to be defined using hex color codes.
|
<strong>Info:</strong> Colors have to be defined using hex color codes (without the #).
|
||||||
You can use websites like <strong>[this](https://redketchup.io/color-picker)</strong> one to find nice hex color codes.
|
You can use the color picker below to find the perfect color.
|
||||||
The example colors are based on the <strong>[Catppuccin Mocha](https://github.com/catppuccin/catppuccin)</strong> color pallette.
|
The example colors are based on the <strong>[Catppuccin Mocha](https://github.com/catppuccin/catppuccin)</strong> color pallette.
|
||||||
</p>
|
</p>
|
||||||
</Notification>
|
</Notification>
|
||||||
|
<ColorPicker/>
|
||||||
|
|
||||||
<center><img alt="The Puzzle logo on a dark background with pastel colors" src="/puzzle/custom-colors.webp" width="650"></img></center>
|
<center><img alt="The Puzzle logo on a dark background with pastel colors" src="/puzzle/custom-colors.webp" width="650"></img></center>
|
||||||
<p class="text-center italic">Dark mode! Finally, my eyes can rest.</p>
|
<p class="text-center italic">Dark mode! Finally, my eyes can rest.</p>
|
||||||
|
|||||||
Reference in New Issue
Block a user