2
0
Эх сурвалжийг харах

feat: rtl display + dark theme improvements

Nick 6 жил өмнө
parent
commit
17f9f0baa9

+ 3 - 1
client/client-app.js

@@ -139,7 +139,9 @@ Vue.use(VueClipboards)
 Vue.use(localization.VueI18Next)
 Vue.use(helpers)
 Vue.use(VeeValidate, { events: '' })
-Vue.use(Vuetify)
+Vue.use(Vuetify, {
+  rtl: siteConfig.rtl
+})
 Vue.use(VueMoment, { moment })
 Vue.use(Vuescroll)
 Vue.use(VueTour)

+ 1 - 1
client/components/admin.vue

@@ -5,7 +5,7 @@
         v-spacer
         .subheading.grey--text Administration Area
         v-spacer
-    v-navigation-drawer.pb-0.admin-sidebar(v-model='adminDrawerShown', app, fixed, clipped, left, permanent)
+    v-navigation-drawer.pb-0.admin-sidebar(v-model='adminDrawerShown', app, fixed, clipped, :right='$vuetify.rtl', permanent)
       vue-scroll(:ops='scrollStyle')
         v-list(dense)
           v-list-tile.pt-2(to='/dashboard')

+ 6 - 0
client/components/admin/admin-locale.vue

