Merge pull request #2949 from ceruleandeep/feature/clickableWelcome Add clickable buttons in Welcome chat message.
Signed| @@ -293,10 +293,17 @@ DOMPurify.addHook('afterSanitizeAttributes', function (node) { | |||
| 293 | } | 293 | } |
| 294 | }); | 294 | }); |
| 295 | 295 | ||
| 296 | DOMPurify.addHook('uponSanitizeAttribute', (_, data, config) => { | 296 | DOMPurify.addHook('uponSanitizeAttribute', (node, data, config) => { |
| 297 | if (!config['MESSAGE_SANITIZE']) { | 297 | if (!config['MESSAGE_SANITIZE']) { |
| 298 | return; | 298 | return; |
| 299 | } | 299 | } |
| 300 | |||
| 301 | /* Retain the classes on UI elements of messages that interact with the main UI */ | ||
| 302 | const permittedNodeTypes = ['BUTTON', 'DIV']; | ||
| 303 | if (config['MESSAGE_ALLOW_SYSTEM_UI'] && node.classList.contains('menu_button') && permittedNodeTypes.includes(node.nodeName)) { | ||
| 304 | return; | ||
| 305 | } | ||
| 306 | |||
| 300 | switch (data.attrName) { | 307 | switch (data.attrName) { |
| 301 | case 'class': { | 308 | case 'class': { |
| 302 | if (data.attrValue) { | 309 | if (data.attrValue) { |
| @@ -650,6 +657,7 @@ async function getSystemMessages() { | |||
| 650 | force_avatar: system_avatar, | 657 | force_avatar: system_avatar, |
| 651 | is_user: false, | 658 | is_user: false, |
| 652 | is_system: true, | 659 | is_system: true, |
| 660 | uses_system_ui: true, | ||
| 653 | mes: await renderTemplateAsync('welcome', { displayVersion }), | 661 | mes: await renderTemplateAsync('welcome', { displayVersion }), |
| 654 | }, | 662 | }, |
| 655 | group: { | 663 | group: { |
| @@ -1916,9 +1924,10 @@ export async function sendTextareaMessage() { | |||
| 1916 | * @param {boolean} isSystem If the message was sent by the system | 1924 | * @param {boolean} isSystem If the message was sent by the system |
| 1917 | * @param {boolean} isUser If the message was sent by the user | 1925 | * @param {boolean} isUser If the message was sent by the user |
| 1918 | * @param {number} messageId Message index in chat array | 1926 | * @param {number} messageId Message index in chat array |
| 1927 | * @param {object} [sanitizerOverrides] DOMPurify sanitizer option overrides | ||
| 1919 | * @returns {string} HTML string | 1928 | * @returns {string} HTML string |
| 1920 | */ | 1929 | */ |
| 1921 | export function messageFormatting(mes, ch_name, isSystem, isUser, messageId) { | 1930 | export function messageFormatting(mes, ch_name, isSystem, isUser, messageId, sanitizerOverrides = {}) { |
| 1922 | if (!mes) { | 1931 | if (!mes) { |
| 1923 | return ''; | 1932 | return ''; |
| 1924 | } | 1933 | } |
| @@ -2029,7 +2038,7 @@ export function messageFormatting(mes, ch_name, isSystem, isUser, messageId) { | |||
| 2029 | } | 2038 | } |
| 2030 | 2039 | ||
| 2031 | /** @type {any} */ | 2040 | /** @type {any} */ |
| 2032 | const config = { MESSAGE_SANITIZE: true, ADD_TAGS: ['custom-style'] }; | 2041 | const config = { MESSAGE_SANITIZE: true, ADD_TAGS: ['custom-style'], ...sanitizerOverrides }; |
| 2033 | mes = encodeStyleTags(mes); | 2042 | mes = encodeStyleTags(mes); |
| 2034 | mes = DOMPurify.sanitize(mes, config); | 2043 | mes = DOMPurify.sanitize(mes, config); |
| 2035 | mes = decodeStyleTags(mes); | 2044 | mes = decodeStyleTags(mes); |
| @@ -2234,6 +2243,18 @@ export function addCopyToCodeBlocks(messageElement) { | |||
| 2234 | } | 2243 | } |
| 2235 | 2244 | ||
| 2236 | 2245 | ||
| 2246 | /** | ||
| 2247 | * Adds a single message to the chat. | ||
| 2248 | * @param {object} mes Message object | ||
| 2249 | * @param {object} [options] Options | ||
| 2250 | * @param {string} [options.type='normal'] Message type | ||
| 2251 | * @param {number} [options.insertAfter=null] Message ID to insert the new message after | ||
| 2252 | * @param {boolean} [options.scroll=true] Whether to scroll to the new message | ||
| 2253 | * @param {number} [options.insertBefore=null] Message ID to insert the new message before | ||
| 2254 | * @param {number} [options.forceId=null] Force the message ID | ||
| 2255 | * @param {boolean} [options.showSwipes=true] Whether to show swipe buttons | ||
| 2256 | * @returns {void} | ||
| 2257 | */ | ||
| 2237 | export function addOneMessage(mes, { type = 'normal', insertAfter = null, scroll = true, insertBefore = null, forceId = null, showSwipes = true } = {}) { | 2258 | export function addOneMessage(mes, { type = 'normal', insertAfter = null, scroll = true, insertBefore = null, forceId = null, showSwipes = true } = {}) { |
| 2238 | let messageText = mes['mes']; | 2259 | let messageText = mes['mes']; |
| 2239 | const momentDate = timestampToMoment(mes.send_date); | 2260 | const momentDate = timestampToMoment(mes.send_date); |
| @@ -2262,7 +2283,7 @@ export function addOneMessage(mes, { type = 'normal', insertAfter = null, scroll | |||
| 2262 | } else if (this_chid === undefined) { | 2283 | } else if (this_chid === undefined) { |
| 2263 | avatarImg = system_avatar; | 2284 | avatarImg = system_avatar; |
| 2264 | } else { | 2285 | } else { |
| 2265 | if (characters[this_chid].avatar != 'none') { | 2286 | if (characters[this_chid].avatar !== 'none') { |
| 2266 | avatarImg = getThumbnailUrl('avatar', characters[this_chid].avatar); | 2287 | avatarImg = getThumbnailUrl('avatar', characters[this_chid].avatar); |
| 2267 | } else { | 2288 | } else { |
| 2268 | avatarImg = default_avatar; | 2289 | avatarImg = default_avatar; |
| @@ -2277,12 +2298,16 @@ export function addOneMessage(mes, { type = 'normal', insertAfter = null, scroll | |||
| 2277 | avatarImg = mes['force_avatar']; | 2298 | avatarImg = mes['force_avatar']; |
| 2278 | } | 2299 | } |
| 2279 | 2300 | ||
| 2301 | // if mes.uses_system_ui is true, set an override on the sanitizer options | ||
| 2302 | const sanitizerOverrides = mes.uses_system_ui ? { MESSAGE_ALLOW_SYSTEM_UI: true } : {}; | ||
| 2303 | |||
| 2280 | messageText = messageFormatting( | 2304 | messageText = messageFormatting( |
| 2281 | messageText, | 2305 | messageText, |
| 2282 | mes.name, | 2306 | mes.name, |
| 2283 | isSystem, | 2307 | isSystem, |
| 2284 | mes.is_user, | 2308 | mes.is_user, |
| 2285 | chat.indexOf(mes), | 2309 | chat.indexOf(mes), |
| 2310 | sanitizerOverrides, | ||
| 2286 | ); | 2311 | ); |
| 2287 | const bias = messageFormatting(mes.extra?.bias ?? '', '', false, false, -1); | 2312 | const bias = messageFormatting(mes.extra?.bias ?? '', '', false, false, -1); |
| 2288 | let bookmarkLink = mes?.extra?.bookmark_link ?? ''; | 2313 | let bookmarkLink = mes?.extra?.bookmark_link ?? ''; |
| @@ -2330,7 +2355,7 @@ export function addOneMessage(mes, { type = 'normal', insertAfter = null, scroll | |||
| 2330 | } | 2355 | } |
| 2331 | 2356 | ||
| 2332 | //shows or hides the Prompt display button | 2357 | //shows or hides the Prompt display button |
| 2333 | let mesIdToFind = type == 'swipe' ? params.mesId - 1 : params.mesId; //Number(newMessage.attr('mesId')); | 2358 | let mesIdToFind = type === 'swipe' ? params.mesId - 1 : params.mesId; //Number(newMessage.attr('mesId')); |
| 2334 | 2359 | ||
| 2335 | //if we have itemized messages, and the array isn't null.. | 2360 | //if we have itemized messages, and the array isn't null.. |
| 2336 | if (params.isUser === false && Array.isArray(itemizedPrompts) && itemizedPrompts.length > 0) { | 2361 | if (params.isUser === false && Array.isArray(itemizedPrompts) && itemizedPrompts.length > 0) { |
| @@ -2651,7 +2676,7 @@ export function sendSystemMessage(type, text, extra = {}) { | |||
| 2651 | newMessage.mes = text; | 2676 | newMessage.mes = text; |
| 2652 | } | 2677 | } |
| 2653 | 2678 | ||
| 2654 | if (type == system_message_types.SLASH_COMMANDS) { | 2679 | if (type === system_message_types.SLASH_COMMANDS) { |
| 2655 | newMessage.mes = getSlashCommandsHelp(); | 2680 | newMessage.mes = getSlashCommandsHelp(); |
| 2656 | } | 2681 | } |
| 2657 | 2682 | ||
| @@ -2665,7 +2690,7 @@ export function sendSystemMessage(type, text, extra = {}) { | |||
| 2665 | chat.push(newMessage); | 2690 | chat.push(newMessage); |
| 2666 | addOneMessage(newMessage); | 2691 | addOneMessage(newMessage); |
| 2667 | is_send_press = false; | 2692 | is_send_press = false; |
| 2668 | if (type == system_message_types.SLASH_COMMANDS) { | 2693 | if (type === system_message_types.SLASH_COMMANDS) { |
| 2669 | const browser = new SlashCommandBrowser(); | 2694 | const browser = new SlashCommandBrowser(); |
| 2670 | const spinner = document.querySelector('#chat .last_mes .custom-slashHelp'); | 2695 | const spinner = document.querySelector('#chat .last_mes .custom-slashHelp'); |
| 2671 | const parent = spinner.parentElement; | 2696 | const parent = spinner.parentElement; |
| @@ -7854,7 +7879,7 @@ function openAlternateGreetings() { | |||
| 7854 | if (menu_type !== 'create') { | 7879 | if (menu_type !== 'create') { |
| 7855 | await createOrEditCharacter(); | 7880 | await createOrEditCharacter(); |
| 7856 | } | 7881 | } |
| 7857 | } | 7882 | }, |
| 7858 | }); | 7883 | }); |
| 7859 | 7884 | ||
| 7860 | for (let index = 0; index < getArray().length; index++) { | 7885 | for (let index = 0; index < getArray().length; index++) { |
| @@ -9070,6 +9095,90 @@ function doTogglePanels() { | |||
| 9070 | return ''; | 9095 | return ''; |
| 9071 | } | 9096 | } |
| 9072 | 9097 | ||
| 9098 | /** | ||
| 9099 | * Event handler to open a navbar drawer when a drawer open button is clicked. | ||
| 9100 | * Handles click events on .drawer-opener elements. | ||
| 9101 | * Opens the drawer associated with the clicked button according to the data-target attribute. | ||
| 9102 | * @returns {void} | ||
| 9103 | */ | ||
| 9104 | function doDrawerOpenClick() { | ||
| 9105 | const targetDrawerID = $(this).attr('data-target'); | ||
| 9106 | const drawer = $(`#${targetDrawerID}`); | ||
| 9107 | const drawerToggle = drawer.find('.drawer-toggle'); | ||
| 9108 | const drawerWasOpenAlready = drawerToggle.parent().find('.drawer-content').hasClass('openDrawer'); | ||
| 9109 | if (drawerWasOpenAlready || drawer.hasClass('resizing')) { return; } | ||
| 9110 | doNavbarIconClick.call(drawerToggle); | ||
| 9111 | } | ||
| 9112 | |||
| 9113 | /** | ||
| 9114 | * Event handler to open or close a navbar drawer when a navbar icon is clicked. | ||
| 9115 | * Handles click events on .drawer-toggle elements. | ||
| 9116 | * @returns {void} | ||
| 9117 | */ | ||
| 9118 | function doNavbarIconClick() { | ||
| 9119 | var icon = $(this).find('.drawer-icon'); | ||
| 9120 | var drawer = $(this).parent().find('.drawer-content'); | ||
| 9121 | if (drawer.hasClass('resizing')) { return; } | ||
| 9122 | var drawerWasOpenAlready = $(this).parent().find('.drawer-content').hasClass('openDrawer'); | ||
| 9123 | let targetDrawerID = $(this).parent().find('.drawer-content').attr('id'); | ||
| 9124 | const pinnedDrawerClicked = drawer.hasClass('pinnedOpen'); | ||
| 9125 | |||
| 9126 | if (!drawerWasOpenAlready) { //to open the drawer | ||
| 9127 | $('.openDrawer').not('.pinnedOpen').addClass('resizing').slideToggle(200, 'swing', async function () { | ||
| 9128 | await delay(50); $(this).closest('.drawer-content').removeClass('resizing'); | ||
| 9129 | }); | ||
| 9130 | $('.openIcon').toggleClass('closedIcon openIcon'); | ||
| 9131 | $('.openDrawer').not('.pinnedOpen').toggleClass('closedDrawer openDrawer'); | ||
| 9132 | icon.toggleClass('openIcon closedIcon'); | ||
| 9133 | drawer.toggleClass('openDrawer closedDrawer'); | ||
| 9134 | |||
| 9135 | //console.log(targetDrawerID); | ||
| 9136 | if (targetDrawerID === 'right-nav-panel') { | ||
| 9137 | $(this).closest('.drawer').find('.drawer-content').addClass('resizing').slideToggle({ | ||
| 9138 | duration: 200, | ||
| 9139 | easing: 'swing', | ||
| 9140 | start: function () { | ||
| 9141 | jQuery(this).css('display', 'flex'); //flex needed to make charlist scroll | ||
| 9142 | }, | ||
| 9143 | complete: async function () { | ||
| 9144 | favsToHotswap(); | ||
| 9145 | await delay(50); | ||
| 9146 | $(this).closest('.drawer-content').removeClass('resizing'); | ||
| 9147 | $('#rm_print_characters_block').trigger('scroll'); | ||
| 9148 | }, | ||
| 9149 | }); | ||
| 9150 | } else { | ||
| 9151 | $(this).closest('.drawer').find('.drawer-content').addClass('resizing').slideToggle(200, 'swing', async function () { | ||
| 9152 | await delay(50); $(this).closest('.drawer-content').removeClass('resizing'); | ||
| 9153 | }); | ||
| 9154 | } | ||
| 9155 | |||
| 9156 | // Set the height of "autoSetHeight" textareas within the drawer to their scroll height | ||
| 9157 | if (!CSS.supports('field-sizing', 'content')) { | ||
| 9158 | $(this).closest('.drawer').find('.drawer-content textarea.autoSetHeight').each(async function () { | ||
| 9159 | await resetScrollHeight($(this)); | ||
| 9160 | return; | ||
| 9161 | }); | ||
| 9162 | } | ||
| 9163 | |||
| 9164 | } else if (drawerWasOpenAlready) { //to close manually | ||
| 9165 | icon.toggleClass('closedIcon openIcon'); | ||
| 9166 | |||
| 9167 | if (pinnedDrawerClicked) { | ||
| 9168 | $(drawer).addClass('resizing').slideToggle(200, 'swing', async function () { | ||
| 9169 | await delay(50); $(this).removeClass('resizing'); | ||
| 9170 | }); | ||
| 9171 | } | ||
| 9172 | else { | ||
| 9173 | $('.openDrawer').not('.pinnedOpen').addClass('resizing').slideToggle(200, 'swing', async function () { | ||
| 9174 | await delay(50); $(this).closest('.drawer-content').removeClass('resizing'); | ||
| 9175 | }); | ||
| 9176 | } | ||
| 9177 | |||
| 9178 | drawer.toggleClass('closedDrawer openDrawer'); | ||
| 9179 | } | ||
| 9180 | } | ||
| 9181 | |||
| 9073 | function addDebugFunctions() { | 9182 | function addDebugFunctions() { |
| 9074 | const doBackfill = async () => { | 9183 | const doBackfill = async () => { |
| 9075 | for (const message of chat) { | 9184 | for (const message of chat) { |
| @@ -10659,69 +10768,8 @@ jQuery(async function () { | |||
| 10659 | stopScriptExecution(); | 10768 | stopScriptExecution(); |
| 10660 | }); | 10769 | }); |
| 10661 | 10770 | ||
| 10662 | $('.drawer-toggle').on('click', function () { | 10771 | $(document).on('click', '.drawer-opener', doDrawerOpenClick); |
| 10663 | var icon = $(this).find('.drawer-icon'); | 10772 | $('.drawer-toggle').on('click', doNavbarIconClick); |
| 10664 | var drawer = $(this).parent().find('.drawer-content'); | ||
| 10665 | if (drawer.hasClass('resizing')) { return; } | ||
| 10666 | var drawerWasOpenAlready = $(this).parent().find('.drawer-content').hasClass('openDrawer'); | ||
| 10667 | let targetDrawerID = $(this).parent().find('.drawer-content').attr('id'); | ||
| 10668 | const pinnedDrawerClicked = drawer.hasClass('pinnedOpen'); | ||
| 10669 | |||
| 10670 | if (!drawerWasOpenAlready) { //to open the drawer | ||
| 10671 | $('.openDrawer').not('.pinnedOpen').addClass('resizing').slideToggle(200, 'swing', async function () { | ||
| 10672 | await delay(50); $(this).closest('.drawer-content').removeClass('resizing'); | ||
| 10673 | }); | ||
| 10674 | $('.openIcon').not('.drawerPinnedOpen').toggleClass('closedIcon openIcon'); | ||
| 10675 | $('.openDrawer').not('.pinnedOpen').toggleClass('closedDrawer openDrawer'); | ||
| 10676 | icon.toggleClass('openIcon closedIcon'); | ||
| 10677 | drawer.toggleClass('openDrawer closedDrawer'); | ||
| 10678 | |||
| 10679 | //console.log(targetDrawerID); | ||
| 10680 | if (targetDrawerID === 'right-nav-panel') { | ||
| 10681 | $(this).closest('.drawer').find('.drawer-content').addClass('resizing').slideToggle({ | ||
| 10682 | duration: 200, | ||
| 10683 | easing: 'swing', | ||
| 10684 | start: function () { | ||
| 10685 | jQuery(this).css('display', 'flex'); //flex needed to make charlist scroll | ||
| 10686 | }, | ||
| 10687 | complete: async function () { | ||
| 10688 | favsToHotswap(); | ||
| 10689 | await delay(50); | ||
| 10690 | $(this).closest('.drawer-content').removeClass('resizing'); | ||
| 10691 | $('#rm_print_characters_block').trigger('scroll'); | ||
| 10692 | }, | ||
| 10693 | }); | ||
| 10694 | } else { | ||
| 10695 | $(this).closest('.drawer').find('.drawer-content').addClass('resizing').slideToggle(200, 'swing', async function () { | ||
| 10696 | await delay(50); $(this).closest('.drawer-content').removeClass('resizing'); | ||
| 10697 | }); | ||
| 10698 | } | ||
| 10699 | |||
| 10700 | // Set the height of "autoSetHeight" textareas within the drawer to their scroll height | ||
| 10701 | if (!CSS.supports('field-sizing', 'content')) { | ||
| 10702 | $(this).closest('.drawer').find('.drawer-content textarea.autoSetHeight').each(async function () { | ||
| 10703 | await resetScrollHeight($(this)); | ||
| 10704 | return; | ||
| 10705 | }); | ||
| 10706 | } | ||
| 10707 | |||
| 10708 | } else if (drawerWasOpenAlready) { //to close manually | ||
| 10709 | icon.toggleClass('closedIcon openIcon'); | ||
| 10710 | |||
| 10711 | if (pinnedDrawerClicked) { | ||
| 10712 | $(drawer).addClass('resizing').slideToggle(200, 'swing', async function () { | ||
| 10713 | await delay(50); $(this).removeClass('resizing'); | ||
| 10714 | }); | ||
| 10715 | } | ||
| 10716 | else { | ||
| 10717 | $('.openDrawer').not('.pinnedOpen').addClass('resizing').slideToggle(200, 'swing', async function () { | ||
| 10718 | await delay(50); $(this).closest('.drawer-content').removeClass('resizing'); | ||
| 10719 | }); | ||
| 10720 | } | ||
| 10721 | |||
| 10722 | drawer.toggleClass('closedDrawer openDrawer'); | ||
| 10723 | } | ||
| 10724 | }); | ||
| 10725 | 10773 | ||
| 10726 | $('html').on('touchstart mousedown', function (e) { | 10774 | $('html').on('touchstart mousedown', function (e) { |
| 10727 | var clickTarget = $(e.target); | 10775 | var clickTarget = $(e.target); |
| @@ -4,30 +4,56 @@ | |||
| 4 | <a href="https://docs.sillytavern.app/usage/update/" target="_blank" data-i18n="Want to update?"> | 4 | <a href="https://docs.sillytavern.app/usage/update/" target="_blank" data-i18n="Want to update?"> |
| 5 | Want to update? | 5 | Want to update? |
| 6 | </a> | 6 | </a> |
| 7 | <hr> | ||
| 8 | <h3 data-i18n="How to start chatting?">How to start chatting?</h3> | 7 | <h3 data-i18n="How to start chatting?">How to start chatting?</h3> |
| 9 | <ol> | 8 | <ol> |
| 10 | <li> | 9 | <li> |
| 11 | <span data-i18n="Click _space">Click </span><code><i class="fa-solid fa-plug"></i></code><span data-i18n="and select a"> and select a </span><a href="https://docs.sillytavern.app/usage/api-connections/" target="_blank" data-i18n="Chat API">Chat API</a>.</span> | 10 | <span data-i18n="Click _space">Click </span> |
| 11 | <button class="menu_button menu_button_icon drawer-opener inline-flex" data-target="sys-settings-button"> | ||
| 12 | <i class="fa-solid fa-plug"></i> | ||
| 13 | <span data-i18n="[title]API Connections">API Connections</span> | ||
| 14 | </button> | ||
| 15 | <span data-i18n="and connect to an">and connect to an</span> | ||
| 16 | <a href="https://docs.sillytavern.app/usage/api-connections/" target="_blank"> | ||
| 17 | <span class="fa-solid fa-circle-question"></span> | ||
| 18 | <span data-i18n="API">API</span></a>. | ||
| 12 | </li> | 19 | </li> |
| 13 | <li> | 20 | <li> |
| 14 | <span data-i18n="Click _space">Click </span><code><i class="fa-solid fa-address-card"></i></code><span data-i18n="and pick a character."> and pick a character.</span> | 21 | <span data-i18n="Click _space">Click </span> |
| 22 | <button class="menu_button menu_button_icon drawer-opener inline-flex" data-target="rightNavHolder"> | ||
| 23 | <i class="fa-solid fa-address-card"></i> | ||
| 24 | <span data-i18n="[title]Character Management">Character Management</span> | ||
| 25 | </button> | ||
| 26 | <span data-i18n="and pick a character."> and pick a character.</span> | ||
| 15 | </li> | 27 | </li> |
| 16 | </ol> | 28 | </ol> |
| 29 | |||
| 30 | <div> | ||
| 31 | <span data-i18n="You can add more">You can add more</span> | ||
| 32 | <button class="open_characters_library menu_button menu_button_icon inline-flex"> | ||
| 33 | <i class="fa-solid fa-image-portrait"></i> | ||
| 34 | <span data-i18n="Sample characters">Sample characters</span> | ||
| 35 | </button> | ||
| 36 | <span data-i18n="or">or</span> | ||
| 37 | <button class="external_import_button menu_button menu_button_icon inline-flex"> | ||
| 38 | <i class="fa-solid fa-cloud-arrow-down"></i> | ||
| 39 | <span data-i18n="Import Characters">Import characters</span> | ||
| 40 | </button> | ||
| 41 | <span data-i18n="from other websites">from other websites.</span> | ||
| 42 | </div> | ||
| 17 | <div> | 43 | <div> |
| 18 | <span data-i18n="You can browse a list of bundled characters in the"> | 44 | <span data-i18n="Go to the">Go to the</span> |
| 19 | You can browse a list of bundled characters in the | 45 | |
| 20 | </span> | 46 | <i data-i18n="Download Extensions & Assets">Download Extensions & Assets</i> |
| 21 | <i data-i18n="Download Extensions & Assets"> | 47 | <span data-i18n="menu within">menu within</span> |
| 22 | Download Extensions & Assets | 48 | |
| 23 | </i> | 49 | <button class="menu_button menu_button_icon drawer-opener inline-flex" data-target="extensions-settings-button"> |
| 24 | <span data-i18n="menu within"> | 50 | <i class="fa-solid fa-cubes"></i> |
| 25 | menu within | 51 | <span data-i18n="[title]Extensions">Extensions</span> |
| 26 | </span> | 52 | </button> |
| 27 | <code><i class="fa-solid fa-cubes"></i></code> | 53 | |
| 28 | <span>.</span> | 54 | <span data-i18n="to install additional features.">to install additional features.</span> |
| 29 | </div> | 55 | </div> |
| 30 | <hr> | 56 | |
| 31 | <h3 data-i18n="Confused or lost?">Confused or lost?</h3> | 57 | <h3 data-i18n="Confused or lost?">Confused or lost?</h3> |
| 32 | <ul> | 58 | <ul> |
| 33 | <li> | 59 | <li> |
| @@ -43,7 +69,6 @@ | |||
| 43 | </li> | 69 | </li> |
| 44 | </ul> | 70 | </ul> |
| 45 | 71 | ||
| 46 | <hr> | ||
| 47 | <h3 data-i18n="Still have questions?">Still have questions?</h3> | 72 | <h3 data-i18n="Still have questions?">Still have questions?</h3> |
| 48 | <ul> | 73 | <ul> |
| 49 | <li> | 74 | <li> |
| @@ -62,4 +87,3 @@ | |||
| 62 | </a> | 87 | </a> |
| 63 | </li> | 88 | </li> |
| 64 | </ul> | 89 | </ul> |
| 65 | |||
| @@ -314,6 +314,12 @@ input[type='checkbox']:focus-visible { | |||
| 314 | display: inline-block; | 314 | display: inline-block; |
| 315 | } | 315 | } |
| 316 | 316 | ||
| 317 | .mes_text ol, | ||
| 318 | .mes_text ul { | ||
| 319 | margin-top: 5px; | ||
| 320 | margin-bottom: 5px; | ||
| 321 | } | ||
| 322 | |||
| 317 | .mes_text br, | 323 | .mes_text br, |
| 318 | .mes_bias br { | 324 | .mes_bias br { |
| 319 | content: ' '; | 325 | content: ' '; |
| @@ -1208,8 +1214,9 @@ textarea.autoSetHeight { | |||
| 1208 | } | 1214 | } |
| 1209 | 1215 | ||
| 1210 | input, | 1216 | input, |
| 1211 | select { | 1217 | select, |
| 1212 | font-family: var(--mainFontFamily); | 1218 | button { |
| 1219 | font-family: var(--mainFontFamily), sans-serif; | ||
| 1213 | font-size: var(--mainFontSize); | 1220 | font-size: var(--mainFontSize); |
| 1214 | color: var(--SmartThemeBodyColor); | 1221 | color: var(--SmartThemeBodyColor); |
| 1215 | } | 1222 | } |