Creating a Book Community - 3. Main Page Production - 1
- web
- study
- react
1. Installing styled-components
Instead of using plain CSS, we will use the styled-components library, which should be installed inside the client folder.
npm install styled-components
To check if everything works well, I copied the Button code from the styled-components official documentation and tried adding it to the main page.
import React from 'react';
import styled from 'styled-components';
const MyButton = styled.button`
background: transparent;
border-radius: 3px;
border: 2px solid palevioletred;
color: palevioletred;
margin: 0 1em;
padding: 0.25em 1em;
`;
function MainPage() {
return (
<MyButton>Example Button</MyButton>
);
}
export default MainPage;
The example button is displayed correctly. Now, let's start creating the elements for the main page.
2. Site Logo
The text for the site logo was created based on the idea of our project team member, Hanul (https://github.com/hamuneulbo). We decided to write "Reviewary - Your and My Review Library" on the logo. Since we are currently in the early phase of just shaping the page, I created it fairly simply.
const HeaderMainLogo = styled.h1`
font-size: 3rem;
margin: 3px;
`;
const HeaderSubLogo = styled.h2`
font-size: 1.5rem;
margin: 0;
`;
function HeaderLogo() {
return (
<>
<HeaderMainLogo>Reviewary</HeaderMainLogo>
<HeaderSubLogo>Your and My Review Library</HeaderSubLogo>
</>
);
}
While not particularly impressive, a reasonably sized logo has been added to the site.
After creating the logo, I separated the logo component into src/common/HeaderLogo.js
as it is expected to be reused on most pages.
3. Creating Containers
I created simple containers that will likely be used frequently. To make them quickly, I designed these containers to use display: flex
to determine whether to align the internal elements horizontally or vertically. Features like element alignment will be added later.
/* src/common/HorizontalContainer.js */
import styled from 'styled-components';
const HorizontalContainer = styled.div`
display: flex;
flex-direction: row;
`;
export default HorizontalContainer;
/* src/common/VerticalContainer.js */
import styled from 'styled-components';
const VerticalContainer = styled.div`
display: flex;
flex-direction: column;
`;
export default VerticalContainer;
Using this, I modified the logo so that HeaderMainLogo
and HeaderSubLogo
are arranged vertically.
/* src/common/HeaderLogo.js part */
function HeaderLogo() {
return (
<VerticalContainer>
<HeaderMainLogo>Reviewary</HeaderMainLogo>
<HeaderSubLogo>Your and My Review Library</HeaderSubLogo>
</VerticalContainer>
);
}
4. Menu
I decided to create a common dropdown menu. The reference documents used while creating the dropdown menu are noted below. The DropDown Menu 2
document was used as a reference to implement the DropDownMenuHeader
component, which expresses the header of the dropdown menu similarly.
const DropDownMenuHeader = styled.div`
font-weight: 500;
font-size: 1.3rem;
background: #ffffff;
height: 1.8rem;
width: 9rem;
`;
Next, I created the DropDownMenuContainer
, which will hold the submenus that appear when the dropdown menu is activated.
const DropDownMenuContainer = styled.div`
color: #000000;
width: 10rem;
margin: 0 auto;
`;
Then, I created the DropDownMenuList
, which is a ul
element that contains the dropdown list items.
const DropDownMenuList = styled.ul`
padding: 0;
margin: 0;
background: #ffffff;
border: 2px solid #000000;
box-sizing: border-box;
color: #000000;
font-size: 1.3rem;
font-weight: 500;
&:first-child {
padding-top: 0.8rem;
}
`;
const DropDownListItem = styled.li`
list-style: none;
margin-bottom: 0.8rem;
`;
Finally, I created the DropDownMenu
component that combines all of these elements. While handling dropdown menu interactions, I created a selectedMenu
state to keep track of which menu item has been selected and used the onClick
event to set that menu item as selected upon clicking.
Such interactions will later be replaced by actions like navigating to a specific board or page when selecting a dropdown menu item.
As multiple dropdown menus will be created, the header name and item names of the dropdown menu can be passed as strings and arrays, respectively. The key in the array's map
function is simply the item itself (key={item}
), as board names typically do not overlap. If there ever comes a case where dropdown menu items have overlapping names, it would be advisable to make the items in the array (here called dropDownItemList
) objects and assign each an id
.
function DropDownMenu({ menuName, dropDownItemList }) {
const [selectedMenu, setSelectedMenu] = useState(null);
const onOptionSelected = (value) => () => {
setSelectedMenu(value);
};
return (
<VerticalContainer>
<DropDownMenuHeader>{menuName}</DropDownMenuHeader>
<DropDownMenuContainer>
<DropDownMenuList>
{dropDownItemList.map((item) => (
<DropDownListItem
onClick={onOptionSelected(item)}
key={item}
>
{item}
</DropDownListItem>
))}
</DropDownMenuList>
</DropDownMenuContainer>
</VerticalContainer>
);
}
Now let's make the dropdown menu functional. The reference document demonstrates having the menu items appear when clicking the header. However, it's more common on websites for the dropdown menu items to be displayed when hovering over the dropdown menu header.
Thus, let’s implement this using CSS. It is not too difficult. Initially, the DropDownMenuContainer
containing the submenu items would be displayed continuously. We will configure it to be hidden in the normal state and to be visible only upon hovering. Now, the DropDownMenuContainer
will be visible as long as the mouse hovers over it.
const DropDownMenuContainer = styled.div`
display: none;
color: #000000;
width: 10rem;
margin: 0 auto;
&:hover {
display: block;
}
`;
However, if the DropDownMenuContainer
is not rendered in the first place, hovering over this container element will not be possible. Following the conventional dropdown menu pattern, we will ensure that DropDownMenuContainer
renders when the mouse hovers over the dropdown menu header. To achieve this, we used the +
selector appropriately, to only show the DropDownMenuContainer
that is a sibling of DropDownMenuHeader
. This selection method was shared by Chang-hee Lee (https://xo.dev/). I felt a need to review CSS as I vaguely remembered such selectors from my initial learning.
const DropDownMenuHeader = styled.div`
margin: 0;
padding: 1rem;
font-weight: 500;
font-size: 1.3rem;
background: #ffffff;
height: 1.8rem;
width: 9rem;
&:hover + ${DropDownMenuContainer} {
display: block;
}
`;
If there is any gap between the header and the menu items, a hover state might be interrupted (as the mouse cursor would exit the menu items while passing over the gap), causing the dropdown menu items to become unclickable. Therefore, I have set all margins of the dropdown menu items to 0. If visual spacing is necessary, padding can be utilized instead (margin controls spacing outside the element, while padding controls spacing inside the element).
Now, upon passing appropriate name strings and item arrays as props, the dropdown menu will render and function correctly.
I will also create a DropDownMenu.js
file in the src/common
folder to separate the dropdown menu.
5. Implementing Carousel
I initially searched for the term "slider menu" to describe a menu where images slide sideways to display information, but I later learned that it is called a carousel. I believe having a carousel on the site we are developing would be beneficial, so I decided to implement one on the main page.
I downloaded some images suitable for the carousel slides from Pixabay (https://pixabay.com/), obtaining images of various sizes. I also sourced book cover images from bookstore websites. Book cover images are typically longer vertically and are not common unless they pertain to books.
6. References
styled-components official documentation https://styled-components.com/
Creating dropdown menus https://programming-oddments.tistory.com/177
Dropdown Menu 2 https://andela.com/insights/react-js-tutorial-on-creating-a-custom-select-dropdown/
CSS flex https://studiomeal.com/archives/197
CSS selector https://poiemaweb.com/css3-selector
Various methods to implement a carousel https://programming119.tistory.com/211
Implementing a carousel using React hooks https://velog.io/@peppermint100/JSReact-Hooks%EB%A1%9C-Carousel-Slider-%EB%A7%8C%EB%93%A4%EA%B8%B0
Creating arrow-shaped buttons https://www.w3schools.com/howto/howto_css_arrows.asp