@@ -199,8 +199,14 @@ export default {
       })
       const resp = _.get(respRaw, 'data.localization.updateLocale.responseResult', {})
       if (resp.succeeded) {
+        // Change UI language
         WIKI.$i18n.i18next.changeLanguage(this.selectedLocale)
         WIKI.$moment.locale(this.selectedLocale)
+
+        // Check for RTL
+        const curLocale = _.find(this.locales, ['code', this.selectedLocale])
+        this.$vuetify.rtl = curLocale && curLocale.isRTL
+
         this.$store.commit('showNotification', {
           message: 'Locale settings updated successfully.',
           style: 'success',

+ 5 - 0
client/components/common/nav-header.vue

@@ -373,6 +373,11 @@ export default {
     right: 12px;
     border-radius: 4px !important;
 
+    @at-root .application--is-rtl & {
+      right: initial;
+      left: 12px;
+    }
+
     &::before {
       border-radius: 4px !important;
     }

+ 13 - 0
client/scss/base/base.scss

@@ -63,3 +63,16 @@ html {
     border-color: lighten(mc('grey', '900'), percentage($i/100)) !important;
   }
 }
+.grey.darken-5 {
+  background-color: #0C0C0C !important;
+  border-color: #0C0C0C !important;
+}
+
+.blue.darken-5 {
+  background-color: darken(mc('blue', '900'), 20%) !important;
+  border-color: darken(mc('blue', '900'), 20%) !important;
+}
+.indigo.darken-5 {
+  background-color: darken(mc('indigo', '900'), 10%) !important;
+  border-color: darken(mc('indigo', '900'), 10%) !important;
+}

+ 1 - 1
client/store/site.js

@@ -3,7 +3,7 @@ import { make } from 'vuex-pathify'
 /* global siteConfig */
 
 const state = {
-  company: '',
+  company: siteConfig.company,
   dark: siteConfig.darkMode,
   mascot: true,
   title: siteConfig.title,

+ 1 - 1
client/themes/default/components/nav-footer.vue

@@ -6,7 +6,7 @@
 </template>
 
 <script>
-import { get, sync } from 'vuex-pathify'
+import { get } from 'vuex-pathify'
 
 export default {
   props: {

+ 20 - 8
client/themes/default/components/page.vue

@@ -2,16 +2,17 @@
   v-app(v-scroll='upBtnScroll', :dark='darkMode')
     nav-header
     v-navigation-drawer(
-      :class='darkMode ? `grey darken-3` : `primary`'
+      :class='darkMode ? `grey darken-5` : `primary`'
       dark
       app
       clipped
       mobile-break-point='600'
       :temporary='$vuetify.breakpoint.mdAndDown'
       v-model='navShown'
+      :right='$vuetify.rtl'
       )
       vue-scroll(:ops='scrollStyle')
-        nav-sidebar(:color='darkMode ? `grey darken-3` : `primary`')
+        nav-sidebar(:color='darkMode ? `grey darken-5` : `primary`')
           slot(name='sidebar')
 
     v-fab-transition
@@ -20,7 +21,8 @@
         color='primary'
         fixed
         bottom
-        left
+        :right='$vuetify.rtl'
+        :left='!$vuetify.rtl'
         small
         @click='navShown = !navShown'
         v-if='$vuetify.breakpoint.mdAndDown'
@@ -48,16 +50,16 @@
         v-divider
       v-layout(row)
         v-flex(xs12, lg9, xl10)
-          v-toolbar(:color='darkMode ? `grey darken-4` : `grey lighten-4`', flat, :height='90')
+          v-toolbar(:color='darkMode ? `grey darken-4-l3` : `grey lighten-4`', flat, :height='90')
             div
-              .headline.grey--text(:class='darkMode ? `text-lighten-2` : `text--darken-3`') {{title}}
+              .headline.grey--text(:class='darkMode ? `text--lighten-2` : `text--darken-3`') {{title}}
               .caption.grey--text.text--darken-1 {{description}}
           v-divider
           .contents(ref='container')
             slot(name='contents')
 
         v-flex(lg3, xl2, fill-height, v-if='$vuetify.breakpoint.lgAndUp')
-          v-toolbar(:color='darkMode ? `grey darken-4` : `grey lighten-4`', flat, :height='90')
+          v-toolbar(:color='darkMode ? `grey darken-4-l3` : `grey lighten-4`', flat, :height='90')
             div
               .caption.grey--text.text--lighten-1 Last edited by
               .body-2.grey--text(:class='darkMode ? `` : `text--darken-3`') {{ authorName }}
@@ -70,7 +72,7 @@
           v-divider
           template(v-if='toc.length')
             v-list.grey.pb-3(dense, :class='darkMode ? `darken-3-d3` : `lighten-3`')
-              v-subheader.pl-4(:class='darkMode ? `blue--text text--lighten-1` : `primary--text`') Table of contents
+              v-subheader.pl-4(:class='darkMode ? `indigo--text text--lighten-3` : `primary--text`') Table of Contents
               template(v-for='(tocItem, tocIdx) in toc')
                 v-list-tile(@click='$vuetify.goTo(tocItem.anchor, scrollOpts)')
                   v-icon(color='grey') arrow_right
@@ -119,7 +121,17 @@
     notify
     search-results
     v-fab-transition
-      v-btn(v-if='upBtnShown', fab, fixed, bottom, right, small, @click='$vuetify.goTo(0, scrollOpts)', color='primary')
+      v-btn(
+        v-if='upBtnShown'
+        fab
+        fixed
+        bottom
+        :right='!$vuetify.rtl'
+        :left='$vuetify.rtl'
+        small
+        @click='$vuetify.goTo(0, scrollOpts)'
+        color='primary'
+        )
         v-icon arrow_upward
 </template>
 

+ 81 - 28
client/themes/default/scss/app.scss

@@ -2,14 +2,19 @@
 
 .contents {
   color: mc('grey', '800');
-  padding-bottom: 50px;
+  padding: 24px 0 50px;
   position: relative;
 
+  > div > *:first-child {
+    margin-top: 0;
+  }
+
   @at-root .theme--dark & {
+    background-color: darken(mc('grey', '900'), 4%);
     color: mc('grey', '300');
 
     a {
-      color: mc('blue', '300');
+      color: mc('indigo', '200');
     }
   }
 
@@ -20,6 +25,10 @@
   h1, h2, h3, h4, h5, h6 {
     position: relative;
 
+    &:first-child {
+      padding-top: 0;
+    }
+
     &:hover {
       .toc-anchor {
         display: block;
@@ -35,16 +44,20 @@
       text-decoration: none;
       color: mc('grey', '500');
     }
+
+    & + h2, & + h3, & + h4, & + h5, & + h6 {
+      margin-top: 8px;
+    }
   }
 
   h1 {
-    padding-left: 24px;
+    padding: 0 24px;
     color: mc('blue', '800');
     margin-top: 2rem;
     position: relative;
 
     @at-root .theme--dark & {
-      color: mc('grey', '400');
+      color: mc('teal', '100');
     }
 
     &::after {
@@ -57,23 +70,25 @@
       background: linear-gradient(to right, mc('theme', 'primary'), rgba(mc('theme', 'primary'), 0));
 
       @at-root .theme--dark & {
-        background: linear-gradient(to right, mc('grey', '600'), rgba(mc('grey', '600'), 0));
+        background: linear-gradient(to right, mc('teal', '300') 0%, mc('teal', '500') 10%, rgba(mc('teal', '900'), 0) 100%);
       }
-    }
 
-    & + h2, & + h3 {
-      margin-top: 8px;
+      @at-root .application--is-rtl & {
+        background: linear-gradient(to left, mc('theme', 'primary'), rgba(mc('theme', 'primary'), 0));
+      }
+      @at-root .theme--dark.application--is-rtl & {
+        background: linear-gradient(to left, mc('grey', '600'), rgba(mc('grey', '600'), 0));
+      }
     }
   }
   h2 {
-    margin-left: 24px;
+    margin: 1rem 24px 0 24px;
     padding: 8px 0 0 0;
     color: mc('grey', '800');
     position: relative;
-    margin-top: 1rem;
 
     @at-root .theme--dark & {
-      color: mc('grey', '500');
+      color: mc('grey', '400');
     }
 
     &::after {
@@ -88,14 +103,17 @@
       @at-root .theme--dark & {
         background: linear-gradient(to right, mc('grey', '300'), rgba(mc('grey', '700'), 0));
       }
-    }
 
-    & + h3 {
-      margin-top: 8px;
+      @at-root .application--is-rtl & {
+        background: linear-gradient(to left, mc('grey', '700'), rgba(mc('grey', '700'), 0));
+      }
+      @at-root .theme--dark.application--is-rtl & {
+        background: linear-gradient(to left, mc('grey', '300'), rgba(mc('grey', '700'), 0));
+      }
     }
   }
   h3 {
-    margin-left: 24px;
+    margin: 0 24px;
     padding: 8px 0 0 0;
     color: mc('grey', '700');
     position: relative;
@@ -111,7 +129,38 @@
       left: 0;
       width: 100%;
       height: 1px;
-      background: linear-gradient(to right, mc('grey', '500'), rgba(mc('grey', '500'), 0));
+      background: linear-gradient(to right, mc('grey', '500'), rgba(mc('grey', '500'), 0) 90%);
+    }
+  }
+  h4, h5, h6 {
+    font-size: 1rem;
+    margin: 0 24px;
+    padding: 8px 0 0 0;
+    color: mc('grey', '700');
+    position: relative;
+
+    @at-root .theme--dark & {
+      color: mc('grey', '600');
+    }
+
+    &::after {
+      content: '';
+      position: absolute;
+      bottom: 0;
+      left: 0;
+      width: 100%;
+      height: 1px;
+      background: linear-gradient(to right, mc('grey', '500'), rgba(mc('grey', '500'), 0) 70%);
+    }
+  }
+  h5 {
+    &::after {
+      background: linear-gradient(to right, mc('grey', '500'), rgba(mc('grey', '500'), 0) 50%);
+    }
+  }
+  h6 {
+    &::after {
+      background: linear-gradient(to right, mc('grey', '500'), rgba(mc('grey', '500'), 0) 30%);
     }
   }
 
@@ -123,6 +172,10 @@
     padding: 1rem 24px 0 24px;
     margin: 0;
     text-align: justify;
+
+    @at-root .contents > div > p:first-child {
+      padding-top: 0;
+    }
   }
 
   hr {
@@ -143,9 +196,9 @@
 
   blockquote {
     padding: 0 0 1rem 0;
-    border: 1px solid mc('blue', '500');
+    border-left: 5px solid mc('blue', '500');
     border-radius: .5rem;
-    margin: 1rem;
+    margin: 1rem 2rem;
 
     > p:first-child .emoji {
       margin-right: .5rem;
@@ -168,8 +221,8 @@
       }
 
       @at-root .theme--dark & {
-        background-color: mc('blue', '900');
-        background-image: radial-gradient(ellipse at top, mc('blue', '900'), darken(mc('blue', '900'), 5%));
+        background-color: mc('grey', '900');
+        background-image: radial-gradient(ellipse at top, mc('blue', '900'), rgba(darken(mc('blue', '900'), 5%), .2));
         border-color: mc('blue', '500');
         box-shadow: 0 0 2px 0 mc('grey', '900');
       }
@@ -186,8 +239,8 @@
       }
 
       @at-root .theme--dark & {
-        background-color: mc('orange', '900');
-        background-image: radial-gradient(ellipse at top, mc('orange', '900'), darken(mc('orange', '900'), 5%));
+        background-color: mc('grey', '900');
+        background-image: radial-gradient(ellipse at top, mc('orange', '900'), rgba(darken(mc('orange', '900'), 5%), .2));
         border-color: mc('orange', '500');
         box-shadow: 0 0 2px 0 mc('grey', '900');
       }
@@ -204,8 +257,8 @@
       }
 
       @at-root .theme--dark & {
-        background-color: mc('red', '900');
-        background-image: radial-gradient(ellipse at top, mc('red', '900'), darken(mc('red', '900'), 5%));
+        background-color: mc('grey', '900');
+        background-image: radial-gradient(ellipse at top, mc('red', '900'), rgba(darken(mc('red', '900'), 5%), .2));
         border-color: mc('red', '500');
         box-shadow: 0 0 2px 0 mc('grey', '900');
       }
@@ -222,8 +275,8 @@
       }
 
       @at-root .theme--dark & {
-        background-color: mc('green', '900');
-        background-image: radial-gradient(ellipse at top, mc('green', '900'), darken(mc('green', '900'), 5%));
+        background-color: mc('grey', '900');
+        background-image: radial-gradient(ellipse at top, mc('green', '900'), rgba(darken(mc('green', '900'), 5%), .2));
         border-color: mc('green', '500');
         box-shadow: 0 0 2px 0 mc('grey', '900');
       }
@@ -304,7 +357,7 @@
 
           &:hover {
             background-image: linear-gradient(to bottom, lighten(mc('grey', '900'), 2%), darken(mc('grey', '900'), 3%));
-            border-left-color: mc('blue', '500');
+            border-left-color: mc('indigo', '300');
             cursor: pointer;
           }
         }
@@ -508,7 +561,7 @@
     }
     &.align-abstopright {
       position: absolute;
-      top: -90px;
+      top: calc(-90px + 1rem);
       right: 1rem;
       height: calc(90px - 2rem);
       width: auto;

+ 1 - 1
dev/templates/master.pug

@@ -29,7 +29,7 @@ html
 
     //- Site Properties
     script.
-      var siteConfig = !{JSON.stringify({ title: config.title, theme: config.theming.theme, darkMode: config.theming.darkMode, lang: config.lang.code, company: config.company })}
+      var siteConfig = !{JSON.stringify({ title: config.title, theme: config.theming.theme, darkMode: config.theming.darkMode, lang: config.lang.code, rtl: config.lang.rtl, company: config.company })}
 
     //- CSS
     <% for (var index in htmlWebpackPlugin.files.css) { %>

+ 1 - 0
server/app/data.yml

@@ -31,6 +31,7 @@ defaults:
       autoUpdate: true
       namespaces: []
       namespacing: false
+      rtl: false
     telemetry:
       clientId: ''
       isEnabled: false

+ 4 - 0
server/graph/resolvers/localization.js

@@ -57,6 +57,10 @@ module.exports = {
         WIKI.config.lang.autoUpdate = args.autoUpdate
         WIKI.config.lang.namespacing = args.namespacing
         WIKI.config.lang.namespaces = args.namespaces
+
+        const newLocale = await WIKI.models.locales.query().select('isRTL').where('code', args.locale).first()
+        WIKI.config.lang.rtl = newLocale.isRTL
+
         await WIKI.configSvc.saveToDb(['lang'])
 
         await WIKI.lang.setCurrentLocale(args.locale)

+ 1 - 1
server/views/master.pug

@@ -29,7 +29,7 @@ html
     
     //- Site Properties
     script.
-      var siteConfig = !{JSON.stringify({ title: config.title, theme: config.theming.theme, darkMode: config.theming.darkMode, lang: config.lang.code, company: config.company })}
+      var siteConfig = !{JSON.stringify({ title: config.title, theme: config.theming.theme, darkMode: config.theming.darkMode, lang: config.lang.code, rtl: config.lang.rtl, company: config.company })}
     
     //- CSS