Browse Source

Onboarding component

pull/118/head
Sebastian Stehle 9 years ago
parent
commit
3184227907
  1. 12
      src/Squidex/app/features/content/pages/contents/contents-page.component.html
  2. 2
      src/Squidex/app/features/content/shared/content-item.component.html
  3. 2
      src/Squidex/app/features/schemas/pages/schema/field.component.html
  4. 2
      src/Squidex/app/features/schemas/pages/schema/schema-page.component.html
  5. 6
      src/Squidex/app/features/webhooks/pages/webhook-events-page.component.scss
  6. 2
      src/Squidex/app/framework/angular/dropdown.component.scss
  7. 17
      src/Squidex/app/framework/angular/image-source.directive.ts
  8. 54
      src/Squidex/app/framework/angular/modal-target.directive.ts
  9. 10
      src/Squidex/app/framework/angular/modal-view.directive.ts
  10. 16
      src/Squidex/app/framework/angular/onboarding-tooltip.component.html
  11. 46
      src/Squidex/app/framework/angular/onboarding-tooltip.component.scss
  12. 98
      src/Squidex/app/framework/angular/onboarding-tooltip.component.ts
  13. 22
      src/Squidex/app/framework/angular/slider.component.ts
  14. 4
      src/Squidex/app/framework/declarations.ts
  15. 5
      src/Squidex/app/framework/module.ts
  16. 4
      src/Squidex/app/framework/services/local-store.service.ts
  17. 0
      src/Squidex/app/framework/services/message-bus.service.spec.ts
  18. 0
      src/Squidex/app/framework/services/message-bus.service.ts
  19. 41
      src/Squidex/app/framework/services/onboarding.service.ts
  20. 2
      src/Squidex/app/shared/components/language-selector.component.html
  21. 1
      src/Squidex/app/theme/_bootstrap.scss
  22. 2
      src/Squidex/app/theme/_forms.scss
  23. 6
      src/Squidex/app/theme/_lists.scss
  24. 41
      src/Squidex/app/theme/_mixins.scss

12
src/Squidex/app/features/content/pages/contents/contents-page.component.html

@ -15,12 +15,20 @@
<form class="form-inline" (ngSubmit)="search()"> <form class="form-inline" (ngSubmit)="search()">
<input class="form-control form-control-expandable" #findInput [formControl]="contentsFilter" placeholder="Search for content" #searchInput /> <input class="form-control form-control-expandable" #findInput [formControl]="contentsFilter" placeholder="Search for content" #searchInput />
<a class="expand-search" (click)="searchModal.toggle()"> <a class="expand-search" (click)="searchModal.toggle()" #archive>
<i class="icon-caret-down"></i> <i class="icon-caret-down"></i>
</a> </a>
</form> </form>
<sqx-onboarding-tooltip id="contentArchive" [for]="archive" position="topRight" after="6000"
text="Click this icon to show the advanced search menu and to show the archive!">
</sqx-onboarding-tooltip>
<sqx-onboarding-tooltip id="contentFind" [for]="findInput" position="topRight" after="120000"
text="Search for content using full text search over all fields and languages!">
</sqx-onboarding-tooltip>
<div class="dropdown-menu" *sqxModalView="searchModal" closeAlways="true" [sqxModalTarget]="searchInput" position="right"> <div class="dropdown-menu" *sqxModalView="searchModal" closeAlways="true" [sqxModalTarget]="searchInput" position="topRight">
<sqx-search-form <sqx-search-form
[canArchive]="!isReadOnly" [canArchive]="!isReadOnly"
(queryChanged)="contentsFilter.setValue($event, { emitEvent: false })" (queryChanged)="contentsFilter.setValue($event, { emitEvent: false })"

2
src/Squidex/app/features/content/shared/content-item.component.html

