Browse Source

Refactor legacy input fields

Added missed length restrictions on input fields
master
Eduard Kuzmenko 4 years ago
parent
commit
d1c9a25129
  1. 4
      src/components/inputField.ts
  2. 40
      src/components/sidebarLeft/tabs/editFolder.ts
  3. 57
      src/components/sidebarLeft/tabs/newChannel.ts
  4. 30
      src/components/sidebarLeft/tabs/newGroup.ts
  5. 36
      src/index.hbs
  6. 5
      src/lib/richtextprocessor.ts
  7. 72
      src/pages/pageSignUp.ts
  8. 1
      src/scss/partials/_input.scss
  9. 1
      src/scss/partials/_leftSidebar.scss
  10. 2
      src/scss/style.scss

4
src/components/inputField.ts

@ -54,6 +54,8 @@ class InputField {
public container: HTMLElement; public container: HTMLElement;
public input: HTMLElement; public input: HTMLElement;
//public onLengthChange: (length: number, isOverflow: boolean) => void;
constructor(private options: { constructor(private options: {
placeholder?: string, placeholder?: string,
label?: string, label?: string,
@ -116,6 +118,8 @@ class InputField {
const isError = diff < 0; const isError = diff < 0;
input.classList.toggle('error', isError); input.classList.toggle('error', isError);
//this.onLengthChange && this.onLengthChange(inputLength, isError);
if(isError || diff <= showLengthOn) { if(isError || diff <= showLengthOn) {
labelEl.innerText = label + ` (${maxLength - inputLength})`; labelEl.innerText = label + ` (${maxLength - inputLength})`;
if(!showingLength) showingLength = true; if(!showingLength) showingLength = true;

40
src/components/sidebarLeft/tabs/editFolder.ts

@ -9,6 +9,8 @@ import { SliderTab } from "../../slider";
import { toast } from "../../toast"; import { toast } from "../../toast";
import appMessagesManager from "../../../lib/appManagers/appMessagesManager"; import appMessagesManager from "../../../lib/appManagers/appMessagesManager";
import { attachClickEvent } from "../../../helpers/dom"; import { attachClickEvent } from "../../../helpers/dom";
import InputField from "../../inputField";
import RichTextProcessor from "../../../lib/richtextprocessor";
const MAX_FOLDER_NAME_LENGTH = 12; const MAX_FOLDER_NAME_LENGTH = 12;
@ -22,7 +24,8 @@ export default class AppEditFolderTab implements SliderTab {
private confirmBtn: HTMLElement; private confirmBtn: HTMLElement;
private menuBtn: HTMLElement; private menuBtn: HTMLElement;
private deleteFolderBtn: HTMLElement; private deleteFolderBtn: HTMLElement;
private nameInput: HTMLInputElement; private nameInput: HTMLElement;
private nameInputField: InputField;
private include_peers: HTMLElement; private include_peers: HTMLElement;
private exclude_peers: HTMLElement; private exclude_peers: HTMLElement;
@ -44,7 +47,19 @@ export default class AppEditFolderTab implements SliderTab {
this.confirmBtn = this.container.querySelector('.btn-confirm'); this.confirmBtn = this.container.querySelector('.btn-confirm');
this.menuBtn = this.container.querySelector('.btn-menu-toggle'); this.menuBtn = this.container.querySelector('.btn-menu-toggle');
this.deleteFolderBtn = this.menuBtn.querySelector('.menu-delete'); this.deleteFolderBtn = this.menuBtn.querySelector('.menu-delete');
this.nameInput = this.container.querySelector('#folder-name');
const inputWrapper = document.createElement('div');
inputWrapper.classList.add('input-wrapper');
this.nameInputField = new InputField({
label: 'Folder Name',
maxLength: MAX_FOLDER_NAME_LENGTH
});
this.nameInput = this.nameInputField.input;
inputWrapper.append(this.nameInputField.container);
this.caption.parentElement.insertBefore(inputWrapper, this.caption.nextSibling);
this.include_peers = this.container.querySelector('.folder-list-included'); this.include_peers = this.container.querySelector('.folder-list-included');
this.exclude_peers = this.container.querySelector('.folder-list-excluded'); this.exclude_peers = this.container.querySelector('.folder-list-excluded');
@ -84,8 +99,12 @@ export default class AppEditFolderTab implements SliderTab {
}); });
this.confirmBtn.addEventListener('click', () => { this.confirmBtn.addEventListener('click', () => {
if(!this.nameInput.value.trim()) { if(this.nameInputField.input.classList.contains('error')) {
this.nameInput.classList.add('error'); return;
}
if(!this.nameInputField.value.trim()) {
this.nameInputField.input.classList.add('error');
return; return;
} }
@ -122,14 +141,7 @@ export default class AppEditFolderTab implements SliderTab {
}); });
this.nameInput.addEventListener('input', () => { this.nameInput.addEventListener('input', () => {
if(this.nameInput.value.length > MAX_FOLDER_NAME_LENGTH) { this.filter.title = this.nameInputField.value;
this.nameInput.value = this.nameInput.value.slice(0, MAX_FOLDER_NAME_LENGTH);
return;
}
this.filter.title = this.nameInput.value;
this.nameInput.classList.remove('error');
this.editCheckForChange(); this.editCheckForChange();
}); });
} }
@ -154,7 +166,7 @@ export default class AppEditFolderTab implements SliderTab {
this.title.innerText = 'New Folder'; this.title.innerText = 'New Folder';
this.menuBtn.classList.add('hide'); this.menuBtn.classList.add('hide');
this.confirmBtn.classList.remove('hide'); this.confirmBtn.classList.remove('hide');
this.nameInput.value = ''; this.nameInputField.value = '';
for(const flag in this.flags) { for(const flag in this.flags) {
// @ts-ignore // @ts-ignore
@ -172,7 +184,7 @@ export default class AppEditFolderTab implements SliderTab {
} }
const filter = this.filter; const filter = this.filter;
this.nameInput.value = filter.title; this.nameInputField.value = RichTextProcessor.wrapEmojiText(filter.title);
for(const flag in this.flags) { for(const flag in this.flags) {
// @ts-ignore // @ts-ignore

57
src/components/sidebarLeft/tabs/newChannel.ts

@ -1,37 +1,64 @@
import appSidebarLeft, { AppSidebarLeft } from ".."; import appSidebarLeft, { AppSidebarLeft } from "..";
import { InputFile } from "../../../layer"; import { InputFile } from "../../../layer";
import appChatsManager from "../../../lib/appManagers/appChatsManager"; import appChatsManager from "../../../lib/appManagers/appChatsManager";
import Button from "../../button";
import InputField from "../../inputField";
import PopupAvatar from "../../popups/avatar"; import PopupAvatar from "../../popups/avatar";
import { SliderTab } from "../../slider"; import { SliderTab } from "../../slider";
export default class AppNewChannelTab implements SliderTab { export default class AppNewChannelTab implements SliderTab {
private container = document.querySelector('.new-channel-container') as HTMLDivElement; private container = document.querySelector('.new-channel-container') as HTMLDivElement;
private canvas = this.container.querySelector('.avatar-edit-canvas') as HTMLCanvasElement; private canvas = this.container.querySelector('.avatar-edit-canvas') as HTMLCanvasElement;
private channelNameInput = this.container.querySelector('.new-channel-name') as HTMLInputElement;
private channelDescriptionInput = this.container.querySelector('.new-channel-description') as HTMLInputElement;
private nextBtn = this.container.querySelector('.btn-corner') as HTMLButtonElement;
private backBtn = this.container.querySelector('.sidebar-close-button') as HTMLButtonElement;
private uploadAvatar: () => Promise<InputFile> = null; private uploadAvatar: () => Promise<InputFile> = null;
private channelNameInputField: InputField;
private channelDescriptionInputField: InputField;
private nextBtn: HTMLButtonElement;
constructor() { constructor() {
const content = this.container.querySelector('.sidebar-content');
this.container.querySelector('.avatar-edit').addEventListener('click', () => { this.container.querySelector('.avatar-edit').addEventListener('click', () => {
new PopupAvatar().open(this.canvas, (_upload) => { new PopupAvatar().open(this.canvas, (_upload) => {
this.uploadAvatar = _upload; this.uploadAvatar = _upload;
}); });
}); });
this.channelNameInput.addEventListener('input', () => { const inputWrapper = document.createElement('div');
let value = this.channelNameInput.value; inputWrapper.classList.add('input-wrapper');
if(value.length) {
this.nextBtn.classList.add('is-visible'); this.channelNameInputField = new InputField({
} else { label: 'Channel Name',
this.nextBtn.classList.remove('is-visible'); maxLength: 128
} });
this.channelDescriptionInputField = new InputField({
label: 'Description (optional)',
maxLength: 255
}); });
inputWrapper.append(this.channelNameInputField.container, this.channelDescriptionInputField.container);
const onLengthChange = () => {
this.nextBtn.classList.toggle('is-visible', !!this.channelNameInputField.value.length &&
!this.channelNameInputField.input.classList.contains('error') &&
!this.channelDescriptionInputField.input.classList.contains('error'));
};
this.channelNameInputField.input.addEventListener('input', onLengthChange);
this.channelDescriptionInputField.input.addEventListener('input', onLengthChange);
const caption = document.createElement('div');
caption.classList.add('caption');
caption.innerText = 'You can provide an optional description for your channel.';
this.nextBtn = Button('btn-corner btn-circle', {icon: 'next'});
content.append(inputWrapper, caption, this.nextBtn);
this.nextBtn.addEventListener('click', () => { this.nextBtn.addEventListener('click', () => {
let title = this.channelNameInput.value; const title = this.channelNameInputField.value;
let about = this.channelDescriptionInput.value; const about = this.channelDescriptionInputField.value;
this.nextBtn.disabled = true; this.nextBtn.disabled = true;
appChatsManager.createChannel(title, about).then((channelId) => { appChatsManager.createChannel(title, about).then((channelId) => {
@ -52,8 +79,8 @@ export default class AppNewChannelTab implements SliderTab {
ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.uploadAvatar = null; this.uploadAvatar = null;
this.channelNameInput.value = ''; this.channelNameInputField.value = '';
this.channelDescriptionInput.value = ''; this.channelDescriptionInputField.value = '';
this.nextBtn.disabled = false; this.nextBtn.disabled = false;
} }
} }

30
src/components/sidebarLeft/tabs/newGroup.ts

@ -4,6 +4,8 @@ import appChatsManager from "../../../lib/appManagers/appChatsManager";
import appDialogsManager from "../../../lib/appManagers/appDialogsManager"; import appDialogsManager from "../../../lib/appManagers/appDialogsManager";
import appUsersManager from "../../../lib/appManagers/appUsersManager"; import appUsersManager from "../../../lib/appManagers/appUsersManager";
import { SearchGroup } from "../../appSearch"; import { SearchGroup } from "../../appSearch";
import Button from "../../button";
import InputField from "../../inputField";
import PopupAvatar from "../../popups/avatar"; import PopupAvatar from "../../popups/avatar";
import Scrollable from "../../scrollable"; import Scrollable from "../../scrollable";
import { SliderTab } from "../../slider"; import { SliderTab } from "../../slider";
@ -12,11 +14,11 @@ export default class AppNewGroupTab implements SliderTab {
private container = document.querySelector('.new-group-container') as HTMLDivElement; private container = document.querySelector('.new-group-container') as HTMLDivElement;
private contentDiv = this.container.querySelector('.sidebar-content') as HTMLDivElement; private contentDiv = this.container.querySelector('.sidebar-content') as HTMLDivElement;
private canvas = this.container.querySelector('.avatar-edit-canvas') as HTMLCanvasElement; private canvas = this.container.querySelector('.avatar-edit-canvas') as HTMLCanvasElement;
private groupNameInput = this.container.querySelector('.new-group-name') as HTMLInputElement;
private nextBtn = this.container.querySelector('.btn-corner') as HTMLButtonElement;
private searchGroup = new SearchGroup(' ', 'contacts', true, 'new-group-members disable-hover', false); private searchGroup = new SearchGroup(' ', 'contacts', true, 'new-group-members disable-hover', false);
private uploadAvatar: () => Promise<InputFile> = null; private uploadAvatar: () => Promise<InputFile> = null;
private userIds: number[]; private userIds: number[];
private nextBtn: HTMLButtonElement;
private groupNameInputField: InputField;
constructor() { constructor() {
this.container.querySelector('.avatar-edit').addEventListener('click', () => { this.container.querySelector('.avatar-edit').addEventListener('click', () => {
@ -25,13 +27,25 @@ export default class AppNewGroupTab implements SliderTab {
}); });
}); });
this.groupNameInput.addEventListener('input', () => { const inputWrapper = document.createElement('div');
const value = this.groupNameInput.value; inputWrapper.classList.add('input-wrapper');
this.nextBtn.classList.toggle('is-visible', !!value.length);
this.groupNameInputField = new InputField({
label: 'Group Name',
maxLength: 128
}); });
inputWrapper.append(this.groupNameInputField.container);
this.groupNameInputField.input.addEventListener('input', () => {
const value = this.groupNameInputField.value;
this.nextBtn.classList.toggle('is-visible', !!value.length && !this.groupNameInputField.input.classList.contains('error'));
});
this.nextBtn = Button('btn-corner btn-circle', {icon: 'next'});
this.nextBtn.addEventListener('click', () => { this.nextBtn.addEventListener('click', () => {
const title = this.groupNameInput.value; const title = this.groupNameInputField.value;
this.nextBtn.disabled = true; this.nextBtn.disabled = true;
appChatsManager.createChat(title, this.userIds).then((chatId) => { appChatsManager.createChat(title, this.userIds).then((chatId) => {
@ -51,7 +65,7 @@ export default class AppNewGroupTab implements SliderTab {
const scrollable = new Scrollable(chatsContainer); const scrollable = new Scrollable(chatsContainer);
this.contentDiv.append(chatsContainer); this.contentDiv.append(inputWrapper, chatsContainer, this.nextBtn);
} }
public onClose() { public onClose() {
@ -65,7 +79,7 @@ export default class AppNewGroupTab implements SliderTab {
ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.uploadAvatar = null; this.uploadAvatar = null;
this.groupNameInput.value = ''; this.groupNameInputField.value = '';
this.nextBtn.disabled = false; this.nextBtn.disabled = false;
this.searchGroup.clear(); this.searchGroup.clear();
} }

36
src/index.hbs

@ -109,17 +109,6 @@
</div> </div>
<h4 class="fullName">Your Name</h4> <h4 class="fullName">Your Name</h4>
<p class="subtitle">Enter your name and add<br>a profile picture</p> <p class="subtitle">Enter your name and add<br>a profile picture</p>
<div class="input-wrapper">
<div class="input-field">
<input type="text" name="name" id="name" autocomplete="off" required />
<label for="name">Name</label>
</div>
<div class="input-field">
<input type="text" name="lastName" id="lastName" autocomplete="off" required />
<label for="lastName">Last Name (optional)</label>
</div>
<button class="btn-primary rp" id="signUp">START MESSAGING</button>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -208,18 +197,6 @@
<canvas class="avatar-edit-canvas"></canvas> <canvas class="avatar-edit-canvas"></canvas>
<span class="tgico tgico-cameraadd"></span> <span class="tgico tgico-cameraadd"></span>
</div> </div>
<div class="input-wrapper">
<div class="input-field">
<input type="text" name="name" class="new-channel-name" id="new-channel-name" autocomplete="xxDDqqOX" required="">
<label for="new-channel-name">Channel Name</label>
</div>
<div class="input-field">
<input type="text" name="description" class="new-channel-description" id="new-channel-description" autocomplete="aintsofunnow" required="">
<label for="new-channel-description">Description (optional)</label>
</div>
</div>
<div class="caption">You can provide an optional description for your channel.</div>
<button class="btn-circle rp btn-corner tgico-next"></button>
</div> </div>
</div> </div>
<div class="sidebar-slider-item addmembers-container"> <div class="sidebar-slider-item addmembers-container">
@ -241,13 +218,6 @@
<canvas class="avatar-edit-canvas"></canvas> <canvas class="avatar-edit-canvas"></canvas>
<span class="tgico tgico-cameraadd"></span> <span class="tgico tgico-cameraadd"></span>
</div> </div>
<div class="input-wrapper">
<div class="input-field">
<input type="text" name="name" class="new-group-name" id="new-group-name" autocomplete="feellikeamonster2112" required="">
<label for="new-group-name">Group Name</label>
</div>
</div>
<button class="btn-circle rp btn-corner tgico-next"></button>
</div> </div>
</div> </div>
<div class="sidebar-slider-item settings-container"> <div class="sidebar-slider-item settings-container">
@ -336,12 +306,6 @@
<div class="edit-folder scrollable scrollable-y"> <div class="edit-folder scrollable scrollable-y">
<div class="sticker-container"></div> <div class="sticker-container"></div>
<div class="caption">Choose chats and types of chats that will<br>appear and never appear in this folder.</div> <div class="caption">Choose chats and types of chats that will<br>appear and never appear in this folder.</div>
<div class="input-wrapper">
<div class="input-field">
<input type="text" name="folder-name" class="folder-name" autocomplete="aintCCZsofunnowhHQ" id="folder-name" required="">
<label for="folder-name">Folder Name</label>
</div>
</div>
<div class="folder-list folder-list-included"> <div class="folder-list folder-list-included">
<div class="sidebar-left-h2">Included chats</div> <div class="sidebar-left-h2">Included chats</div>
<div class="folder-categories"> <div class="folder-categories">

5
src/lib/richtextprocessor.ts

@ -4,7 +4,6 @@ import emojiRegExp from '../emoji/regex';
import { encodeEmoji } from '../emoji'; import { encodeEmoji } from '../emoji';
import { MOUNT_CLASS_TO } from './mtproto/mtproto_config'; import { MOUNT_CLASS_TO } from './mtproto/mtproto_config';
import { MessageEntity } from '../layer'; import { MessageEntity } from '../layer';
import { copy } from '../helpers/object';
import { encodeEntities } from '../helpers/string'; import { encodeEntities } from '../helpers/string';
import { isSafari } from '../helpers/userAgent'; import { isSafari } from '../helpers/userAgent';
@ -373,14 +372,14 @@ namespace RichTextProcessor {
return currentEntities; return currentEntities;
} }
export function wrapRichNestedText(text: string, nested: MessageEntity[], options: any) { /* export function wrapRichNestedText(text: string, nested: MessageEntity[], options: any) {
if(nested === undefined) { if(nested === undefined) {
return encodeEntities(text); return encodeEntities(text);
} }
options.hasNested = true; options.hasNested = true;
return wrapRichText(text, {entities: nested, nested: true}); return wrapRichText(text, {entities: nested, nested: true});
} } */
export function wrapRichText(text: string, options: Partial<{ export function wrapRichText(text: string, options: Partial<{
entities: MessageEntity[], entities: MessageEntity[],

72
src/pages/pageSignUp.ts

@ -1,15 +1,18 @@
import Button from '../components/button';
import InputField from '../components/inputField';
import { putPreloader } from '../components/misc'; import { putPreloader } from '../components/misc';
import PopupAvatar from '../components/popups/avatar'; import PopupAvatar from '../components/popups/avatar';
import appStateManager from '../lib/appManagers/appStateManager'; import appStateManager from '../lib/appManagers/appStateManager';
//import apiManager from '../lib/mtproto/apiManager'; //import apiManager from '../lib/mtproto/apiManager';
import apiManager from '../lib/mtproto/mtprotoworker'; import apiManager from '../lib/mtproto/mtprotoworker';
import RichTextProcessor from '../lib/richtextprocessor';
import { AuthState } from '../types'; import { AuthState } from '../types';
import Page from './page'; import Page from './page';
import pageIm from './pageIm'; import pageIm from './pageIm';
let authCode: AuthState.signUp['authCode'] = null; let authCode: AuthState.signUp['authCode'] = null;
let onFirstMount = () => import('../lib/appManagers/appProfileManager').then(imported => { const onFirstMount = () => import('../lib/appManagers/appProfileManager').then(imported => {
const pageElement = page.pageEl; const pageElement = page.pageEl;
const avatarPreview = pageElement.querySelector('#canvas-avatar') as HTMLCanvasElement; const avatarPreview = pageElement.querySelector('#canvas-avatar') as HTMLCanvasElement;
const appProfileManager = imported.default; const appProfileManager = imported.default;
@ -23,19 +26,18 @@ let onFirstMount = () => import('../lib/appManagers/appProfileManager').then(imp
const headerName = pageElement.getElementsByClassName('fullName')[0] as HTMLHeadingElement; const headerName = pageElement.getElementsByClassName('fullName')[0] as HTMLHeadingElement;
let handleInput = function(this: typeof fieldName, e: Event) { const handleInput = (e: Event) => {
let name = fieldName.value || ''; const name = nameInputField.value || '';
let lastName = fieldLastName.value || ''; const lastName = lastNameInputField.value || '';
let fullName = name || lastName const fullName = name || lastName
? (name + ' ' + lastName).trim() ? (name + ' ' + lastName).trim()
: 'Your Name'; : 'Your Name';
if(headerName.innerText != fullName) headerName.innerText = fullName; if(headerName.innerHTML != fullName) headerName.innerHTML = RichTextProcessor.wrapEmojiText(fullName);
this.classList.remove('error');
}; };
let sendAvatar = () => new Promise((resolve, reject) => { let sendAvatar = () => new Promise<void>((resolve, reject) => {
if(!uploadAvatar) { if(!uploadAvatar) {
//console.log('User has not selected avatar'); //console.log('User has not selected avatar');
return resolve(); return resolve();
@ -49,29 +51,49 @@ let onFirstMount = () => import('../lib/appManagers/appProfileManager').then(imp
}, reject); }, reject);
}); });
const fieldName = document.getElementById('name') as HTMLInputElement; const inputWrapper = document.createElement('div');
fieldName.addEventListener('input', handleInput); inputWrapper.classList.add('input-wrapper');
const fieldLastName = document.getElementById('lastName') as HTMLInputElement; const nameInputField = new InputField({
fieldLastName.addEventListener('input', handleInput); label: 'Name',
maxLength: 70
});
const signUpButton = document.getElementById('signUp') as HTMLButtonElement; const lastNameInputField = new InputField({
signUpButton.addEventListener('click', function(this: typeof signUpButton, e) { label: 'Last Name (optional)',
this.setAttribute('disabled', 'true'); maxLength: 64
});
const btnSignUp = Button('btn-primary');
btnSignUp.append('START MESSAGING');
inputWrapper.append(nameInputField.container, lastNameInputField.container, btnSignUp);
headerName.parentElement.append(inputWrapper);
if(!fieldName.value.length) { nameInputField.input.addEventListener('input', handleInput);
fieldName.classList.add('error'); lastNameInputField.input.addEventListener('input', handleInput);
btnSignUp.addEventListener('click', function(this: typeof btnSignUp, e) {
if(nameInputField.input.classList.contains('error') || lastNameInputField.input.classList.contains('error')) {
return false;
}
if(!nameInputField.value.length) {
nameInputField.input.classList.add('error');
return false; return false;
} }
let name = fieldName.value; this.setAttribute('disabled', 'true');
let lastName = fieldLastName.value;
const name = nameInputField.value.trim();
const lastName = lastNameInputField.value.trim();
let params = { const params = {
'phone_number': authCode.phone_number, phone_number: authCode.phone_number,
'phone_code_hash': authCode.phone_code_hash, phone_code_hash: authCode.phone_code_hash,
'first_name': name, first_name: name,
'last_name': lastName last_name: lastName
}; };
//console.log('invoking auth.signUp with params:', params); //console.log('invoking auth.signUp with params:', params);
@ -80,7 +102,7 @@ let onFirstMount = () => import('../lib/appManagers/appProfileManager').then(imp
putPreloader(this); putPreloader(this);
apiManager.invokeApi('auth.signUp', params) apiManager.invokeApi('auth.signUp', params)
.then((response: any) => { .then((response) => {
//console.log('auth.signUp response:', response); //console.log('auth.signUp response:', response);
switch(response._) { switch(response._) {

1
src/scss/partials/_input.scss

@ -61,6 +61,7 @@
transition: .2s border-color; transition: .2s border-color;
position: relative; position: relative;
z-index: 1; z-index: 1;
text-align: left;
//line-height: calc(54px - var(--border-width)); //line-height: calc(54px - var(--border-width));
/* overflow: hidden; /* overflow: hidden;
white-space: nowrap; */ white-space: nowrap; */

1
src/scss/partials/_leftSidebar.scss

@ -547,6 +547,7 @@
p { p {
height: unset; height: unset;
justify-content: start;
} }
p:last-child { p:last-child {

2
src/scss/style.scss

@ -277,7 +277,7 @@ html {
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-webkit-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0); -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
text-rendering: optimizeSpeed; //text-rendering: optimizeSpeed;
} }
body { body {

Loading…
Cancel
Save