Skip to content
This repository has been archived by the owner on Oct 8, 2022. It is now read-only.

Commit

Permalink
feat: Allow the board to be styled (#291)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: You need to import the default styles or provide your own: `import '@lourenci/react-kanban/dist/styles.css'`.
  • Loading branch information
lourenci authored Jun 4, 2020
1 parent faeadec commit f9b4717
Show file tree
Hide file tree
Showing 22 changed files with 333 additions and 279 deletions.
30 changes: 24 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,22 @@ Yet another Kanban/Trello board lib for React.

### ▶️ Demo

[Usage](https://5k7py44kl.codesandbox.io/)
[Usage](https://nvjp3.csb.app/)

[![Edit react-kanban-demo](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/5k7py44kl?fontsize=14)
[![Edit react-kanban-demo](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/react-kanban-demo-nvjp3)

## ❓ Why?

- 👊 Reliable: 100% tested on CI; 100% coverage; 100% SemVer.
- 🎮 Having fun: Play with Hooks 🎣 and Styled Components 💅🏻.
- 🎮 Having fun: Play with Hooks 🎣 and ~~Styled Components~~.
- ♿️ Accessible: Keyboard and mobile friendly.
- 🔌 Pluggable: For use in projects.

## 🛠 Install and usage

Since this project use Hooks and Styled Components, you have to install them:
Since this project use Hooks, you have to install them:

- `react>=16.8.5`
- `styled-components>=4`

After, Install the lib on your project:

Expand All @@ -37,6 +36,7 @@ Import the lib and use it on your project:

```js
import Board from '@lourenci/react-kanban'
import '@lourenci/react-kanban/dist/styles.css'

const board = {
columns: [
Expand Down Expand Up @@ -498,7 +498,25 @@ function onCardNew (newCard) {

## 💅🏻 Styling

This might be our next major release. For the time being, you can use it in the [`beta` branch](https://github.com/lourenci/react-kanban/tree/beta). We are eager for your feedback.
You can either style all the board or import our style and override it with the styles you want:

| Class |
| ----- |
| `react-kanban-board` |
| `react-kanban-card` |
| `react-kanban-card-skeleton` |
| `react-kanban-card--dragging` |
| `react-kanban-card__description` |
| `react-kanban-card__title` |
| `react-kanban-column` |
| `react-kanban-card-adder-form` |
| `react-kanban-card-adder-button` |
| `react-kanban-card-adder-form__title` |
| `react-kanban-card-adder-form__description` |
| `react-kanban-card-adder-form__button` |
| `react-kanban-column-header` |
| `react-kanban-column-header__button` |
| `react-kanban-column-adder-button` |

## 🧪 Tests

Expand Down
1 change: 1 addition & 0 deletions assets/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react'
import { render } from 'react-dom'
import Board from '../src'
import getUrlParams from './services/getUrlParams'
import '../src/styles.scss'

const board = {
columns: [
Expand Down
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ module.exports = {
moduleNameMapper: {
'^@services/(.*)$': '<rootDir>/src/services/$1',
'^@components/(.*)$': '<rootDir>/src/components/$1',
'\\.s?css$': 'identity-obj-proxy',
},
}
11 changes: 8 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
"description": "Yet another Kanban/Trello board lib for React.",
"main": "dist/index.js",
"files": [
"dist/index.js"
"dist/index.js",
"dist/styles.css"
],
"repository": "https://github.com/lourenci/react-kanban",
"author": "Leandro Lourenci",
"license": "MIT",
"peerDependencies": {
"react": "^16.8.0",
"react-dom": "^16.8.0",
"styled-components": ">=3"
"react-dom": "^16.8.0"
},
"devDependencies": {
"@babel/core": "7.9.6",
Expand All @@ -28,6 +28,7 @@
"babel-plugin-istanbul": "6.0.0",
"babel-plugin-react-remove-properties": "0.3.0",
"cross-env": "7.0.2",
"css-loader": "^3.4.2",
"cypress": "4.5.0",
"eslint": "6.8.0",
"eslint-config-prettier": "6.11.0",
Expand All @@ -43,12 +44,16 @@
"eslint-plugin-react-hooks": "2.5.1",
"eslint-plugin-standard": "4.0.1",
"html-webpack-plugin": "3.2.0",
"identity-obj-proxy": "^3.0.0",
"istanbul-lib-coverage": "3.0.0",
"jest": "26.0.1",
"mini-css-extract-plugin": "^0.9.0",
"node-sass": "^4.13.1",
"jest-circus": "26.0.1",
"prettier": "2.0.5",
"react": "16.13.1",
"react-dom": "16.13.1",
"sass-loader": "^8.0.2",
"semantic-release": "17.0.7",
"start-server-and-test": "1.10.11",
"styled-components": "5.0.1",
Expand Down
7 changes: 0 additions & 7 deletions src/components/Board/components/CardSkeleton/index.js

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
import React from 'react'
import { Draggable } from 'react-beautiful-dnd'
import styled from 'styled-components'

const CardTemplate = styled.div`
display: inline-block;
white-space: normal;
`

function Card({ children, index, renderCard, disableCardDrag }) {
return (
Expand All @@ -18,7 +12,7 @@ function Card({ children, index, renderCard, disableCardDrag }) {
{...provided.dragHandleProps}
data-testid={`card-${children.id}`}
>
<CardTemplate>{renderCard(isDragging)}</CardTemplate>
<div style={{ display: 'inline-block', whiteSpace: 'normal' }}>{renderCard(isDragging)}</div>
</div>
)
}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,56 +1,5 @@
import React, { useRef } from 'react'
import styled from 'styled-components'
import { when } from '@services/utils'
import CardSkeleton from '@components/Board/components/CardSkeleton'

const DefaultCard = styled(CardSkeleton)`
border-radius: 3px;
background-color: #fff;
padding: 10px;
margin-bottom: 7px;
input {
border: 0px;
font-family: inherit;
font-size: inherit;
}
`

const CardTitle = styled.input`
font-weight: bold;
border-bottom: 1px solid #eee;
padding-bottom: 5px;
font-weight: bold;
display: flex;
justify-content: space-between;
width: 100%;
padding: 0px;
`

const CardDescription = styled.input`
input {
width: 100%;
}
margin-top: 10px;
`
const StyledFormButtons = styled.div`
display: flex;
justify-content: space-between;
margin-top: 5px;
`

const StyledButton = styled.button`
background-color: #eee;
border: none;
padding: 5px;
width: 45%;
margin-top: 5px;
border-radius: 3px;
&:hover {
transition: 0.3s;
cursor: pointer;
background-color: #ccc;
}
`

function CardForm({ onConfirm, onCancel }) {
const inputCardTitle = useRef()
Expand All @@ -64,18 +13,31 @@ function CardForm({ onConfirm, onCancel }) {
}

return (
<DefaultCard>
<div className='react-kanban-card-adder-form'>
<form onSubmit={addCard}>
<CardTitle name='title' autoFocus defaultValue='Title' ref={inputCardTitle} />
<CardDescription name='description' defaultValue='Description' ref={inputCardDescription} />
<StyledFormButtons>
<StyledButton type='submit'>Add</StyledButton>
<StyledButton type='button' onClick={onCancel}>
<input
className='react-kanban-card-adder-form__title'
name='title'
autoFocus
defaultValue='Title'
ref={inputCardTitle}
/>
<input
className='react-kanban-card-adder-form__description'
name='description'
defaultValue='Description'
ref={inputCardDescription}
/>
<div style={{ display: 'flex', justifyContent: 'space-between', marginTop: '5px' }}>
<button className='react-kanban-card-adder-form__button' type='submit'>
Add
</button>
<button className='react-kanban-card-adder-form__button' type='button' onClick={onCancel}>
Cancel
</StyledButton>
</StyledFormButtons>
</button>
</div>
</form>
</DefaultCard>
</div>
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,6 @@
import React, { useState } from 'react'
import styled from 'styled-components'
import CardForm from './components/CardForm'

const AddCardButton = styled.button`
width: 100%;
margin-top: 5px;
background-color: transparent;
cursor: pointer;
border: 1px solid #ccc;
transition: 0.3s;
:hover {
background-color: #ccc;
}
border-radius: 3px;
font-size: 20px;
margin-bottom: 10px;
font-weight: bold;
`

export default function CardAdder({ column, onConfirm }) {
function confirmCard(card) {
onConfirm(column, card)
Expand All @@ -31,7 +14,9 @@ export default function CardAdder({ column, onConfirm }) {
{addingCard ? (
<CardForm onConfirm={confirmCard} onCancel={() => setAddingCard(false)} />
) : (
<AddCardButton onClick={() => setAddingCard(!addingCard)}>+</AddCardButton>
<button className='react-kanban-card-adder-button' onClick={() => setAddingCard(!addingCard)}>
+
</button>
)}
</>
)
Expand Down
85 changes: 43 additions & 42 deletions src/components/Board/components/Column/index.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,15 @@
import React from 'react'
import styled from 'styled-components'
import { Draggable } from 'react-beautiful-dnd'
import Card from './components/Card'
import CardSkeleton from '../CardSkeleton'
import withDroppable from '../../../withDroppable'
import CardAdder from './components/CardAdder'
import { pickPropOut } from '@services/utils'

export const StyledColumn = styled.div`
height: 100%;
min-height: 28px;
display: inline-block;
padding: 15px;
border-radius: 2px;
background-color: #eee;
margin: 5px;
vertical-align: top;
`
const ColumnEmptyPlaceholder = React.forwardRef((props, ref) => (
<div ref={ref} style={{ minHeight: 'inherit', height: 'inherit' }} {...props} />
))

const DroppableColumn = withDroppable(styled.div`
height: inherit;
min-height: inherit;
`)
const DroppableColumn = withDroppable(ColumnEmptyPlaceholder)

function Column({
children,
Expand All @@ -34,32 +23,44 @@ function Column({
}) {
return (
<Draggable draggableId={`column-draggable-${children.id}`} index={columnIndex} isDragDisabled={disableColumnDrag}>
{(columnProvided) => (
<StyledColumn
ref={columnProvided.innerRef}
{...columnProvided.draggableProps}
data-testid={`column-${children.id}`}
>
<div {...columnProvided.dragHandleProps}>{renderColumnHeader(children)}</div>
{allowAddCard && <CardAdder column={children} onConfirm={onCardNew} />}
<DroppableColumn droppableId={String(children.id)}>
{children.cards.length ? (
children.cards.map((card, index) => (
<Card
key={card.id}
index={index}
renderCard={(dragging) => renderCard(children, card, dragging)}
disableCardDrag={disableCardDrag}
>
{card}
</Card>
))
) : (
<CardSkeleton />
)}
</DroppableColumn>
</StyledColumn>
)}
{(columnProvided) => {
const draggablePropsWithoutStyle = pickPropOut(columnProvided.draggableProps, 'style')

return (
<div
ref={columnProvided.innerRef}
{...draggablePropsWithoutStyle}
style={{
height: '100%',
minHeight: '28px',
display: 'inline-block',
verticalAlign: 'top',
...columnProvided.draggableProps.style,
}}
className='react-kanban-column'
data-testid={`column-${children.id}`}
>
<div {...columnProvided.dragHandleProps}>{renderColumnHeader(children)}</div>
{allowAddCard && <CardAdder column={children} onConfirm={onCardNew} />}
<DroppableColumn droppableId={String(children.id)}>
{children.cards.length ? (
children.cards.map((card, index) => (
<Card
key={card.id}
index={index}
renderCard={(dragging) => renderCard(children, card, dragging)}
disableCardDrag={disableCardDrag}
>
{card}
</Card>
))
) : (
<div className='react-kanban-card-skeleton' />
)}
</DroppableColumn>
</div>
)
}}
</Draggable>
)
}
Expand Down
Loading

0 comments on commit f9b4717

Please sign in to comment.