mirror of
https://github.com/Sonny93/my-links.git
synced 2025-12-10 15:35:35 +00:00
feat: update input/button style + add react-toggle
This commit is contained in:
28
package-lock.json
generated
28
package-lock.json
generated
@@ -9,6 +9,7 @@
|
|||||||
"@ducanh2912/next-pwa": "^9.7.2",
|
"@ducanh2912/next-pwa": "^9.7.2",
|
||||||
"@prisma/client": "^5.6.0",
|
"@prisma/client": "^5.6.0",
|
||||||
"@svgr/webpack": "^8.1.0",
|
"@svgr/webpack": "^8.1.0",
|
||||||
|
"@types/react-toggle": "^4.0.5",
|
||||||
"accept-language": "^3.0.18",
|
"accept-language": "^3.0.18",
|
||||||
"axios": "^1.6.2",
|
"axios": "^1.6.2",
|
||||||
"clsx": "^2.0.0",
|
"clsx": "^2.0.0",
|
||||||
@@ -28,6 +29,7 @@
|
|||||||
"react-icons": "^4.12.0",
|
"react-icons": "^4.12.0",
|
||||||
"react-select": "^5.8.0",
|
"react-select": "^5.8.0",
|
||||||
"react-tabs": "^6.0.2",
|
"react-tabs": "^6.0.2",
|
||||||
|
"react-toggle": "^4.1.3",
|
||||||
"sass": "^1.69.5",
|
"sass": "^1.69.5",
|
||||||
"sharp": "^0.32.6",
|
"sharp": "^0.32.6",
|
||||||
"yup": "^1.3.2"
|
"yup": "^1.3.2"
|
||||||
@@ -2815,6 +2817,14 @@
|
|||||||
"csstype": "^3.0.2"
|
"csstype": "^3.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/react-toggle": {
|
||||||
|
"version": "4.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-toggle/-/react-toggle-4.0.5.tgz",
|
||||||
|
"integrity": "sha512-MHHEDe7GnF/EhLtI5sT70Dqab8rwlgjRZtu/u6gmfbYd+HeYxWiUSRog16+1BCfkz7Wy2VU6+TPU2oCsDtqDzA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/react": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/react-transition-group": {
|
"node_modules/@types/react-transition-group": {
|
||||||
"version": "4.4.5",
|
"version": "4.4.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.5.tgz",
|
||||||
@@ -3909,6 +3919,11 @@
|
|||||||
"node": ">=6.0"
|
"node": ">=6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/classnames": {
|
||||||
|
"version": "2.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz",
|
||||||
|
"integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw=="
|
||||||
|
},
|
||||||
"node_modules/clean-webpack-plugin": {
|
"node_modules/clean-webpack-plugin": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-4.0.0.tgz",
|
||||||
@@ -7955,6 +7970,19 @@
|
|||||||
"react": "^18.0.0"
|
"react": "^18.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-toggle": {
|
||||||
|
"version": "4.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-toggle/-/react-toggle-4.1.3.tgz",
|
||||||
|
"integrity": "sha512-WoPrvbwfQSvoagbrDnXPrlsxwzuhQIrs+V0I162j/s+4XPgY/YDAUmHSeWiroznfI73wj+MBydvW95zX8ABbSg==",
|
||||||
|
"dependencies": {
|
||||||
|
"classnames": "^2.2.5"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"prop-types": ">= 15.3.0 < 19",
|
||||||
|
"react": ">= 15.3.0 < 19",
|
||||||
|
"react-dom": ">= 15.3.0 < 19"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-transition-group": {
|
"node_modules/react-transition-group": {
|
||||||
"version": "4.4.5",
|
"version": "4.4.5",
|
||||||
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
|
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
"@ducanh2912/next-pwa": "^9.7.2",
|
"@ducanh2912/next-pwa": "^9.7.2",
|
||||||
"@prisma/client": "^5.6.0",
|
"@prisma/client": "^5.6.0",
|
||||||
"@svgr/webpack": "^8.1.0",
|
"@svgr/webpack": "^8.1.0",
|
||||||
|
"@types/react-toggle": "^4.0.5",
|
||||||
"accept-language": "^3.0.18",
|
"accept-language": "^3.0.18",
|
||||||
"axios": "^1.6.2",
|
"axios": "^1.6.2",
|
||||||
"clsx": "^2.0.0",
|
"clsx": "^2.0.0",
|
||||||
@@ -33,6 +34,7 @@
|
|||||||
"react-icons": "^4.12.0",
|
"react-icons": "^4.12.0",
|
||||||
"react-select": "^5.8.0",
|
"react-select": "^5.8.0",
|
||||||
"react-tabs": "^6.0.2",
|
"react-tabs": "^6.0.2",
|
||||||
|
"react-toggle": "^4.1.3",
|
||||||
"sass": "^1.69.5",
|
"sass": "^1.69.5",
|
||||||
"sharp": "^0.32.6",
|
"sharp": "^0.32.6",
|
||||||
"yup": "^1.3.2"
|
"yup": "^1.3.2"
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { MutableRefObject, useState } from 'react';
|
import { MutableRefObject, useState } from 'react';
|
||||||
|
import Toggle from 'react-toggle';
|
||||||
|
|
||||||
interface SelectorProps {
|
interface SelectorProps {
|
||||||
name: string;
|
name: string;
|
||||||
@@ -22,7 +23,7 @@ export default function Checkbox({
|
|||||||
placeholder = 'Type something...',
|
placeholder = 'Type something...',
|
||||||
isChecked,
|
isChecked,
|
||||||
onChangeCallback,
|
onChangeCallback,
|
||||||
}: SelectorProps): JSX.Element {
|
}: Readonly<SelectorProps>): JSX.Element {
|
||||||
const [checkboxValue, setCheckboxValue] = useState<boolean>(isChecked);
|
const [checkboxValue, setCheckboxValue] = useState<boolean>(isChecked);
|
||||||
|
|
||||||
function onChange({ target }) {
|
function onChange({ target }) {
|
||||||
@@ -50,13 +51,11 @@ export default function Checkbox({
|
|||||||
{labelComponent}
|
{labelComponent}
|
||||||
</label>
|
</label>
|
||||||
)}
|
)}
|
||||||
<input
|
<Toggle
|
||||||
type='checkbox'
|
|
||||||
id={name}
|
|
||||||
name={name}
|
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
checked={checkboxValue}
|
checked={checkboxValue}
|
||||||
placeholder={placeholder}
|
id={name}
|
||||||
|
name={name}
|
||||||
ref={innerRef}
|
ref={innerRef}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ import { makeRequest } from 'lib/request';
|
|||||||
|
|
||||||
export default function PageRemoveCategory({
|
export default function PageRemoveCategory({
|
||||||
category,
|
category,
|
||||||
}: {
|
}: Readonly<{
|
||||||
category: Category;
|
category: Category;
|
||||||
}) {
|
}>) {
|
||||||
const { t, i18n } = useTranslation();
|
const { t, i18n } = useTranslation();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
|||||||
@@ -7,20 +7,20 @@ import PATHS from 'constants/paths';
|
|||||||
import useAutoFocus from 'hooks/useAutoFocus';
|
import useAutoFocus from 'hooks/useAutoFocus';
|
||||||
import { getServerSideTranslation } from 'i18n';
|
import { getServerSideTranslation } from 'i18n';
|
||||||
import getUserCategories from 'lib/category/getUserCategories';
|
import getUserCategories from 'lib/category/getUserCategories';
|
||||||
|
import { makeRequest } from 'lib/request';
|
||||||
|
import { isValidHttpUrl } from 'lib/url';
|
||||||
import { useTranslation } from 'next-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { FormEvent, useMemo, useState } from 'react';
|
import { FormEvent, useMemo, useState } from 'react';
|
||||||
import styles from 'styles/form.module.scss';
|
import styles from 'styles/form.module.scss';
|
||||||
import { Category, Link } from 'types';
|
import { Category, Link } from 'types';
|
||||||
import { withAuthentication } from 'utils/session';
|
import { withAuthentication } from 'utils/session';
|
||||||
import { makeRequest } from 'lib/request';
|
|
||||||
import { isValidHttpUrl } from 'lib/url';
|
|
||||||
|
|
||||||
export default function PageCreateLink({
|
export default function PageCreateLink({
|
||||||
categories,
|
categories,
|
||||||
}: {
|
}: Readonly<{
|
||||||
categories: Category[];
|
categories: Category[];
|
||||||
}) {
|
}>) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const autoFocusRef = useAutoFocus();
|
const autoFocusRef = useAutoFocus();
|
||||||
|
|||||||
@@ -8,22 +8,22 @@ import useAutoFocus from 'hooks/useAutoFocus';
|
|||||||
import { getServerSideTranslation } from 'i18n';
|
import { getServerSideTranslation } from 'i18n';
|
||||||
import getUserCategories from 'lib/category/getUserCategories';
|
import getUserCategories from 'lib/category/getUserCategories';
|
||||||
import getUserLink from 'lib/link/getUserLink';
|
import getUserLink from 'lib/link/getUserLink';
|
||||||
|
import { makeRequest } from 'lib/request';
|
||||||
|
import { isValidHttpUrl } from 'lib/url';
|
||||||
import { useTranslation } from 'next-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { FormEvent, useMemo, useState } from 'react';
|
import { FormEvent, useMemo, useState } from 'react';
|
||||||
import styles from 'styles/form.module.scss';
|
import styles from 'styles/form.module.scss';
|
||||||
import { Category, Link } from 'types';
|
import { Category, Link } from 'types';
|
||||||
import { isValidHttpUrl } from 'lib/url';
|
|
||||||
import { withAuthentication } from 'utils/session';
|
import { withAuthentication } from 'utils/session';
|
||||||
import { makeRequest } from 'lib/request';
|
|
||||||
|
|
||||||
export default function PageEditLink({
|
export default function PageEditLink({
|
||||||
link,
|
link,
|
||||||
categories,
|
categories,
|
||||||
}: {
|
}: Readonly<{
|
||||||
link: Link;
|
link: Link;
|
||||||
categories: Category[];
|
categories: Category[];
|
||||||
}) {
|
}>) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const autoFocusRef = useAutoFocus();
|
const autoFocusRef = useAutoFocus();
|
||||||
|
|||||||
@@ -5,15 +5,15 @@ import TextBox from 'components/TextBox';
|
|||||||
import PATHS from 'constants/paths';
|
import PATHS from 'constants/paths';
|
||||||
import { getServerSideTranslation } from 'i18n';
|
import { getServerSideTranslation } from 'i18n';
|
||||||
import getUserLink from 'lib/link/getUserLink';
|
import getUserLink from 'lib/link/getUserLink';
|
||||||
|
import { makeRequest } from 'lib/request';
|
||||||
import { useTranslation } from 'next-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { FormEvent, useMemo, useState } from 'react';
|
import { FormEvent, useMemo, useState } from 'react';
|
||||||
import styles from 'styles/form.module.scss';
|
import styles from 'styles/form.module.scss';
|
||||||
import { Link } from 'types';
|
import { Link } from 'types';
|
||||||
import { withAuthentication } from 'utils/session';
|
import { withAuthentication } from 'utils/session';
|
||||||
import { makeRequest } from 'lib/request';
|
|
||||||
|
|
||||||
export default function PageRemoveLink({ link }: { link: Link }) {
|
export default function PageRemoveLink({ link }: Readonly<{ link: Link }>) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
|||||||
143
src/styles/checkbox.scss
Normal file
143
src/styles/checkbox.scss
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
@import 'colors.scss';
|
||||||
|
|
||||||
|
.react-toggle {
|
||||||
|
touch-action: pan-x;
|
||||||
|
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: transparent;
|
||||||
|
border: 0;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-khtml-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-toggle-screenreader-only {
|
||||||
|
border: 0;
|
||||||
|
clip: rect(0 0 0 0);
|
||||||
|
height: 1px;
|
||||||
|
margin: -1px;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 0;
|
||||||
|
position: absolute;
|
||||||
|
width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-toggle--disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
opacity: 0.5;
|
||||||
|
-webkit-transition: opacity 0.25s;
|
||||||
|
transition: opacity 0.25s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-toggle-track {
|
||||||
|
width: 50px;
|
||||||
|
height: 24px;
|
||||||
|
padding: 0;
|
||||||
|
border-radius: 30px;
|
||||||
|
background-color: #4d4d4d;
|
||||||
|
-webkit-transition: all 0.2s ease;
|
||||||
|
-moz-transition: all 0.2s ease;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-toggle:hover:not(.react-toggle--disabled) .react-toggle-track {
|
||||||
|
background-color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-toggle--checked .react-toggle-track {
|
||||||
|
background-color: $blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-toggle--checked:hover:not(.react-toggle--disabled) .react-toggle-track {
|
||||||
|
background-color: $dark-blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-toggle-track-check {
|
||||||
|
position: absolute;
|
||||||
|
width: 14px;
|
||||||
|
height: 10px;
|
||||||
|
top: 0px;
|
||||||
|
bottom: 0px;
|
||||||
|
margin-top: auto;
|
||||||
|
margin-bottom: auto;
|
||||||
|
line-height: 0;
|
||||||
|
left: 8px;
|
||||||
|
opacity: 0;
|
||||||
|
-webkit-transition: opacity 0.25s ease;
|
||||||
|
-moz-transition: opacity 0.25s ease;
|
||||||
|
transition: opacity 0.25s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-toggle--checked .react-toggle-track-check {
|
||||||
|
opacity: 1;
|
||||||
|
-webkit-transition: opacity 0.25s ease;
|
||||||
|
-moz-transition: opacity 0.25s ease;
|
||||||
|
transition: opacity 0.25s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-toggle-track-x {
|
||||||
|
position: absolute;
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
top: 0px;
|
||||||
|
bottom: 0px;
|
||||||
|
margin-top: auto;
|
||||||
|
margin-bottom: auto;
|
||||||
|
line-height: 0;
|
||||||
|
right: 10px;
|
||||||
|
opacity: 1;
|
||||||
|
-webkit-transition: opacity 0.25s ease;
|
||||||
|
-moz-transition: opacity 0.25s ease;
|
||||||
|
transition: opacity 0.25s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-toggle--checked .react-toggle-track-x {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-toggle-thumb {
|
||||||
|
transition: all 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0ms;
|
||||||
|
position: absolute;
|
||||||
|
top: 1px;
|
||||||
|
left: 1px;
|
||||||
|
width: 22px;
|
||||||
|
height: 22px;
|
||||||
|
border: 1px solid $lightest-blue;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #fafafa;
|
||||||
|
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
-webkit-transition: all 0.25s ease;
|
||||||
|
-moz-transition: all 0.25s ease;
|
||||||
|
transition: all 0.25s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-toggle--checked .react-toggle-thumb {
|
||||||
|
left: 27px;
|
||||||
|
border-color: #19ab27;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-toggle--focus .react-toggle-thumb {
|
||||||
|
-webkit-box-shadow: 0px 0px 3px 2px $blue;
|
||||||
|
-moz-box-shadow: 0px 0px 3px 2px $blue;
|
||||||
|
box-shadow: 0px 0px 2px 3px $blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-toggle:active:not(.react-toggle--disabled) .react-toggle-thumb {
|
||||||
|
-webkit-box-shadow: 0px 0px 5px 5px $blue;
|
||||||
|
-moz-box-shadow: 0px 0px 5px 5px $blue;
|
||||||
|
box-shadow: 0px 0px 5px 5px $blue;
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
@import 'keyframes.scss';
|
@import 'keyframes.scss';
|
||||||
@import 'colors.scss';
|
@import 'colors.scss';
|
||||||
|
@import 'checkbox.scss';
|
||||||
|
|
||||||
*:not(ul) {
|
*:not(ul) {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@@ -84,6 +85,8 @@ h6 {
|
|||||||
button:not(.reset) {
|
button:not(.reset) {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
|
text-transform: uppercase;
|
||||||
color: $white;
|
color: $white;
|
||||||
background: $blue;
|
background: $blue;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
@@ -92,8 +95,8 @@ button:not(.reset) {
|
|||||||
transition: 0.15s;
|
transition: 0.15s;
|
||||||
|
|
||||||
&:disabled {
|
&:disabled {
|
||||||
cursor: default;
|
cursor: not-allowed;
|
||||||
opacity: 0.5;
|
opacity: 0.75;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:not(:disabled):hover {
|
&:not(:disabled):hover {
|
||||||
@@ -131,11 +134,12 @@ input:not(.reset) {
|
|||||||
background: $white;
|
background: $white;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border: 1px solid $lightest-grey;
|
border: 1px solid $lightest-grey;
|
||||||
border-bottom: 3px solid $lightest-grey;
|
border-bottom: 2px solid $lightest-grey;
|
||||||
|
border-radius: 5px;
|
||||||
transition: 0.15s;
|
transition: 0.15s;
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
border-bottom: 3px solid $blue;
|
border-bottom: 2px solid $blue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,9 +191,7 @@ kbd {
|
|||||||
padding: 0.25em 0.5em;
|
padding: 0.25em 0.5em;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
border: 1px solid rgb(204, 204, 204);
|
border: 1px solid rgb(204, 204, 204);
|
||||||
box-shadow:
|
box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 2px #ffffff inset;
|
||||||
0 1px 0 rgba(0, 0, 0, 0.2),
|
|
||||||
0 0 0 2px #ffffff inset;
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user