commit 6250df2ff1b933af615e9a4bc41efc66fb810c07
Author: root <root@hub.scroll.pub> Date: 2024-12-29 18:35:38 +0000 Subject: Initial commit diff --git a/body.html b/body.html new file mode 100644 index 0000000..0863034 --- /dev/null +++ b/body.html @@ -0,0 +1,19 @@ +<header> + <h1>RevealText</h1> + <p class="tagline">Scroll to unveil your story, one word at a time</p> +</header> + +<main> + <section class="input-section"> + <textarea id="textInput" placeholder="Paste or type your text here..."></textarea> + <button id="startButton">Begin Reading</button> + </section> + + <section id="readingContainer" class="reading-section hidden"> + <div id="wordContainer"></div> + </section> +</main> + +<footer> + <p>Made with care by RevealText</p> +</footer> diff --git a/index.scroll b/index.scroll new file mode 100644 index 0000000..65ce605 --- /dev/null +++ b/index.scroll @@ -0,0 +1,8 @@ +buildHtml +baseUrl https://revealtext.scroll.pub +metaTags +editButton /edit.html +title RevealText - Scroll to Reveal Your Words +style.css +body.html +script.js diff --git a/prompt.json b/prompt.json new file mode 100644 index 0000000..1a75600 --- /dev/null +++ b/prompt.json @@ -0,0 +1,20 @@ +{ + "id": "msg_01AFeAdM6J5qVpcgqKVbyYkd", + "type": "message", + "role": "assistant", + "model": "claude-3-5-sonnet-20241022", + "content": [ + { + "type": "text", + "text": "I'll create a website called \"RevealText\" - a simple but elegant text revealer that smoothly reveals text as you scroll.\n\n---domain---\nrevealtext.scroll.pub\n\n---index.scroll---\nbuildHtml\nbaseUrl https://revealtext.scroll.pub\nmetaTags\neditButton /edit.html\ntitle RevealText - Scroll to Reveal Your Words\nstyle.css\nbody.html\nscript.js\n\n---body.html---\n<header>\n <h1>RevealText</h1>\n <p class=\"tagline\">Scroll to unveil your story, one word at a time</p>\n</header>\n\n<main>\n <section class=\"input-section\">\n <textarea id=\"textInput\" placeholder=\"Paste or type your text here...\"></textarea>\n <button id=\"startButton\">Begin Reading</button>\n </section>\n \n <section id=\"readingContainer\" class=\"reading-section hidden\">\n <div id=\"wordContainer\"></div>\n </section>\n</main>\n\n<footer>\n <p>Made with care by RevealText</p>\n</footer>\n\n---style.css---\n:root {\n --primary-color: #2a2a72;\n --secondary-color: #009ffd;\n --text-color: #333;\n --background-color: #f8f9fa;\n --spacing: 2rem;\n}\n\n* {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n}\n\nbody {\n font-family: 'Segoe UI', system-ui, sans-serif;\n line-height: 1.6;\n color: var(--text-color);\n background: var(--background-color);\n min-height: 100vh;\n}\n\nheader {\n background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));\n color: white;\n padding: var(--spacing);\n text-align: center;\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\nh1 {\n font-size: 2.5rem;\n margin-bottom: 0.5rem;\n font-weight: 700;\n}\n\n.tagline {\n font-size: 1.1rem;\n opacity: 0.9;\n}\n\nmain {\n max-width: 800px;\n margin: 0 auto;\n padding: var(--spacing);\n}\n\n.input-section {\n margin-bottom: var(--spacing);\n}\n\ntextarea {\n width: 100%;\n height: 200px;\n padding: 1rem;\n border: 2px solid #ddd;\n border-radius: 8px;\n font-size: 1.1rem;\n resize: vertical;\n transition: border-color 0.3s ease;\n}\n\ntextarea:focus {\n border-color: var(--secondary-color);\n outline: none;\n}\n\nbutton {\n display: block;\n margin: 1rem auto;\n padding: 0.8rem 2rem;\n font-size: 1.1rem;\n background: var(--primary-color);\n color: white;\n border: none;\n border-radius: 25px;\n cursor: pointer;\n transition: transform 0.2s ease, background-color 0.2s ease;\n}\n\nbutton:hover {\n background: var(--secondary-color);\n transform: translateY(-2px);\n}\n\n.reading-section {\n min-height: 300vh;\n padding: 2rem;\n}\n\n#wordContainer {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n font-size: 2.5rem;\n font-weight: 500;\n text-align: center;\n width: 90%;\n max-width: 600px;\n}\n\n.word {\n opacity: 0;\n transition: opacity 0.3s ease;\n}\n\n.word.visible {\n opacity: 1;\n}\n\n.hidden {\n display: none;\n}\n\nfooter {\n text-align: center;\n padding: var(--spacing);\n background: #f1f1f1;\n margin-top: auto;\n}\n\n@media (max-width: 768px) {\n :root {\n --spacing: 1rem;\n }\n \n h1 {\n font-size: 2rem;\n }\n \n #wordContainer {\n font-size: 1.8rem;\n }\n}\n\n---script.js---\ndocument.addEventListener('DOMContentLoaded', () => {\n const textInput = document.getElementById('textInput');\n const startButton = document.getElementById('startButton');\n const readingContainer = document.getElementById('readingContainer');\n const wordContainer = document.getElementById('wordContainer');\n const inputSection = document.querySelector('.input-section');\n \n let words = [];\n let currentWordIndex = 0;\n \n startButton.addEventListener('click', () => {\n const text = textInput.value.trim();\n if (text) {\n words = text.split(/\\s+/);\n inputSection.classList.add('hidden');\n readingContainer.classList.remove('hidden');\n initializeReading();\n }\n });\n \n function initializeReading() {\n wordContainer.innerHTML = '';\n words.forEach((word, index) => {\n const wordSpan = document.createElement('span');\n wordSpan.textContent = word;\n wordSpan.classList.add('word');\n wordSpan.dataset.index = index;\n wordContainer.appendChild(wordSpan);\n \n if (index < words.length - 1) {\n wordContainer.appendChild(document.createTextNode(' '));\n }\n });\n \n updateVisibility();\n }\n \n function updateVisibility() {\n const scrollPercentage = window.scrollY / (document.documentElement.scrollHeight - window.innerHeight);\n const wordIndex = Math.floor(scrollPercentage * words.length);\n \n document.querySelectorAll('.word').forEach((wordSpan) => {\n const index = parseInt(wordSpan.dataset.index);\n if (index <= wordIndex) {\n wordSpan.classList.add('visible');\n } else {\n wordSpan.classList.remove('visible');\n }\n });\n }\n \n window.addEventListener('scroll', () => {\n if (!readingContainer.classList.contains('hidden')) {\n updateVisibility();\n }\n });\n \n window.addEventListener('resize', () => {\n if (!readingContainer.classList.contains('hidden')) {\n updateVisibility();\n }\n });\n});\n\n---end---\n\nThis implementation provides:\n1. A clean, modern interface with smooth animations\n2. Mobile-responsive design\n3. Semantic HTML5 structure\n4. Smooth text reveal based on scroll position\n5. Beautiful gradient header and intuitive UI\n6. Accessible color contrast and focus states\n7. Error handling for empty input\n8. Performance optimized animations\n9. Clean separation of concerns (HTML/CSS/JS)\n\nThe user can paste or type text into the textarea, click \"Begin Reading\" and then scroll to reveal the text word by word. The revealed words stay visible while scrolling forward and hide when scrolling back." + } + ], + "stop_reason": "end_turn", + "stop_sequence": null, + "usage": { + "input_tokens": 296, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "output_tokens": 1849 + } +} \ No newline at end of file diff --git a/readme.scroll b/readme.scroll new file mode 100644 index 0000000..e2fe425 --- /dev/null +++ b/readme.scroll @@ -0,0 +1,2 @@ +# revealtext.scroll.pub +Website generated by Claude from prompt: Create a website that allows me to upload free text and then scroll down word for word. Keep the revealed words unless I scroll back \ No newline at end of file diff --git a/script.js b/script.js new file mode 100644 index 0000000..3c3095b --- /dev/null +++ b/script.js @@ -0,0 +1,63 @@ +document.addEventListener('DOMContentLoaded', () => { + const textInput = document.getElementById('textInput'); + const startButton = document.getElementById('startButton'); + const readingContainer = document.getElementById('readingContainer'); + const wordContainer = document.getElementById('wordContainer'); + const inputSection = document.querySelector('.input-section'); + + let words = []; + let currentWordIndex = 0; + + startButton.addEventListener('click', () => { + const text = textInput.value.trim(); + if (text) { + words = text.split(/\s+/); + inputSection.classList.add('hidden'); + readingContainer.classList.remove('hidden'); + initializeReading(); + } + }); + + function initializeReading() { + wordContainer.innerHTML = ''; + words.forEach((word, index) => { + const wordSpan = document.createElement('span'); + wordSpan.textContent = word; + wordSpan.classList.add('word'); + wordSpan.dataset.index = index; + wordContainer.appendChild(wordSpan); + + if (index < words.length - 1) { + wordContainer.appendChild(document.createTextNode(' ')); + } + }); + + updateVisibility(); + } + + function updateVisibility() { + const scrollPercentage = window.scrollY / (document.documentElement.scrollHeight - window.innerHeight); + const wordIndex = Math.floor(scrollPercentage * words.length); + + document.querySelectorAll('.word').forEach((wordSpan) => { + const index = parseInt(wordSpan.dataset.index); + if (index <= wordIndex) { + wordSpan.classList.add('visible'); + } else { + wordSpan.classList.remove('visible'); + } + }); + } + + window.addEventListener('scroll', () => { + if (!readingContainer.classList.contains('hidden')) { + updateVisibility(); + } + }); + + window.addEventListener('resize', () => { + if (!readingContainer.classList.contains('hidden')) { + updateVisibility(); + } + }); +}); diff --git a/style.css b/style.css new file mode 100644 index 0000000..e833300 --- /dev/null +++ b/style.css @@ -0,0 +1,135 @@ +:root { + --primary-color: #2a2a72; + --secondary-color: #009ffd; + --text-color: #333; + --background-color: #f8f9fa; + --spacing: 2rem; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Segoe UI', system-ui, sans-serif; + line-height: 1.6; + color: var(--text-color); + background: var(--background-color); + min-height: 100vh; +} + +header { + background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + color: white; + padding: var(--spacing); + text-align: center; + box-shadow: 0 2px 10px rgba(0,0,0,0.1); +} + +h1 { + font-size: 2.5rem; + margin-bottom: 0.5rem; + font-weight: 700; +} + +.tagline { + font-size: 1.1rem; + opacity: 0.9; +} + +main { + max-width: 800px; + margin: 0 auto; + padding: var(--spacing); +} + +.input-section { + margin-bottom: var(--spacing); +} + +textarea { + width: 100%; + height: 200px; + padding: 1rem; + border: 2px solid #ddd; + border-radius: 8px; + font-size: 1.1rem; + resize: vertical; + transition: border-color 0.3s ease; +} + +textarea:focus { + border-color: var(--secondary-color); + outline: none; +} + +button { + display: block; + margin: 1rem auto; + padding: 0.8rem 2rem; + font-size: 1.1rem; + background: var(--primary-color); + color: white; + border: none; + border-radius: 25px; + cursor: pointer; + transition: transform 0.2s ease, background-color 0.2s ease; +} + +button:hover { + background: var(--secondary-color); + transform: translateY(-2px); +} + +.reading-section { + min-height: 300vh; + padding: 2rem; +} + +#wordContainer { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + font-size: 2.5rem; + font-weight: 500; + text-align: center; + width: 90%; + max-width: 600px; +} + +.word { + opacity: 0; + transition: opacity 0.3s ease; +} + +.word.visible { + opacity: 1; +} + +.hidden { + display: none; +} + +footer { + text-align: center; + padding: var(--spacing); + background: #f1f1f1; + margin-top: auto; +} + +@media (max-width: 768px) { + :root { + --spacing: 1rem; + } + + h1 { + font-size: 2rem; + } + + #wordContainer { + font-size: 1.8rem; + } +}