Skip to content

Commit

Permalink
Revisit menu and close icons (#149)
Browse files Browse the repository at this point in the history
* setup `@svgr/webpack` to be able to style SVGs and optimize them

* rework Menu and Close icon buttons to use icons from the designs

* remove `react-icons` as it's unused now
  • Loading branch information
rtrembecky authored Aug 7, 2023
1 parent ac473cd commit 001a0de
Show file tree
Hide file tree
Showing 20 changed files with 2,322 additions and 155 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ module.exports = {
'security/detect-object-injection': 'off',

// Improve regexes by making them shorter, more consistent, and safer
'require-unicode-regexp': 'warn',
// 'require-unicode-regexp': 'warn',
'unicorn/better-regex': 'warn',
'unicorn/no-unsafe-regex': 'warn',

Expand Down
26 changes: 26 additions & 0 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,30 @@ module.exports = {
transform: '@mui/material/{{member}}',
},
},
// https://react-svgr.com/docs/next/
webpack(config) {
// Grab the existing rule that handles SVG imports
const fileLoaderRule = config.module.rules.find((rule) => rule.test?.test?.('.svg'))

config.module.rules.push(
// Reapply the existing rule, but only for svg imports ending in ?url
{
...fileLoaderRule,
test: /\.svg$/i,
resourceQuery: /url/, // *.svg?url
},
// Convert all other *.svg imports to React components
{
test: /\.svg$/i,
issuer: /\.[jt]sx?$/,
resourceQuery: {not: /url/}, // exclude if *.svg?url
use: ['@svgr/webpack'],
},
)

// Modify the file loader rule to ignore *.svg, since we have it handled now.
fileLoaderRule.exclude = /\.svg$/i

return config
},
}
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
"name": "webstrom-frontend",
"version": "0.1.0",
"private": true,
"engines": {
"node": ">=16.0.0"
},
"scripts": {
"dev": "next dev",
"start": "next start",
Expand Down Expand Up @@ -35,7 +38,6 @@
"react-dom": "^18.2.0",
"react-dropzone": "^14.2.3",
"react-hook-form": "^7.43.9",
"react-icons": "^3.11.0",
"react-markdown": "^8.0.7",
"rehype-katex": "^6.0.3",
"remark-gfm": "^3.0.1",
Expand All @@ -44,6 +46,7 @@
"unstated-next": "^1.1.0"
},
"devDependencies": {
"@svgr/webpack": "^8.0.1",
"@testing-library/dom": "^9.2.0",
"@types/jest": "^29.5.1",
"@types/katex": "^0",
Expand Down
27 changes: 27 additions & 0 deletions src/components/CloseButton/CloseButton.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.closeButton {
cursor: pointer;

color: white;
background-color: black;

&.active,
&:hover {
color: black;
background-color: white;
}
}
.invertColors {
color: black;
background-color: white;

&.active,
&:hover {
color: white;
background-color: black;
}
}

.alignRight {
position: absolute;
right: 12px;
}
12 changes: 12 additions & 0 deletions src/components/CloseButton/CloseButton.module.scss.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export type Styles = {
active: string
alignRight: string
closeButton: string
invertColors: string
}

export type ClassNames = keyof Styles

declare const styles: Styles

export default styles
30 changes: 11 additions & 19 deletions src/components/CloseButton/CloseButton.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,21 @@
import {Close} from '@mui/icons-material'
import clsx from 'clsx'
import {FC} from 'react'

import Close from '@/svg/close.svg'

import styles from './CloseButton.module.scss'

interface CloseButtonProps {
onClick: () => void
size?: number
alignRight?: boolean
size: number
invertColors?: boolean
className?: string
}

export const CloseButton: FC<CloseButtonProps> = ({onClick, size, alignRight, invertColors}) => {
export const CloseButton: FC<CloseButtonProps> = ({onClick, size, invertColors, className}) => {
return (
<Close
sx={[
{
fontSize: size,
cursor: 'pointer',
color: !invertColors ? 'white' : 'black',
'active, :hover': {
color: !invertColors ? 'black' : 'white',
backgroundColor: !invertColors ? 'white' : 'black',
},
},
!!alignRight && {position: 'absolute', right: '8px'},
]}
onClick={onClick}
/>
<div className={clsx(styles.closeButton, invertColors && styles.invertColors, className)} onClick={onClick}>
<Close width={size} height={size} />
</div>
)
}
43 changes: 30 additions & 13 deletions src/components/PageLayout/MenuMain/MenuMain.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,45 @@
}
}

