Skip to content

Commit

Permalink
Use custom scrollbar for GroupSelector (#62)
Browse files Browse the repository at this point in the history
* Use custom scrollbar for group selector for consistent experience

The group selector has some complicated scrolling behavior, and not all browses displayed the scrollbar above the content. Sometimes, placing the content above the scrollbar.

Using css to attempt to alter the scrollbar was not a viable solution due to Firefox not supporting the css required.

Using a custom scrollbar allows us to have control over the location of the scrollbar and get a consistent look accross browsers.

* Fix small 3px gap that would show scroll content through the header

* Fix small buttons sizing on secondary modal content
  • Loading branch information
JordanSjodinFaithlife authored and dustinsoftware committed Oct 10, 2018
1 parent d6748e5 commit e5ba146
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 120 deletions.
207 changes: 101 additions & 106 deletions components/group-selector/modal/component.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,6 @@ export class GroupSelectorModal extends React.Component {
searchResultsRef = React.createRef();
fixedCreateWrapper = false;

componentDidMount = () => {
window.addEventListener('scroll', this.handleScroll, true);
};

componentWillUnmount = () => {
window.removeEventListener('scroll', this.handleScroll, true);
};

createGroupClick = () => {
this.toggle();
this.props.onCreateGroup(this.state.newChurchName, this.state.newChurchLocation);
Expand Down Expand Up @@ -174,26 +166,19 @@ export class GroupSelectorModal extends React.Component {
this.props.onClaimGroupClick(groupId);
};

handleScroll = event => {
if (this.modalRef.current) {
const element = event.target;
if (this.modalRef.current.contains(element)) {
if (element.scrollTop >= 82 && !this.fixedCreateWrapper) {
this.setState({
createGroupFixed: true,
resultsTopMargin: 232,
scrollWidthDelta: element.offsetWidth - element.clientWidth,
});
this.fixedCreateWrapper = true;
} else if (element.scrollTop < 82) {
this.setState({
createGroupFixed: false,
resultsTopMargin: defaultResultsTopMargin + element.scrollTop,
scrollWidthDelta: 0,
});
this.fixedCreateWrapper = false;
}
}
handleScroll = scrollData => {
if (scrollData.topPosition >= 82 && !this.fixedCreateWrapper) {
this.setState({
createGroupFixed: true,
resultsTopMargin: 232,
});
this.fixedCreateWrapper = true;
} else if (scrollData.topPosition < 82) {
this.setState({
createGroupFixed: false,
resultsTopMargin: defaultResultsTopMargin + scrollData.topPosition,
});
this.fixedCreateWrapper = false;
}
};

Expand All @@ -202,85 +187,95 @@ export class GroupSelectorModal extends React.Component {

return (
<Styled.GroupSelectorModal>
<SimpleModal isOpen={this.props.isOpen} onClose={this.toggle}>
<Styled.GroupSelectorModalBody innerRef={this.modalRef}>
{this.state.modalContent === 'main' && (
<Styled.MainModalContent>
<Styled.ModalTopGradient />
<Styled.ModalTitle>Find Your Church</Styled.ModalTitle>
<Styled.ModalSubtitle>in the Faithlife Church Directory</Styled.ModalSubtitle>
<Styled.CreateGroupWrapper fixed={this.state.createGroupFixed}>
<Styled.CreateGroupBackground scrollWidthDelta={this.state.scrollWidthDelta}>
<CreateGroup
onChurchNameInputChange={this.handleChurchNameInputChange}
onChurchLocationInputChange={this.handleChurchLocationInputChange}
newChurchName={this.state.newChurchName}
newChurchLocation={this.state.newChurchLocation}
showRequiredStars={this.state.createGroupFixed}
/>
<Styled.CreateGroupButtonWrapper>
<Styled.CreateGroupButtonText>
Don't see your church?
</Styled.CreateGroupButtonText>
<Button
small
primary
disabled={disableButton}
onClick={this.createGroupClick}
>
Create
</Button>
</Styled.CreateGroupButtonWrapper>
</Styled.CreateGroupBackground>
</Styled.CreateGroupWrapper>
<Styled.SearchResultsContainer
style={{ marginTop: this.state.resultsTopMargin }}
fixed={this.state.createGroupFixed}
innerRef={this.searchResultsRef}
>
{this.getSearchResults()}
</Styled.SearchResultsContainer>
</Styled.MainModalContent>
)}
{this.state.modalContent === 'admin' && (
<Styled.SecondaryModalContent>
<Styled.SecondaryModalText>
<Styled.SearchResultBoldText>Admin</Styled.SearchResultBoldText>
<span> membership is neccessarry to perform this action.</span>
</Styled.SecondaryModalText>
<Styled.SecondaryModalText>
Contact a group administrator to request Admin membership
</Styled.SecondaryModalText>
<Styled.SecondaryModalButtonContainer>
<Styled.SecondaryModalButtonWrapper>
<Button primary onClick={this.redirectToGroup}>
Request access
</Button>
</Styled.SecondaryModalButtonWrapper>
<Button onClick={this.resetModalState}>Cancel</Button>
</Styled.SecondaryModalButtonContainer>
</Styled.SecondaryModalContent>
)}
{this.state.modalContent === 'change' && (
<Styled.SecondaryModalContent>
<Styled.SecondaryModalText>
This group type must be set to{' '}
<Styled.SearchResultBoldText>"Church"</Styled.SearchResultBoldText>
</Styled.SecondaryModalText>
<Styled.SecondaryModalText>
Visit the group settings page to change
</Styled.SecondaryModalText>
<Styled.SecondaryModalButtonContainer>
<Styled.SecondaryModalButtonWrapper>
<Button primary onClick={this.redirectToGroup}>
Change to Church
<SimpleModal
isOpen={this.props.isOpen}
onClose={this.toggle}
theme={{ background: 'transparent' }}
>
{this.state.modalContent === 'main' && (
<Styled.ModalScrollView
horizontal={false}
contentClassName={Styled.ModalScrollViewContentClass}
onScroll={this.handleScroll}
verticalScrollbarStyle={{
borderRadius: '6px',
marginTop: '1px',
marginBottom: '1px',
}}
>
<Styled.ModalTopGradient />
<Styled.ModalTitle>Find Your Church</Styled.ModalTitle>
<Styled.ModalSubtitle>in the Faithlife Church Directory</Styled.ModalSubtitle>
<Styled.CreateGroupWrapper fixed={this.state.createGroupFixed}>
<Styled.CreateGroupBackground scrollWidthDelta={this.state.scrollWidthDelta}>
<CreateGroup
onChurchNameInputChange={this.handleChurchNameInputChange}
onChurchLocationInputChange={this.handleChurchLocationInputChange}
newChurchName={this.state.newChurchName}
newChurchLocation={this.state.newChurchLocation}
showRequiredStars={this.state.createGroupFixed}
/>
<Styled.CreateGroupButtonWrapper>
<Styled.CreateGroupButtonText>
Don't see your church?
</Styled.CreateGroupButtonText>
<Button small primary disabled={disableButton} onClick={this.createGroupClick}>
Create
</Button>
</Styled.SecondaryModalButtonWrapper>
<Button onClick={this.resetModalState}>Cancel</Button>
</Styled.SecondaryModalButtonContainer>
</Styled.SecondaryModalContent>
)}
</Styled.GroupSelectorModalBody>
</Styled.CreateGroupButtonWrapper>
</Styled.CreateGroupBackground>
</Styled.CreateGroupWrapper>
<Styled.SearchResultsContainer
style={{ marginTop: this.state.resultsTopMargin }}
fixed={this.state.createGroupFixed}
innerRef={this.searchResultsRef}
>
{this.getSearchResults()}
</Styled.SearchResultsContainer>
</Styled.ModalScrollView>
)}
{this.state.modalContent === 'admin' && (
<Styled.SecondaryModalContent>
<Styled.SecondaryModalText>
<Styled.SearchResultBoldText>Admin</Styled.SearchResultBoldText>
<span> membership is neccessarry to perform this action.</span>
</Styled.SecondaryModalText>
<Styled.SecondaryModalText>
Contact a group administrator to request Admin membership
</Styled.SecondaryModalText>
<Styled.SecondaryModalButtonContainer>
<Styled.SecondaryModalButtonWrapper>
<Button small primary onClick={this.redirectToGroup}>
Request access
</Button>
</Styled.SecondaryModalButtonWrapper>
<Button small onClick={this.resetModalState}>
Cancel
</Button>
</Styled.SecondaryModalButtonContainer>
</Styled.SecondaryModalContent>
)}
{this.state.modalContent === 'change' && (
<Styled.SecondaryModalContent>
<Styled.SecondaryModalText>
This group type must be set to{' '}
<Styled.SearchResultBoldText>"Church"</Styled.SearchResultBoldText>
</Styled.SecondaryModalText>
<Styled.SecondaryModalText>
Visit the group settings page to change
</Styled.SecondaryModalText>
<Styled.SecondaryModalButtonContainer>
<Styled.SecondaryModalButtonWrapper>
<Button small primary onClick={this.redirectToGroup}>
Change to Church
</Button>
</Styled.SecondaryModalButtonWrapper>
<Button small onClick={this.resetModalState}>
Cancel
</Button>
</Styled.SecondaryModalButtonContainer>
</Styled.SecondaryModalContent>
)}
</SimpleModal>
</Styled.GroupSelectorModal>
);
Expand Down
32 changes: 19 additions & 13 deletions components/group-selector/styled.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import styled from 'styled-components';
import ScrollArea from 'react-scrollbar';
import { resetStyles } from '../utils/index.js';

export const GroupSelector = styled.div`
Expand Down Expand Up @@ -126,7 +127,20 @@ export const DropdownButtonContainer = styled.div`

export const GroupSelectorModal = styled.div`
${resetStyles};
`;

export const ModalScrollViewContentClass = 'modal-scroll-view-content';
export const ModalScrollView = styled(ScrollArea)`
position: relative;
height: 60vh;
width: 375px;
background: white;
border-radius: 4px;
.${ModalScrollViewContentClass} {
padding-top: 30px;
position: unset;
}
`;

export const ModalTopGradient = styled.div`
Expand All @@ -140,7 +154,7 @@ export const ModalTopGradient = styled.div`
width: 100%;
height: 30px;
z-index: 2;
box-shadow: 0px 10px 8px -4px white;
box-shadow: 0px 5px 10px -4px white;
`;

export const ModalTopGradientWrapper = styled.div`
Expand All @@ -166,11 +180,6 @@ export const ModalSubtitle = styled.div`
line-height: 1.2;
`;

export const MainModalContent = styled.div`
padding-top: 30px;
height: 60vh;
`;

export const CreateGroupWrapper = styled.div`
position: ${props => (props.fixed ? 'absolute' : 'relative')};
width: 100%;
Expand All @@ -179,7 +188,7 @@ export const CreateGroupWrapper = styled.div`
${props =>
props.fixed &&
`
top: 17px;
top: 14px;
`};
`;

Expand Down Expand Up @@ -232,12 +241,6 @@ export const CreateGroupRequiredStar = styled.div`
color: #d94848;
`;

export const GroupSelectorModalBody = styled.div`
border-radius: 6px;
min-width: 375px;
overflow-y: scroll;
`;

export const SearchResult = styled.div`
height: 100px;
background-color: white;
Expand Down Expand Up @@ -309,6 +312,9 @@ export const SecondaryModalContent = styled.div`
padding-right: 12px;
padding-top: 36px;
padding-bottom: 12px;
background: white;
border-radius: 4px;
width: 375px;
`;

export const SecondaryModalText = styled.div`
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"lodash.debounce": "^4.0.8",
"prop-types": "^15.6.1",
"react-bootstrap-typeahead": "^3.1.4",
"react-scrollbar": "^0.5.4",
"react-transition-group": "^2.4.0",
"reactstrap": "^6.1.0"
},
Expand Down
Loading

0 comments on commit e5ba146

Please sign in to comment.