@ -16,7 +16,7 @@
<button type="button" class="btn btn-link btn-decent" (click)="dropdown.toggle(); $event.stopPropagation()" [class.active]="dropdown.isOpen | async" #optionsButton> <button type="button" class="btn btn-link btn-decent" (click)="dropdown.toggle(); $event.stopPropagation()" [class.active]="dropdown.isOpen | async" #optionsButton>
<i class="icon-dots"></i> <i class="icon-dots"></i>
</button> </button>
<div class="dropdown-menu" *sqxModalView="dropdown" closeAlways="true" [sqxModalTarget]="optionsButton" position="right" [@fade]> <div class="dropdown-menu" *sqxModalView="dropdown" closeAlways="true" [sqxModalTarget]="optionsButton" position="topRight" [@fade]>
<a class="dropdown-item" (click)="publishing.emit(); $event.stopPropagation()" *ngIf="content.status === 'Draft'"> <a class="dropdown-item" (click)="publishing.emit(); $event.stopPropagation()" *ngIf="content.status === 'Draft'">
Publish Publish
</a> </a>

2
src/Squidex/app/features/schemas/pages/schema/field.component.html

@ -26,7 +26,7 @@
<button type="button" class="btn btn-link btn-decent" (click)="dropdown.toggle()" [class.active]="dropdown.isOpen | async" #optionsButton> <button type="button" class="btn btn-link btn-decent" (click)="dropdown.toggle()" [class.active]="dropdown.isOpen | async" #optionsButton>
<i class="icon-dots"></i> <i class="icon-dots"></i>
</button> </button>
<div class="dropdown-menu" *sqxModalView="dropdown" closeAlways="true" [sqxModalTarget]="optionsButton" position="right" [@fade]> <div class="dropdown-menu" *sqxModalView="dropdown" closeAlways="true" [sqxModalTarget]="optionsButton" position="topRight" [@fade]>
<a class="dropdown-item" (click)="enabling.emit()" *ngIf="field.isDisabled" [class.disabled]="field.isLocked"> <a class="dropdown-item" (click)="enabling.emit()" *ngIf="field.isDisabled" [class.disabled]="field.isLocked">
Enable Enable
</a> </a>

2
src/Squidex/app/features/schemas/pages/schema/schema-page.component.html

@ -21,7 +21,7 @@
<button type="button" class="btn btn-link btn-decent" (click)="editOptionsDropdown.toggle()" [class.active]="editOptionsDropdown.isOpen | async" #optionsButton> <button type="button" class="btn btn-link btn-decent" (click)="editOptionsDropdown.toggle()" [class.active]="editOptionsDropdown.isOpen | async" #optionsButton>
<i class="icon-dots"></i> <i class="icon-dots"></i>
</button> </button>
<div class="dropdown-menu" *sqxModalView="editOptionsDropdown" closeAlways="true" [sqxModalTarget]="optionsButton" position="right" [@fade]> <div class="dropdown-menu" *sqxModalView="editOptionsDropdown" closeAlways="true" [sqxModalTarget]="optionsButton" position="topRight" [@fade]>
<a class="dropdown-item" (click)="configureScriptsDialog.show()"> <a class="dropdown-item" (click)="configureScriptsDialog.show()">
Scripts Scripts
</a> </a>

6
src/Squidex/app/features/webhooks/pages/webhook-events-page.component.scss

@ -30,10 +30,8 @@ h3 {
} }
&::before { &::before {
@include caret-top; @include caret-top($color-border);
@include absolute(-.5rem, 1.9rem, auto, auto); @include absolute(-1.1rem, 1.9rem, auto, auto);
border-color: transparent transparent $color-border;
border-width: .6rem;
} }
h3 { h3 {

2
src/Squidex/app/framework/angular/dropdown.component.scss

@ -30,7 +30,9 @@ $color-input-disabled: #eef1f4;
.icon-caret-down { .icon-caret-down {
@include absolute(30%, .4rem, auto, auto); @include absolute(30%, .4rem, auto, auto);
cursor: pointer;
font-size: .9rem; font-size: .9rem;
font-weight: normal; font-weight: normal;
pointer-events: none;
} }
} }

17
src/Squidex/app/framework/angular/image-source.directive.ts

