diff --git a/src/js/app/components/icons.js b/src/js/app/components/icons.js
index 67e3d46..bed6501 100644
--- a/src/js/app/components/icons.js
+++ b/src/js/app/components/icons.js
@@ -1,11 +1,30 @@
-export const icon_sun = ``
+const icon_sun = ``
-export const icon_moon = ``
+const icon_moon = ``
-export const icon_moon_full = ``
+const icon_moon_full = ``
-export const icon_settings = ``
+const icon_settings = ``
-export const icon_paint = ``
+const icon_paint = ``
-export const icon_palette = ``
+const icon_palette = ``
+
+const icon_full_width = ``
+
+const icon_sync = ``
+
+const icon_lock = ``
+// const icon_lock = ``
+
+export {
+ icon_sun,
+ icon_moon,
+ icon_moon_full,
+ icon_settings,
+ icon_paint,
+ icon_palette,
+ icon_full_width,
+ icon_sync,
+ icon_lock,
+}
diff --git a/src/js/app/components/renderButtons.js b/src/js/app/components/renderButtons.js
new file mode 100644
index 0000000..7d2b74e
--- /dev/null
+++ b/src/js/app/components/renderButtons.js
@@ -0,0 +1,7 @@
+export function renderButton({ name, className, id, content, disabled = false }) {
+ return `
+
+ `
+}
diff --git a/src/js/app/components/renderFonts.js b/src/js/app/components/renderFonts.js
index 16eea1b..89209cb 100644
--- a/src/js/app/components/renderFonts.js
+++ b/src/js/app/components/renderFonts.js
@@ -91,11 +91,3 @@ export function renderFontBigCard({
// return cardHtml
// }
-
-export function renderButton({ name, className, id, content, disabled = false }) {
- return `
-
- `
-}
diff --git a/src/js/app/components/renderSwitch.js b/src/js/app/components/renderSwitch.js
new file mode 100644
index 0000000..68b7842
--- /dev/null
+++ b/src/js/app/components/renderSwitch.js
@@ -0,0 +1,105 @@
+import { icon_lock } from './icons'
+
+function renderSwitchOption({ inputId, isChecked = false, icon, textTitle, textSubtitle }) {
+ const sanitizedInputId = sanitizeString(inputId)
+ const sanitizedTextTitle = sanitizeString(textTitle)
+ const sanitizedTextSubtitle = sanitizeString(textSubtitle)
+
+ return `
+ `
+}
+
+function renderSmallCardOption({
+ name,
+ inputId,
+ inputType,
+ inputValue,
+ inputPlaceholder,
+ min = 10,
+ max = 100,
+ unit = '%',
+ isLocked = false,
+}) {
+ const sanitizedName = sanitizeString(name)
+ const sanitizedInputId = sanitizeString(inputId)
+ const sanitizedInputValue = sanitizeString(inputValue)
+ const sanitizedInputPlaceholder = sanitizeString(inputPlaceholder)
+
+ const lockIcon = isLocked ? icon_lock : ''
+
+ return `
+
+
+ ${lockIcon}
+
`
+}
+
+function sanitizeString(str) {
+ const div = document.createElement('div')
+ div.textContent = str
+ return div.innerHTML
+}
+
+export { renderSwitchOption, renderSmallCardOption }
diff --git a/src/js/app/floatingBtn.js b/src/js/app/floatingBtn.js
index 3e73a6e..077cde6 100644
--- a/src/js/app/floatingBtn.js
+++ b/src/js/app/floatingBtn.js
@@ -4,8 +4,8 @@ import browser from 'webextension-polyfill'
import { icon_sun, icon_moon, icon_moon_full, icon_settings, icon_paint } from './components/icons.js'
import { hexToHSL } from '../utils/hexToHSL'
-// import { fontHtmlCode, addFontsEventHandlers } from './customFonts'
import { fontHtmlCode, handleFontsListeners } from './mainFonts'
+import { assetsHtmlCode, handleAssetsListeners } from './mainAssets'
// console.log(fontHtmlCode)
// let isOptionsShown = false
@@ -203,8 +203,7 @@ function renderSettings() {
-
ooops, such empty
-
Coming Soon
+ ${assetsHtmlCode}
@@ -225,8 +224,8 @@ function renderSettings() {
$settings.querySelector('#resetAllSettings').addEventListener('click', resetAllSettings)
- // addFontsEventHandlers()
handleFontsListeners()
+ handleAssetsListeners()
}
function openSettings() {
diff --git a/src/js/app/mainAssets.js b/src/js/app/mainAssets.js
new file mode 100644
index 0000000..0bca22a
--- /dev/null
+++ b/src/js/app/mainAssets.js
@@ -0,0 +1,382 @@
+import browser from 'webextension-polyfill'
+import { renderSwitchOption, renderSmallCardOption } from './components/renderSwitch'
+import { icon_full_width, icon_sync } from './components/icons'
+import { renderButton } from './components/renderButtons'
+
+// Configuration object
+const CONFIG = {
+ RESIZING_BREAKPOINT: 768,
+ FW_DEFAULTS: {
+ w_chat_user: 'max-content',
+ max_w_chat_user: '70%',
+ w_chat_gpt: '49rem',
+ w_prompt_textarea: '48rem',
+ chat_user_edit_icon_right: '100%',
+ chat_user_edit_icon_top: '0',
+ chat_user_edit_icon_transform: 'unset',
+ },
+ FW_OPTIONS: {
+ w_chat_gpt: '100%',
+ w_chat_user: '100%',
+ max_w_chat_user: '100%',
+ chat_user_edit_icon_right: 'calc(0% + 2rem)',
+ chat_user_edit_icon_top: '100%',
+ chat_user_edit_icon_transform: 'translateY(-1.25rem)',
+ },
+}
+
+// Utility functions
+const ensureValidPercentage = (value) => {
+ const numValue = parseInt(value, 10)
+ return isNaN(numValue) ? '0' : Math.max(0, Math.min(100, numValue)).toString()
+}
+
+const removePercentAndRem = (str) => str?.replace(/%|rem/g, '')
+
+const isChatWidthModified = (settings) => settings.w_chat_gpt !== CONFIG.FW_DEFAULTS.w_chat_gpt
+
+const debounce = (func, delay) => {
+ let timeoutId
+ return (...args) => {
+ clearTimeout(timeoutId)
+ timeoutId = setTimeout(() => func(...args), delay)
+ }
+}
+
+// State management
+let currentSettings = { ...CONFIG.FW_DEFAULTS }
+let isSyncEnabled = false
+
+// DOM manipulation
+const setElementProperty = (selector, property, value) => {
+ const element = document.querySelector(selector)
+ if (element) element[property] = value
+}
+
+const applySettings = (settings) => {
+ const isNarrowScreen = window.innerWidth <= CONFIG.RESIZING_BREAKPOINT
+
+ if (isChatWidthModified(settings) && isNarrowScreen) {
+ Object.entries(CONFIG.FW_OPTIONS).forEach(([key, value]) => {
+ document.documentElement.style.setProperty(`--${key}`, value)
+ })
+ // Ensure textarea is full width on narrow screens
+ document.documentElement.style.setProperty('--w_prompt_textarea', '100%')
+ } else {
+ Object.entries(settings).forEach(([key, value]) => {
+ // For wider screens, apply the stored setting or default to full width for narrow screens
+ const appliedValue = isNarrowScreen && key === 'w_prompt_textarea' ? '100%' : value
+ document.documentElement.style.setProperty(`--${key}`, appliedValue)
+ })
+ }
+}
+
+const updateUI = (settings) => {
+ const isFullWidth = settings.w_chat_gpt === '100%'
+ const textareaWidthSlider = document.querySelector('#gpth-textarea-width-custom')
+ const textareaWidthCard = textareaWidthSlider?.closest('.card')
+
+ const chatGptUnit = settings.w_chat_gpt.includes('rem') ? 'REM' : '%'
+ const promptUnit = settings.w_prompt_textarea.includes('rem') ? 'REM' : '%'
+
+ setElementProperty('.gpth-settings #gpth-full-width', 'checked', isFullWidth)
+ setElementProperty('.gpth-settings #gpth-full-width-custom', 'value', removePercentAndRem(settings.w_chat_gpt))
+ setElementProperty(
+ '.gpth-settings #range-output-gpth-full-width-custom',
+ 'textContent',
+ removePercentAndRem(settings.w_chat_gpt)
+ )
+ setElementProperty('.gpth-settings #unit-gpth-full-width-custom', 'textContent', chatGptUnit)
+
+ setElementProperty('.gpth-settings #gpth-sync-textarea-chat-width', 'checked', isSyncEnabled)
+ setElementProperty(
+ '.gpth-settings #gpth-textarea-width-custom',
+ 'value',
+ removePercentAndRem(settings.w_prompt_textarea)
+ )
+ setElementProperty(
+ '.gpth-settings #range-output-gpth-textarea-width-custom',
+ 'textContent',
+ removePercentAndRem(settings.w_prompt_textarea)
+ )
+ setElementProperty('.gpth-settings #unit-gpth-textarea-width-custom', 'textContent', promptUnit)
+
+ if (textareaWidthSlider) textareaWidthSlider.disabled = isSyncEnabled
+
+ if (textareaWidthCard) textareaWidthCard.classList.toggle('is-locked', isSyncEnabled)
+
+ updateEditIconPosition(settings.w_chat_gpt)
+}
+
+const updateEditIconPosition = (chatWidth) => {
+ const chatWidthValue = parseInt(removePercentAndRem(chatWidth))
+ const iconSettings = chatWidthValue > 48 ? CONFIG.FW_OPTIONS : CONFIG.FW_DEFAULTS
+
+ Object.assign(currentSettings, {
+ chat_user_edit_icon_right: iconSettings.chat_user_edit_icon_right,
+ chat_user_edit_icon_top: iconSettings.chat_user_edit_icon_top,
+ chat_user_edit_icon_transform: iconSettings.chat_user_edit_icon_transform,
+ })
+
+ applySettings(currentSettings)
+}
+
+// Event handlers
+const toggleChatFullWidth = (e) => {
+ const isFullWidth = e.target.checked
+ const { w_chat_gpt, w_chat_user, max_w_chat_user } = isFullWidth ? CONFIG.FW_OPTIONS : CONFIG.FW_DEFAULTS
+
+ Object.assign(currentSettings, {
+ w_chat_gpt,
+ w_chat_user,
+ max_w_chat_user,
+ w_prompt_textarea: isSyncEnabled ? w_chat_gpt : currentSettings.w_prompt_textarea,
+ })
+
+ if (isChatWidthModified(currentSettings)) {
+ addResizeListener()
+ } else if (window.resizeListenerAdded) {
+ window.removeEventListener('resize', window.resizeListener)
+ window.resizeListenerAdded = false
+ }
+
+ applySettings(currentSettings)
+ debouncedSaveSettings(currentSettings)
+ updateUI(currentSettings)
+}
+
+const toggleSyncTextareaWithChatWidth = (e) => {
+ isSyncEnabled = e.target.checked
+
+ if (isSyncEnabled) currentSettings.w_prompt_textarea = currentSettings.w_chat_gpt
+
+ applySettings(currentSettings)
+ debouncedSaveSettings(currentSettings)
+ updateUI(currentSettings)
+}
+
+const handleWidthChange = (key, e) => {
+ const value = `${ensureValidPercentage(e.target.value)}${e.target.dataset.unit || '%'}`
+ currentSettings[key] = value
+
+ if (key === 'w_chat_gpt') {
+ currentSettings.w_chat_user = value
+ currentSettings.max_w_chat_user = value
+
+ if (isSyncEnabled) currentSettings.w_prompt_textarea = value
+
+ setElementProperty('.gpth-settings #gpth-full-width', 'checked', e.target.value === '100')
+ } else if (key === 'w_prompt_textarea' && isSyncEnabled && value !== currentSettings.w_chat_gpt) {
+ isSyncEnabled = false
+ setElementProperty('.gpth-settings #gpth-sync-textarea-chat-width', 'checked', false)
+ }
+
+ setElementProperty(`.gpth-settings #unit-${e.target.id}`, 'textContent', e.target.dataset.unit || '%')
+
+ if (isChatWidthModified(currentSettings)) addResizeListener()
+
+ applySettings(currentSettings)
+ debouncedSaveSettings(currentSettings)
+ updateUI(currentSettings)
+}
+
+// Update the resetWidths function
+const resetWidths = async () => {
+ try {
+ // Get keys from FW_DEFAULTS
+ const resettableKeys = Object.keys(CONFIG.FW_DEFAULTS)
+
+ // Remove resettable items from storage
+ await browser.storage.sync.remove(resettableKeys)
+
+ // Reset current settings in memory
+ currentSettings = { ...CONFIG.FW_DEFAULTS }
+ isSyncEnabled = false
+
+ // Remove resize listener if it exists
+ if (window.resizeListenerAdded) {
+ window.removeEventListener('resize', window.resizeListener)
+ window.resizeListenerAdded = false
+ }
+
+ // Apply default settings
+ applySettings(currentSettings)
+
+ // Update UI
+ updateUI(currentSettings)
+
+ console.log('Settings reset successfully', currentSettings)
+ } catch (error) {
+ console.error('Failed to reset settings:', error)
+ // TODO: Implement user-friendly error message
+ }
+}
+
+// Storage management
+const saveSettings = async (settings) => {
+ try {
+ await browser.storage.sync.set(settings)
+ } catch (error) {
+ console.error('Failed to save settings:', error)
+ // TODO: Implement user-friendly error message
+ }
+}
+
+const debouncedSaveSettings = debounce(saveSettings, 300)
+
+const loadSettings = async () => {
+ try {
+ const settings = await browser.storage.sync.get(null)
+
+ // Only load settings for keys that are in FW_DEFAULTS
+ const filteredSettings = Object.fromEntries(
+ Object.entries(settings).filter(([key]) => key in CONFIG.FW_DEFAULTS)
+ )
+
+ currentSettings = { ...CONFIG.FW_DEFAULTS, ...filteredSettings }
+ isSyncEnabled = currentSettings.w_chat_gpt === currentSettings.w_prompt_textarea
+
+ if (isChatWidthModified(currentSettings)) {
+ addResizeListener()
+ }
+
+ applySettings(currentSettings)
+ updateUI(currentSettings)
+ } catch (error) {
+ console.error('Failed to load settings:', error)
+ // TODO: Implement user-friendly error message
+ }
+}
+
+// Resize handling
+const addResizeListener = () => {
+ if (!window.resizeListenerAdded) {
+ window.resizeListener = debounce(() => {
+ applySettings(currentSettings)
+ }, 250)
+ window.addEventListener('resize', window.resizeListener)
+ window.resizeListenerAdded = true
+ }
+}
+/* const confirmReset = () => {
+ return new Promise((resolve) => {
+ const confirmed = window.confirm('Are you sure you want to reset all width and layout settings to default?')
+ resolve(confirmed)
+ })
+} */
+
+// Event listeners
+const handleAssetsListeners = () => {
+ document.querySelector('.gpth-settings #gpth-full-width')?.addEventListener('change', toggleChatFullWidth)
+
+ document
+ .querySelector('.gpth-settings #gpth-sync-textarea-chat-width')
+ ?.addEventListener('change', toggleSyncTextareaWithChatWidth)
+ document
+ .querySelector('.gpth-settings #gpth-full-width-custom')
+ ?.addEventListener('input', (e) => handleWidthChange('w_chat_gpt', e))
+
+ document
+ .querySelector('.gpth-settings #gpth-textarea-width-custom')
+ ?.addEventListener('input', (e) => handleWidthChange('w_prompt_textarea', e))
+
+ document.querySelector('.gpth-settings #resetWidths')?.addEventListener('click', resetWidths)
+
+ // Then update the click handler for the reset button
+ /* document.querySelector('.gpth-settings #resetWidths')?.addEventListener('click', async () => {
+ if (await confirmReset()) {
+ resetWidths()
+ }
+ }) */
+}
+
+// HTML template
+const assetsHtmlCode = `
+
+
+ ${renderSmallCardOption({
+ name: 'Chats Width',
+ inputId: 'gpth-full-width-custom',
+ inputType: 'range',
+ inputValue: removePercentAndRem(CONFIG.FW_DEFAULTS.w_chat_gpt),
+ inputPlaceholder: '100%',
+ min: 0,
+ max: 100,
+ unit: 'REM',
+ })}
+ ${renderSmallCardOption({
+ name: 'Prompt Width',
+ inputId: 'gpth-textarea-width-custom',
+ inputType: 'range',
+ inputValue: removePercentAndRem(CONFIG.FW_DEFAULTS.w_prompt_textarea),
+ inputPlaceholder: '100%',
+ min: 0,
+ max: 100,
+ unit: 'REM',
+ isLocked: true,
+ })}
+
+
+
+ ${renderSwitchOption({
+ inputId: 'gpth-full-width',
+ isChecked: false,
+ icon: icon_full_width,
+ textTitle: 'Chat Full Width',
+ textSubtitle: "Expand chats to screen's edge for wider conversation view",
+ })}
+ ${renderSwitchOption({
+ inputId: 'gpth-sync-textarea-chat-width',
+ isChecked: false,
+ icon: icon_sync,
+ textTitle: 'Sync Prompt Width',
+ textSubtitle: 'Adjust prompt field to match the chat width for a more streamlined and consistent view',
+ })}
+
+
+
+
+`
+
+// Initialization
+const init = () => {
+ loadSettings()
+}
+
+export { assetsHtmlCode, handleAssetsListeners, init }
+
+/* // ? =============== DEV ONLY fn ===============
+const assetsStorageKeys = Object.keys(CONFIG.FW_DEFAULTS) // ? DEV ONLY var - Get the keys from FW_DEFAULTS object
+
+async function getAllStorageItems(itemsToGet = null) {
+ //assetsStorageKeys
+ try {
+ const items = await browser.storage.sync.get(itemsToGet)
+ console.log(items)
+ return items
+ } catch (error) {
+ console.error('Error getting storage items:', error)
+ }
+}
+// ? =============== DEV ONLY fn ===============
+// Function to remove specific named items from sync storage
+async function removeSpecificStorageItems(keys) {
+ try {
+ // Remove the items by keys from the sync storage
+ await browser.storage.sync.remove(keys)
+ console.log('Specified items removed from sync storage:', keys)
+ } catch (error) {
+ console.error('Error removing storage items:', error)
+ }
+}
+
+const init = () => {
+ // removeSpecificStorageItems(assetsStorageKeys)
+ getAllStorageItems(assetsStorageKeys)
+ loadSettings()
+ // getAllStorageItems()
+ getAllStorageItems(assetsStorageKeys)
+}
+export { assetsHtmlCode, handleAssetsListeners, init } */
diff --git a/src/js/app/mainFonts.js b/src/js/app/mainFonts.js
index ab02749..01933cf 100644
--- a/src/js/app/mainFonts.js
+++ b/src/js/app/mainFonts.js
@@ -1,6 +1,7 @@
// main.js
import browser from 'webextension-polyfill'
import { renderFontSmallCard, renderFontBigCard, renderButton } from './components/renderFonts'
+import { renderButton } from './components/renderButtons'
// Constants
const DEFAULTS = {
diff --git a/src/js/content.js b/src/js/content.js
index f88a6d0..226ddf2 100644
--- a/src/js/content.js
+++ b/src/js/content.js
@@ -1,2 +1,5 @@
import './app/floatingBtn'
import './app/mainFonts'
+import { init as initAssets } from './app/mainAssets'
+
+initAssets()
diff --git a/src/sass/abstract/_vars.scss b/src/sass/abstract/_vars.scss
index 237043e..4571c73 100644
--- a/src/sass/abstract/_vars.scss
+++ b/src/sass/abstract/_vars.scss
@@ -12,9 +12,15 @@
--lineHeight: 28;
/* ? --- Widths and Heights --- */
+ --min-w-btn: 5.5rem;
--h-header: calc(3.5rem + 0.5rem + 0.375rem);
- --max-w-chat-bubble: 48rem;
--w-scrollbar: 0.22rem;
+ // --max-w-chat-bubble: 48rem;
+ --w_chat_user: max-content;
+ --max_w_chat_user: 70%; // 70%
+ --w_chat_gpt: 48rem;
+ // --w_prompt_textarea: var(--w_chat_gpt);
+ --w_prompt_textarea: initial;
/* ? --- Border-radius --- */
--br: 1rem;
@@ -32,6 +38,7 @@
/* ? --- Paddings --- */
--p-chat-bubble: 1.2rem;
+ --px-chat-bubble-edge-gap: 4vw;
--p-contextmenu: 0.8rem;
--p-contextmenu-item: 0.9rem 1rem;
--p-prompt-textarea: 0.7rem;
@@ -56,14 +63,26 @@
--blur-sticky: 20px;
--blur-modal: 8px;
- /* ? --- Width --- */
- --min-w-btn: 5.5rem;
-
/* ? --- Shadow things --- */
--box-shadow-values: 0px 0px 100px 0px;
--z-modal: 100;
+ --c-bg-gradient: linear-gradient(135deg,
+ hsla(var(--accent-hsl) / 0.45) 0%,
+ hsla(var(--accent-hsl) / 0.1) 40%,
+ hsla(var(--accent-hsl) / 0.05) 60%,
+ hsla(var(--accent-hsl) / 0.45) 100%);
+
+ /* ? --- OTHERER --- */
+ --chat_user_edit_icon_right: 100%;
+ // --chat_user_edit_icon_top: translateY(100%);
+ --chat_user_edit_icon_top: 0;
+ --chat_user_edit_icon_transform: unset;
+
+ // --chat_user_edit_icon_top: initial;
+
+
/* .bg-token-sidebar-surface-primary
- sidebar bg
- nav item bg on hover */
@@ -109,30 +128,22 @@
- "ChatGPT 3.5 - Fastest" in 4o menu when hover on it in chat bubbles*/
--text-quaternary: var(--c-subtext-2) !important;
--text-error: var(--c-danger) !important;
+ --box-shadow-primary: inset 0 -20px 80px -20px #ffffff1f;
@include dev(tab) {
- // --h-header: 40px;
--p-chat-bubble: .8rem;
--br-chat-bubble: calc(var(--br) * 1.55);
-
--p-contextmenu: .5rem;
- // --p-contextmenu-item: 0.9rem 1rem;
--p-prompt-textarea: 0.5rem;
- // --p-tooltips: 0.2rem;
- // --p-btn: 0.7rem;
- // --py-btn: 1rem;
- // --px-btn: 1rem;
-
- // --p-sidebar-nav: 0.5rem;
- // --p-sidebar-nav-a-new-chat: 1.8rem;
- // --p-sidebar-nav-a: 0.6rem;
--p-dialog: 0.3rem;
--br-dialog: calc(var(--br) * 1.5);
- // --br: .7rem;
--p-sidebar-nav: 0.3rem;
}
- --box-shadow-primary: inset 0 -20px 80px -20px #ffffff1f;
+ @include dev(mob) {
+ --px-chat-bubble-edge-gap: 0.45rem;
+ }
+
// --color-error: #fe8bbb;
// --color-three: #9e7aff;
diff --git a/src/sass/elements/_chats-textarea-max-width.scss b/src/sass/elements/_chats-textarea-max-width.scss
index 8b664e9..bbd6cc5 100644
--- a/src/sass/elements/_chats-textarea-max-width.scss
+++ b/src/sass/elements/_chats-textarea-max-width.scss
@@ -1,19 +1,40 @@
-main:has(#prompt-textarea) [class*='lg:max-w-[40rem]'] {
- // border: 1px solid red;
+// main:has(#prompt-textarea) [class*='lg:max-w-[40rem]'] {
+main:has(#prompt-textarea) {
+ .px-3.text-base.m-auto {
+ padding-left: var(--px-chat-bubble-edge-gap) !important;
+ padding-right: var(--px-chat-bubble-edge-gap) !important;
- max-width: var(--max-w-chat-bubble) !important;
-
- @include dev(laptop) {
- --max-w-chat-bubble: 40rem;
- // border-color: lightblue;
+ /* Textarea and chats wrapper */
+ // .mx-auto.flex.flex-1.text-base {
+ // max-width: var(--w_prompt_textarea) !important;
+ // }
+ /* Only textarea wrapper */
+ .mx-auto.flex.flex-1.text-base:has(>form) {
+ max-width: var(--w_prompt_textarea) !important;
+ }
}
- // @include dev(tab-land) {
- // --max-w-chat-bubble: 40rem;
- // border-color: lightpink;
+
+ // [class*='xl:max-w-[48rem]'] {
+ // // [class*='lg:max-w-[40rem]'] {
+ // border: 1px solid greenyellow;
+
+ // max-width: var(--w_prompt_textarea) !important;
+ // // max-width: var(--w_chat_gpt) !important;
+
+ // // @include dev(laptop) {
+ // // --w_prompt_textarea: 40rem;
+ // // // border-color: lightblue;
+ // // }
+
+ // // // @include dev(tab-land) {
+ // // // --w_prompt_textarea: 40rem;
+ // // // border-color: lightpink;
+ // // // }
+
+ // // @include dev(big-desktop) {
+ // // --w_prompt_textarea: 52rem;
+ // // // border-color: lightgreen;
+ // // }
// }
- @include dev(big-desktop) {
- --max-w-chat-bubble: 52rem;
- // border-color: lightgreen;
- }
-}
+}
\ No newline at end of file
diff --git a/src/sass/elements/_right--main.scss b/src/sass/elements/_right--main.scss
index f60c746..fc4da39 100644
--- a/src/sass/elements/_right--main.scss
+++ b/src/sass/elements/_right--main.scss
@@ -36,22 +36,34 @@ main [role='presentation'] {
// margin-bottom: var(--mb-chat-txt) !important;
// }
+
/* @ === RIGHT - CHATS BUBBLES ===*/
main [data-testid^='conversation-turn-'] {
-
/* Edit icon in user chat for example. Edit state user chat bg */
--main-surface-tertiary: var(--c-surface-3) !important;
- // --main-surface-tertiary: hsla(var(--accent-hsl) / 0.5) !important;
margin-bottom: var(--mb-chat-bubble) !important;
+ .mx-auto.flex.flex-1.text-base,
+ [class*='xl:max-w-[48rem]'] {
+ max-width: var(--w_chat_gpt) !important;
+ }
+
+ // TODO proveriti ovo sve kad ima #prompt-textarea i kad nema (tipa u shared link layout-u)
+ /* .px-3.text-base.m-auto {
+ padding-left: var(--px-chat-bubble-edge-gap) !important;
+ padding-right: var(--px-chat-bubble-edge-gap) !important;
+ } */
+
/* Horizontal gap from chat bubble to screen-edge */
& > div {
+ // padding-left: var(--px-chat-bubble-edge-gap);
+ // padding-right: var(--px-chat-bubble-edge-gap);
/* Original is px-4 or 1rem */
- @include dev(mob) {
- padding-left: 0.45rem;
- padding-right: 0.45rem;
- }
+ // @include dev(mob) {
+ // padding-left: 0.45rem;
+ // padding-right: 0.45rem;
+ // }
}
/* RIGHT - CHATS BUBBLES DIV */
@@ -129,6 +141,8 @@ main [data-testid^='conversation-turn-'] {
&:has([data-message-author-role='user']) {
line-height: calc(var(--lineHeight) / 16) !important;
+
+
/* RIGHT - CHATS BUBBLE BG */
// & > div:first-child > div:first-child {
/* ? gpt4o - User message */
@@ -136,6 +150,10 @@ main [data-testid^='conversation-turn-'] {
background-color: var(--c-bg-msg-user);
padding: var(--p-chat-bubble) calc(var(--p-chat-bubble) * 1.2);
border-radius: var(--br-chat-bubble) !important;
+ // width: var(--w_chat_user) !important;
+ // width: max-content !important;
+ width: var(--max_w_chat_user) !important;
+ max-width: var(--w_chat_user) !important;
}
// }
@@ -143,11 +161,19 @@ main [data-testid^='conversation-turn-'] {
/* Flex-end the Reply in user chat bubble */
[data-message-author-role='user'] {
align-items: flex-end !important;
+ /* TODO: Make this only when full-width! See what this can break since the origitnal is overflow-x-hidden, and when i make chats full-width, edit icon for user chat is cut-of so i need to fix it by this and editing the position of the edit icon. BUT HAVE TO TEST THIS!! */
+ overflow: visible !important;
/* Edit icon in User chat */
.absolute.bottom-0.top-0.right-full {
+ /* TODO: Make this only when full-width! - EDIT ICON */
+ right: var(--chat_user_edit_icon_right) !important; // TODO: this
+ top: var(--chat_user_edit_icon_top) !important; // TODO: this
+ transform: var(--chat_user_edit_icon_transform) !important; // TODO: this
+
button {
background-color: hsla(var(--accent-hsl) / 0.1);
+ backdrop-filter: blur(8px);
}
}
@@ -393,4 +419,14 @@ html[data-gptheme='oled'] main [data-testid^='conversation-turn-']:has([data-mes
background-color: var(--c-surface-2);
}
}
+}
+
+main {
+
+ [data-testid^='conversation-turn-'] .mx-auto.flex.flex-1.text-base,
+ [data-testid^='conversation-turn-']:has([data-message-author-role='user']) [class*='bg-[#f4f4f4]'],
+ &:has(#prompt-textarea) [class*='lg:max-w-[40rem]'],
+ &:has(#prompt-textarea) .px-3.text-base.m-auto .mx-auto.flex.flex-1.text-base:has(>form) {
+ transition: 0.3s ease-in-out;
+ }
}
\ No newline at end of file
diff --git a/src/sass/elements/_right--textarea.scss b/src/sass/elements/_right--textarea.scss
index 14c53e7..db7ce36 100644
--- a/src/sass/elements/_right--textarea.scss
+++ b/src/sass/elements/_right--textarea.scss
@@ -64,18 +64,6 @@ main form {
color: var(--c-accent) !important;
}
- /* 📎 "Attach files" button parent oof parent which has items-end */
- // div:has(& > div[type='button'][aria-haspopup='dialog']:has(button[aria-label='Attach files'])) {
- // div[type='button'][aria-haspopup='dialog']:has(button[aria-label='Attach files']) {
- // margin-bottom: calc(var(--p-prompt-textarea) / 2);
- // }
-
- /* 📎 Attach files svg */
- // button[aria-label='Attach files'] svg {
- // color: var(--c-accent) !important;
- // }
- /* Moram ovako jer imamo dva div[type='button'][aria-haspopup='dialog'] */
-
div:has(> input[type='file']) {
/* 📎 "Attach files" svg */
@@ -92,22 +80,10 @@ main form {
/* 🖼️ "Attach Files" - attached image wrapper */
div[type='button'][aria-haspopup='dialog'] {
- // border: 2px solid lightgreen !important;
/* "Attach Files" attached image */
span.bg-cover {
border-radius: 10px !important;
}
-
- // div[type='button'][aria-haspopup='dialog']:has(input[type='file']) {
- // // border: 2px solid red !important;
-
- // /* 📎 "Attach files" svg */
- // // button:has(> svg) {
- // // svg {
- // // color: var(--c-accent) !important;
- // // }
- // // }
- // }
}
}
diff --git a/src/sass/gpthemes/_gpth-v2.scss b/src/sass/gpthemes/_gpth-floating-btn.scss
similarity index 97%
rename from src/sass/gpthemes/_gpth-v2.scss
rename to src/sass/gpthemes/_gpth-floating-btn.scss
index b23c9b9..9702f90 100644
--- a/src/sass/gpthemes/_gpth-v2.scss
+++ b/src/sass/gpthemes/_gpth-floating-btn.scss
@@ -42,11 +42,7 @@
width: var(--floating-icon-size);
height: var(--floating-icon-size);
color: var(--c-accent);
- background-image: linear-gradient(135deg,
- hsla(var(--accent-hsl) / 0.45) 0%,
- hsla(var(--accent-hsl) / 0.1) 40%,
- hsla(var(--accent-hsl) / 0.05) 60%,
- hsla(var(--accent-hsl) / 0.45) 100%);
+ background-image: var(--c-bg-gradient);
// border: 1px solid hsla(var(--accent-hsl) / 0.2);
backdrop-filter: blur(10px);
diff --git a/src/sass/gpthemes/theme-manager/_gpth-settings.scss b/src/sass/gpthemes/_gpth-settings.scss
similarity index 70%
rename from src/sass/gpthemes/theme-manager/_gpth-settings.scss
rename to src/sass/gpthemes/_gpth-settings.scss
index 25b0f05..25c2c44 100644
--- a/src/sass/gpthemes/theme-manager/_gpth-settings.scss
+++ b/src/sass/gpthemes/_gpth-settings.scss
@@ -1,26 +1,15 @@
-@import 'components/_colorpicker';
-@import 'layouts/_header';
-@import 'components/_tabs';
-@import 'components/_cards';
-@import 'components/_fonts';
-@import 'components/_error-msg';
-
.gpth-settings {
overflow: clip;
--top: calc(var(--h-header) + 0.5rem + 3rem);
--right: 1.3rem;
--shadow-color: hsla(var(--accent-hsl) / 0.09);
--shadow-values: inset 0 0 20px 10px;
- // @extend [role='dialog'];
opacity: 0;
pointer-events: none;
padding: 2.2rem 2.8rem;
border-radius: var(--br-dialog);
top: var(--top);
right: var(--right);
- // width: 26rem;
- // height: 50vh;
- // max-width: 30rem;
width: clamp(25rem, 25vw, 30rem);
max-height: 70vh;
transform: translateX(calc(100% + 1.5rem)) !important;
@@ -52,11 +41,4 @@
max-height: 70vh;
padding: 2rem;
}
-}
-
-// html.light {
-// .gpth-settings {
-// // background-color: hsla(var(--accent-h) var(--surface-s) var(--surface-l) / 0.7);
-// background-color: hsla(0 0% calc(var(--surface-l) / 1.18) / 0.7);
-// }
-// }
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/src/sass/gpthemes/_notifications.scss b/src/sass/gpthemes/_notifications.scss
deleted file mode 100644
index 92cc15d..0000000
--- a/src/sass/gpthemes/_notifications.scss
+++ /dev/null
@@ -1,66 +0,0 @@
-.gpth-notification {
- font-size: 0.9rem;
- position: fixed;
- top: 3rem;
- left: 50%;
- transform: translateX(-50%) translateY(-10%);
- visibility: hidden;
- opacity: 0;
- width: clamp(80vw, 40vw, 40rem);
- background-color: hsla(var(--accent-hsl) / 0.2);
- backdrop-filter: blur(1.5rem);
- border: 1px solid hsla(var(--accent-hsl) / 0.2);
- z-index: calc(var(--z-modal) - 4);
- pointer-events: none;
- display: grid;
- gap: 1rem;
- padding: var(--p-dialog);
- border-radius: var(--br-dialog);
- overflow-y: clip;
- transition: opacity 0.3s linear, transform 0.3s linear;
-
- h2,
- strong {
- color: var(--c-accent);
- }
-
- &--open {
- transform: translateX(-50%);
- visibility: visible;
- opacity: 1;
- pointer-events: all;
- }
-
- ul {
- list-style-type: disc;
- padding: calc(var(--p-btn) * 0.5) calc(var(--p-btn) * 2);
-
- li {
- padding: 0.2rem 0;
- }
- }
-
- h3 {
- font-size: 1.2em;
- }
-
- &__version {
- background-color: var(--c-accent);
- color: var(--c-on-accent);
- border-radius: calc(var(--br-btn) * 0.5);
- font-size: 0.7em;
- }
-
- &__changes {
- overflow-y: scroll;
- height: 50vh;
- }
-
- footer {
- a {
- font-weight: bold;
- @extend %link_hover_underlined;
- // color: var(--c-on-accent) !important;
- }
- }
-}
\ No newline at end of file
diff --git a/src/sass/gpthemes/gpth-index.scss b/src/sass/gpthemes/gpth-index.scss
new file mode 100644
index 0000000..5b8bc89
--- /dev/null
+++ b/src/sass/gpthemes/gpth-index.scss
@@ -0,0 +1,15 @@
+@import 'theme-manager/components/_colorpicker';
+@import 'theme-manager/components/_range';
+@import 'theme-manager/components/_tabs';
+@import 'theme-manager/components/_cards';
+@import 'theme-manager/components/_error-msg';
+@import 'theme-manager/components/_fonts';
+@import 'theme-manager/components/_switch';
+
+@import 'theme-manager/sections/_header';
+@import 'theme-manager/sections/_main';
+@import 'theme-manager/sections/_header';
+@import 'theme-manager/layouts/_gpth-assets';
+
+@import '_gpth-floating-btn';
+@import '_gpth-settings';
\ No newline at end of file
diff --git a/src/sass/gpthemes/theme-manager/components/_cards.scss b/src/sass/gpthemes/theme-manager/components/_cards.scss
index c317fe9..3195bb6 100644
--- a/src/sass/gpthemes/theme-manager/components/_cards.scss
+++ b/src/sass/gpthemes/theme-manager/components/_cards.scss
@@ -106,6 +106,7 @@
appearance: textfield;
}
+ /* _________________ SMALL CARDS _________________ */
&--small {
label {
@@ -148,7 +149,7 @@
font-size: 0.42em;
}
- &:has(input:focus) {
+ &:has(input:focus):not(&[type="range"]) {
.card__unitname-wrapper {
display: none;
}
@@ -268,4 +269,122 @@
}
}
+
+ /* _________________ RANGE CARDS _________________ */
+ &--range {
+ label {
+ // height: 5.5rem;
+ // padding: 0.3rem;
+ background-color: var(--c-surface-2);
+ }
+
+ input {
+ width: 85% !important;
+ margin: 0 auto;
+ align-self: flex-end;
+ }
+
+ .card__unit {
+ --px: 0.5rem;
+ background-color: hsla(var(--accent-hsl) / 0.12);
+ color: var(--c-accent);
+ font-size: 0.5em;
+ width: max-content;
+ line-height: 1;
+ padding: 0.2rem var(--px);
+ translate: -0.15rem 0;
+ }
+
+ .card__name {
+ font-size: 0.42em;
+ }
+
+ .card__output {
+ --output-size: 2.5rem;
+ // width: var(--output-size);
+ // height: var(--output-size);
+ aspect-ratio: 1 / 1;
+ background-color: hsla(var(--accent-hsl) / 0.2);
+ color: var(--c-accent);
+ font-size: 0.8em;
+ line-height: 1;
+ }
+
+ &.is-locked {
+ position: relative;
+ cursor: not-allowed !important;
+
+ label {
+ transform: .3s ease;
+ pointer-events: none !important;
+ opacity: 0.7 !important;
+
+ &::after {
+ will-change: backdrop-filter;
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background-image: radial-gradient(circle at 100% 0%, hsla(var(--accent-hsl) / 0.02) 5%, hsla(var(--accent-hsl) / 0.4) 100%);
+ z-index: 8;
+ border-radius: inherit;
+ backdrop-filter: blur(2px);
+ /* font-size: .5em;
+ font-weight: bold;
+ text-transform: uppercase;
+ text-align: center;
+ vertical-align: center;
+ display: grid;
+ place-items: center; */
+ }
+ }
+
+ &:hover {
+ label::after {
+ // content: '' !important;
+ backdrop-filter: blur(0px) !important;
+ background-image: radial-gradient(circle at 100% 0%, hsla(var(--accent-hsl) / 0.4) 5%, hsla(var(--accent-hsl) / 0.02) 42%) !important;
+ }
+ }
+
+
+ // .icon-lock-wrapper {
+ // display: block;
+ // position: absolute;
+ // top: 50%;
+ // left: 50%;
+ // transform: translate(-50%, -50%);
+ // background-color: hsla(var(--accent-hsl) / 0.5);
+ // width: 100%;
+ // height: 100%;
+ // display: grid;
+ // place-items: center;
+ // z-index: 10;
+ // border-radius: inherit;
+
+ // .icon-lock {
+ // width: 1.5rem;
+ // height: 1.5rem;
+ // color: var(--c-accent);
+ // }
+ // }
+
+ .icon-locked {
+ position: absolute;
+ top: 6%;
+ right: 7%;
+ width: 1.8rem;
+ color: var(--c-accent);
+ @extend %animScaleIn;
+ z-index: 10;
+ }
+ }
+
+ &:not(.is-locked) .icon-locked {
+ display: none;
+ }
+ }
+
}
\ No newline at end of file
diff --git a/src/sass/gpthemes/theme-manager/components/_range.scss b/src/sass/gpthemes/theme-manager/components/_range.scss
new file mode 100644
index 0000000..3e4364d
--- /dev/null
+++ b/src/sass/gpthemes/theme-manager/components/_range.scss
@@ -0,0 +1,74 @@
+.gpth-settings {
+ input[type="range"] {
+ --track-bg: hsla(var(--accent-hsl) / 0.5);
+ --thumb-bg: var(--c-accent);
+ --thumb-focus-outline: var(--c-accent);
+ --track-height: 0.75rem;
+ --track-radius: 50vw;
+ --track-outline: 3px solid hsla(var(--accent-hsl) / 0.8);
+ --thumb-size-multiplier: 0.8;
+ --thumb-size: calc(var(--track-height) * var(--thumb-size-multiplier));
+ --thumb-radius: 50vw;
+ --thumb-margin-top: calc((var(--track-height) - var(--thumb-size)) / 2);
+ --focus-outline-size: 3px;
+ --focus-outline-offset: 0.125rem;
+
+ -webkit-appearance: none;
+ appearance: none;
+ background-color: transparent;
+ cursor: pointer;
+ // width: var(--input-width)
+
+ &:hover,
+ &:focus {
+ // --track-height: 0.8rem;
+ --thumb-size-multiplier: 1.4;
+ --track-outline: 3px solid transparent;
+ }
+
+ &:focus {
+
+ &::-webkit-slider-thumb,
+ &::-moz-range-thumb {
+ outline: var(--focus-outline-size) solid var(--thumb-focus-outline);
+ outline-offset: var(--focus-outline-offset);
+ // outline: var(--focus-outline-size) solid var(--thumb-focus-outline);
+ // outline-offset: var(--focus-outline-offset);
+ }
+ }
+
+ &::-webkit-slider-runnable-track {
+ background-color: var(--track-bg);
+ border-radius: var(--track-radius);
+ height: var(--track-height);
+ width: 100%;
+ transition: .25s;
+ outline: var(--track-outline);
+ // outline-offset: 2px;
+ }
+
+ &::-webkit-slider-thumb,
+ &::-moz-range-thumb {
+ background-color: var(--thumb-bg);
+ border-radius: var(--thumb-radius);
+ height: var(--thumb-size);
+ width: var(--thumb-size);
+ transition: .25s;
+
+ // &:focus {
+ // outline: var(--focus-outline-size) solid var(--thumb-focus-outline);
+ // outline-offset: var(--focus-outline-offset);
+ // }
+ }
+
+ &::-webkit-slider-thumb {
+ -webkit-appearance: none;
+ appearance: none;
+ margin-top: var(--thumb-margin-top);
+ }
+
+ &::-moz-range-thumb {
+ border: none;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/sass/gpthemes/theme-manager/components/_switch.scss b/src/sass/gpthemes/theme-manager/components/_switch.scss
new file mode 100644
index 0000000..502f8dd
--- /dev/null
+++ b/src/sass/gpthemes/theme-manager/components/_switch.scss
@@ -0,0 +1,112 @@
+.gpth-switch {
+ display: flex;
+ align-items: center;
+ flex-wrap: wrap;
+ justify-content: space-between;
+ margin-bottom: 0.5rem;
+ cursor: pointer;
+ font-size: 1rem;
+ gap: 0.8rem;
+ border-radius: calc(var(--br-btn) * 1.5);
+ padding: var(--p-btn);
+ border: 1px solid transparent;
+ transition: .25s ease-in;
+
+ &:hover {
+ // background-image: var(--c-bg-gradient);
+ background-color: hsla(var(--accent-hsl) / 0.1);
+ border-color: hsla(var(--accent-hsl) / 0.1) !important;
+ transform: scale(0.98);
+ }
+
+ &__icon {
+ --icon-size: 2.8em;
+ --svg-muliplicator: 0.6;
+ width: var(--icon-size);
+ height: var(--icon-size);
+ display: grid;
+ place-items: center;
+ border-radius: 1rem;
+ background-color: hsla(var(--accent-hsl) / 0.2);
+ color: var(--c-accent);
+
+ svg {
+ width: calc(var(--icon-size) * var(--svg-muliplicator));
+ height: calc(var(--icon-size) * var(--svg-muliplicator));
+ }
+ }
+
+ &__text {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 0.1rem;
+
+ .title {
+ font-size: 0.8em;
+ font-weight: bold;
+ color: var(--c-accent);
+ text-transform: uppercase;
+ line-height: 1;
+ }
+
+ .subtitle {
+ font-size: 0.7em;
+ line-height: 1.1;
+ font-weight: 500;
+ }
+ }
+
+ &__checkbox {
+ --chb-w: 3rem;
+ --chb-h: 1.8rem;
+ --chb-edge-gap: 0.25rem;
+ --chb-slider-circle-size: calc(var(--chb-h) - 2 * var(--chb-edge-gap));
+ position: relative;
+ display: inline-block;
+ width: var(--chb-w);
+ height: var(--chb-h);
+
+ input {
+ opacity: 0;
+ width: 0;
+ height: 0;
+ }
+
+ .slider {
+ display: flex;
+ align-items: center;
+ position: absolute;
+ cursor: pointer;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: hsla(var(--accent-hsl) / 0.3);
+ border: 2px solid hsla(var(--accent-hsl) / 0.5);
+ transition: .4s;
+ border-radius: var(--chb-w);
+
+ &::before {
+ position: absolute;
+ content: "";
+ height: var(--chb-slider-circle-size);
+ aspect-ratio: 1/1;
+ left: var(--chb-edge-gap);
+ background-color: hsla(var(--accent-hsl) / 0.5);
+ transition: .4s $easeInOutCirc;
+ border-radius: 50%;
+ }
+ }
+
+ input:checked + .slider {
+ background-color: var(--c-accent);
+ border-color: transparent !important;
+
+ &::before {
+ transform: translateX(calc(var(--chb-w) - 145%));
+ background-color: var(--c-on-accent);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/sass/gpthemes/theme-manager/layouts/_gpth-assets.scss b/src/sass/gpthemes/theme-manager/layouts/_gpth-assets.scss
new file mode 100644
index 0000000..b0a0770
--- /dev/null
+++ b/src/sass/gpthemes/theme-manager/layouts/_gpth-assets.scss
@@ -0,0 +1,7 @@
+.gpth-assets {
+ &__custom-width {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
+ gap: 1rem 0.5rem;
+ }
+}
\ No newline at end of file
diff --git a/src/sass/gpthemes/theme-manager/layouts/_footer.scss b/src/sass/gpthemes/theme-manager/sections/_footer.scss
similarity index 100%
rename from src/sass/gpthemes/theme-manager/layouts/_footer.scss
rename to src/sass/gpthemes/theme-manager/sections/_footer.scss
diff --git a/src/sass/gpthemes/theme-manager/layouts/_header.scss b/src/sass/gpthemes/theme-manager/sections/_header.scss
similarity index 100%
rename from src/sass/gpthemes/theme-manager/layouts/_header.scss
rename to src/sass/gpthemes/theme-manager/sections/_header.scss
diff --git a/src/sass/gpthemes/theme-manager/layouts/_main.scss b/src/sass/gpthemes/theme-manager/sections/_main.scss
similarity index 100%
rename from src/sass/gpthemes/theme-manager/layouts/_main.scss
rename to src/sass/gpthemes/theme-manager/sections/_main.scss
diff --git a/src/sass/index.scss b/src/sass/index.scss
index 33423a0..4228848 100644
--- a/src/sass/index.scss
+++ b/src/sass/index.scss
@@ -46,6 +46,4 @@
// @import 'layouts/_old-ui';
@import 'layouts/_old-ui-index';
-@import 'gpthemes/_gpth-v2';
-@import 'gpthemes/_notifications';
-@import 'gpthemes/theme-manager/_gpth-settings';
\ No newline at end of file
+@import 'gpthemes/gpth-index';
\ No newline at end of file