Skip to content

Commit

Permalink
fix(advanced checklist): style and layout improvements (#1182)
Browse files Browse the repository at this point in the history
* fix: reorder icon color

* fix: change reorder icon design

* feat: useResize hook

* feat: responsive task item

* fix: adjust padding for mobile devices

* fix: checkbox size should be proportional to text size

Co-authored-by: Johnny Almonte <johnny243@users.noreply.github.com>
  • Loading branch information
johnny243 and johnny243 committed Jun 29, 2022
1 parent 38dc61a commit 6c19adb
Show file tree
Hide file tree
Showing 16 changed files with 172 additions and 78 deletions.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
"@reach/alert-dialog": "0.16.2",
"@reach/menu-button": "0.16.2",
"@reach/visually-hidden": "0.16.0",
"@react-hook/resize-observer": "^1.2.5",
"@reduxjs/toolkit": "1.8.0",
"@standardnotes/editor-kit": "2.2.5",
"@standardnotes/stylekit": "5.23.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useEffect, useState } from 'react'
import useResizeObserver from '@react-hook/resize-observer'
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'
import type { AppDispatch, RootState } from './store'

Expand All @@ -16,3 +17,18 @@ export const useDidMount = (effect: React.EffectCallback, deps?: React.Dependenc
}
}, [deps, didMount, effect])
}