@ -5,14 +5,16 @@
* Copyright (c) Sebastian Stehle. All rights reserved * Copyright (c) Sebastian Stehle. All rights reserved
*/ */
import { AfterViewInit, Directive, ElementRef, HostListener, Input, OnChanges, OnInit, Renderer } from '@angular/core'; import { AfterViewInit, Directive, ElementRef, HostListener, Input, OnChanges, OnDestroy, OnInit, Renderer } from '@angular/core';
import { MathHelper } from './../utils/math-helper'; import { MathHelper } from './../utils/math-helper';
@Directive({ @Directive({
selector: '[sqxImageSource]' selector: '[sqxImageSource]'
}) })
export class ImageSourceDirective implements OnChanges, OnInit, AfterViewInit { export class ImageSourceDirective implements OnChanges, OnDestroy, OnInit, AfterViewInit {
private parentResizeListener: Function;
private size: any; private size: any;
private loadRetries = 0; private loadRetries = 0;
private loadQuery: string | null = null; private loadQuery: string | null = null;
@ -43,14 +45,19 @@ export class ImageSourceDirective implements OnChanges, OnInit, AfterViewInit {
this.resize(this.parent); this.resize(this.parent);
} }
public ngOnDestroy() {
this.parentResizeListener();
}
public ngOnInit() { public ngOnInit() {
if (this.parent === null) { if (this.parent === null) {
this.parent = this.element.nativeElement.parentElement; this.parent = this.element.nativeElement.parentElement;
} }
this.renderer.listen(this.parent, 'resize', () => { this.parentResizeListener =
this.resize(this.parent); this.renderer.listen(this.parent, 'resize', () => {
}); this.resize(this.parent);
});
} }
@HostListener('load') @HostListener('load')

54
src/Squidex/app/framework/angular/modal-target.directive.ts

@ -24,7 +24,10 @@ export class ModalTargetDirective implements AfterViewInit, OnDestroy, OnInit {
public offset = 2; public offset = 2;
@Input() @Input()
public position = 'left'; public position = 'topLeft';
@Input()
public auto = true;
constructor( constructor(
private readonly renderer: Renderer, private readonly renderer: Renderer,
@ -78,23 +81,56 @@ export class ModalTargetDirective implements AfterViewInit, OnDestroy, OnInit {
private updatePosition() { private updatePosition() {
const viewportHeight = document.documentElement.clientHeight; const viewportHeight = document.documentElement.clientHeight;
const viewportWidth = document.documentElement.clientWidth;
const modalRef = this.element.nativeElement; const modalRef = this.element.nativeElement;
const modalRect = this.element.nativeElement.getBoundingClientRect(); const modalRect = this.element.nativeElement.getBoundingClientRect();
const targetRect: ClientRect = this.targetElement.getBoundingClientRect(); const targetRect: ClientRect = this.targetElement.getBoundingClientRect();
const left = this.position === 'left' ? let top = 0, left = 0;
targetRect.left :
targetRect.right - modalRect.width; if (this.position === 'topLeft' || this.position === 'topRight') {
top = targetRect.bottom + this.offset;
if (this.auto && top + modalRect.height > viewportHeight) {
const t = targetRect.top - modalRect.height - this.offset;
if (t > 0) {
top = t;
}
}
} else {
top = targetRect.top - modalRect.height - this.offset;
if (this.auto && top < 0) {
const t = targetRect.bottom + this.offset;
let top = targetRect.bottom + this.offset; if (t + modalRect.height > viewportHeight) {
top = t;
}
}
}
if (this.position === 'topLeft' || this.position === 'bottomLeft') {
left = targetRect.left + this.offset;
if (this.auto && left + modalRect.width > viewportWidth) {
const l = targetRect.right - modalRect.width - this.offset;
if (l > 0) {
left = l;
}
}
} else {
left = targetRect.right - modalRect.width - this.offset;
if (top + modalRect.height > viewportHeight) { if (this.auto && left < 0) {
const potentialTop = targetRect.top - modalRect.height - this.offset; const l = targetRect.left + this.offset;
if (potentialTop > 0) { if (l + modalRect.width > viewportWidth) {
top = potentialTop; left = l;
}
} }
} }

10
src/Squidex/app/framework/angular/modal-view.directive.ts

@ -17,7 +17,7 @@ import { RootViewService } from './../services/root-view.service';
}) })
export class ModalViewDirective implements OnChanges, OnDestroy { export class ModalViewDirective implements OnChanges, OnDestroy {
private subscription: Subscription | null = null; private subscription: Subscription | null = null;
private clickHandler: Function | null = null; private documentClickListener: Function | null = null;
private renderedView: EmbeddedViewRef<any> | null = null; private renderedView: EmbeddedViewRef<any> | null = null;
@Input('sqxModalView') @Input('sqxModalView')
@ -81,7 +81,7 @@ export class ModalViewDirective implements OnChanges, OnDestroy {
} }
private startListening() { private startListening() {
this.clickHandler = this.documentClickListener =
this.renderer.listenGlobal('document', 'click', (event: MouseEvent) => { this.renderer.listenGlobal('document', 'click', (event: MouseEvent) => {
if (!event.target || this.renderedView === null) { if (!event.target || this.renderedView === null) {
return; return;
@ -109,9 +109,9 @@ export class ModalViewDirective implements OnChanges, OnDestroy {
} }
private stopListening() { private stopListening() {
if (this.clickHandler) { if (this.documentClickListener) {
this.clickHandler(); this.documentClickListener();
this.clickHandler = null; this.documentClickListener = null;
} }
} }
} }

16
src/Squidex/app/framework/angular/onboarding-tooltip.component.html

@ -0,0 +1,16 @@
<div *sqxModalView="tooltipModal;onRoot:true" closeAlways="true" [sqxModalTarget]="for" [position]="position" [offset]="4" [auto]="false">
<div class="onboarding-tooltip" [ngClass]="position">
<div class="arrow1"></div>
<div class="arrow2"></div>
<div class="content">{{text}}</div>
<a (click)="hideThis()" class="hide-this btn-link btn-default btn-sm">
<i class="icon-close"></i>
</a>
<button (click)="hideAll()" class="hide-all btn-link btn-primary btn-sm">
Hide all Tooltips
</button>
</div>
</div>

46
src/Squidex/app/framework/angular/onboarding-tooltip.component.scss

@ -0,0 +1,46 @@
@import '_mixins';
@import '_vars';
$color: $color-theme-blue;
$size-arrow: 10px;
// sass-lint:disable class-name-format
.onboarding-tooltip {
& {
@include box-shadow(0, 2px, 20px, .3);
max-width: 20rem;
background: $color-dark-foreground;
border: 1px solid $color;
position: relative;
}
.content {
padding: 1.6rem 1.6rem 2.5rem;
}
.hide-this {
@include absolute(.1rem, .1rem, auto, auto);
}
.hide-all {
@include absolute(auto, .1rem, .1rem, auto);
}
&.topRight {
& {
margin-right: -$size-arrow - 1;
}
.arrow1 {
@include caret-top($color, $size-arrow);
@include absolute(-$size-arrow * 2, $size-arrow * .5, auto, auto);
}
.arrow2 {
@include caret-top($color-dark-foreground, $size-arrow);
@include absolute(-$size-arrow * 2 + 1, $size-arrow * .5, auto, auto);
}
}
}

98
src/Squidex/app/framework/angular/onboarding-tooltip.component.ts

@ -0,0 +1,98 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
import { Component, Input, OnDestroy, OnInit, Renderer } from '@angular/core';
import { ModalView } from './../utils/modal-view';
import { OnboardingService } from './../services/onboarding.service';
@Component({
selector: 'sqx-onboarding-tooltip',
styleUrls: ['./onboarding-tooltip.component.scss'],
templateUrl: './onboarding-tooltip.component.html'
})
export class OnboardingTooltipComponent implements OnDestroy, OnInit {
private showTimer: any;
private closeTimer: any;
private forClickListener: Function;
public tooltipModal = new ModalView();
@Input()
public for: any;
@Input()
public id: string;
@Input()
public position = 'left';
@Input()
public after = 1000;
@Input()
public text: string;
constructor(
private readonly onboardingService: OnboardingService,
private readonly renderer: Renderer
) {
}
public ngOnDestroy() {
if (this.showTimer) {
clearTimeout(this.showTimer);
this.showTimer = null;
}
if (this.closeTimer) {
clearTimeout(this.closeTimer);
this.closeTimer = null;
}
if (this.forClickListener) {
this.forClickListener();
this.forClickListener = null;
}
}
public ngOnInit() {
if (this.for && this.id) {
this.showTimer = setTimeout(() => {
if (this.onboardingService.shouldShow(this.id)) {
this.tooltipModal.show();
this.closeTimer = setTimeout(() => {
this.hideThis();
}, 10000);
}
}, this.after);
this.forClickListener =
this.renderer.listen(this.for, 'mousedown', () => {
this.onboardingService.disable(this.id);
this.hideThis();
});
}
}
public hideThis() {
this.onboardingService.disable(this.id);
this.tooltipModal.hide();
this.ngOnDestroy();
}
public hideAll() {
this.onboardingService.disableAll();
this.tooltipModal.hide();
this.ngOnDestroy();
}
}

22
src/Squidex/app/framework/angular/slider.component.ts

@ -23,8 +23,8 @@ export const SQX_SLIDER_CONTROL_VALUE_ACCESSOR: any = {
export class SliderComponent implements ControlValueAccessor { export class SliderComponent implements ControlValueAccessor {
private callChange = (v: any) => { /* NOOP */ }; private callChange = (v: any) => { /* NOOP */ };
private callTouched = () => { /* NOOP */ }; private callTouched = () => { /* NOOP */ };
private mouseMoveSubscription: Function | null = null; private windowMouseMoveListener: Function | null = null;
private mouseUpSubscription: Function | null = null; private windowMouseUpListener: Function | null = null;
private centerStartOffset = 0; private centerStartOffset = 0;
private startValue: number; private startValue: number;
private lastValue: number; private lastValue: number;
@ -69,7 +69,7 @@ export class SliderComponent implements ControlValueAccessor {
} }
public onBarMouseClick(event: MouseEvent): boolean { public onBarMouseClick(event: MouseEvent): boolean {
if (this.mouseMoveSubscription) { if (this.windowMouseMoveListener) {
return true; return true;
} }
@ -89,12 +89,12 @@ export class SliderComponent implements ControlValueAccessor {
this.startValue = this.value; this.startValue = this.value;
this.mouseMoveSubscription = this.windowMouseMoveListener =
this.renderer.listenGlobal('window', 'mousemove', (e: MouseEvent) => { this.renderer.listenGlobal('window', 'mousemove', (e: MouseEvent) => {
this.onMouseMove(e); this.onMouseMove(e);
}); });
this.mouseUpSubscription = this.windowMouseUpListener =
this.renderer.listenGlobal('window', 'mouseup', () => { this.renderer.listenGlobal('window', 'mouseup', () => {
this.onMouseUp(); this.onMouseUp();
}); });
@ -175,14 +175,14 @@ export class SliderComponent implements ControlValueAccessor {
} }
private releaseMouseHandlers() { private releaseMouseHandlers() {
if (this.mouseMoveSubscription) { if (this.windowMouseMoveListener) {
this.mouseMoveSubscription(); this.windowMouseMoveListener();
this.mouseMoveSubscription = null; this.windowMouseMoveListener = null;
} }
if (this.mouseUpSubscription) { if (this.windowMouseUpListener) {
this.mouseUpSubscription(); this.windowMouseUpListener();
this.mouseUpSubscription = null; this.windowMouseUpListener = null;
} }
this.isDragging = false; this.isDragging = false;

4
src/Squidex/app/framework/declarations.ts

@ -30,6 +30,7 @@ export * from './angular/modal-view.directive';
export * from './angular/money.pipe'; export * from './angular/money.pipe';
export * from './angular/name.pipe'; export * from './angular/name.pipe';
export * from './angular/numbers.pipes'; export * from './angular/numbers.pipes';
export * from './angular/onboarding-tooltip.component';
export * from './angular/panel.component'; export * from './angular/panel.component';
export * from './angular/panel-container.directive'; export * from './angular/panel-container.directive';
export * from './angular/parent-link.directive'; export * from './angular/parent-link.directive';
@ -56,7 +57,8 @@ export * from './services/clipboard.service';
export * from './services/dialog.service'; export * from './services/dialog.service';
export * from './services/local-store.service'; export * from './services/local-store.service';
export * from './services/local-cache.service'; export * from './services/local-cache.service';
export * from './services/message-bus'; export * from './services/message-bus.service';
export * from './services/onboarding.service';
export * from './services/resource-loader.service'; export * from './services/resource-loader.service';
export * from './services/root-view.service'; export * from './services/root-view.service';
export * from './services/shortcut.service'; export * from './services/shortcut.service';

5
src/Squidex/app/framework/module.ts

@ -46,6 +46,8 @@ import {
ModalViewDirective, ModalViewDirective,
MoneyPipe, MoneyPipe,
MonthPipe, MonthPipe,
OnboardingService,
OnboardingTooltipComponent,
PanelContainerDirective, PanelContainerDirective,
PanelComponent, PanelComponent,
ParentLinkDirective, ParentLinkDirective,
@ -107,6 +109,7 @@ import {
ModalViewDirective, ModalViewDirective,
MoneyPipe, MoneyPipe,
MonthPipe, MonthPipe,
OnboardingTooltipComponent,
PanelContainerDirective, PanelContainerDirective,
PanelComponent, PanelComponent,
ParentLinkDirective, ParentLinkDirective,
@ -155,6 +158,7 @@ import {
ModalViewDirective, ModalViewDirective,
MoneyPipe, MoneyPipe,
MonthPipe, MonthPipe,
OnboardingTooltipComponent,
PanelContainerDirective, PanelContainerDirective,
PanelComponent, PanelComponent,
ParentLinkDirective, ParentLinkDirective,
@ -193,6 +197,7 @@ export class SqxFrameworkModule {
LocalCacheService, LocalCacheService,
LocalStoreService, LocalStoreService,
MessageBus, MessageBus,
OnboardingService,
ResourceLoaderService, ResourceLoaderService,
RootViewService, RootViewService,
ShortcutService, ShortcutService,

4
src/Squidex/app/framework/services/local-store.service.ts

@ -20,7 +20,7 @@ export class LocalStoreService {
this.store = store; this.store = store;
} }
public get(key: string): any { public get(key: string): string | null {
try { try {
return this.store.getItem(key); return this.store.getItem(key);
} catch (e) { } catch (e) {
@ -28,7 +28,7 @@ export class LocalStoreService {
} }
} }
public set(key: string, value: any) { public set(key: string, value: string) {
try { try {
this.store.setItem(key, value); this.store.setItem(key, value);
} catch (e) { } catch (e) {

0
src/Squidex/app/framework/services/message-bus.spec.ts → src/Squidex/app/framework/services/message-bus.service.spec.ts

0
src/Squidex/app/framework/services/message-bus.ts → src/Squidex/app/framework/services/message-bus.service.ts

41
src/Squidex/app/framework/services/onboarding.service.ts

@ -0,0 +1,41 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
import { Injectable } from '@angular/core';
import { LocalStoreService } from './local-store.service';
export const OnboardingServiceFactory = (localStore: LocalStoreService) => {
return new OnboardingService(localStore);
};
@Injectable()
export class OnboardingService {
constructor(
private readonly localStore: LocalStoreService
) {
}
public disableAll() {
this.disable('all');
}
public disable(key: string) {
this.localStore.set(`squidex.onboarding.disable.${key}`, '1');
}
public shouldShow(key: string) {
return this.shouldShowKey(key) && this.shouldShowKey('all');
}
private shouldShowKey(key: string) {
return this.localStore.get(`squidex.onboarding.disable.${key}`) !== '1';
}
}

2
src/Squidex/app/shared/components/language-selector.component.html

@ -8,7 +8,7 @@
<button type="button" class="btn btn-secondary dropdown-toggle" [attr.title]="selectedLanguage.englishName" (click)="dropdown.toggle(); $event.stopPropagation()" #button> <button type="button" class="btn btn-secondary dropdown-toggle" [attr.title]="selectedLanguage.englishName" (click)="dropdown.toggle(); $event.stopPropagation()" #button>
{{selectedLanguage.iso2Code}} {{selectedLanguage.iso2Code}}
</button> </button>
<div class="dropdown-menu" *sqxModalView="dropdown" closeAlways="true" [sqxModalTarget]="button" position="right" [@fade]> <div class="dropdown-menu" *sqxModalView="dropdown" closeAlways="true" [sqxModalTarget]="button" position="topRight" [@fade]>
<div class="dropdown-item" *ngFor="let language of languages" [class.active]="language == selectedLanguage" (click)="selectLanguage(language)"> <div class="dropdown-item" *ngFor="let language of languages" [class.active]="language == selectedLanguage" (click)="selectLanguage(language)">
<strong class="iso-code">{{language.iso2Code}}</strong> &nbsp; &nbsp; ({{language.englishName}}) <strong class="iso-code">{{language.iso2Code}}</strong> &nbsp; &nbsp; ({{language.englishName}})
</div> </div>

1
src/Squidex/app/theme/_bootstrap.scss

@ -317,7 +317,6 @@ a {
// Special button groups // Special button groups
&-group { &-group {
.btn-toggle { .btn-toggle {
& { & {
border: 2px solid $color-border; border: 2px solid $color-border;

2
src/Squidex/app/theme/_forms.scss

@ -92,7 +92,7 @@
@include absolute(2px, auto, auto, 0); @include absolute(2px, auto, auto, 0);
@include border-radius(.25em); @include border-radius(.25em);
@include box-shadow; @include box-shadow;
max-height: 10rem; max-height: 15rem;
border: 1px solid $color-input-border; border: 1px solid $color-input-border;
background: $color-dark-foreground; background: $color-dark-foreground;
padding: .3rem 0; padding: .3rem 0;

6
src/Squidex/app/theme/_lists.scss

@ -122,10 +122,8 @@
// Caret that is placed next to the expand button. // Caret that is placed next to the expand button.
&::before { &::before {
@include caret-top; @include caret-top($color-border);
@include absolute(-.5rem, 5.2rem, auto, auto); @include absolute(-1.1rem, 5.2rem, auto, auto);
border-color: transparent transparent $color-border;
border-width: .6rem;
} }
&-tab { &-tab {

41
src/Squidex/app/theme/_mixins.scss

@ -130,29 +130,40 @@
box-sizing: border-box; box-sizing: border-box;
} }
@mixin caret-top() { @mixin caret-top($color, $size: .6rem) {
display: inline-block; @include caret;
width: 0; border: $size solid transparent;
height: 0; border-bottom-color: $color;
content: ''; }
border-bottom: .3em solid;
border-right: .3em solid transparent; @mixin caret-left($color, $size: .6rem) {
border-left: .3em solid transparent; @include caret;
border: $size solid transparent;
border-right-color: $color;
} }
@mixin caret-bottom() { @mixin caret-right($color, $size: .6rem) {
@include caret;
border: $size solid transparent;
border-left-color: $color;
}
@mixin caret-bottom($color, $size: .6rem) {
@include caret;
border: $size solid transparent;
border-top-color: $color;
}
@mixin caret() {
display: inline-block; display: inline-block;
width: 0; width: 0;
height: 0; height: 0;
content: ''; content: '';
border-top: .3em solid;
border-right: .3em solid transparent;
border-left: .3em solid transparent;
} }
@mixin circle($size) { @mixin circle($size) {
@include border-radius($size * .5); @include border-radius($size * .5);
width: $size; width: $size;
height: $size; height: $size;
} }

Loading…
Cancel
Save