diff --git a/src/index.html b/src/index.html index 83e0f1c..e08218d 100644 --- a/src/index.html +++ b/src/index.html @@ -15,6 +15,13 @@
+
+ +
@@ -67,6 +74,103 @@
+ +
+ + +
+
+

Roleplay Tools

+ +
+ +
+ + + +
+ +
+
+
+ +

+ Create entries that inject context when keywords are mentioned. +

+ +
+
+ +
+
+
+ +
+
+
+ +

+ Instructions inserted near the end of the prompt before the latest messages. +

+ +
+
+ +
+ +
+
+ +
+
+
+ + +
+
+ +

+ Describe yourself as the user in this roleplay. +

+ +
+
+ +
+ +
+
+
+
diff --git a/src/main.js b/src/main.js index eadfdfa..80dca5a 100644 --- a/src/main.js +++ b/src/main.js @@ -1061,8 +1061,24 @@ function hideSettings() { overlay.classList.remove('show'); } +// Show/hide roleplay panel +function showRoleplayPanel() { + const panel = document.getElementById('roleplay-panel'); + const overlay = document.getElementById('roleplay-overlay'); + panel.classList.add('open'); + overlay.classList.add('show'); +} + +function hideRoleplayPanel() { + const panel = document.getElementById('roleplay-panel'); + const overlay = document.getElementById('roleplay-overlay'); + panel.classList.remove('open'); + overlay.classList.remove('show'); +} + // Tab switching function setupTabs() { + // Settings tabs const tabBtns = document.querySelectorAll('.tab-btn'); const tabContents = document.querySelectorAll('.tab-content'); @@ -1079,6 +1095,24 @@ function setupTabs() { document.getElementById(`${targetTab}-tab`).classList.add('active'); }); }); + + // Roleplay tabs + const roleplayTabBtns = document.querySelectorAll('.roleplay-tab-btn'); + const roleplayTabContents = document.querySelectorAll('.roleplay-tab-content'); + + roleplayTabBtns.forEach(btn => { + btn.addEventListener('click', () => { + const targetTab = btn.getAttribute('data-tab'); + + // Remove active class from all roleplay tabs and contents + roleplayTabBtns.forEach(b => b.classList.remove('active')); + roleplayTabContents.forEach(c => c.classList.remove('active')); + + // Add active class to clicked tab and corresponding content + btn.classList.add('active'); + document.getElementById(`${targetTab}-tab`).classList.add('active'); + }); + }); } // Handle form submission @@ -1246,6 +1280,9 @@ function setupAppControls() { document.getElementById('settings-btn').addEventListener('click', showSettings); document.getElementById('close-settings-btn').addEventListener('click', hideSettings); document.getElementById('settings-overlay').addEventListener('click', hideSettings); + document.getElementById('roleplay-btn').addEventListener('click', showRoleplayPanel); + document.getElementById('close-roleplay-btn').addEventListener('click', hideRoleplayPanel); + document.getElementById('roleplay-overlay').addEventListener('click', hideRoleplayPanel); document.getElementById('clear-btn').addEventListener('click', clearHistory); document.getElementById('export-chat-btn').addEventListener('click', exportChatHistory); document.getElementById('import-chat-btn').addEventListener('click', importChatHistory); diff --git a/src/styles.css b/src/styles.css index 052643a..55d45f0 100644 --- a/src/styles.css +++ b/src/styles.css @@ -1505,6 +1505,117 @@ body.view-comfortable .message-content pre { margin: 12px 0; } +/* Roleplay Panel - Slide-in from Left */ +.roleplay-panel { + position: fixed; + top: 0; + left: -500px; + width: 500px; + height: 100vh; + background: var(--bg-primary); + border-right: 1px solid var(--border); + box-shadow: 4px 0 20px rgba(0, 0, 0, 0.3); + z-index: 1000; + overflow-y: auto; + padding: 20px; + transition: left 0.3s ease; +} + +.roleplay-panel.open { + left: 0; +} + +.roleplay-overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.5); + z-index: 999; + opacity: 0; + pointer-events: none; + transition: opacity 0.3s ease; +} + +.roleplay-overlay.show { + opacity: 1; + pointer-events: auto; +} + +.roleplay-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 24px; + padding-bottom: 16px; + border-bottom: 1px solid var(--border); +} + +.roleplay-header h2 { + font-size: 24px; + font-weight: 600; + color: var(--text-primary); + margin: 0; +} + +.roleplay-tabs { + display: flex; + gap: 8px; + margin-bottom: 24px; +} + +.roleplay-tab-btn { + flex: 1; + padding: 10px 16px; + background: var(--bg-tertiary); + border: 1px solid var(--border); + border-radius: 8px; + color: var(--text-secondary); + font-size: 13px; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; + font-family: inherit; +} + +.roleplay-tab-btn:hover { + background: var(--border); + color: var(--text-primary); +} + +.roleplay-tab-btn.active { + background: var(--accent); + color: white; + border-color: var(--accent); +} + +.roleplay-tab-content { + display: none; +} + +.roleplay-tab-content.active { + display: block; +} + +.roleplay-content { + display: flex; + flex-direction: column; + gap: 20px; +} + +.worldinfo-list { + display: flex; + flex-direction: column; + gap: 12px; + margin-top: 12px; +} + +.header-left-controls { + display: flex; + gap: 8px; +} + /* Responsive */ @media (max-width: 600px) { .messages-list { @@ -1527,4 +1638,13 @@ body.view-comfortable .message-content pre { .settings-panel.open { right: 0; } + + .roleplay-panel { + width: 100%; + left: -100%; + } + + .roleplay-panel.open { + left: 0; + } }