Refactor CSS pt. 3 (semantically @extend Bootstrap)

This commit is contained in:
riggraz
2019-09-16 12:22:30 +02:00
parent 8d297a897e
commit 41795ce963
16 changed files with 199 additions and 70 deletions

View File

@@ -74,7 +74,7 @@ class BoardP extends React.Component<Props> {
const { filters } = posts; const { filters } = posts;
return ( return (
<div className="boardContainer d-flex justify-content-between align-items-start"> <div className="boardContainer">
<div className="sidebar"> <div className="sidebar">
<NewPost <NewPost
board={board} board={board}

View File

@@ -8,6 +8,7 @@ import {
DangerText, DangerText,
SuccessText, SuccessText,
} from '../shared/CustomTexts'; } from '../shared/CustomTexts';
import Button from '../shared/Button';
import IBoard from '../../interfaces/IBoard'; import IBoard from '../../interfaces/IBoard';
@@ -145,11 +146,12 @@ class NewPost extends React.Component<Props, State> {
<MutedText>{board.description}</MutedText> <MutedText>{board.description}</MutedText>
{ {
isLoggedIn ? isLoggedIn ?
<button <Button
onClick={this.toggleForm} onClick={this.toggleForm}
className={`submitBtn btn btn-${showForm ? 'outline-' : ''}dark my-2`}> className="submitBtn"
outline={showForm}>
{ showForm ? 'Cancel' : 'Submit feedback' } { showForm ? 'Cancel' : 'Submit feedback' }
</button> </Button>
: :
<a href="/users/sign_in" className="btn btn-dark"> <a href="/users/sign_in" className="btn btn-dark">
Log in / Sign up Log in / Sign up

View File

@@ -1,5 +1,7 @@
import * as React from 'react'; import * as React from 'react';
import Button from '../shared/Button';
interface Props { interface Props {
title: string; title: string;
description: string; description: string;
@@ -41,11 +43,9 @@ const NewPostForm = ({
id="postDescription" id="postDescription"
></textarea> ></textarea>
</div> </div>
<button <Button onClick={e => handleSubmit(e)} className="submitBtn d-block mx-auto">
onClick={e => handleSubmit(e)} Submit feedback
className="submitBtn btn btn-dark d-block mx-auto"> </Button>
Submit feedback
</button>
</form> </form>
</div> </div>
); );

View File

@@ -32,7 +32,7 @@ const PostList = ({
page, page,
hasMore hasMore
}: Props) => ( }: Props) => (
<div className="postList d-flex flex-column flex-grow-1"> <div className="postList">
{ error ? <DangerText>{error}</DangerText> : null } { error ? <DangerText>{error}</DangerText> : null }
<InfiniteScroll <InfiniteScroll
initialLoad={false} initialLoad={false}

View File

@@ -15,11 +15,11 @@ interface Props {
const PostListItem = ({ id, title, description, postStatus}: Props) => ( const PostListItem = ({ id, title, description, postStatus}: Props) => (
<a href={`/posts/${id}`} className="postLink"> <a href={`/posts/${id}`} className="postLink">
<div className="postListItem d-flex flex-column justify-content-between m-0 px-2 py-1"> <div className="postListItem">
<TitleText>{title}</TitleText> <TitleText>{title}</TitleText>
<DescriptionText limit={120}>{description}</DescriptionText> <DescriptionText limit={120}>{description}</DescriptionText>
<div className="postDetails d-flex justify-content-between text-uppercase"> <div className="postDetails">
<CommentsNumber number={0} /> <CommentsNumber number={0} />
{ postStatus ? <PostStatusLabel {...postStatus} /> : null } { postStatus ? <PostStatusLabel {...postStatus} /> : null }
</div> </div>

View File

@@ -1,6 +1,7 @@
import * as React from 'react'; import * as React from 'react';
import PostStatusLabel from '../shared/PostStatusLabel'; import PostStatusLabel from '../shared/PostStatusLabel';
import Button from '../shared/Button';
interface Props { interface Props {
name: string; name: string;
@@ -19,17 +20,18 @@ const PostStatusListItem = ({
handleResetFilter, handleResetFilter,
}: Props) => ( }: Props) => (
<div className={ <div className={
"postStatusListItemContainer " + `postStatus${name.replace(/ /g, '')} d-flex align-self-stretch` "postStatusListItemContainer " + `postStatus${name.replace(/ /g, '')}`
}> }>
<a onClick={handleClick} className="postStatusListItemLink flex-grow-1"> <a onClick={handleClick} className="postStatusListItemLink">
<div className="postStatusListItem p-1"> <div className="postStatusListItem">
<PostStatusLabel id={undefined} name={name} color={color} /> <PostStatusLabel id={undefined} name={name} color={color} />
</div> </div>
</a> </a>
{ {
isCurrentFilter ? isCurrentFilter ?
<button onClick={handleResetFilter} <Button onClick={handleResetFilter} className="resetFilter" outline>
className="resetFilter btn btn-outline-dark">X</button> X
</Button>
: :
null null
} }

View File

@@ -4,8 +4,6 @@ import { Provider } from 'react-redux';
import Board from '../../containers/Board'; import Board from '../../containers/Board';
import createStoreHelper from '../../helpers/createStore'; import createStoreHelper from '../../helpers/createStore';
import '../../stylesheets/components/Board.scss';
import IBoard from '../../interfaces/IBoard'; import IBoard from '../../interfaces/IBoard';
interface Props { interface Props {

View File

@@ -14,13 +14,13 @@ interface Props {
} }
const PostListByPostStatus = ({ postStatus, posts, boards }: Props) => ( const PostListByPostStatus = ({ postStatus, posts, boards }: Props) => (
<div className="roadmapColumn card my-2 px-2" style={{borderColor: postStatus.color}}> <div className="roadmapColumn" style={{borderColor: postStatus.color}}>
<div className="columnHeader card-header d-flex bg-transparent" <div className="columnHeader"
style={{borderBottomColor: postStatus.color}}> style={{borderBottomColor: postStatus.color}}>
<div className="dot" style={{backgroundColor: postStatus.color}}></div> <div className="dot" style={{backgroundColor: postStatus.color}}></div>
<div className="columnTitle"><TitleText>{postStatus.name}</TitleText></div> <div className="columnTitle"><TitleText>{postStatus.name}</TitleText></div>
</div> </div>
<div className="scrollContainer card-body"> <div className="scrollContainer">
<PostList <PostList
posts={posts} posts={posts}
boards={boards} boards={boards}

View File

@@ -10,7 +10,7 @@ interface Props {
const PostListItem = ({id, title, boardName}: Props) => ( const PostListItem = ({id, title, boardName}: Props) => (
<a href={`/posts/${id}`} className="postLink"> <a href={`/posts/${id}`} className="postLink">
<div className="postListItem d-flex flex-column my-1 py-2"> <div className="postListItem">
<TitleText>{title}</TitleText> <TitleText>{title}</TitleText>
<UppercaseText>{boardName}</UppercaseText> <UppercaseText>{boardName}</UppercaseText>
</div> </div>

View File

@@ -6,8 +6,6 @@ import IPostStatus from '../../interfaces/IPostStatus';
import IPostJSON from '../../interfaces/json/IPost'; import IPostJSON from '../../interfaces/json/IPost';
import IBoard from '../../interfaces/IBoard'; import IBoard from '../../interfaces/IBoard';
import '../../stylesheets/components/Roadmap.scss';
interface Props { interface Props {
postStatuses: Array<IPostStatus>; postStatuses: Array<IPostStatus>;
posts: Array<IPostJSON>; posts: Array<IPostJSON>;
@@ -19,7 +17,7 @@ class Roadmap extends React.Component<Props> {
const { postStatuses, posts, boards } = this.props; const { postStatuses, posts, boards } = this.props;
return ( return (
<div className="roadmapColumns d-flex justify-content-between flex-wrap"> <div className="roadmapColumns">
{postStatuses.map((postStatus, i) => ( {postStatuses.map((postStatus, i) => (
<PostListByPostStatus <PostListByPostStatus
postStatus={postStatus} postStatus={postStatus}

View File

@@ -0,0 +1,20 @@
import * as React from 'react';
import { FormEvent } from 'react';
interface Props {
children: string;
onClick(e: FormEvent): void;
className?: string;
outline?: boolean;
}
const Button = ({ children, onClick, className = '', outline = false}: Props) => (
<button
onClick={onClick}
className={`${className} btn btn-${outline ? 'outline-' : ''}dark my-2`}
>
{children}
</button>
);
export default Button;

View File

@@ -10,27 +10,27 @@ interface DescriptionTextProps {
} }
export const TitleText = ({ children }: Props) => ( export const TitleText = ({ children }: Props) => (
<span className="text-dark font-weight-bolder">{children}</span> <span className="titleText">{children}</span>
); );
export const MutedText = ({ children }: Props) => ( export const MutedText = ({ children }: Props) => (
<span className="text-muted text-center">{children}</span> <span className="mutedText">{children}</span>
); );
export const UppercaseText = ({ children }: Props) => ( export const UppercaseText = ({ children }: Props) => (
<span className="text-secondary text-uppercase font-weight-lighter">{children}</span> <span className="uppercaseText">{children}</span>
); );
export const SuccessText = ({ children }: Props) => ( export const SuccessText = ({ children }: Props) => (
<span className="text-success text-center">{children}</span> <span className="successText">{children}</span>
); );
export const DangerText = ({ children }: Props) => ( export const DangerText = ({ children }: Props) => (
<span className="text-danger text-center">{children}</span> <span className="dangerText">{children}</span>
); );
export const DescriptionText = ({ children, limit = 90}: DescriptionTextProps) => ( export const DescriptionText = ({ children, limit = 90}: DescriptionTextProps) => (
<span className="text-muted"> <span className="descriptionText">
{ {
children && children.length > limit ? children && children.length > limit ?
children.slice(0, limit-1) + '...' children.slice(0, limit-1) + '...'

View File

@@ -1,4 +1,20 @@
.boardContainer { .boardContainer {
@extend
.d-flex,
.justify-content-between,
.align-items-start;
flex-direction: row;
.sidebar {
position: sticky;
top: 20px;
.sidebarBox {
width: 250px;
}
}
@media (max-width: 800px) { @media (max-width: 800px) {
flex-direction: column; flex-direction: column;
@@ -13,26 +29,14 @@
} }
} }
@media (min-width: 801px) {
flex-direction: row;
.sidebar {
position: sticky;
top: 20px;
.sidebarBox {
width: 250px;
}
}
}
.sidebarBox { .sidebarBox {
flex: 0 0 auto; @extend
.d-flex,
display: flex; .flex-column,
flex-direction: column; .justify-content-start,
justify-content: flex-start; .align-items-center,
align-items: center; .flex-grow-0,
.flex-shrink-0;
border: thin solid black; border: thin solid black;
border-radius: 4px; border-radius: 4px;
@@ -41,7 +45,21 @@
padding: 8px; padding: 8px;
} }
.postStatusListItemContainer {
@extend
.d-flex,
.align-self-stretch;
}
.postStatusListItemLink {
@extend
.flex-grow-1;
}
.postStatusListItem { .postStatusListItem {
@extend
.p-1;
height: 40px; height: 40px;
&:hover { &:hover {
@@ -53,13 +71,21 @@
} }
.resetFilter { .resetFilter {
flex: 0 0 auto; @extend
.flex-grow-0,
.flex-shrink-0,
.align-self-center,
.p-0;
width: 30px; width: 30px;
height: 30px; height: 30px;
}
padding: 0; .postList {
@extend
align-self: center; .d-flex,
.flex-column,
.flex-grow-1;
} }
.postLink { .postLink {
@@ -67,14 +93,29 @@
border-radius: 4px; border-radius: 4px;
margin: 8px 0; margin: 8px 0;
color: black; color: black;
}
.postLink:hover { &:hover {
text-decoration: none; text-decoration: none;
background-color: #f5f5f5; background-color: #f5f5f5;
}
} }
.postListItem { .postListItem {
@extend
.d-flex,
.flex-column,
.justify-content-between,
.m-0,
.px-2,
.py-1;
height: 114px; height: 114px;
} }
.postDetails {
@extend
.d-flex,
.justify-content-between,
.text-uppercase;
}
} }

View File

@@ -1,17 +1,33 @@
.roadmapColumns { .roadmapColumns {
@media (max-width: 800px) { @extend
.roadmapColumn { .d-flex,
.justify-content-between,
.flex-wrap;
.roadmapColumn {
@extend
.card,
.my-2,
.px-2;
width: 32%;
@media (max-width: 800px) {
width: 100%; width: 100%;
} }
} }
@media (min-width: 801px) { .columnHeader {
.roadmapColumn { @extend
width: 32%; .card-header,
} .d-flex,
.bg-transparent;
} }
.scrollContainer { .scrollContainer {
@extend
.card-body;
overflow-y: auto; overflow-y: auto;
max-height: 350px; max-height: 350px;
} }
@@ -19,4 +35,12 @@
.postLink:hover { .postLink:hover {
text-decoration: none; text-decoration: none;
} }
.postListItem {
@extend
.d-flex,
.flex-column,
.my-1,
.py-2;
}
} }

View File

@@ -0,0 +1,40 @@
/*
This styles apply to custom texts defined in
/app/javascript/components/shared/CustomTexts.tsx
*/
.titleText {
@extend
.text-dark,
.font-weight-bolder;
}
.mutedText {
@extend
.text-muted,
.text-center;
}
.uppercaseText {
@extend
.text-secondary,
.text-uppercase,
.font-weight-lighter;
}
.successText {
@extend
.text-success,
.text-center;
}
.dangerText {
@extend
.text-danger,
.text-center;
}
.descriptionText {
@extend
.text-muted;
}

View File

@@ -1,12 +1,16 @@
@import 'vendors/bootstrap_custom'; @import 'vendors/bootstrap_custom';
@import 'general/index'; @import 'general/custom_texts';
@import 'general/navbar';
@import 'general/form'; @import 'general/form';
@import 'general/icons'; @import 'general/icons';
@import 'general/index';
@import 'general/navbar';
/* /*
Components stylesheets are not imported here. Instead, Components stylesheets are not imported here. Instead,
they are imported in the specific React components they are imported in the specific React components
that use them that use them
*/ */
@import 'components/Board';
@import 'components/Post';
@import 'components/Roadmap';