diff --git a/app/controllers/Dev.scala b/app/controllers/Dev.scala
index 7b393fd083..98bcd53d3c 100644
--- a/app/controllers/Dev.scala
+++ b/app/controllers/Dev.scala
@@ -62,4 +62,8 @@ object Dev extends LilaController {
private def runAs(user: lila.user.User.ID, command: String): Fu[String] =
Env.mod.logApi.cli(user, command) >>
Env.api.cli(command.split(" ").toList)
+
+ def ui = Open { implicit ctx =>
+ Ok(html.dev.ui()).fuccess
+ }
}
diff --git a/app/ui/scalatags.scala b/app/ui/scalatags.scala
index f98674edf6..18cb8e1780 100644
--- a/app/ui/scalatags.scala
+++ b/app/ui/scalatags.scala
@@ -65,7 +65,7 @@ trait ScalatagsTemplate extends Styles
with ScalatagsPrefix {
val trans = lila.i18n.I18nKeys
- val main = tag("main")
+ def main = scalatags.Text.tags2.main
}
object ScalatagsTemplate extends ScalatagsTemplate
diff --git a/app/views/dev/ui.scala b/app/views/dev/ui.scala
new file mode 100644
index 0000000000..64ff41d258
--- /dev/null
+++ b/app/views/dev/ui.scala
@@ -0,0 +1,30 @@
+package views.html.dev
+
+import lila.api.Context
+import lila.app.templating.Environment._
+import lila.app.ui.ScalatagsTemplate._
+
+object ui {
+
+ def apply()(implicit ctx: Context) = views.html.base.layout(
+ title = "UI test",
+ moreCss = responsiveCssTag("palette"),
+ responsive = true
+ ) {
+ main(cls := "ui-test box box-pad")(
+ h1("H1 header title"),
+ h2("H2 header title"),
+ h3("H3 header title"),
+ h4("H4 header title"),
+ p(
+ "
Random quotes: ",
+ (1 to 10).map(_ => lila.quote.Quote.one.text).mkString(" ")
+ ),
+ div(cls := "palette")(
+ List("background", "primary", "secondary", "accent", "brag", "error", "fancy", "font").map { c =>
+ div(cls := s"color $c")(div(cls := "variants"))
+ }
+ )
+ )
+ }.toHtml
+}
diff --git a/app/views/game/importGame.scala b/app/views/game/importGame.scala
index 4a9d2e8b5e..18de076ffb 100644
--- a/app/views/game/importGame.scala
+++ b/app/views/game/importGame.scala
@@ -19,7 +19,7 @@ object importGame {
openGraph = lila.app.ui.OpenGraph(
title = "Paste PGN chess game",
url = s"$netBaseUrl${routes.Importer.importGame.url}",
- description = "When pasting a game PGN, you get a browsable replay, a computer analysis, a game chat and a sharable URL"
+ description = trans.importGameExplanation.txt()
).some,
responsive = true
) {
diff --git a/conf/routes b/conf/routes
index fe62557972..ee24ae0e91 100644
--- a/conf/routes
+++ b/conf/routes
@@ -589,6 +589,7 @@ POST /dev/cli controllers.Dev.cliPost
POST /cli controllers.Dev.command
GET /dev/settings controllers.Dev.settings
POST /dev/settings/:id controllers.Dev.settingsPost(id: String)
+GET /dev/ui controllers.Dev.ui
# Mobile Push
POST /mobile/register/:platform/:deviceId controllers.Main.mobileRegister(platform: String, deviceId: String)
diff --git a/translation/source/site.xml b/translation/source/site.xml
index 17909df04f..b2a7a4beb3 100644
--- a/translation/source/site.xml
+++ b/translation/source/site.xml
@@ -338,8 +338,8 @@
From position
Continue from here
Import game
- When pasting a game PGN you get a browsable replay,
-a computer analysis, a game chat and a shareable URL.
+ Paste a game PGN to get a browsable replay,
+computer analysis, game chat and shareable URL.
- %s imported game
- %s imported games
diff --git a/ui/common/css/_lichess.scss b/ui/common/css/_lichess.scss
index 46c3ccc71b..5de1bbf648 100644
--- a/ui/common/css/_lichess.scss
+++ b/ui/common/css/_lichess.scss
@@ -7,10 +7,12 @@
@import 'abstracts/mixins';
@import 'abstracts/extends';
@import 'abstracts/z-index';
+@import 'abstracts/fluid-size';
@import 'base/reset';
@import 'base/fonts';
@import 'base/elements';
+@import 'base/typography';
@import 'base/layout';
@import 'base/data-icon';
diff --git a/ui/common/css/abstracts/_extends.scss b/ui/common/css/abstracts/_extends.scss
index 1a80ddd21a..4b3f3447c2 100644
--- a/ui/common/css/abstracts/_extends.scss
+++ b/ui/common/css/abstracts/_extends.scss
@@ -3,10 +3,12 @@
padding-bottom: 100%;
width: 100%;
}
+%box-radius {
+ @include box-radius;
+}
%box-shadow {
- box-shadow: $box-shadow;
+ @include box-shadow;
}
%box-neat {
- box-shadow: $box-shadow;
- border-radius: $border-radius;
+ @include box-neat;
}
diff --git a/ui/common/css/abstracts/_fluid-size.scss b/ui/common/css/abstracts/_fluid-size.scss
new file mode 100644
index 0000000000..595304b33f
--- /dev/null
+++ b/ui/common/css/abstracts/_fluid-size.scss
@@ -0,0 +1,22 @@
+@function strip-unit($value) {
+ @return $value / ($value * 0 + 1);
+}
+
+@mixin fluid-size($min-vw, $max-vw, $min-font-size, $max-font-size) {
+ $u1: unit($min-vw);
+ $u2: unit($max-vw);
+ $u3: unit($min-font-size);
+ $u4: unit($max-font-size);
+
+ @if $u1 == $u2 and $u1 == $u3 and $u1 == $u4 {
+ & {
+ font-size: $min-font-size;
+ @media screen and (min-width: $min-vw) {
+ font-size: calc(#{$min-font-size} + #{strip-unit($max-font-size - $min-font-size)} * ((100vw - #{$min-vw}) / #{strip-unit($max-vw - $min-vw)}));
+ }
+ @media screen and (min-width: $max-vw) {
+ font-size: $max-font-size;
+ }
+ }
+ }
+}
diff --git a/ui/common/css/abstracts/_media-queries.scss b/ui/common/css/abstracts/_media-queries.scss
index c9308a3cf1..6ba88d0173 100644
--- a/ui/common/css/abstracts/_media-queries.scss
+++ b/ui/common/css/abstracts/_media-queries.scss
@@ -25,6 +25,8 @@ $mq-hover-no: (hover none);
/* Aliases */
+$mq-main-margin: $mq-medium;
+
$mq-topnav-visible: $mq-medium;
$mq-topnav-hidden: $mq-not-medium;
diff --git a/ui/common/css/abstracts/_mixins.scss b/ui/common/css/abstracts/_mixins.scss
index 10d8f5269e..5c299d7ce3 100644
--- a/ui/common/css/abstracts/_mixins.scss
+++ b/ui/common/css/abstracts/_mixins.scss
@@ -1,6 +1,12 @@
-@mixin box-neat {
+@mixin box-radius {
+ border-radius: $box-radius-size;
+}
+@mixin box-shadow {
box-shadow: $box-shadow;
- border-radius: $border-radius;
+}
+@mixin box-neat {
+ @include box-radius;
+ @include box-shadow;
}
@mixin board-scale-config {
diff --git a/ui/common/css/abstracts/_variables.scss b/ui/common/css/abstracts/_variables.scss
index 3096c5b67a..576c66fd32 100644
--- a/ui/common/css/abstracts/_variables.scss
+++ b/ui/common/css/abstracts/_variables.scss
@@ -2,7 +2,7 @@ $font-path: "../font";
$block-gap: 1.5vmin;
-$border-radius: 3px;
+$box-radius-size: 3px;
$site-header-tall-height: 60px;
$site-header-short-height: 40px;
diff --git a/ui/common/css/base/_elements.scss b/ui/common/css/base/_elements.scss
index 79c96bb31e..5dff910364 100644
--- a/ui/common/css/base/_elements.scss
+++ b/ui/common/css/base/_elements.scss
@@ -1,18 +1,9 @@
-html {
- font: 1rem/1.6 'Noto Sans', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, Sans-Serif;
-}
-
body {
background: $c-background linear-gradient(to bottom, $c-body-gradient, $c-background 116px) no-repeat;
color: $c-font;
overflow-x: hidden;
}
-h1 {
- font: 3rem 'Roboto';
- font-weight: normal;
-}
-
a {
color: $c-link;
text-decoration: none;
diff --git a/ui/common/css/base/_layout.scss b/ui/common/css/base/_layout.scss
index f7cdad4ca0..2bccca6592 100644
--- a/ui/common/css/base/_layout.scss
+++ b/ui/common/css/base/_layout.scss
@@ -5,7 +5,7 @@ body {
}
--main-margin: 0;
- @include breakpoint($mq-medium) {
+ @include breakpoint($mq-main-margin) {
--main-margin: #{$block-gap};
margin-bottom: $block-gap;
}
diff --git a/ui/common/css/base/_typography.scss b/ui/common/css/base/_typography.scss
new file mode 100644
index 0000000000..687dcac2de
--- /dev/null
+++ b/ui/common/css/base/_typography.scss
@@ -0,0 +1,37 @@
+/* Viewport limits */
+$vp-min-width: 320px;
+$vp-max-width: 1200px;
+
+html {
+ // font-family: 'Noto Sans', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, Sans-Serif;
+ // font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", 'Noto Sans', Roboto, Ubuntu, "Helvetica Neue", sans-serif;
+ font-family: 'Noto Sans', system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, "Helvetica Neue", sans-serif;
+ @include fluid-size($vp-min-width, $vp-max-width, 14px, 16px);
+ font-smoothing: antialiased;
+}
+// html {
+// font: 1rem/1.6 'Noto Sans', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, Sans-Serif;
+// }
+
+h1,
+h2,
+h3,
+h4 {
+ font-family: 'Roboto';
+ font-weight: normal;
+}
+h1 {
+ @include fluid-size($vp-min-width, $vp-max-width, 27px, 50px);
+}
+h2 {
+ @include fluid-size($vp-min-width, $vp-max-width, 23px, 40px);
+}
+h3 {
+ font-weight: bold;
+ color: $c-font-dim;
+ @include fluid-size($vp-min-width, $vp-max-width, 20px, 30px);
+}
+h4 {
+ color: $c-font-dim;
+ @include fluid-size($vp-min-width, $vp-max-width, 20px, 26px);
+}
diff --git a/ui/common/css/components/_box.scss b/ui/common/css/components/_box.scss
index 95b85058f4..5bf5aa9b66 100644
--- a/ui/common/css/components/_box.scss
+++ b/ui/common/css/components/_box.scss
@@ -1,8 +1,14 @@
.box {
- @extend %box-neat;
background: $c-background-clear;
+ @extend %box-shadow;
&-pad {
padding: 3vh 3vw;
}
}
+
+@include breakpoint($mq-main-margin) {
+ main.box {
+ @include box-radius;
+ }
+}
diff --git a/ui/common/css/components/_site-header.scss b/ui/common/css/components/_site-header.scss
index d44112d184..6b648eb0a5 100644
--- a/ui/common/css/components/_site-header.scss
+++ b/ui/common/css/components/_site-header.scss
@@ -103,6 +103,7 @@ body.dark #clinput input {
}
#reconnecting {
+ display: none;
opacity: 0;
}
body.offline #reconnecting,
diff --git a/ui/common/css/components/_subnav.scss b/ui/common/css/components/_subnav.scss
index a029ea7899..9ac54ea680 100644
--- a/ui/common/css/components/_subnav.scss
+++ b/ui/common/css/components/_subnav.scss
@@ -14,7 +14,7 @@
display: flex;
align-items: center;
background: $c-background-clear;
- border-radius: $border-radius;
+ @include box-radius;
&:hover {
color: $c-link;
}
@@ -37,7 +37,7 @@
border-bottom: 1px solid $c-link;
}
&.active {
- border-radius: 3px 0 0 3px;
+ border-radius: $box-radius-size 0 0 $box-radius-size;
background: $c-background-clear;
font-weight: bold;
box-shadow: $box-shadow;
diff --git a/ui/site/css/_importer.scss b/ui/site/css/_importer.scss
index 10201421bc..48d13dc915 100644
--- a/ui/site/css/_importer.scss
+++ b/ui/site/css/_importer.scss
@@ -29,7 +29,7 @@ main.importer {
}
& button.submit {
- margin: 1em auto 0 auto;
+ margin: 0 auto;
display: block;
}
diff --git a/ui/site/css/_palette.scss b/ui/site/css/_palette.scss
new file mode 100644
index 0000000000..83f72a99be
--- /dev/null
+++ b/ui/site/css/_palette.scss
@@ -0,0 +1,131 @@
+$palette-colors: (
+'background': (
+'dim': $c-background-dim,
+'base': $c-background,
+'clear': $c-background-clear
+),
+'primary': (
+'dim': c-dimmer($c-primary),
+'base': $c-primary,
+'clear': c-clearer($c-primary)
+),
+'secondary': (
+'dim': c-dimmer($c-secondary),
+'base': $c-secondary,
+'clear': c-clearer($c-secondary)
+),
+'accent': (
+'dim': c-dimmer($c-accent),
+'base': $c-accent,
+'clear': c-clearer($c-accent)
+),
+'brag': (
+'dim': c-dimmer($c-brag),
+'base': $c-brag,
+'clear': c-clearer($c-brag)
+),
+'error': (
+'dim': c-dimmer($c-error),
+'base': $c-error,
+'clear': c-clearer($c-error)
+),
+'fancy': (
+'dim': c-dimmer($c-fancy),
+'base': $c-fancy,
+'clear': c-clearer($c-fancy)
+),
+'font': (
+'dim': c-dimmer($c-font),
+'base': $c-font,
+'clear': c-clearer($c-font)
+),
+);
+
+$variant-height: 2.5rem;
+
+.palette {
+ display: grid;
+ grid-column-gap: $block-gap;
+ grid-row-gap: $block-gap;
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
+
+ & *,
+ & *:before,
+ & *:after {
+ position: relative;
+ }
+
+ & .color {
+ height: 16rem;
+ display: block;
+ @extend %box-neat;
+
+ &:before, &:after {
+ content: '';
+ position: absolute;
+ display: block;
+ width: 100%;
+ height: 30%;
+ bottom: 0;
+ left: 0;
+ border-top: $borders;
+ padding: 0.5rem;
+ text-transform: uppercase;
+ overflow: hidden;
+ }
+
+ &:before {
+ background-color: $c-background-clear;
+ border-radius: 0 0 $box-radius-size $box-radius-size;
+ font-weight: bold;
+ }
+
+ &:after {
+ padding-top: 2rem;
+ font-size: 80%;
+ }
+
+ @each $color-key, $color-variants in $palette-colors {
+ $base-color-value: map-get($color-variants, 'base');
+
+ &.#{$color-key} {
+ background-color: $base-color-value;
+
+ &:before { content: "#{$color-key}"; }
+ &:after { content: "#{$base-color-value}"; }
+
+ $variant-gradient: (unquote("to bottom"),);
+
+ $index: 0;
+ @each $variant-name, $variant-value in $color-variants {
+ $variant-gradient: append($variant-gradient, $variant-value $index * $variant-height);
+ $index: $index + 1;
+ $variant-gradient: append($variant-gradient, $variant-value $index * $variant-height);
+ }
+
+ .variants {
+ border-left: 1px solid white;
+ border-bottom: 1px solid white;
+ border-radius: 0 0 0 $box-radius-size;
+ position: absolute;
+ height: $variant-height * length($color-variants);
+ width: 60%;
+ right: 0;
+ top: 0;
+ background: linear-gradient(#{$variant-gradient});
+ overflow: hidden;
+ &::before {
+ line-height: 2.5rem;
+ content: 'Zombie ipsum reversus ab viral inferno, nam rick grimes malum cerebro. De carne lumbering animata corpora quaeritis. Summus brains sit, morbo vel maleficia? De apocalypsi gorger omero undead survivor dictum mauris.';
+ left: .5rem;
+ }
+ color: #fff;
+ }
+ }
+ }
+ &.background .variants {
+ color: $c-font;
+ }
+ }
+}
+
diff --git a/ui/site/css/build/_palette.scss b/ui/site/css/build/_palette.scss
new file mode 100644
index 0000000000..cb686bce70
--- /dev/null
+++ b/ui/site/css/build/_palette.scss
@@ -0,0 +1,3 @@
+@import '../../../common/css/lichess';
+@import '../../../common/css/components/form3';
+@import '../palette';
diff --git a/ui/site/css/build/palette.dark.scss b/ui/site/css/build/palette.dark.scss
new file mode 100644
index 0000000000..33f132a03d
--- /dev/null
+++ b/ui/site/css/build/palette.dark.scss
@@ -0,0 +1,2 @@
+@import '../../../common/css/themes/dark';
+@import 'palette';
diff --git a/ui/site/css/build/palette.light.scss b/ui/site/css/build/palette.light.scss
new file mode 100644
index 0000000000..a2548e6785
--- /dev/null
+++ b/ui/site/css/build/palette.light.scss
@@ -0,0 +1,2 @@
+@import '../../../common/css/themes/light';
+@import 'palette';
diff --git a/ui/site/css/build/palette.transp.scss b/ui/site/css/build/palette.transp.scss
new file mode 100644
index 0000000000..d7105bad19
--- /dev/null
+++ b/ui/site/css/build/palette.transp.scss
@@ -0,0 +1,2 @@
+@import '../../../common/css/themes/transp';
+@import 'palette';