diff --git a/.eslintrc.js b/.eslintrc.js index cb0f755..fbb8c55 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -2,7 +2,7 @@ module.exports = { globals: { __PATH_PREFIX__: true, }, - extends: "react-app", + extends: ["react-app", "plugin:react/recommended"], rules: { "quotes": ["error", "double"], "curly": ["error", "all"], @@ -11,6 +11,8 @@ module.exports = { "SwitchCase": 1 }], "react/react-in-jsx-scope": "off", - "react/self-closing-comp": "error" + "react/self-closing-comp": "error", + // For now we don't habe prop-types validation + "react/prop-types": "off" } }; diff --git a/.gitignore b/.gitignore index a110030..30713b7 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ # Gatsby /.cache /public +/schema.json # IDE (WebStorm) *.iml diff --git a/.graphqlconfig b/.graphqlconfig new file mode 100644 index 0000000..b35a137 --- /dev/null +++ b/.graphqlconfig @@ -0,0 +1,3 @@ +{ + "schemaPath": "schema.json" +} diff --git a/package-lock.json b/package-lock.json index eb07192..8b8e4db 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1538,6 +1538,29 @@ "@hapi/hoek": "^8.3.0" } }, + "@hot-loader/react-dom": { + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/@hot-loader/react-dom/-/react-dom-17.0.1.tgz", + "integrity": "sha512-QttzEibkIFkl/WV1dsLXg73YIweNo9ySbB0/26068RqFGWyv7pKyictWsaQXqSj1y66/BDn3kglCHgroGrv3vA==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "scheduler": "^0.20.1" + }, + "dependencies": { + "scheduler": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.1.tgz", + "integrity": "sha512-LKTe+2xNJBNxu/QhHvDR14wUXHRQbVY5ZOYpOGWRzhydZUqrLb2JBvLPY7cAqFmqrWuDED0Mjk7013SZiOz6Bw==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + } + } + }, "@iarna/toml": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", @@ -1736,6 +1759,108 @@ } } }, + "@styled-system/background": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@styled-system/background/-/background-5.1.2.tgz", + "integrity": "sha512-jtwH2C/U6ssuGSvwTN3ri/IyjdHb8W9X/g8Y0JLcrH02G+BW3OS8kZdHphF1/YyRklnrKrBT2ngwGUK6aqqV3A==", + "requires": { + "@styled-system/core": "^5.1.2" + } + }, + "@styled-system/border": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@styled-system/border/-/border-5.1.5.tgz", + "integrity": "sha512-JvddhNrnhGigtzWRCVuAHepniyVi6hBlimxWDVAdcTuk7aRn9BYJUwfHslURtwYFsF5FoEs8Zmr1oZq2M1AP0A==", + "requires": { + "@styled-system/core": "^5.1.2" + } + }, + "@styled-system/color": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@styled-system/color/-/color-5.1.2.tgz", + "integrity": "sha512-1kCkeKDZkt4GYkuFNKc7vJQMcOmTl3bJY3YBUs7fCNM6mMYJeT1pViQ2LwBSBJytj3AB0o4IdLBoepgSgGl5MA==", + "requires": { + "@styled-system/core": "^5.1.2" + } + }, + "@styled-system/core": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@styled-system/core/-/core-5.1.2.tgz", + "integrity": "sha512-XclBDdNIy7OPOsN4HBsawG2eiWfCcuFt6gxKn1x4QfMIgeO6TOlA2pZZ5GWZtIhCUqEPTgIBta6JXsGyCkLBYw==", + "requires": { + "object-assign": "^4.1.1" + } + }, + "@styled-system/css": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@styled-system/css/-/css-5.1.5.tgz", + "integrity": "sha512-XkORZdS5kypzcBotAMPBoeckDs9aSZVkvrAlq5K3xP8IMAUek+x2O4NtwoSgkYkWWzVBu6DGdFZLR790QWGG+A==" + }, + "@styled-system/flexbox": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@styled-system/flexbox/-/flexbox-5.1.2.tgz", + "integrity": "sha512-6hHV52+eUk654Y1J2v77B8iLeBNtc+SA3R4necsu2VVinSD7+XY5PCCEzBFaWs42dtOEDIa2lMrgL0YBC01mDQ==", + "requires": { + "@styled-system/core": "^5.1.2" + } + }, + "@styled-system/grid": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@styled-system/grid/-/grid-5.1.2.tgz", + "integrity": "sha512-K3YiV1KyHHzgdNuNlaw8oW2ktMuGga99o1e/NAfTEi5Zsa7JXxzwEnVSDSBdJC+z6R8WYTCYRQC6bkVFcvdTeg==", + "requires": { + "@styled-system/core": "^5.1.2" + } + }, + "@styled-system/layout": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@styled-system/layout/-/layout-5.1.2.tgz", + "integrity": "sha512-wUhkMBqSeacPFhoE9S6UF3fsMEKFv91gF4AdDWp0Aym1yeMPpqz9l9qS/6vjSsDPF7zOb5cOKC3tcKKOMuDCPw==", + "requires": { + "@styled-system/core": "^5.1.2" + } + }, + "@styled-system/position": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@styled-system/position/-/position-5.1.2.tgz", + "integrity": "sha512-60IZfMXEOOZe3l1mCu6sj/2NAyUmES2kR9Kzp7s2D3P4qKsZWxD1Se1+wJvevb+1TP+ZMkGPEYYXRyU8M1aF5A==", + "requires": { + "@styled-system/core": "^5.1.2" + } + }, + "@styled-system/shadow": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@styled-system/shadow/-/shadow-5.1.2.tgz", + "integrity": "sha512-wqniqYb7XuZM7K7C0d1Euxc4eGtqEe/lvM0WjuAFsQVImiq6KGT7s7is+0bNI8O4Dwg27jyu4Lfqo/oIQXNzAg==", + "requires": { + "@styled-system/core": "^5.1.2" + } + }, + "@styled-system/space": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@styled-system/space/-/space-5.1.2.tgz", + "integrity": "sha512-+zzYpR8uvfhcAbaPXhH8QgDAV//flxqxSjHiS9cDFQQUSznXMQmxJegbhcdEF7/eNnJgHeIXv1jmny78kipgBA==", + "requires": { + "@styled-system/core": "^5.1.2" + } + }, + "@styled-system/typography": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@styled-system/typography/-/typography-5.1.2.tgz", + "integrity": "sha512-BxbVUnN8N7hJ4aaPOd7wEsudeT7CxarR+2hns8XCX1zp0DFfbWw4xYa/olA0oQaqx7F1hzDg+eRaGzAJbF+jOg==", + "requires": { + "@styled-system/core": "^5.1.2" + } + }, + "@styled-system/variant": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@styled-system/variant/-/variant-5.1.5.tgz", + "integrity": "sha512-Yn8hXAFoWIro8+Q5J8YJd/mP85Teiut3fsGVR9CAxwgNfIAiqlYxsk5iHU7VHJks/0KjL4ATSjmbtCDC/4l1qw==", + "requires": { + "@styled-system/core": "^5.1.2", + "@styled-system/css": "^5.1.5" + } + }, "@szmarczak/http-timer": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", @@ -5858,9 +5983,9 @@ } }, "eslint-plugin-react": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.21.5.tgz", - "integrity": "sha512-8MaEggC2et0wSF6bUeywF7qQ46ER81irOdWS4QWxnnlAEsnzeBevk1sWh7fhpCghPpXb+8Ks7hvaft6L/xsR6g==", + "version": "7.22.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.22.0.tgz", + "integrity": "sha512-p30tuX3VS+NWv9nQot9xIGAHBXR0+xJVaZriEsHoJrASGCJZDJ8JLNM0YqKqI0AKm6Uxaa1VUHoNEibxRCMQHA==", "requires": { "array-includes": "^3.1.1", "array.prototype.flatmap": "^1.2.3", @@ -7421,6 +7546,15 @@ "integrity": "sha512-vAMy37povmQJNg6ZxY78fkWR3pKwG8MNMhO3u+4vXj2MYT5avhFvHPJTAb126ZCuygf30gAWlpwbV50zP894Jw==", "dev": true }, + "gatsby-plugin-extract-schema": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/gatsby-plugin-extract-schema/-/gatsby-plugin-extract-schema-0.0.5.tgz", + "integrity": "sha512-99xOTw3OzjsMDvUa39V5Q+iUiyA1f5KmY26h2cqUjM4pu3SWL/RmODf4VKsRnrRNCTHUOyQ9RYROYusJsDuYug==", + "dev": true, + "requires": { + "write": "^1.0.3" + } + }, "gatsby-plugin-fontawesome-css": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/gatsby-plugin-fontawesome-css/-/gatsby-plugin-fontawesome-css-1.0.0.tgz", @@ -8641,9 +8775,9 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, "inline-style-parser": { "version": "0.1.1", @@ -13352,12 +13486,30 @@ } }, "side-channel": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.3.tgz", - "integrity": "sha512-A6+ByhlLkksFoUepsGxfj5x1gTSrs+OydsRptUxeNCabQpCFUvcwIczgOigI8vhY/OJCnPnyE9rGiwgvr9cS1g==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", "requires": { - "es-abstract": "^1.18.0-next.0", - "object-inspect": "^1.8.0" + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "dependencies": { + "get-intrinsic": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.2.tgz", + "integrity": "sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "object-inspect": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", + "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==" + } } }, "signal-exit": { @@ -14179,6 +14331,26 @@ "supports-color": "^5.5.0" } }, + "styled-system": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/styled-system/-/styled-system-5.1.5.tgz", + "integrity": "sha512-7VoD0o2R3RKzOzPK0jYrVnS8iJdfkKsQJNiLRDjikOpQVqQHns/DXWaPZOH4tIKkhAT7I6wIsy9FWTWh2X3q+A==", + "requires": { + "@styled-system/background": "^5.1.2", + "@styled-system/border": "^5.1.5", + "@styled-system/color": "^5.1.2", + "@styled-system/core": "^5.1.2", + "@styled-system/flexbox": "^5.1.2", + "@styled-system/grid": "^5.1.2", + "@styled-system/layout": "^5.1.2", + "@styled-system/position": "^5.1.2", + "@styled-system/shadow": "^5.1.2", + "@styled-system/space": "^5.1.2", + "@styled-system/typography": "^5.1.2", + "@styled-system/variant": "^5.1.5", + "object-assign": "^4.1.1" + } + }, "stylehacks": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz", diff --git a/package.json b/package.json index 68e0825..a235c05 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "react-helmet": "^6.1.0", "react-media": "^2.0.0-rc.1", "styled-components": "^5.2.0", + "styled-system": "^5.1.5", "swr": "^0.3.2", "use-debounce": "^3.4.3" }, @@ -41,9 +42,12 @@ }, "devDependencies": { "@babel/plugin-transform-react-jsx": "^7.12.7", + "@hot-loader/react-dom": "^17.0.1", "eslint": "^7.14.0", "eslint-config-react-app": "^6.0.0", "eslint-loader": "^4.0.2", - "gatsby-plugin-eslint": "^2.0.8" + "eslint-plugin-react": "^7.22.0", + "gatsby-plugin-eslint": "^2.0.8", + "gatsby-plugin-extract-schema": "0.0.5" } } diff --git a/src/components/card/searchResult/anime.js b/src/components/card/searchResult/anime.js index 0e3dd25..111371d 100644 --- a/src/components/card/searchResult/anime.js +++ b/src/components/card/searchResult/anime.js @@ -2,17 +2,19 @@ import {Link} from "gatsby"; import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"; import {faEllipsisH} from "@fortawesome/free-solid-svg-icons"; import Button from "components/button"; -import Flex from "components/flex"; import Text from "components/text"; import SearchResultCard, {SearchResultDescription} from "components/card/searchResult"; import Elevator from "components/elevator"; import ButtonPlay from "components/button/play"; import useImage from "hooks/useImage"; import createVideoSlug from "utils/createVideoSlug"; +import { Flex } from "components/flex"; export default function AnimeSearchResultCard({ anime, hideThemes = false }) { const { smallCover } = useImage(anime); + const animeLink = `/anime/${anime.slug}`; + let premiere = anime.year; let premiereLink = `/year/${anime.year}`; if (anime.season) { @@ -37,11 +39,11 @@ export default function AnimeSearchResultCard({ anime, hideThemes = false }) { title={anime.name} description={description} image={smallCover} - to={`/anime/${anime.slug}`} + to={animeLink} > {!hideThemes && ( - + {anime.themes .slice(0, 4) .filter((theme) => theme.entries.length && theme.entries[0].videos.length) @@ -51,14 +53,14 @@ export default function AnimeSearchResultCard({ anime, hideThemes = false }) { const videoSlug = createVideoSlug(theme, entry, video); return ( - + {theme.slug} ); }) } {anime.themes.length > 4 && ( - )} diff --git a/src/components/card/searchResult/index.js b/src/components/card/searchResult/index.js index dff4c27..5a76b6e 100644 --- a/src/components/card/searchResult/index.js +++ b/src/components/card/searchResult/index.js @@ -34,16 +34,21 @@ const StyledChildren = styled.div` display: none; } `; -const StyledLink = styled(Link)` - display: block; -`; export default function SearchResultCard({ title, description, image, to, children, ...props }) { - const card = ( + return ( - + + + - {title} + + {typeof title === "string" ? ( + + {title} + + ) : title} + {description} @@ -51,21 +56,11 @@ export default function SearchResultCard({ title, description, image, to, childr ); - - if (to) { - return ( - - {card} - - ); - } - - return card; } export function SearchResultDescription({ children }) { return children.filter((child) => !!child).map((child, index, { length }) => ( - + {child} {index < length - 1 && ( diff --git a/src/components/card/searchResult/theme.js b/src/components/card/searchResult/theme.js index 748241e..22eebfe 100644 --- a/src/components/card/searchResult/theme.js +++ b/src/components/card/searchResult/theme.js @@ -20,6 +20,7 @@ export default function ThemeSearchResultCard({ theme }) { const video = entry.videos[0]; const videoSlug = createVideoSlug(theme, entry, video); + const to = `/anime/${theme.anime.slug}/${videoSlug}`; const description = ( @@ -33,10 +34,10 @@ export default function ThemeSearchResultCard({ theme }) { return ( } + title={} description={description} image={smallCover} - to={`/anime/${theme.anime.slug}/${videoSlug}`} + to={to} /> ); } diff --git a/src/components/card/theme/style.js b/src/components/card/theme/style.js index 6065bea..79c85eb 100644 --- a/src/components/card/theme/style.js +++ b/src/components/card/theme/style.js @@ -1,5 +1,5 @@ import styled, {css} from "styled-components"; -import Flex from "components/flex"; +import { Flex } from "components/flex"; import Text from "components/text"; import {gapsColumn} from "styles/mixins"; import Card from "components/card"; @@ -54,8 +54,7 @@ export const StyledVideoListContainer = styled.div` `; export const StyledVideoList = styled(Flex).attrs({ - row: true, - wrap: true, + flexWrap: "wrap", gapsBoth: "0.75rem" })` @media (min-width: 721px) { diff --git a/src/components/descriptionList/index.js b/src/components/descriptionList/index.js index 8fef97d..64b2ae6 100644 --- a/src/components/descriptionList/index.js +++ b/src/components/descriptionList/index.js @@ -1,5 +1,6 @@ -import Title from "components/text/title"; +import {Fragment} from "react"; import styled from "styled-components"; +import Title from "components/text/title"; const StyledDescriptionList = styled.dl` display: flex; @@ -22,15 +23,13 @@ const StyledValue = styled.dd` export default function DescriptionList({ children, ...props }) { return ( - {Object.entries(children).map(([ title, description ]) => ( - !!description && ( - <> - - {title} - - {description} - - ) + {Object.entries(children).filter(([, description]) => !!description).map(([ title, description ]) => ( + + + {title} + + {description} + ))} ); diff --git a/src/components/flex/index.js b/src/components/flex/index.js index 13f1e53..a4f48a9 100644 --- a/src/components/flex/index.js +++ b/src/components/flex/index.js @@ -1,43 +1,58 @@ -import React from "react"; -import styled, {css} from "styled-components"; -import {gapsColumn, gapsRow} from "styles/mixins"; +import styled from "styled-components"; +import { space, layout, typography, color, flexbox, grid, system, get } from "styled-system"; -const StyledFlex = styled.div` - display: flex; - flex-direction: ${(props) => props.row ? "row" : "column"}; - flex-wrap: ${(props) => props.wrap ? "wrap" : "nowrap"}; - justify-content: ${(props) => props.justifyContent || "flex-start"}; - align-items: ${(props) => props.alignItems || "stretch"}; +const gapsAxesSystem = system({ + gapsRow: { + property: "marginLeft", + scale: "space" + }, + gapsColumn: { + property: "marginTop", + scale: "space" + } +}); - ${(props) => props.gapsRow && gapsRow(props.gapsRow)} - ${(props) => props.gapsColumn && gapsColumn(props.gapsColumn)} - ${(props) => props.gapsBoth && css` - // Hack to have gutters between items without an outer margin - margin: calc(${props.gapsBoth} / -2); +const gapsBothSystem = system({ + gapsBoth: { + property: "margin", + scale: "space", + transform: (value, scale) => `calc(${get(scale, value, value)} / -2)` + } +}); - & > * { - margin: calc(${props.gapsBoth} / 2); - } - `} -`; -const StyledFlexItem = styled.div` - flex: ${(props) => props.flex || "0 0 auto"}; - align-self: ${(props) => props.alignSelf || "auto"}; - justify-self: ${(props) => props.justifySelf || "auto"}; +const gapsBothItemSystem = system({ + gapsBoth: { + property: "margin", + scale: "space", + transform: (value, scale) => `calc(${get(scale, value, value)} / 2)` + } +}); + +export const Box = styled.div` + ${space} + ${layout} + ${typography} + ${color} + ${flexbox} + + & > :not(:first-child) { + ${gapsAxesSystem} + } + + // Hack to have gutters between items without an outer margin + ${gapsBothSystem} + + & > * { + ${gapsBothItemSystem} + } `; -export default function Flex({ children, ...props }) { - return ( - - {children} - - ); -} +export const Flex = styled(Box)` + display: ${(props) => props.flexInline ? "inline-flex" : "flex"}; +`; -export function FlexItem({ children, ...props }) { - return ( - - {children} - - ); -} +export const Grid = styled(Box)` + display: ${(props) => props.gridInline ? "inline-grid" : "grid"}; + + ${grid} +`; diff --git a/src/components/layout/index.js b/src/components/layout/index.js index ce63353..a048d47 100644 --- a/src/components/layout/index.js +++ b/src/components/layout/index.js @@ -28,18 +28,19 @@ export default function Layout({ children, data }) { + + {currentVideo && ( + + )} - {currentVideo && ( - - )} {children} diff --git a/src/components/navigation/index.js b/src/components/navigation/index.js index b70b5ba..1e6e223 100644 --- a/src/components/navigation/index.js +++ b/src/components/navigation/index.js @@ -36,6 +36,13 @@ export default function Navigation() { window.localStorage.setItem("theme", newTheme); } + function submitSearch() { + navigate(`/search?q=${quickSearchQuery}`); + + // Hide navigation after user submits search so the user can see the results. + setShow(false); + } + return ( <> setShow(false)}> @@ -48,7 +55,7 @@ export default function Navigation() { navigate(`/search?q=${quickSearchQuery}`)} + onSubmit={submitSearch} /> {/* Other links */} diff --git a/src/components/navigation/season.js b/src/components/navigation/season.js index 3238817..a45de1e 100644 --- a/src/components/navigation/season.js +++ b/src/components/navigation/season.js @@ -1,11 +1,11 @@ -import Flex from "components/flex"; +import { Flex } from "components/flex"; import Switcher from "components/switcher"; import Button from "components/button"; import React from "react"; export default function SeasonNavigation({ year, season, seasonList }) { return ( - + {seasonList.map((availableSeason) => ( diff --git a/src/components/navigation/year.js b/src/components/navigation/year.js index 5084c5c..179f8b2 100644 --- a/src/components/navigation/year.js +++ b/src/components/navigation/year.js @@ -2,7 +2,7 @@ import {graphql, Link, useStaticQuery} from "gatsby"; import Button from "components/button"; import Title from "components/text/title"; import styled from "styled-components"; -import Flex from "components/flex"; +import { Flex } from "components/flex"; const StyledYear = styled.div` flex: 1; @@ -33,7 +33,7 @@ export default function YearNavigation({ year }) { const nextYear = yearList.indexOf(year) < yearList.length - 1 ? yearList[yearList.indexOf(year) + 1] : null; return ( - + {previousYear && ( diff --git a/src/components/search/global.js b/src/components/search/global.js index b4b0304..9179d50 100644 --- a/src/components/search/global.js +++ b/src/components/search/global.js @@ -9,7 +9,7 @@ import Button from "components/button"; import Text from "components/text"; import Title from "components/text/title"; import ArtistSearchResultCard from "components/card/searchResult/artist"; -import Flex from "components/flex"; +import { Box, Flex } from "components/flex"; export default function GlobalSearch({ searchQuery, searchEntity }) { const [ results, isSearching ] = useSearch(searchQuery); @@ -31,16 +31,16 @@ export default function GlobalSearch({ searchQuery, searchEntity }) { } return ( - No results found for query "{searchQuery}". Did you spell it correctly? + No results found for query "{searchQuery}". Did you spell it correctly? ); } return ( - + - + ); } @@ -72,18 +72,18 @@ function EntitySearch({ searchEntity, entity, title, results }) { }); return ( - + {!searchEntity && ( {title} )} {resultCards} {!searchEntity && totalResults > 3 && ( - + )} - + ); } diff --git a/src/components/switcher/index.js b/src/components/switcher/index.js index 9cfce90..b49e9b0 100644 --- a/src/components/switcher/index.js +++ b/src/components/switcher/index.js @@ -1,17 +1,15 @@ import React from "react"; import styled from "styled-components"; import elevatedPrimaryBackground from "styles/helper"; -import {gapsRow} from "styles/mixins"; - -const StyledSwitcher = styled.div` - display: flex; - flex-direction: row; +import { Flex } from "components/flex"; +const StyledSwitcher = styled(Flex).attrs({ + flexInline: true, + gapsRow: "0.5rem" +})` background-color: ${elevatedPrimaryBackground}; border-radius: 1rem; - - ${gapsRow("0.5rem")} `; export default function Switcher({ children, ...props }) { diff --git a/src/components/switcher/theme.js b/src/components/switcher/theme.js index 74eef49..8af91ef 100644 --- a/src/components/switcher/theme.js +++ b/src/components/switcher/theme.js @@ -1,6 +1,6 @@ import React, {useMemo, useState} from "react"; import ThemeCard from "components/card/theme"; -import Flex, {FlexItem} from "components/flex"; +import { Box } from "components/flex"; import Button from "components/button"; import Switcher from "components/switcher"; @@ -21,25 +21,23 @@ export default function ThemeSwitcher({ themes }) { const [activeGroup, setActiveGroup] = useState(groups[0]); return ( - + {groups.length > 1 && ( - - - {groups.map((group) => ( - - ))} - - + + {groups.map((group) => ( + + ))} + )} {activeGroup.themes.map((theme, index) => ( ))} - + ); } diff --git a/src/components/text/style.js b/src/components/text/style.js index 46df26b..9bf7150 100644 --- a/src/components/text/style.js +++ b/src/components/text/style.js @@ -29,6 +29,12 @@ export const StyledTextBase = styled.span.attrs((props) => ({ -webkit-box-orient: vertical; overflow: hidden; `} + + ${(props) => props.truncate && css` + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + `} ${(props) => props.code && css` font-family: monospace; diff --git a/src/components/utils/songTitleWithArtists.js b/src/components/utils/songTitleWithArtists.js index ae86b7f..8c97f43 100644 --- a/src/components/utils/songTitleWithArtists.js +++ b/src/components/utils/songTitleWithArtists.js @@ -1,18 +1,28 @@ -import Text from "components/text"; +import {Fragment} from "react"; import {Link} from "gatsby"; import theme from "theme"; +import Text from "components/text"; -export default function SongTitleWithArtists({ song }) { +export default function SongTitleWithArtists({ song, songTitleLinkTo }) { return ( - <> - {song.title} + + {songTitleLinkTo + ? ( + + {song.title} + + ) + : ( + {song.title} + ) + } {!!song.performances && !!song.performances.length && ( <> by {song.performances.map((performance, index) => ( - <> + - + {performance.as || performance.artist.name} @@ -21,10 +31,10 @@ export default function SongTitleWithArtists({ song }) { {index === song.performances.length - 2 ? " & " : ", "} )} - + ))} )} - + ); } diff --git a/src/components/utils/themeEntryTags.js b/src/components/utils/themeEntryTags.js index d6dc66a..00b9eda 100644 --- a/src/components/utils/themeEntryTags.js +++ b/src/components/utils/themeEntryTags.js @@ -1,11 +1,11 @@ import Tag from "components/tag"; import {faBomb, faExclamationTriangle, faFilm} from "@fortawesome/free-solid-svg-icons"; -import Flex from "components/flex"; +import { Flex } from "components/flex"; import React from "react"; export default function ThemeEntryTags({ entry }) { return ( - + {entry.episodes || "—"} diff --git a/src/components/utils/videoTags.js b/src/components/utils/videoTags.js index ebc00ff..5a2487d 100644 --- a/src/components/utils/videoTags.js +++ b/src/components/utils/videoTags.js @@ -7,11 +7,11 @@ import { faStream } from "@fortawesome/free-solid-svg-icons"; import Tag from "components/tag"; -import Flex from "components/flex"; +import { Flex } from "components/flex"; export default function VideoTags({ video }) { return ( - + {video.resolution}p diff --git a/src/components/videoPlayer/index.js b/src/components/videoPlayer/index.js index c638ea1..b3591aa 100644 --- a/src/components/videoPlayer/index.js +++ b/src/components/videoPlayer/index.js @@ -2,40 +2,38 @@ import React, {useContext, useRef, useState} from "react"; import styled, {css} from "styled-components"; import {motion} from "framer-motion"; import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"; -import {faExpand, faPause, faPlay, faTimes} from "@fortawesome/free-solid-svg-icons"; +import { faExpandAlt, faPause, faPlay, faTimes } from "@fortawesome/free-solid-svg-icons"; import Button from "components/button"; import {gapsRow} from "styles/mixins"; import {navigate} from "gatsby"; import PlayerContext from "context/playerContext"; -import elevatedPrimaryBackground from "styles/helper"; import Elevator from "components/elevator"; import createVideoSlug from "utils/createVideoSlug"; +import { useMedia } from "react-media"; const videoBaseUrl = process.env.GATSBY_VIDEO_URL || "https://animethemes.moe"; const StyledPlayer = styled.div` ${(props) => props.background ? css` position: fixed; - width: calc((100vw - 1100px) / 2 - 2rem); + width: 352px; bottom: 1rem; left: 1rem; z-index: 10; - - @media (max-width: 1600px) { - width: calc(100% - 2rem); - max-width: 400px; - right: 1rem; - border-left: 4px solid ${(props) => props.theme.colors.secondaryTitle}; - border-radius: 0 0.5rem 0.5rem 0; - background-color: ${elevatedPrimaryBackground}; - box-shadow: 0 0 20px rgb(0, 0, 0); - - display: flex; - flex-direction: row; + @media (max-width: 720px) { + width: calc(50vw - 2rem); } ` : css` - margin-bottom: 2rem; + @media (max-width: 720px) and (orientation: portrait) { + position: sticky; + top: 0; + } + @media (min-width: 721px) { + margin: 0 auto; + padding: 1.5rem 1rem 0 1rem; + max-width: 1100px; + } `} `; const StyledVideoContainer = styled(motion.div)` @@ -45,12 +43,6 @@ const StyledVideoContainer = styled(motion.div)` width: 100%; height: 0; padding-top: 56.25%; - - @media (max-width: 1600px) { - ${(props) => props.background && css` - padding-top: calc(56.25% / 3); - `} - } `; const StyledVideo = styled.video` outline: none; @@ -72,20 +64,22 @@ const StyledOverlay = styled(motion.div)` ${gapsRow("0.5rem")} - @media (min-width: 1601px) { - position: absolute; - width: 100%; - height: 100%; - top: 0; - left: 0; - z-index: 20; + position: absolute; + width: 100%; + height: 100%; + top: 0; + left: 0; + z-index: 20; - opacity: ${(props) => props.force ? 1 : 0}; - transition: 250ms opacity; - - &:hover { - opacity: 1; - } + opacity: ${(props) => props.force ? 1 : 0}; + transition: 250ms opacity; + + &:hover { + opacity: 1; + } + + @media (max-width: 720px) { + display: none; } `; const StyledPlayerButton = styled(Button)` @@ -95,18 +89,10 @@ const StyledPlayerButton = styled(Button)` font-size: ${(props) => props.size || "1rem"}; color: ${(props) => props.theme.colors.primaryTitle}; - @media (min-width: 1601px) { - background-color: ${(props) => props.theme.colors.primaryTransparent}; + background-color: ${(props) => props.theme.colors.primaryTransparent}; - &:hover { - background-color: ${(props) => props.theme.colors.primaryBackground[0]}; - } - } - - @media (max-width: 1600px) { - padding: 0.5rem; - - font-size: calc(${(props) => props.size || "1rem"} * 0.75); + &:hover { + background-color: ${(props) => props.theme.colors.primaryBackground[0]}; } `; @@ -114,6 +100,7 @@ export default function VideoPlayer({ video, entry, background, ...props }) { const [ isPlaying, setPlaying ] = useState(false); const playerRef = useRef(); const { setCurrentVideo } = useContext(PlayerContext); + const isMobile = useMedia({ query: "(max-width: 720px)" }); function togglePlay() { if (isPlaying) { @@ -136,8 +123,18 @@ export default function VideoPlayer({ video, entry, background, ...props }) { return ( - - + + setPlaying(false)} onEnded={() => setPlaying(false)} > - Your browser doesn't support HTML5 video playback. Please use a modern browser. + Your browser doesn't support HTML5 video playback. Please use a modern browser. {background && ( @@ -160,7 +157,7 @@ export default function VideoPlayer({ video, entry, background, ...props }) { - + diff --git a/src/pages/index.js b/src/pages/index.js index 1d3c473..c2abb32 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -5,24 +5,13 @@ import styled from "styled-components"; import {gapsColumn} from "styles/mixins"; import Card from "components/card"; import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"; -import {faDesktop, faInfo, faMobileAlt} from "@fortawesome/free-solid-svg-icons"; -import Flex from "components/flex"; -import Tag from "components/tag"; -import {useMedia} from "react-media"; +import {faInfo} from "@fortawesome/free-solid-svg-icons"; +import { Box, Flex, Grid } from "components/flex"; +import theme from "theme"; const StyledIndexPage = styled.div` ${gapsColumn("1.5rem")} `; -const StyledPageGrid = styled.div` - display: grid; - grid-template-columns: auto 1fr auto auto; - grid-gap: 1rem; - align-items: center; - - @media (max-width: 720px) { - grid-template-columns: 1fr; - } -`; const StyledAnnouncement = styled(Text)` & a { color: ${(props) => props.theme.colors.secondaryTitle}; @@ -55,7 +44,7 @@ export default function IndexPage({ data: { allAnnouncement } }) { These are for demo purposes only. The content may not be accurate. {allAnnouncement.nodes.map((announcement) => ( - + @@ -66,55 +55,69 @@ export default function IndexPage({ data: { allAnnouncement } }) { )} Pages - + + - + {!!process.env.GATSBY_CI && ( <> GitHub Pages @@ -123,7 +126,7 @@ export default function IndexPage({ data: { allAnnouncement } }) { animethemes-web repository this site gets updated. This also comes with some limitations like .htaccess - files not working. So don't expect everything on this site to work the same way as on the production site. + files not working. So don't expect everything on this site to work the same way as on the production site. )} @@ -131,33 +134,36 @@ export default function IndexPage({ data: { allAnnouncement } }) { ); } -function PageGridItem({ path, description, desktop, mobile, children }) { - const isMobile = useMedia({ query: "(max-width: 720px)" }); - +function PageGridItem({ path, otherPaths = {}, description }) { return ( - <> - - {path} - - {description || children} - {desktop ? ( - - {isMobile && "Compatible with desktop devices"} - - ) : } - {mobile ? ( - - {isMobile && "Compatible with mobile devices"} - - ) : } - + + + {description} + {Object.entries(otherPaths).map(([path, description]) => ( + <> + + {description} + + ))} + ); } +function PageLink({ path }) { + return ( + + + {path} + + + ) +} + export const query = graphql` query IndexPageQuery { allAnnouncement { nodes { + id content } totalCount diff --git a/src/pages/search.js b/src/pages/search.js index ebe1565..ee0e331 100644 --- a/src/pages/search.js +++ b/src/pages/search.js @@ -6,7 +6,7 @@ import SearchInput from "components/input/search"; import GlobalSearch from "components/search/global"; import {gapsColumn, gapsRow} from "styles/mixins"; import Title from "components/text/title"; -import Flex, {FlexItem} from "components/flex"; +import { Box, Flex } from "components/flex"; import Switcher from "components/switcher"; import Button from "components/button"; import SEO from "components/seo"; @@ -68,9 +68,9 @@ export default function SearchPage({ location: { pathname, search, hash } }) { Search - + - + {!!entity && ( diff --git a/src/theme/index.js b/src/theme/index.js index c5bba96..b3ed55b 100644 --- a/src/theme/index.js +++ b/src/theme/index.js @@ -1,4 +1,5 @@ const theme = { + breakpoints: ["721px"], colors: { primaryBackground: [ createColor("--primary-background-0", { diff --git a/src/utils/transientProps.js b/src/utils/transientProps.js new file mode 100644 index 0000000..c2c7efb --- /dev/null +++ b/src/utils/transientProps.js @@ -0,0 +1,15 @@ +export default function transientProps(props, filterNonStandard = true) { + return { + shouldForwardProp: (prop, defaultValidator) => { + if (props.includes(prop)) { + return false; + } + + if (filterNonStandard) { + return defaultValidator(prop) + } + + return true; + } + }; +}