🎨 styling timelines

Signed-off-by: Baptiste Lemoine <contact@cipherbliss.com>
This commit is contained in:
Baptiste Lemoine 2019-12-23 17:00:57 +01:00
parent 0e3069c8d7
commit 5175059c24
14 changed files with 323 additions and 149 deletions

View File

@ -312,8 +312,6 @@ class Status extends ImmutablePureComponent {
return null;
}
const moreStatusCount = this.props.status.replies;
const handlers = this.props.muted ? {} : {
reply : this.handleHotkeyReply,
favourite : this.handleHotkeyFavourite,

View File

@ -551,9 +551,9 @@ class Status extends ImmutablePureComponent {
className={classNames('scrollable', { fullscreen })}
ref={this.setRef}
>
<h2 className='debug'>ancestors:</h2 >
{/*<h2 className='debug'>ancestors:</h2 >*/}
{ancestors}
<h2 className='debug'>common:</h2 >
{/*<h2 className='debug'>common:</h2 >*/}
<HotKeys handlers={handlers}>
<div
className={classNames('focusable', 'detailed-status__wrapper')}
@ -592,7 +592,7 @@ class Status extends ImmutablePureComponent {
/>
</div >
</HotKeys >
<h2 className='debug'>Descendants:</h2 >
{/*<h2 className='debug'>Descendants:</h2 >*/}
{descendants}
</div >
</ScrollContainer >

View File

@ -31,6 +31,7 @@ import NavigationPanel from './navigation_panel';
import detectPassiveEvents from 'detect-passive-events';
import { scrollRight } from '../../../scroll';
import LinkFooter from './link_footer';
const componentMap = {
'COMPOSE' : Compose,
@ -157,10 +158,10 @@ class ColumnsArea extends ImmutablePureComponent {
const view = (index === columnIndex) ?
React.cloneElement(this.props.children) :
<ColumnLoading
(<ColumnLoading
title={title}
icon={icon}
/>;
/>);
return (
<div
@ -187,12 +188,12 @@ class ColumnsArea extends ImmutablePureComponent {
const columnIndex = getIndex(this.context.router.history.location.pathname);
if (singleColumn) {
const floatingActionButton = shouldHideFAB(this.context.router.history.location.pathname) ? null : <Link
const floatingActionButton = shouldHideFAB(this.context.router.history.location.pathname) ? null : (<Link
key='floating-action-button'
to='/statuses/new'
className='floating-action-button'
aria-label={intl.formatMessage(messages.publish)}
><Icon id='pencil' /></Link >;
><Icon id='pencil' /></Link >);
const content = columnIndex !== -1 ? (
<ReactSwipeableViews
@ -217,6 +218,7 @@ class ColumnsArea extends ImmutablePureComponent {
return (
<div className='columns-area__panels'>
<LinkFooter withHotkeys />
<div className='columns-area__panels__pane columns-area__panels__pane--compositional'>
<div className='columns-area__panels__pane__inner'>
<ComposePanel />
@ -255,17 +257,20 @@ class ColumnsArea extends ImmutablePureComponent {
loading={this.renderLoading(column.get('id'))}
error={this.renderError}
>
{SpecificComponent => <SpecificComponent
{SpecificComponent => (<SpecificComponent
columnId={column.get('uuid')}
params={params}
multiColumn {...other} />}
multiColumn {...other}
/>)}
</BundleContainer >
);
})}
{React.Children.map(children, child => React.cloneElement(child, { multiColumn: true }))}
</div >
);
)
;
}
}

View File

@ -2,15 +2,20 @@ import React from 'react';
import SearchContainer from 'mastodon/features/compose/containers/search_container';
import ComposeFormContainer from 'mastodon/features/compose/containers/compose_form_container';
import NavigationContainer from 'mastodon/features/compose/containers/navigation_container';
import LinkFooter from './link_footer';
import InstantMessaging from './messaging/instantMessaging';
const showIM = false;
const ComposePanel = () => (
<div className='compose-panel'>
<SearchContainer openInRoute />
<NavigationContainer />
<ComposeFormContainer singleColumn />
<LinkFooter withHotkeys />
</div>
{showIM && (
<InstantMessaging />
)}
</div >
);
export default ComposePanel;

View File

@ -70,7 +70,7 @@ class LinkFooter extends React.PureComponent {
.then((snowstorm) => {
Window.snowstorm = snowstorm.default;
this.state.snow = Window.snowstorm;
console.log('snowstorm', snowstorm);
console.log('this.state.snow ', this.state.snow);
// snowstorm.start();
this.state.snowActive = true;
})
@ -79,7 +79,7 @@ class LinkFooter extends React.PureComponent {
}
toggleSnow() {
toggleSnow = () => {
console.log('toggle snow');
if (this.state.snow) {
if (this.state.snowActive) {
@ -91,7 +91,7 @@ class LinkFooter extends React.PureComponent {
}
}
}
};
changeTheme(newTheme) {
console.log('change theme en ', newTheme);
@ -104,6 +104,7 @@ class LinkFooter extends React.PureComponent {
return (
<div className='getting-started__footer'>
<div className='extras'>
{/*// TODO*/}
@ -127,7 +128,7 @@ class LinkFooter extends React.PureComponent {
{this.state.enableChristmasSnow && (
<div
onClick={this.toggleSnow()}
onClick={this.toggleSnow}
className='christmas-snow'
>
<div className={snowClasses}>
@ -136,17 +137,23 @@ class LinkFooter extends React.PureComponent {
aria-hidden='true'
/>
</div >
<br />
<div > Joyeuses fêtes!</div >
{isStaff && (
<a href='/admin/tags?pending_review=1'>
<i className='fa fa-fire' />
Trending hashtags</a >
)}
<br />
<div className='external-utilities'>
<a href='https://mastodon.cipherbliss.com/@tykayn'>
<i className='fa fa-paper-plane' />
contactez nous
</a >
<br /><a href='https://liberapay.com/cipherbliss'>Supportez Cipherbliss</a >
<a href='https://liberapay.com/cipherbliss'>Supportez Cipherbliss</a >
<br /><a href='https://peertube.cipherbliss.com'> <i className='fa fa-play ' /> Videos</a >
<a href='https://peertube.cipherbliss.com'> <i className='fa fa-play ' /> Videos</a >
<a href='https://framadate.org/'> <i className='fa fa-calendar' /> FramaDate</a >
<a href='https://framapad.org/'> <i className='fa fa-file-text' /> Pad</a >
<a href='https://framagit.org/tykayn/mastodon'> <i className='fa fa-gitlab' /> Source</a >
@ -157,17 +164,6 @@ class LinkFooter extends React.PureComponent {
<ul >
{isStaff && (
<li >
<a href='/admin/tags?pending_review=1'>
<i className='fa fa-fire' />
Trending hashtags</a >
<hr />
</li >
)}
{invitesEnabled && <li ><a
href='/invites'
target='_blank'

View File

@ -1,12 +1,41 @@
import React from 'react';
import { isStaff } from '../../../../initial_state';
import PropTypes from 'prop-types';
export default class ContactsList extends React.PureComponent {
submitCompose() {
static propTypes = {
showList : PropTypes.bool,
contactList : PropTypes.array,
conversationList: PropTypes.array,
};
static defaultProps = {
showList : true,
contactList: ['machin', 'bidule', 'chuck norris'],
};
constructor(props) {
super(props);
this.state = {
showList : true,
contactList : ['machin', 'bidule', 'chuck norris'],
conversationList: ['machin', 'bidule', 'chuck norris'],
};
}
submitCompose() {
console.log('submit message');
}
toggleList = () => {
console.log('toggle');
this.setState((state) => {
console.log('state.showList', state.showList);
return {
showList: !state.showList,
};
});
};
render() {
// return (
@ -14,50 +43,46 @@ export default class ContactsList extends React.PureComponent {
// liste de contacts
// </div >
// );
const contactlist = ['machin', 'bidule', 'chuck norris'];
const conversationList = ['machin', 'bidule', 'chuck norris'];
const renderedList = this.state.contactList.forEach(elem => {
return (
<li className='contact-item'>
{elem}
</li >
);
});
return (
<div className='messaging-container'>
<div className='messaging-box'>
<div className='title'>
<div className='title column-header'>
<i
role='img'
className='fa fa-envelope column-header__icon fa-fw'
/>
Messaging box
{isStaff &&
<span >
Je suis admin oui oui
</span >
}
</div >
<div className='user-list column-header'>
<h2 className='title'>la liste de contacts</h2 >
<ul className='contact-list'>
{contactlist.forEach(elem => {
return (
<li className='contact-item'>
{elem}
</li >
);
})}
</ul >
<h2 className='title'>la liste de {this.state.contactList.lengh} contacts
<button
className='btn btn-primary'
onClick={this.toggleList}
>
<i className='fa fa-caret-up' />
</button >
</h2 >
{this.state.showList && (
<div className='contact-list-container'>
<h3 >show list</h3 >
<ul className='contact-list'>
{renderedList}
</ul >
</div >
)}
</div >
</div >
<div className='conversations_list'>
<ul >
{conversationList.forEach(elem => {
return (
<div className='conversation'>
{elem}
</div >
);
})}
</ul >
</div >
</div >
);
}

View File

@ -1,24 +1,38 @@
import React from 'react';
export default class Conversation extends React.PureComponent {
import PropTypes from 'prop-types';
following = [];
const following = ['bidule', 'chose', 'truc'];
export default class Conversation extends React.Component {
static propTypes = {
following: PropTypes.array,
// conversations: PropTypes.array,
};
static defaultProps = {
following: following,
};
openConversationWith(name) {
console.log('openConversationWith name', name);
}
render() {
const contactlist = this.following.foreEach(elem => (
<li className='user-item'>
{/*<div*/}
{/* className='username'*/}
{/* onClick={this.openConversationWith(elem.username)}*/}
{/*>*/}
Machin {elem}
{/*</div >*/}
{/*<div className='last-active'>3 min</div >*/}
</li >
));
return contactlist;
return this.props.following.map(elem =>
}
(<li className='user-item'>
<div
className='username'
onClick={this.openConversationWith(elem)}
>
Machin {elem}
</div >
<div className='last-active'>3 min</div >
</li >),
);
};
}

View File

@ -1,13 +1,15 @@
import React from 'react';
import ContactsList from './contacts-list';
export default class Messaging extends React.PureComponent {
export default class InstantMessaging extends React.PureComponent {
// static propTypes = {
// following : ImmutablePropTypes.list,
// conversations: ImmutablePropTypes.list,
// following : PropTypes.array,
// conversations: PropTypes.array,
// };
// static defaultProps = {
// threadsCompile: true,
// };
// openConversationWith(account) {
// let conversationFound = account;
// if conversation exist, focus on it
@ -49,9 +51,12 @@ export default class Messaging extends React.PureComponent {
render() {
return (
<div >
messagerie todo
<div className='debug'>
<ContactsList />
messagerie todo
<ContactsList />
</div >
{/*<Conversation />*/}
</div >
);

View File

@ -7,26 +7,54 @@ import NotificationsCounterIcon from './notifications_counter_icon';
import FollowRequestsNavLink from './follow_requests_nav_link';
import ListPanel from './list_panel';
import TrendsContainer from 'mastodon/features/getting_started/containers/trends_container';
import Messaging from './messaging/messaging';
const showMessaging = true;
const NavigationPanel = () => (
<div className='navigation-panel'>
<div className='small-texts timelines'>
<NavLink
className='column-link column-link--transparent'
to='/timelines/home'
data-preview-title-id='column.home'
data-preview-icon='home'
><Icon
className='column-link__icon'
id='home'
fixedWidth
/><FormattedMessage
id='tabs_bar.home'
defaultMessage='Home'
/></NavLink >
<NavLink
className='column-link column-link--transparent'
to='/timelines/public/local'
data-preview-title-id='column.community'
data-preview-icon='users'
><Icon
className='column-link__icon'
id='users'
fixedWidth
/><FormattedMessage
id='tabs_bar.local_timeline'
defaultMessage='Local'
/></NavLink >
<NavLink
className='column-link column-link--transparent'
to='/timelines/home'
data-preview-title-id='column.home'
data-preview-icon='home'
><Icon
className='column-link__icon'
id='home'
fixedWidth
/><FormattedMessage
id='tabs_bar.home'
defaultMessage='Home'
/></NavLink >
<NavLink
className='column-link column-link--transparent'
exact
to='/timelines/public'
data-preview-title-id='column.public'
data-preview-icon='globe'
><Icon
className='column-link__icon'
id='globe'
fixedWidth
/><FormattedMessage
id='tabs_bar.federated_timeline'
defaultMessage='Federated'
/></NavLink >
</div >
<div className='spacer'></div >
<NavLink
className='column-link column-link--transparent'
to='/notifications'
@ -38,34 +66,6 @@ const NavigationPanel = () => (
id='tabs_bar.notifications'
defaultMessage='Notifications'
/></NavLink >
<FollowRequestsNavLink />
<NavLink
className='column-link column-link--transparent'
to='/timelines/public/local'
data-preview-title-id='column.community'
data-preview-icon='users'
><Icon
className='column-link__icon'
id='users'
fixedWidth
/><FormattedMessage
id='tabs_bar.local_timeline'
defaultMessage='Local'
/></NavLink >
<NavLink
className='column-link column-link--transparent'
exact
to='/timelines/public'
data-preview-title-id='column.public'
data-preview-icon='globe'
><Icon
className='column-link__icon'
id='globe'
fixedWidth
/><FormattedMessage
id='tabs_bar.federated_timeline'
defaultMessage='Federated'
/></NavLink >
<NavLink
className='column-link column-link--transparent'
to='/timelines/direct'
@ -77,6 +77,10 @@ const NavigationPanel = () => (
id='navigation_bar.direct'
defaultMessage='Direct messages'
/></NavLink >
<FollowRequestsNavLink />
<div className='spacer'></div >
<NavLink
className='column-link column-link--transparent'
to='/favourites'
@ -152,7 +156,6 @@ const NavigationPanel = () => (
{showTrends && <div className='flex-spacer' />}
{showTrends && <TrendsContainer />}
{showMessaging && <Messaging />}
</div >
);

View File

@ -8,19 +8,81 @@ import Icon from 'mastodon/components/icon';
import NotificationsCounterIcon from './notifications_counter_icon';
export const links = [
<NavLink className='tabs-bar__link' to='/timelines/home' data-preview-title-id='column.home' data-preview-icon='home' ><Icon id='home' fixedWidth /><FormattedMessage id='tabs_bar.home' defaultMessage='Home' /></NavLink>,
<NavLink className='tabs-bar__link' to='/notifications' data-preview-title-id='column.notifications' data-preview-icon='bell' ><NotificationsCounterIcon /><FormattedMessage id='tabs_bar.notifications' defaultMessage='Notifications' /></NavLink>,
<NavLink className='tabs-bar__link' to='/timelines/public/local' data-preview-title-id='column.community' data-preview-icon='users' ><Icon id='users' fixedWidth /><FormattedMessage id='tabs_bar.local_timeline' defaultMessage='Local' /></NavLink>,
<NavLink className='tabs-bar__link' exact to='/timelines/public' data-preview-title-id='column.public' data-preview-icon='globe' ><Icon id='globe' fixedWidth /><FormattedMessage id='tabs_bar.federated_timeline' defaultMessage='Federated' /></NavLink>,
<NavLink className='tabs-bar__link optional' to='/search' data-preview-title-id='tabs_bar.search' data-preview-icon='bell' ><Icon id='search' fixedWidth /><FormattedMessage id='tabs_bar.search' defaultMessage='Search' /></NavLink>,
<NavLink className='tabs-bar__link' style={{ flexGrow: '0', flexBasis: '30px' }} to='/getting-started' data-preview-title-id='getting_started.heading' data-preview-icon='bars' ><Icon id='bars' fixedWidth /></NavLink>,
<NavLink
className='tabs-bar__link'
to='/timelines/home'
data-preview-title-id='column.home'
data-preview-icon='home'
><Icon
id='home'
fixedWidth
/><FormattedMessage
id='tabs_bar.home'
defaultMessage='Home'
/></NavLink >,
<NavLink
className='tabs-bar__link'
to='/notifications'
data-preview-title-id='column.notifications'
data-preview-icon='bell'
><NotificationsCounterIcon /><FormattedMessage
id='tabs_bar.notifications'
defaultMessage='Notifications'
/></NavLink >,
<NavLink
className='tabs-bar__link'
to='/timelines/public/local'
data-preview-title-id='column.community'
data-preview-icon='users'
><Icon
id='users'
fixedWidth
/><FormattedMessage
id='tabs_bar.local_timeline'
defaultMessage='Local'
/></NavLink >,
<NavLink
className='tabs-bar__link'
exact
to='/timelines/public'
data-preview-title-id='column.public'
data-preview-icon='globe'
><Icon
id='globe'
fixedWidth
/><FormattedMessage
id='tabs_bar.federated_timeline'
defaultMessage='Federated'
/></NavLink >,
<NavLink
className='tabs-bar__link optional'
to='/search'
data-preview-title-id='tabs_bar.search'
data-preview-icon='bell'
><Icon
id='search'
fixedWidth
/><FormattedMessage
id='tabs_bar.search'
defaultMessage='Search'
/></NavLink >,
<NavLink
className='tabs-bar__link'
style={{ flexGrow: '0', flexBasis: '30px' }}
to='/getting-started'
data-preview-title-id='getting_started.heading'
data-preview-icon='bars'
><Icon
id='bars'
fixedWidth
/></NavLink >,
];
export function getIndex (path) {
export function getIndex(path) {
return links.findIndex(link => link.props.to === path);
}
export function getLink (index) {
export function getLink(index) {
return links[index].props.to;
}
@ -29,13 +91,13 @@ export default @injectIntl
class TabsBar extends React.PureComponent {
static propTypes = {
intl: PropTypes.object.isRequired,
intl : PropTypes.object.isRequired,
history: PropTypes.object.isRequired,
}
};
setRef = ref => {
this.node = ref;
}
};
handleClick = (e) => {
// Only apply optimization for touch devices, which we assume are slower
@ -50,7 +112,6 @@ class TabsBar extends React.PureComponent {
const nextTab = tabs.find(tab => tab.contains(e.target));
const { props: { to } } = links[Array(...this.node.childNodes).indexOf(nextTab)];
if (currentTab !== nextTab) {
if (currentTab) {
currentTab.classList.remove('active');
@ -67,19 +128,28 @@ class TabsBar extends React.PureComponent {
});
}
}
};
render () {
render() {
const { intl: { formatMessage } } = this.props;
return (
<div className='tabs-bar__wrapper'>
<nav className='tabs-bar' ref={this.setRef}>
{links.map(link => React.cloneElement(link, { key: link.props.to, onClick: this.handleClick, 'aria-label': formatMessage({ id: link.props['data-preview-title-id'] }) }))}
</nav>
<nav
className='tabs-bar'
ref={this.setRef}
>
{links.map(link => React.cloneElement(link, {
key : link.props.to,
onClick : this.handleClick,
'aria-label': formatMessage({ id: link.props['data-preview-title-id'] }),
}))}
</nav >
<div id='tabs-bar__portal' />
</div>
</div >
);
}

View File

@ -160,3 +160,5 @@ button {
height: 100%;
}
}

View File

@ -2663,6 +2663,28 @@ a.account__display-name {
padding: 15px;
text-decoration: none;
.timelines & {
display: inline-block;
width: 20%;
display: inline-block !important;
float: left;
text-align: center;
span {
opacity: 0;
transition: opacity ease-in 1s;
}
&:hover {
span {
opacity: 1;
transition: opacity ease-in 0.2s;
}
}
}
&:hover,
&:focus,
&:active {

View File

@ -137,6 +137,13 @@
}
.getting-started__footer {
display: block;
position: fixed;
bottom: 0;
left: 1em;
width: 32vw;
z-index: 10;
text-align: right;
ul {
list-style-type: none;
@ -150,4 +157,8 @@
i {
margin: 0.5ch;
}
a {
margin-left: 2ch;
}
}

View File

@ -36,3 +36,21 @@ $media-modal-media-max-height: 80%;
color: #222;
}
.spacer {
display: block;
padding: 2em;
}
.small-texts {
.timelines {
.column-link {
}
span {
display: none;
}
}
}