mirror of
https://gitlab.com/openstapps/openstapps.git
synced 2026-01-05 13:02:54 +00:00
fix: favorite button
This commit is contained in:
@@ -43,10 +43,6 @@
|
||||
}
|
||||
],
|
||||
"styles": [
|
||||
{
|
||||
"input": "src/theme/variables.scss",
|
||||
"inject": true
|
||||
},
|
||||
{
|
||||
"input": "src/global.scss",
|
||||
"inject": true
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
|
||||
ion-segment-button {
|
||||
max-width: 100%;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
.margin-top {
|
||||
|
||||
@@ -13,10 +13,11 @@
|
||||
~ this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<ion-button (click)="toggle($event)" color="medium" size="small" fill="clear">
|
||||
<ion-button (click)="toggle($event)" fill="clear" shape="round">
|
||||
<ion-icon
|
||||
slot="icon-only"
|
||||
[fill]="(isFavorite$ | async) ?? false"
|
||||
[size]="24"
|
||||
[fill]="(isFavorite$ | async) || false"
|
||||
[class.selected]="isFavorite$ | async"
|
||||
name="grade"
|
||||
></ion-icon>
|
||||
|
||||
@@ -13,22 +13,25 @@
|
||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
:host {
|
||||
ion-button {
|
||||
--border-radius: 50%;
|
||||
ion-button {
|
||||
--background-activated: currentcolor;
|
||||
--background-hover: currentcolor;
|
||||
--background-focused: currentcolor;
|
||||
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
aspect-ratio: 1;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.selected {
|
||||
// TODO
|
||||
color: #fbc02d;
|
||||
}
|
||||
.selected {
|
||||
color: #fbc02d;
|
||||
}
|
||||
|
||||
@media (hover: hover) {
|
||||
ion-button:hover ::ng-deep stapps-icon {
|
||||
--fill: 1;
|
||||
}
|
||||
@media (hover: hover) {
|
||||
ion-button:hover ::ng-deep stapps-icon {
|
||||
--fill: 1 !important;
|
||||
}
|
||||
}
|
||||
|
||||
::ng-deep ion-item stapps-favorite-button ion-button {
|
||||
color: var(--ion-color-medium) !important;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import {Component, Input} from '@angular/core';
|
||||
import {ChangeDetectionStrategy, Component, Input} from '@angular/core';
|
||||
import {SCIndexableThings} from '@openstapps/core';
|
||||
import {FavoritesService} from '../../favorites/favorites.service';
|
||||
import {Observable} from 'rxjs';
|
||||
@@ -25,6 +25,7 @@ import {map, take} from 'rxjs/operators';
|
||||
selector: 'stapps-favorite-button',
|
||||
templateUrl: './favorite-button.component.html',
|
||||
styleUrls: ['./favorite-button.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class FavoriteButtonComponent {
|
||||
/**
|
||||
|
||||
@@ -38,7 +38,6 @@ ion-toolbar:first-of-type {
|
||||
ion-button {
|
||||
width: 50%;
|
||||
margin: 0;
|
||||
text-transform: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,10 +13,6 @@
|
||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
ion-segment-button {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
ion-segment {
|
||||
overflow: auto;
|
||||
justify-content: space-between;
|
||||
|
||||
@@ -27,7 +27,6 @@ $hours-width: 40px;
|
||||
ion-button {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-transform: none;
|
||||
|
||||
ion-label {
|
||||
overflow: visible !important;
|
||||
|
||||
@@ -49,7 +49,6 @@ div {
|
||||
|
||||
ion-segment-button {
|
||||
max-width: 100%;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
ion-toolbar.in-toolbar {
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
<ion-modal #modal [canDismiss]="!pendingChanges || canDismissModal">
|
||||
<ng-template>
|
||||
<ion-header mode="ios">
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>{{ 'modal.TITLE_EDIT' | translate }}</ion-title>
|
||||
<ion-buttons slot="end">
|
||||
|
||||
@@ -34,16 +34,13 @@ export class IconComponent {
|
||||
@Input()
|
||||
grade?: number;
|
||||
|
||||
@HostBinding('style.--fill')
|
||||
@Input()
|
||||
fill: boolean;
|
||||
fill?: number;
|
||||
|
||||
@HostBinding('innerHtml')
|
||||
@Input()
|
||||
name: string;
|
||||
|
||||
@HostBinding('style.--fill') get fillStyle(): number | undefined {
|
||||
return this.fill ? 1 : undefined;
|
||||
}
|
||||
|
||||
@HostBinding('class.material-symbols-rounded') hostClass = true;
|
||||
}
|
||||
|
||||
@@ -56,11 +56,13 @@ export class IonBackButtonDirective extends IconReplacer implements OnInit {
|
||||
|
||||
async ngOnInit() {
|
||||
await super.ngOnInit();
|
||||
this.translateService
|
||||
.stream('back')
|
||||
.pipe(takeUntilDestroyed(this.destroy$))
|
||||
.subscribe((value: string) => {
|
||||
this.ionBackButton.text = this.titleCasePipe.transform(value);
|
||||
});
|
||||
if (document.querySelector('ion-app[mode=ios]')) {
|
||||
this.translateService
|
||||
.stream('back')
|
||||
.pipe(takeUntilDestroyed(this.destroy$))
|
||||
.subscribe((value: string) => {
|
||||
this.ionBackButton.text = this.titleCasePipe.transform(value);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ export class IonIconDirective implements OnInit, OnDestroy, OnChanges {
|
||||
|
||||
@Input() ios: string;
|
||||
|
||||
@Input() fill = false;
|
||||
@Input() fill: boolean;
|
||||
|
||||
@Input() weight: number;
|
||||
|
||||
@@ -61,7 +61,7 @@ export class IonIconDirective implements OnInit, OnDestroy, OnChanges {
|
||||
|
||||
iconComponent?: ComponentRef<IconComponent>;
|
||||
|
||||
private static get mode(): 'md' | 'ios' {
|
||||
private get mode(): 'md' | 'ios' {
|
||||
return document.querySelector(':root')?.getAttribute('mode') as 'md' | 'ios';
|
||||
}
|
||||
|
||||
@@ -102,22 +102,22 @@ export class IonIconDirective implements OnInit, OnDestroy, OnChanges {
|
||||
|
||||
ngOnChanges() {
|
||||
if (!this.iconComponent) return;
|
||||
for (const key of ['name', 'weight', 'fill', 'size', 'grade'] as Array<
|
||||
keyof IconComponent & keyof IonIconDirective
|
||||
>) {
|
||||
// @ts-expect-error type mismatch
|
||||
this.iconComponent.instance[key] = this[key];
|
||||
}
|
||||
|
||||
for (const mode of ['md', 'ios'] as Array<'md' | 'ios'>) {
|
||||
if (this[mode] && IonIconDirective.mode === mode) {
|
||||
this.iconComponent.instance.name = this[mode];
|
||||
}
|
||||
this.iconComponent.setInput('fill', this.fill === true ? 1 : this.fill === false ? 0 : this.fill);
|
||||
this.iconComponent.setInput('weight', this.weight);
|
||||
this.iconComponent.setInput('grade', this.grade);
|
||||
|
||||
if (this.mode === 'ios') {
|
||||
this.iconComponent.setInput('name', this.ios || this.name);
|
||||
} else {
|
||||
this.iconComponent.setInput('name', this.md || this.name);
|
||||
}
|
||||
|
||||
if (this.size) {
|
||||
this.element.nativeElement.style.cssText = `font-size: ${this.size}px;`;
|
||||
const size = this.size === 'small' ? 16 : this.size === 'large' ? 24 : this.size;
|
||||
this.element.nativeElement.style.fontSize = `${size}px`;
|
||||
}
|
||||
|
||||
if (this.style) {
|
||||
this.element.nativeElement.style.cssText += this.style;
|
||||
}
|
||||
|
||||
@@ -30,11 +30,32 @@
|
||||
@import 'swiper/scss/controller';
|
||||
@import 'swiper/scss/navigation';
|
||||
|
||||
// @import 'material-symbols/rounded.scss';
|
||||
@import './theme/material-symbols';
|
||||
@import './theme/common/helper';
|
||||
@import './theme/common/ion-alert';
|
||||
@import './theme/common/ion-button';
|
||||
@import './theme/common/ion-card';
|
||||
@import './theme/common/ion-content-parallax';
|
||||
@import './theme/common/ion-header';
|
||||
@import './theme/common/ion-img';
|
||||
@import './theme/common/ion-item';
|
||||
@import './theme/common/ion-menu';
|
||||
@import './theme/common/ion-modal';
|
||||
@import './theme/common/ion-popover';
|
||||
@import './theme/common/ion-refresher';
|
||||
@import './theme/common/ion-searchbar';
|
||||
@import './theme/common/ion-toolbar';
|
||||
@import './theme/common/link';
|
||||
@import './theme/common/maplibre';
|
||||
@import './theme/common/material-symbols';
|
||||
@import './theme/common/swiper';
|
||||
@import './theme/common/title';
|
||||
|
||||
/* StApps */
|
||||
@import './theme/components/card';
|
||||
@import './theme/components/centered-message-container';
|
||||
@import './theme/components/image-dark';
|
||||
@import './theme/components/section';
|
||||
|
||||
@import './theme/variables';
|
||||
|
||||
stapps-icon {
|
||||
--size-unit: 1px;
|
||||
@@ -43,113 +64,7 @@ stapps-icon {
|
||||
--fill: 0;
|
||||
}
|
||||
|
||||
.map-location-pin {
|
||||
font-variation-settings: 'FILL' 1;
|
||||
color: var(--ion-color-tertiary);
|
||||
|
||||
&::before {
|
||||
content: attr(name);
|
||||
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
||||
font-variation-settings: 'FILL' 0;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
ion-item {
|
||||
h2.name {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
ion-thumbnail {
|
||||
--size: 36px;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
margin: 0;
|
||||
padding: 10px;
|
||||
|
||||
background: transparent;
|
||||
|
||||
ion-icon {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ion-item,
|
||||
ion-card.compact {
|
||||
ion-grid,
|
||||
ion-col {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-inline-start: 0;
|
||||
}
|
||||
}
|
||||
|
||||
ion-header stapps-favorite-button ion-icon {
|
||||
color: var(--ion-color-primary-contrast);
|
||||
}
|
||||
|
||||
ion-alert {
|
||||
button.alert-button.preferred {
|
||||
color: var(--ion-color-primary-contrast);
|
||||
background-color: var(--ion-color-primary);
|
||||
}
|
||||
|
||||
button.alert-button.default {
|
||||
color: var(--ion-color-primary);
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.centered-message-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
min-height: 50vh;
|
||||
margin: 20px;
|
||||
|
||||
text-align: center;
|
||||
|
||||
ion-icon {
|
||||
font-size: 64px;
|
||||
}
|
||||
|
||||
ion-label {
|
||||
font-size: x-large;
|
||||
}
|
||||
}
|
||||
|
||||
.stapps-location ion-icon {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: #fd435c;
|
||||
}
|
||||
|
||||
.stapps-device-location ion-icon {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: #4387fd;
|
||||
}
|
||||
|
||||
.add-event-popover {
|
||||
--width: fit-content;
|
||||
--max-width: 95%;
|
||||
}
|
||||
|
||||
ion-card.bold-header {
|
||||
ion-card-header {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
9
frontend/app/src/theme/THEMING.md
Normal file
9
frontend/app/src/theme/THEMING.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Theming
|
||||
|
||||
## Customizing the theme
|
||||
|
||||
- `colors.scss` contains the brand colors you can customize
|
||||
- `color-processing.scss` contains some values you can use to adjust how the theme is generated.
|
||||
You might need to edit this in if your brand colors result in low contrast.
|
||||
- `font.scss` contains the font face definitions
|
||||
- `theme.scss` contains general variables you can customize
|
||||
11
frontend/app/src/theme/common/_ion-alert.scss
Normal file
11
frontend/app/src/theme/common/_ion-alert.scss
Normal file
@@ -0,0 +1,11 @@
|
||||
ion-alert {
|
||||
button.alert-button.preferred {
|
||||
color: var(--ion-color-primary-contrast);
|
||||
background-color: var(--ion-color-primary);
|
||||
}
|
||||
|
||||
button.alert-button.default {
|
||||
color: var(--ion-color-primary);
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,12 @@
|
||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
ion-segment-button,
|
||||
ion-back-button,
|
||||
ion-button {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
.can-go-back ion-header ion-back-button {
|
||||
display: block;
|
||||
}
|
||||
|
||||
5
frontend/app/src/theme/common/_ion-card.scss
Normal file
5
frontend/app/src/theme/common/_ion-card.scss
Normal file
@@ -0,0 +1,5 @@
|
||||
ion-card.bold-header {
|
||||
ion-card-header {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
$icon-size: 23px;
|
||||
|
||||
app-root ion-searchbar[class*='sc-ion-searchbar-'] {
|
||||
--border-radius: var(--border-radius-default);
|
||||
|
||||
height: 38px;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
|
||||
&.filterable {
|
||||
--box-shadow: none;
|
||||
|
||||
position: relative;
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
|
||||
ion-menu-button {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
right: 5px;
|
||||
}
|
||||
|
||||
.searchbar-clear-button {
|
||||
right: 45px;
|
||||
}
|
||||
}
|
||||
|
||||
ion-icon.searchbar-search-icon {
|
||||
top: 50%;
|
||||
left: var(--spacing-sm);
|
||||
transform: translateY(-50%);
|
||||
|
||||
width: $icon-size;
|
||||
height: $icon-size;
|
||||
|
||||
color: var(--ion-color-medium-shade);
|
||||
}
|
||||
|
||||
input.searchbar-input {
|
||||
padding-top: var(--spacing-xs);
|
||||
padding-bottom: var(--spacing-xs);
|
||||
padding-left: calc(var(--spacing-lg) + #{$icon-size});
|
||||
}
|
||||
}
|
||||
9
frontend/app/src/theme/common/_ion-item.scss
Normal file
9
frontend/app/src/theme/common/_ion-item.scss
Normal file
@@ -0,0 +1,9 @@
|
||||
ion-item,
|
||||
ion-card.compact {
|
||||
ion-grid,
|
||||
ion-col {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-inline-start: 0;
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,48 @@
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
$icon-size: 23px;
|
||||
|
||||
ion-searchbar {
|
||||
app-root ion-searchbar[class*='sc-ion-searchbar-'] {
|
||||
--border-radius: var(--border-radius-default);
|
||||
--background: var(--ion-item-background) !important;
|
||||
|
||||
height: 38px;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
|
||||
&.filterable {
|
||||
--box-shadow: none;
|
||||
|
||||
position: relative;
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
|
||||
ion-menu-button {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
right: 5px;
|
||||
}
|
||||
|
||||
.searchbar-clear-button {
|
||||
right: 45px;
|
||||
}
|
||||
}
|
||||
|
||||
ion-icon.searchbar-search-icon {
|
||||
top: 50%;
|
||||
left: var(--spacing-sm);
|
||||
transform: translateY(-50%);
|
||||
|
||||
width: $icon-size;
|
||||
height: $icon-size;
|
||||
|
||||
color: var(--ion-color-medium-shade);
|
||||
}
|
||||
|
||||
input.searchbar-input {
|
||||
padding-top: var(--spacing-xs);
|
||||
padding-bottom: var(--spacing-xs);
|
||||
padding-left: calc(var(--spacing-lg) + #{$icon-size});
|
||||
}
|
||||
}
|
||||
|
||||
31
frontend/app/src/theme/common/_maplibre.scss
Normal file
31
frontend/app/src/theme/common/_maplibre.scss
Normal file
@@ -0,0 +1,31 @@
|
||||
.maplibregl-map {
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.maplibregl-ctrl-scale {
|
||||
position: relative;
|
||||
|
||||
padding: 0 0 2px;
|
||||
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
color: var(--ion-text-color);
|
||||
|
||||
background: none;
|
||||
filter: drop-shadow(0 0 2px rgba(0 0 0 / 60%));
|
||||
border: none;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
|
||||
height: 8px;
|
||||
|
||||
border-right: 2px solid var(--ion-color-dark);
|
||||
border-bottom: 2px solid var(--ion-color-dark);
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@
|
||||
font-weight: 100 700;
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
src: url('../assets/icons.min.woff2') format('woff2');
|
||||
src: url('../../assets/icons.min.woff2') format('woff2');
|
||||
}
|
||||
|
||||
.material-symbols-rounded {
|
||||
@@ -18,19 +18,11 @@ body app-root {
|
||||
.title[class*='sc-ion-label'] {
|
||||
font-size: var(--font-size-md);
|
||||
font-weight: var(--font-weight-semi-bold);
|
||||
|
||||
// TODO Condensed Font
|
||||
}
|
||||
|
||||
.title-sub,
|
||||
.title-sub[class*='sc-ion-label'] {
|
||||
font-size: var(--font-size-md);
|
||||
font-weight: var(--font-weight-regular);
|
||||
|
||||
// TODO Condensed Font
|
||||
}
|
||||
|
||||
.title-sub {
|
||||
// color: var(--ion-color-medium);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
.centered-message-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
min-height: 50vh;
|
||||
margin: 20px;
|
||||
|
||||
text-align: center;
|
||||
|
||||
ion-icon {
|
||||
font-size: 64px;
|
||||
}
|
||||
|
||||
ion-label {
|
||||
font-size: x-large;
|
||||
}
|
||||
}
|
||||
@@ -15,8 +15,6 @@
|
||||
// Ionic Variables and Theming. For more info, please see:
|
||||
// http://ionicframework.com/docs/theming/
|
||||
@import './colors';
|
||||
|
||||
// Import all other styles
|
||||
@import './fonts';
|
||||
@import './common/typo';
|
||||
@import './common/helper';
|
||||
@@ -34,10 +32,6 @@
|
||||
@import './common/ion-searchbar';
|
||||
@import './components/image-dark';
|
||||
|
||||
@import './components/card';
|
||||
@import './components/section';
|
||||
|
||||
/** Ionic CSS Variables **/
|
||||
:root {
|
||||
// Fonts
|
||||
--ion-font-family: 'Barlow', helvetica, arial, sans-serif;
|
||||
|
||||
Reference in New Issue
Block a user