&__header {
height: 70px;
border-radius: var(--border-radius-large) var(--border-radius-large) 0 0;
+ background-color: var(--color-primary);
+ background-image: linear-gradient(40deg, var(--color-primary) 0%, var(--color-primary-element-light) 100%);
span {
bottom: 0;
'verb' => 'POST'
],
[
- 'name' => 'Theming#getThemeVariables',
+ 'name' => 'Theming#getThemeStylesheet',
'url' => '/theme/{themeId}.css',
'verb' => 'GET',
],
use OCP\IRequest;
use OCP\ITempManager;
use OCP\IURLGenerator;
+use ScssPhp\ScssPhp\Compiler;
/**
* Class ThemingController
*
* @return FileDisplayResponse|NotFoundResponse
*/
- public function getThemeVariables(string $themeId, bool $plain = false) {
+ public function getThemeStylesheet(string $themeId, bool $plain = false, bool $withCustomCss = false) {
$themes = $this->themesService->getThemes();
if (!in_array($themeId, array_keys($themes))) {
return new NotFoundResponse();
}
$theme = $themes[$themeId];
+ $customCss = $theme->getCustomCss();
// Generate variables
$variables = '';
// If plain is set, the browser decides of the css priority
if ($plain) {
- $css = ":root { $variables }";
+ $css = ":root { $variables } " . $customCss;
} else {
// If not set, we'll rely on the body class
- $css = "body[data-theme-$themeId] { $variables }";
+ $compiler = new Compiler();
+ $compiledCss = $compiler->compileString("body[data-theme-$themeId] { $variables $customCss }");
+ $css = $compiledCss->getCss();;
}
try {
* @since 25.0.0
*/
public function getCSSVariables(): array;
+
+ /**
+ * Return the custom css necessary for that app
+ * ⚠️ Warning, should be used slightly.
+ * Theoretically, editing the variables should be enough.
+ *
+ * @return string
+ * @since 25.0.0
+ */
+ public function getCustomCss(): string;
}
* @param string $media media query to use in the <link> element
*/
private function addThemeHeader(string $themeId, bool $plain = true, string $media = null) {
- $linkToCSS = $this->urlGenerator->linkToRoute('theming.Theming.getThemeVariables', [
+ $linkToCSS = $this->urlGenerator->linkToRoute('theming.Theming.getThemeStylesheet', [
'themeId' => $themeId,
'plain' => $plain,
]);
use OCA\Theming\ITheme;
-class DarkHighContrastTheme extends HighContrastTheme implements ITheme {
+class DarkHighContrastTheme extends DarkTheme implements ITheme {
public function getId(): string {
return 'dark-highcontrast';
return $this->l->t('Similar to the high contrast mode, but with dark colours.');
}
+ /**
+ * Try to keep this consistent with HighContrastTheme
+ */
public function getCSSVariables(): array {
$variables = parent::getCSSVariables();
+ $colorMainText = '#ffffff';
+ $colorMainBackground = '#000000';
+ $colorBoxShadowRGB = join(',', $this->util->hexToRGB($colorMainText));
- // FIXME …
- $variables = $variables;
+ $variables['--color-main-background'] = $colorMainBackground;
+ $variables['--color-main-text'] = $colorMainText;
+
+ $variables['--color-background-dark'] = $this->util->lighten($colorMainBackground, 30);
+ $variables['--color-background-darker'] = $this->util->lighten($colorMainBackground, 30);
+
+ $variables['--color-placeholder-light'] = $this->util->lighten($colorMainBackground, 30);
+ $variables['--color-placeholder-dark'] = $this->util->lighten($colorMainBackground, 45);
+
+ $variables['--color-text-maxcontrast'] = $colorMainText;
+ $variables['--color-text-light'] = $colorMainText;
+ $variables['--color-text-lighter'] = $colorMainText;
+
+ // used for the icon loading animation
+ $variables['--color-loading-light'] = '#000000';
+ $variables['--color-loading-dark'] = '#dddddd';
+
+
+ $variables['--color-box-shadow-rgb'] = $colorBoxShadowRGB;
+ $variables['--color-box-shadow'] = $colorBoxShadowRGB;
+
+
+ $variables['--color-border'] = $this->util->lighten($colorMainBackground, 50);
+ $variables['--color-border-dark'] = $this->util->lighten($colorMainBackground, 50);
return $variables;
}
+
+ public function getCustomCss(): string {
+ return "
+ [class^='icon-'], [class*=' icon-'],
+ .action,
+ #appmenu li a,
+ .menutoggle {
+ opacity: 1 !important;
+ }
+ ";
+ }
}
class DefaultTheme implements ITheme {
public Util $util;
public ThemingDefaults $themingDefaults;
- public IURLGenerator $urlGenerator;
public ImageManager $imageManager;
public IConfig $config;
public IL10N $l;
return $variables;
}
+
+ public function getCustomCss(): string {
+ return '';
+ }
}
return $variables;
}
-}
-// @font-face {
-// font-family: 'OpenDyslexic';
-// font-style: normal;
-// font-weight: 400;
-// src: url('../fonts/OpenDyslexic-Regular.woff') format('woff');
-// }
+ public function getCustomCss(): string {
+ return "
+ @font-face {
+ font-family: 'OpenDyslexic';
+ font-style: normal;
+ font-weight: 400;
+ src: url('../fonts/OpenDyslexic-Regular.woff') format('woff'),
+ url('../fonts/OpenDyslexic-Regular.otf') format('opentype'),
+ url('../fonts/OpenDyslexic-Regular.ttf') format('truetype');
+ }
+
+ @font-face {
+ font-family: 'OpenDyslexic';
+ font-style: normal;
+ font-weight: 700;
+ src: url('../fonts/OpenDyslexic-Bold.woff') format('woff'),
+ url('../fonts/OpenDyslexic-Bold.otf') format('opentype'),
+ url('../fonts/OpenDyslexic-Bold.ttf') format('truetype');
+ }
+ ";
+ }
+}
-// @font-face {
-// font-family: 'OpenDyslexic';
-// font-style: normal;
-// font-weight: 700;
-// src: url('../fonts/OpenDyslexic-Bold.woff') format('woff');
-// }
public function getCSSVariables(): array {
$variables = parent::getCSSVariables();
+ $colorMainText = '#000000';
+ $colorMainBackground = '#ffffff';
- // FIXME …
- $variables = $variables;
+ $variables['--color-main-background'] = $colorMainBackground;
+ $variables['--color-main-text'] = $colorMainText;
+
+ $variables['--color-background-dark'] = $this->util->darken($colorMainBackground, 30);
+ $variables['--color-background-darker'] = $this->util->darken($colorMainBackground, 30);
+
+ $variables['--color-placeholder-light'] = $this->util->darken($colorMainBackground, 30);
+ $variables['--color-placeholder-dark'] = $this->util->darken($colorMainBackground, 45);
+
+ $variables['--color-text-maxcontrast'] = 'var(--color-main-text)';
+ $variables['--color-text-light'] = 'var(--color-main-text)';
+ $variables['--color-text-lighter'] = 'var(--color-main-text)';
+
+ // used for the icon loading animation
+ $variables['--color-loading-light'] = '#dddddd';
+ $variables['--color-loading-dark'] = '#000000';
+
+ $variables['--color-box-shadow'] = 'var(--color-main-text)';
+
+ $variables['--color-border'] = $this->util->darken($colorMainBackground, 50);
+ $variables['--color-border-dark'] = $this->util->darken($colorMainBackground, 50);
return $variables;
}
+
+ public function getCustomCss(): string {
+ return "
+ [class^='icon-'], [class*=' icon-'],
+ .action,
+ #appmenu li a,
+ .menutoggle {
+ opacity: 1 !important;
+ }
+ ";
+ }
}
<template>
- <SettingsSection class="theming" :title="t('themes', 'Appaerance and accessibility')">
+ <SettingsSection class="theming" :title="t('themes', 'Appearance and accessibility')">
<p v-html="description" />
<p v-html="descriptionDetail" />
}
&__preview-list {
+ --gap: 30px;
+
+ display: grid;
+ margin-top: var(--gap);
+ column-gap: var(--gap);
+ row-gap: var(--gap);
+ grid-template-columns: 1fr 1fr;
+ }
+}
+
+@media (max-width: 1440px) {
+ .theming__preview-list {
display: flex;
flex-direction: column;
- max-width: 800px;
}
}
}
</script>
<style lang="scss" scoped>
+// We make previews on 16/10 screens
+$ratio: 16;
.theming__preview {
+ --ratio: 16;
position: relative;
display: flex;
justify-content: flex-start;
- height: 140px;
- margin-top: 3em;
+ max-width: 800px;
&,
* {
}
&-image {
- flex-basis: 200px;
+ flex-basis: calc(16px * var(--ratio));
flex-shrink: 0;
- margin-right: 30px;
+ height: calc(10px * var(--ratio));
+ margin-right: var(--gap);
border-radius: var(--border-radius);
background-repeat: no-repeat;
background-position: top left;
}
}
-@media (max-width: (1024 / 2)) {
+@media (max-width: (1024px / 1.5)) {
.theming__preview {
- display: unset;
+ flex-direction: column;
&-image {
- height: 150px;
+ margin: 0;
}
}
}