diff --git a/README.md b/README.md
index 838c472a..12c7733a 100644
--- a/README.md
+++ b/README.md
@@ -21,6 +21,11 @@ npm run typecheck:watch
```
## Code generation
+generate new SolidJS component:
+```
+npx hygen component new NewComponentName
+```
+
generate new SolidJS context:
```
npx hygen context new NewContextName
diff --git a/_templates/component/new/component.ejs.t b/_templates/component/new/component.ejs.t
new file mode 100644
index 00000000..6f6a7c04
--- /dev/null
+++ b/_templates/component/new/component.ejs.t
@@ -0,0 +1,18 @@
+---
+to: src/components/<%= h.changeCase.pascal(name) %>/<%= h.changeCase.pascal(name) %>.tsx
+---
+
+import { clsx } from 'clsx'
+import styles from './<%= h.changeCase.pascal(name) %>.module.scss'
+
+type Props = {
+ class?: string
+}
+
+export const <%= h.changeCase.pascal(name) %> = (props: Props) => {
+ return (
+
, props.class)}>
+ <%= h.changeCase.pascal(name) %>
+
+ )
+}
diff --git a/_templates/component/new/index.ejs.t b/_templates/component/new/index.ejs.t
new file mode 100644
index 00000000..13e22de4
--- /dev/null
+++ b/_templates/component/new/index.ejs.t
@@ -0,0 +1,4 @@
+---
+to: src/components/<%= h.changeCase.pascal(name) %>/index.ts
+---
+export { <%= h.changeCase.pascal(name) %> } from './<%= h.changeCase.pascal(name) %>'
diff --git a/_templates/component/new/styles.ejs.t b/_templates/component/new/styles.ejs.t
new file mode 100644
index 00000000..2a0ed70c
--- /dev/null
+++ b/_templates/component/new/styles.ejs.t
@@ -0,0 +1,7 @@
+---
+to: src/components/<%= h.changeCase.pascal(name) %>/<%= h.changeCase.pascal(name) %>.module.scss
+---
+
+.<%= h.changeCase.pascal(name) %> {
+ display: block;
+}
diff --git a/_templates/context/new/hello.ejs.t b/_templates/context/new/context.ejs.t
similarity index 100%
rename from _templates/context/new/hello.ejs.t
rename to _templates/context/new/context.ejs.t
diff --git a/public/icons/up-button.svg b/public/icons/up-button.svg
new file mode 100644
index 00000000..a5a436ca
--- /dev/null
+++ b/public/icons/up-button.svg
@@ -0,0 +1,4 @@
+
diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json
index 7ecd9c34..5d9b89ff 100644
--- a/public/locales/en/translation.json
+++ b/public/locales/en/translation.json
@@ -166,6 +166,7 @@
"Restore password": "Restore password",
"Save draft": "Save draft",
"Save settings": "Save settings",
+ "Scroll up": "Scroll up",
"Search": "Search",
"Search author": "Search author",
"Search topic": "Search topic",
diff --git a/public/locales/ru/translation.json b/public/locales/ru/translation.json
index b888e763..0d00d8eb 100644
--- a/public/locales/ru/translation.json
+++ b/public/locales/ru/translation.json
@@ -187,6 +187,7 @@
"Send": "Отправить",
"Send link again": "Прислать ссылку ещё раз",
"Settings": "Настройки",
+ "Scroll up": "Наверх",
"Share": "Поделиться",
"Short opening": "Небольшое вступление, чтобы заинтересовать читателя",
"Show": "Показать",
diff --git a/src/components/Nav/Header.module.scss b/src/components/Nav/Header.module.scss
index fe344927..f9e9bb83 100644
--- a/src/components/Nav/Header.module.scss
+++ b/src/components/Nav/Header.module.scss
@@ -392,7 +392,7 @@
}
.userControl {
- align-items: baseline;
+ align-items: center;
display: flex;
opacity: 1;
transition: opacity 0.3s;
@@ -428,6 +428,7 @@
display: flex;
height: 2.4em;
justify-content: center;
+ margin-left: 0.5em;
position: relative;
transition: margin-left 0.3s;
width: 2.4em;
@@ -484,11 +485,8 @@
width: 100%;
}
}
- .icon {
- display: inline-flex;
- align-items: center;
- justify-content: center;
+ .icon {
img {
height: 20px;
width: auto;
@@ -508,7 +506,20 @@
}
.userControlItemVerbose {
- margin-right: 0.5em;
+ margin-left: 0.5em;
+
+ &:global(.loginbtn) {
+ .icon {
+ height: 2.4rem;
+ width: 2.4rem;
+ }
+
+ img {
+ max-width: none;
+ height: 2.4rem;
+ width: 2.4rem;
+ }
+ }
@include media-breakpoint-up(lg) {
margin-right: 0;
@@ -519,8 +530,7 @@
}
.textLabel {
- // padding: 0 1.2rem;
-
+ padding: 0 1.2rem;
display: inline;
position: relative;
z-index: 1;
@@ -531,4 +541,10 @@
a::before {
border-radius: 1.2em !important;
}
+
+ a:hover {
+ .icon {
+ filter: invert(0);
+ }
+ }
}
diff --git a/src/components/Views/Edit.module.scss b/src/components/Views/Edit.module.scss
index 8fd0dc46..cfd06498 100644
--- a/src/components/Views/Edit.module.scss
+++ b/src/components/Views/Edit.module.scss
@@ -13,6 +13,8 @@
}
.container {
+ position: relative;
+
.titleInput,
.subtitleInput {
border: 0;
@@ -98,6 +100,49 @@
}
}
+.scrollTopButton {
+ cursor: pointer;
+ left: 2rem;
+ position: sticky;
+ top: calc(100vh - 40px);
+ width: 2.8rem;
+ z-index: 2;
+
+ @include media-breakpoint-down(md) {
+ display: none;
+ }
+
+ @include media-breakpoint-up(xl) {
+ left: 4rem;
+ }
+
+ &:hover {
+ .icon {
+ opacity: 1;
+ }
+
+ .scrollTopButtonLabel {
+ display: block;
+ }
+ }
+
+ .icon {
+ opacity: 0.4;
+ }
+}
+
+.scrollTopButtonLabel {
+ @include font-size(1.4rem);
+
+ display: none;
+ font-weight: bold;
+ left: 100%;
+ padding-left: 0.5em;
+ position: absolute;
+ top: 50%;
+ transform: translateY(-50%);
+}
+
.inputContainer {
position: relative;
diff --git a/src/components/Views/Edit.tsx b/src/components/Views/Edit.tsx
index 8568045e..1eadc8a1 100644
--- a/src/components/Views/Edit.tsx
+++ b/src/components/Views/Edit.tsx
@@ -10,6 +10,7 @@ import { useRouter } from '../../stores/router'
import { Editor } from '../Editor/Editor'
import { Panel } from '../Editor/Panel'
import { useEditorContext } from '../../context/editor'
+import { Icon } from '../_shared/Icon'
type EditViewProps = {
shout: Shout
@@ -68,8 +69,20 @@ export const EditView = (props: EditViewProps) => {
setForm('slug', slug)
}
+ const scrollTop = () => {
+ window.scrollTo({
+ top: 0,
+ behavior: 'smooth'
+ })
+ }
+
return (
<>
+
+
{t('Write an article')}