export const useResize = (ref: React.RefObject<HTMLElement>, effect: (target: HTMLElement) => void) => {
const [size, setSize] = useState<DOMRect>()

function isDeepEqual(prevSize?: DOMRect, nextSize?: DOMRect) {
return JSON.stringify(prevSize) === JSON.stringify(nextSize)
}

useResizeObserver(ref, ({ contentRect, target }) => {
if (!isDeepEqual(size, contentRect)) {
setSize(contentRect)
effect(target as HTMLElement)
}
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const StyledTextArea = styled.textarea`
background-color: transparent;
border: none;
color: inherit;
font-size: var(--sn-stylekit-font-size-h3);
font-size: 1rem;
font-weight: 400;
margin-left: 6px;
outline: none;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ type ReorderIconProps = {
export const ReorderIcon: React.FC<ReorderIconProps> = ({ highlight = false }) => {
return (
<svg
viewBox="0 0 24 24"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={`sn-icon block ${highlight ? 'info' : ''}`}
className={`sn-icon block ${highlight ? 'info' : 'neutral'}`}
data-testid="reorder-icon"
>
<path d="M3 15H21V13H3V15ZM3 19H21V17H3V19ZM3 11H21V9H3V11ZM3 5V7H21V5H3Z" />
<path d="M17 5V6.66667H3V5H17ZM3 15H17V13.3333H3V15ZM3 10.8333H17V9.16667H3V10.8333Z" />
</svg>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ $transition-duration: 750ms;
width: 22px;
}

.align-baseline {
.checkbox-button {
top: -10px !important;
}
}

.checkbox-square,
.checkbox-mark {
cursor: pointer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ const TaskGroupContainer = styled.div<{ isLast?: boolean }>`
box-sizing: border-box;
padding: 16px;
margin-bottom: ${({ isLast }) => (!isLast ? '9px' : '0px')};
@media only screen and (max-width: 600px) {
padding: 8px 10px;
}
`

type CollapsableContainerProps = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import './TaskItem.scss'

import { ChangeEvent, createRef, KeyboardEvent, useEffect, useState } from 'react'
import { ChangeEvent, createRef, KeyboardEvent, useState } from 'react'
import styled from 'styled-components'

import { useAppDispatch, useAppSelector, useDidMount } from '../../app/hooks'
import { useAppDispatch, useAppSelector, useDidMount, useResize } from '../../app/hooks'
import { taskDeleted, TaskModel, taskModified, taskToggled } from './tasks-slice'

import { CheckBoxInput, TextAreaInput } from '../../common/components'
Expand Down Expand Up @@ -33,7 +33,7 @@ const Container = styled.div<{ completed?: boolean }>`
`}
min-width: 10%;
max-width: 85%;
max-width: 90%;
`

export type TaskItemProps = {
Expand All @@ -53,22 +53,29 @@ const TaskItem: React.FC<TaskItemProps> = ({ task, groupName, innerRef, ...props
const [completed, setCompleted] = useState(!!task.completed)
const [description, setDescription] = useState(task.description)

function resizeTextArea(textarea: HTMLTextAreaElement | null): void {
function resizeTextArea(textarea: HTMLElement): void {
if (!textarea) {
return
}

const heightOffset = 4
/**
* Set to 1px first to reset scroll height in case it shrunk.
*/
const heightOffset = 4
textarea.style.height = '1px'
textarea.style.height = textarea.scrollHeight - heightOffset + 'px'
}

useEffect(() => {
resizeTextArea(textAreaRef.current)
})
const singleLineHeight = 20
const currentHeight = parseFloat(textarea.style.height)

if (currentHeight > singleLineHeight) {
textarea.parentElement?.classList.add('align-baseline')
textarea.parentElement?.classList.remove('align-center')
} else {
textarea.parentElement?.classList.add('align-center')
textarea.parentElement?.classList.remove('align-baseline')
}
}

function onCheckBoxToggle() {
const newCompletedState = !completed
Expand Down Expand Up @@ -122,6 +129,8 @@ const TaskItem: React.FC<TaskItemProps> = ({ task, groupName, innerRef, ...props
return () => clearTimeout(timeoutId)
}, [description, groupName])

useResize(textAreaRef, resizeTextArea)

return (
<Container data-testid="task-item" completed={completed} ref={innerRef} {...props}>
<CheckBoxInput testId="check-box-input" checked={completed} disabled={!canEdit} onChange={onCheckBoxToggle} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const InnerTasksContainer = styled.div<{ collapsed: boolean }>`
flex-direction: column;
& > *:not(:last-child) {
margin-bottom: 5px;
margin-bottom: 7px;
}
`

Expand Down Expand Up @@ -94,72 +94,70 @@ const TasksSection: React.FC<TasksSectionProps> = ({ groupName, tasks, section,
ref={provided.innerRef}
>
<TransitionGroup component={null} childFactory={(child) => React.cloneElement(child)}>
{tasks.map((task, index) => {
return (
<CSSTransition
key={`${task.id}-${!!task.completed}`}
classNames={{
enter: 'fade-in',
enterActive: 'fade-in',
enterDone: 'fade-in',
exit: 'fade-out',
exitActive: 'fade-out',
exitDone: 'fade-out',
}}
timeout={{
enter: 1_500,
exit: 1_250,
}}
onEnter={(node: HTMLElement) => {
node.classList.remove('explode')
}}
onEntered={(node: HTMLElement) => {
node.classList.remove('fade-in')

const completed = !!task.completed
completed && node.classList.add('explode')

node.addEventListener(
'animationend',
() => {
node.classList.remove('explode')
},
false,
{tasks.map((task, index) => (
<CSSTransition
key={`${task.id}-${!!task.completed}`}
classNames={{
enter: 'fade-in',
enterActive: 'fade-in',
enterDone: 'fade-in',
exit: 'fade-out',
exitActive: 'fade-out',
exitDone: 'fade-out',
}}
timeout={{
enter: 1_500,
exit: 1_250,
}}
onEnter={(node: HTMLElement) => {
node.classList.remove('explode')
}}
onEntered={(node: HTMLElement) => {
node.classList.remove('fade-in')

const completed = !!task.completed
completed && node.classList.add('explode')

node.addEventListener(
'animationend',
() => {
node.classList.remove('explode')
},
false,
)
}}
onExited={(node: HTMLElement) => {
node.classList.remove('fade-out')
}}
addEndListener={(node, done) => {
done()
}}
mountOnEnter
unmountOnExit
>
<Draggable
key={`draggable-${task.id}`}
draggableId={`draggable-${task.id}`}
index={index}
isDragDisabled={!canEdit}
>
{({ innerRef, draggableProps, dragHandleProps }, { isDragging }) => {
const { style, ...restDraggableProps } = draggableProps
return (
<div className="task-item" style={getItemStyle(isDragging, style)} {...restDraggableProps}>
<TaskItem
key={`task-item-${task.id}`}
task={task}
groupName={groupName}
innerRef={innerRef}
{...dragHandleProps}
/>
</div>
)
}}
onExited={(node: HTMLElement) => {
node.classList.remove('fade-out')
}}
addEndListener={(node, done) => {
done()
}}
mountOnEnter
unmountOnExit
>
<Draggable
key={`draggable-${task.id}`}
draggableId={`draggable-${task.id}`}
index={index}
isDragDisabled={!canEdit}
>
{({ innerRef, draggableProps, dragHandleProps }, { isDragging }) => {
const { style, ...restDraggableProps } = draggableProps
return (
<div className="task-item" style={getItemStyle(isDragging, style)} {...restDraggableProps}>
<TaskItem
key={`task-item-${task.id}`}
task={task}
groupName={groupName}
innerRef={innerRef}
{...dragHandleProps}
/>
</div>
)
}}
</Draggable>
</CSSTransition>
)
})}
</Draggable>
</CSSTransition>
))}
</TransitionGroup>
{provided.placeholder}
</InnerTasksContainer>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ import { getPlainPreview } from './common/utils'
const MainContainer = styled.div`
margin: 16px;
padding-bottom: 60px;
@media only screen and (max-width: 600px) {
margin: 8px;
}
`

const FloatingContainer = styled.div`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@ html {
.pt-1px {
padding-top: 1px;
}

.align-baseline {
align-items: baseline;
}

.align-center {
align-items: center;
}
}

:root {
Expand Down
48 changes: 48 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2995,6 +2995,13 @@ __metadata:
languageName: node
linkType: hard

"@juggle/resize-observer@npm:^3.3.1":
version: 3.3.1
resolution: "@juggle/resize-observer@npm:3.3.1"
checksum: ddabc4044276a2cb57d469c4917206c7e39f2463aa8e3430e33e4eda554412afe29c22afa40e6708b49dad5d56768dc83acd68a704b1dcd49a0906bb96b991b2
languageName: node
linkType: hard

"@leichtgewicht/ip-codec@npm:^2.0.1":
version: 2.0.4
resolution: "@leichtgewicht/ip-codec@npm:2.0.4"
Expand Down Expand Up @@ -4425,6 +4432,39 @@ __metadata:
languageName: node
linkType: hard

"@react-hook/latest@npm:^1.0.2":
version: 1.0.3
resolution: "@react-hook/latest@npm:1.0.3"
peerDependencies:
react: ">=16.8"
checksum: 2408c9cd35c5cfa7697b6da3bc5eebef254a932ade70955074c474f23be7dd3e2f81bbba12edcc9208bd0f89c6ed366d6b11d4f6d7b1052877a0bac8f74afad4
languageName: node
linkType: hard

"@react-hook/passive-layout-effect@npm:^1.2.0":
version: 1.2.1
resolution: "@react-hook/passive-layout-effect@npm:1.2.1"
peerDependencies:
react: ">=16.8"
checksum: 217cb8aa90fb8e677672319a9a466d7752890cf4357c76df000b207696e9cc717cf2ee88080671cc9dae238a82f92093ab4f61ab2f6032d2a8db958fc7d99b5d
languageName: node
linkType: hard

"@react-hook/resize-observer@npm:^1.2.5":
version: 1.2.5
resolution: "@react-hook/resize-observer@npm:1.2.5"
dependencies:
"@juggle/resize-observer": ^3.3.1
"@react-hook/latest": ^1.0.2
"@react-hook/passive-layout-effect": ^1.2.0
"@types/raf-schd": ^4.0.0
raf-schd: ^4.0.2
peerDependencies:
react: ">=16.8"
checksum: a2f3b333e344adb3d7a4cfd2bc77fd75054b07063fba706d57bef0c497650c3e82038eafb64fa4148c08527e8b0a34f2f70392da1700a7a0d9676ee8ba795c16
languageName: node
linkType: hard

"@react-native-community/async-storage@npm:1.12.1":
version: 1.12.1
resolution: "@react-native-community/async-storage@npm:1.12.1"
Expand Down Expand Up @@ -4884,6 +4924,7 @@ __metadata:
"@reach/alert-dialog": 0.16.2
"@reach/menu-button": 0.16.2
"@reach/visually-hidden": 0.16.0
"@react-hook/resize-observer": ^1.2.5
"@reduxjs/toolkit": 1.8.0
"@standardnotes/editor-kit": 2.2.5
"@standardnotes/stylekit": 5.23.0
Expand Down Expand Up @@ -7342,6 +7383,13 @@ __metadata:
languageName: node
linkType: hard

"@types/raf-schd@npm:^4.0.0":
version: 4.0.1
resolution: "@types/raf-schd@npm:4.0.1"
checksum: 0babaa85541aadc6e5f8aa64ec79cd68bf67ea56abb7610c8daf3ca5f4b1a75d12e4e147a0b5434938a4031650ebddc733021ec4e7db4f11f7955390ec32c917
languageName: node
linkType: hard

"@types/range-parser@npm:*":
version: 1.2.4
resolution: "@types/range-parser@npm:1.2.4"
Expand Down

0 comments on commit 6c19adb

Please sign in to comment.