.menuOpenButton {
.menuButton {
cursor: pointer;
height: 50px;
width: 50px;
font-size: 2.5rem;
display: grid;
place-items: center;
color: black;
// buttons taking top-left corner of the screen
}

.menuOpenButton {
// button taking top-left corner of the whole screen
position: fixed;
top: 0;
left: 0;
top: 50px;
left: 50px;
// index high enough to cover the background, but menu rolls over it
z-index: 5;

// more space around icon looks better on hover
padding: 7.5px;

color: black;
background-color: white;

&.active,
&:hover {
color: white;
background-color: black;
}
}

.menuOpenButton.active,
.menuOpenButton:hover {
color: white;
background-color: black;
.menuCloseButton {
// button taking top-left corner of the rolling menu
position: absolute;
top: 50px;
left: 50px;

// less space around X is enough for hover to look good
padding: 2.5px;
}

.menuItems {
margin-top: 80px;
margin-top: 176px;
}

.loading {
Expand Down
2 changes: 2 additions & 0 deletions src/components/PageLayout/MenuMain/MenuMain.module.scss.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ export type Styles = {
active: string
loading: string
menu: string
menuButton: string
menuCloseButton: string
menuItem: string
menuItems: string
menuOpenButton: string
Expand Down
35 changes: 20 additions & 15 deletions src/components/PageLayout/MenuMain/MenuMain.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import clsx from 'clsx'
import Link from 'next/link'
import {useRouter} from 'next/router'
import {FC, useState} from 'react'
import * as FaIcons from 'react-icons/fa'

import {CloseButton} from '@/components/CloseButton/CloseButton'
import {Loading} from '@/components/Loading/Loading'
import Menu from '@/svg/menu.svg'
import {useSeminarInfo} from '@/utils/useSeminarInfo'

import {Authentication} from '../Authentication/Authentication'
Expand All @@ -32,23 +32,28 @@ export const MenuMain: FC = () => {
const menuItems = menuItemsData?.data ?? []

return (
<div className={clsx(styles.menu, isVisible && styles.visible)}>
<div className={styles.menuOpenButton}>
{isVisible ? <CloseButton onClick={toggleMenu} size={50} /> : <FaIcons.FaBars onClick={toggleMenu} />}
</div>
{menuItemsIsLoading && (
<div className={styles.loading}>
<Loading />
<>
{!isVisible && (
<div className={clsx(styles.menuButton, styles.menuOpenButton)} onClick={toggleMenu}>
<Menu width={40} height={40} />
</div>
)}
<div className={styles.menuItems}>
{menuItems.map((menuItem: MenuItemInterface) => {
// `menuItem.url` je vo formate `/vysledky/` alebo `/akcie/matboj/`
return <MenuMainItem key={menuItem.id} caption={menuItem.caption} url={`/${seminar}${menuItem.url}`} />
})}
<div className={clsx(styles.menu, isVisible && styles.visible)}>
<CloseButton size={40} onClick={toggleMenu} className={clsx(styles.menuButton, styles.menuCloseButton)} />
{menuItemsIsLoading && (
<div className={styles.loading}>
<Loading />
</div>
)}
<div className={styles.menuItems}>
{menuItems.map((menuItem: MenuItemInterface) => {
// `menuItem.url` je vo formate `/vysledky/` alebo `/akcie/matboj/`
return <MenuMainItem key={menuItem.id} caption={menuItem.caption} url={`/${seminar}${menuItem.url}`} />
})}
</div>
<Authentication />
</div>
<Authentication />
</div>
</>
)
}

Expand Down
7 changes: 6 additions & 1 deletion src/components/Problems/SideContainer.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,9 @@
display: flex;
justify-content: center;
align-items: center;
}
}

.closeButton {
position: absolute;
right: 12px;
}
1 change: 1 addition & 0 deletions src/components/Problems/SideContainer.module.scss.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export type Styles = {
closeButton: string
container: string
title: string
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/Problems/SideContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const SideContainer: FC<{title: string; children: ReactNode; onClose: ()
return (
<aside className={styles.container}>
<div className={styles.title}>
<CloseButton onClick={onClose} alignRight />
<CloseButton onClick={onClose} size={24} className={styles.closeButton} />
<span>{title}</span>
</div>
{children}
Expand Down
5 changes: 5 additions & 0 deletions src/components/Problems/UploadProblemForm.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,8 @@
justify-content: flex-end;
column-gap: 20px;
}

.closeButton {
position: absolute;
right: 0;
}
1 change: 1 addition & 0 deletions src/components/Problems/UploadProblemForm.module.scss.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export type Styles = {
actions: string
bottomAction: string
closeButton: string
container: string
files: string
problemSubmitted: string
Expand Down
2 changes: 1 addition & 1 deletion src/components/Problems/UploadProblemForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export const UploadProblemForm: FC<{

return (
<div className={styles.container}>
<CloseButton onClick={handleCloseButton} alignRight invertColors />
<CloseButton onClick={handleCloseButton} size={24} invertColors className={styles.closeButton} />
{problemSubmitted && (
<div className={styles.problemSubmitted}>
Pozor, nahraním nového riešenia prepíšeš svoje predošlé odovzdanie.
Expand Down
4 changes: 4 additions & 0 deletions src/svg/close.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions src/svg/menu.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 18 additions & 0 deletions svgo.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// config for SVGO as part of @svgr/webpack
// - https://github.com/svg/svgo/blob/main/README.md#configuration
// adds back the viewBox attribute to SVGs
// - problem acknowledged here: https://github.com/svg/svgo#svg-wont-scale-when-css-is-applied-on-it
// - loong discussion on the topic here: https://github.com/svg/svgo/issues/1128
// - tl;dr: using viewBox with width/height allows for scaling the SVGs
module.exports = {
plugins: [
{
name: 'preset-default',
params: {
overrides: {
removeViewBox: false,
},
},
},
],
}
15 changes: 1 addition & 14 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,7 @@
"jsx": "preserve",
"noFallthroughCasesInSwitch": true,
"baseUrl": ".",
"paths": {
"@/components/*": [
"src/components/*"
],
"@/pages/*": [
"src/pages/*"
],
"@/types/*": [
"src/types/*"
],
"@/utils/*": [
"src/utils/*"
]
},
"paths": {"@/*": ["src/*"]},
"incremental": true
},
"include": [
Expand Down
Loading

0 comments on commit 001a0de

Please sign in to comment.