Refactor and restyle UI (#645)
Tweaks to visual output and code organisation related to styles of: - sidebar (category grid, data view/edit, section headers and action buttons) - header/menu - map controls (search box) - layout (sidebar, menu, header sizes)
This commit is contained in:
parent
9219f76c12
commit
3a0c852088
@ -1,57 +1,37 @@
|
||||
/**
|
||||
* Data categories
|
||||
*/
|
||||
.data-category-list {
|
||||
padding: 0px 0 10px 9px;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
text-align: left;
|
||||
max-width: 480px;
|
||||
}
|
||||
.navbar .data-category-list {
|
||||
padding: 0px 0 0px 15px;
|
||||
}
|
||||
.data-category-list li {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
vertical-align: bottom;
|
||||
width: 110px;
|
||||
height: 110px;
|
||||
margin: 2px;
|
||||
box-shadow: 0 0 2px 3px #ffffff;
|
||||
transition: box-shadow 0.2s;
|
||||
}
|
||||
.navbar .data-category-list li {
|
||||
width: 105px;
|
||||
height: 105px;
|
||||
}
|
||||
.data-category-list li:nth-child(4n) {
|
||||
margin-right: 0;
|
||||
}
|
||||
.data-category-list li:hover {
|
||||
box-shadow: 0 0 2px 3px #00ffff;
|
||||
z-index: 1;
|
||||
}
|
||||
.data-category-list a {
|
||||
color: #222;
|
||||
text-decoration: none;
|
||||
}
|
||||
.data-category-list .category-link {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 0.1em;
|
||||
margin-bottom: 10px;
|
||||
padding: 2px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.data-category-list .category-link:hover,
|
||||
.data-category-list .category-link:active,
|
||||
.data-category-list .category-link:focus {
|
||||
color: #222;
|
||||
height: 340px;
|
||||
max-height: 340px;
|
||||
max-width: 470px;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.data-category-list .category {
|
||||
text-align: center;
|
||||
font-size: 1em;
|
||||
margin: 0 0 0.5em;
|
||||
.data-category-list li {
|
||||
box-sizing: border-box;
|
||||
flex-basis: 7rem;
|
||||
flex-grow: 1;
|
||||
max-height: 7em;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
@media(min-width:734px) {
|
||||
.data-category-list li {
|
||||
flex-basis: 24%;
|
||||
height: 6.75rem;
|
||||
flex-grow: 0;
|
||||
max-height: 6.75rem;
|
||||
}
|
||||
|
||||
.data-category-list li:hover {
|
||||
box-shadow: 0 0 2px 3px #00ffff;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
import React from 'react';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
|
||||
import { CategoryLink } from './category-link';
|
||||
import { ListWrapper } from '../components/list-wrapper';
|
||||
|
||||
import './categories.css';
|
||||
|
||||
@ -9,8 +11,8 @@ interface CategoriesProps {
|
||||
}
|
||||
|
||||
const Categories: React.FC<CategoriesProps> = (props) => (
|
||||
<ol className="data-category-list">
|
||||
<Category
|
||||
<ListWrapper className='data-category-list'>
|
||||
<CategoryLink
|
||||
title="Location"
|
||||
slug="location"
|
||||
help="https://pages.colouring.london/location"
|
||||
@ -18,7 +20,7 @@ const Categories: React.FC<CategoriesProps> = (props) => (
|
||||
mode={props.mode}
|
||||
building_id={props.building_id}
|
||||
/>
|
||||
<Category
|
||||
<CategoryLink
|
||||
title="Current Use"
|
||||
slug="use"
|
||||
help="https://pages.colouring.london/use"
|
||||
@ -26,7 +28,7 @@ const Categories: React.FC<CategoriesProps> = (props) => (
|
||||
mode={props.mode}
|
||||
building_id={props.building_id}
|
||||
/>
|
||||
<Category
|
||||
<CategoryLink
|
||||
title="Type"
|
||||
slug="type"
|
||||
help="https://pages.colouring.london/buildingtypology"
|
||||
@ -34,7 +36,7 @@ const Categories: React.FC<CategoriesProps> = (props) => (
|
||||
mode={props.mode}
|
||||
building_id={props.building_id}
|
||||
/>
|
||||
<Category
|
||||
<CategoryLink
|
||||
title="Age"
|
||||
slug="age"
|
||||
help="https://pages.colouring.london/age"
|
||||
@ -42,7 +44,7 @@ const Categories: React.FC<CategoriesProps> = (props) => (
|
||||
mode={props.mode}
|
||||
building_id={props.building_id}
|
||||
/>
|
||||
<Category
|
||||
<CategoryLink
|
||||
title="Size & Shape"
|
||||
slug="size"
|
||||
help="https://pages.colouring.london/shapeandsize"
|
||||
@ -50,7 +52,7 @@ const Categories: React.FC<CategoriesProps> = (props) => (
|
||||
mode={props.mode}
|
||||
building_id={props.building_id}
|
||||
/>
|
||||
<Category
|
||||
<CategoryLink
|
||||
title="Construction"
|
||||
slug="construction"
|
||||
help="https://pages.colouring.london/construction"
|
||||
@ -58,7 +60,7 @@ const Categories: React.FC<CategoriesProps> = (props) => (
|
||||
mode={props.mode}
|
||||
building_id={props.building_id}
|
||||
/>
|
||||
<Category
|
||||
<CategoryLink
|
||||
title="Streetscape"
|
||||
slug="streetscape"
|
||||
help="https://pages.colouring.london/greenery"
|
||||
@ -66,7 +68,7 @@ const Categories: React.FC<CategoriesProps> = (props) => (
|
||||
mode={props.mode}
|
||||
building_id={props.building_id}
|
||||
/>
|
||||
<Category
|
||||
<CategoryLink
|
||||
title="Team"
|
||||
slug="team"
|
||||
help="https://pages.colouring.london/team"
|
||||
@ -74,7 +76,7 @@ const Categories: React.FC<CategoriesProps> = (props) => (
|
||||
mode={props.mode}
|
||||
building_id={props.building_id}
|
||||
/>
|
||||
<Category
|
||||
<CategoryLink
|
||||
title="Planning"
|
||||
slug="planning"
|
||||
help="https://pages.colouring.london/planning"
|
||||
@ -82,7 +84,7 @@ const Categories: React.FC<CategoriesProps> = (props) => (
|
||||
mode={props.mode}
|
||||
building_id={props.building_id}
|
||||
/>
|
||||
<Category
|
||||
<CategoryLink
|
||||
title="Sustainability"
|
||||
slug="sustainability"
|
||||
help="https://pages.colouring.london/sustainability"
|
||||
@ -90,7 +92,7 @@ const Categories: React.FC<CategoriesProps> = (props) => (
|
||||
mode={props.mode}
|
||||
building_id={props.building_id}
|
||||
/>
|
||||
<Category
|
||||
<CategoryLink
|
||||
title="Dynamics"
|
||||
slug="dynamics"
|
||||
help="https://pages.colouring.london/dynamics"
|
||||
@ -98,7 +100,7 @@ const Categories: React.FC<CategoriesProps> = (props) => (
|
||||
mode={props.mode}
|
||||
building_id={props.building_id}
|
||||
/>
|
||||
<Category
|
||||
<CategoryLink
|
||||
title="Community"
|
||||
slug="community"
|
||||
help="https://pages.colouring.london/community"
|
||||
@ -106,38 +108,7 @@ const Categories: React.FC<CategoriesProps> = (props) => (
|
||||
mode={props.mode}
|
||||
building_id={props.building_id}
|
||||
/>
|
||||
</ol>
|
||||
</ListWrapper>
|
||||
);
|
||||
|
||||
interface CategoryProps {
|
||||
mode: 'view' | 'edit' | 'multi-edit';
|
||||
building_id?: number;
|
||||
slug: string;
|
||||
title: string;
|
||||
help: string;
|
||||
inactive: boolean;
|
||||
}
|
||||
|
||||
const Category: React.FC<CategoryProps> = (props) => {
|
||||
let categoryLink = `/${props.mode}/${props.slug}`;
|
||||
if (props.building_id != undefined) categoryLink += `/${props.building_id}`;
|
||||
|
||||
return (
|
||||
<li className={`category-block ${props.slug} background-${props.slug}`}>
|
||||
<NavLink
|
||||
className="category-link"
|
||||
to={categoryLink}
|
||||
title={
|
||||
(props.inactive)?
|
||||
'Coming soon… Click more info for details.'
|
||||
: 'View/Edit Map'
|
||||
}>
|
||||
<div className="category-title-container">
|
||||
<h3 className="category">{props.title}</h3>
|
||||
</div>
|
||||
</NavLink>
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
||||
export default Categories;
|
||||
|
22
app/src/frontend/building/category-link.css
Normal file
22
app/src/frontend/building/category-link.css
Normal file
@ -0,0 +1,22 @@
|
||||
.category-link {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
/* padding: 0.1em; */
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
a.category-link {
|
||||
color: #222;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.category-title {
|
||||
display: block;
|
||||
text-align: center;
|
||||
font-size: 1em;
|
||||
margin: 0;
|
||||
}
|
||||
|
33
app/src/frontend/building/category-link.tsx
Normal file
33
app/src/frontend/building/category-link.tsx
Normal file
@ -0,0 +1,33 @@
|
||||
import React from 'react';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
|
||||
import './category-link.css';
|
||||
|
||||
interface CategoryLinkProps {
|
||||
mode: 'view' | 'edit' | 'multi-edit';
|
||||
building_id?: number;
|
||||
slug: string;
|
||||
title: string;
|
||||
help: string;
|
||||
inactive: boolean;
|
||||
}
|
||||
|
||||
const CategoryLink: React.FC<CategoryLinkProps> = (props) => {
|
||||
let categoryLink = `/${props.mode}/${props.slug}`;
|
||||
if (props.building_id != undefined) categoryLink += `/${props.building_id}`;
|
||||
|
||||
return (
|
||||
<NavLink
|
||||
className={`category-link background-${props.slug}`}
|
||||
to={categoryLink}
|
||||
title={
|
||||
(props.inactive)?
|
||||
'Coming soon… Click more info for details.'
|
||||
: 'View/Edit Map'
|
||||
}>
|
||||
<h3 className="category-title">{props.title}</h3>
|
||||
</NavLink>
|
||||
);
|
||||
};
|
||||
|
||||
export { CategoryLink };
|
53
app/src/frontend/building/container-header.css
Normal file
53
app/src/frontend/building/container-header.css
Normal file
@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Data section headers
|
||||
*/
|
||||
.section-header {
|
||||
padding: 0 0.5em;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
|
||||
text-decoration: none;
|
||||
color: #222;
|
||||
z-index: 1000;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.section-header .h2 {
|
||||
display: inline-block;
|
||||
flex-basis: 150px;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 1;
|
||||
margin: 0.75rem 0 0.5em 0.1em;
|
||||
font-size: 1.5rem;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.section-header .h2 a.icon-button.back {
|
||||
line-height: 1em;
|
||||
vertical-align: top;
|
||||
margin-right: 0.3em;
|
||||
}
|
||||
|
||||
.section-header .section-header-actions {
|
||||
display: inline-block;
|
||||
flex-basis: 200px;
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
align-items: center;
|
||||
|
||||
justify-content: flex-end;
|
||||
margin-left: -5px;
|
||||
}
|
||||
.section-header-actions .icon-button {
|
||||
display: inline-block;
|
||||
font-size: 0.8333rem;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.section-header-actions .icon-button:hover svg,
|
||||
.section-header-actions .icon-button:active svg {
|
||||
color: rgb(11, 225, 225);
|
||||
}
|
@ -1,15 +1,27 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { BackIcon } from '../components/icons';
|
||||
|
||||
|
||||
import './container-header.css';
|
||||
|
||||
interface ContainerHeaderProps {
|
||||
cat?: string;
|
||||
backLink: string;
|
||||
backLink?: string;
|
||||
title: string;
|
||||
}
|
||||
|
||||
const ContainerHeader: React.FunctionComponent<ContainerHeaderProps> = (props) => (
|
||||
<header className={`section-header view ${props.cat ? props.cat : ''} ${props.cat ? `background-${props.cat}` : ''}`}>
|
||||
<h2 className="h2">{props.title}</h2>
|
||||
<nav className="icon-buttons">
|
||||
<h2 className="h2">
|
||||
{props.backLink &&
|
||||
<Link className="icon-button back" to={props.backLink}>
|
||||
<BackIcon />
|
||||
</Link>
|
||||
}
|
||||
{props.title}
|
||||
</h2>
|
||||
<nav className="section-header-actions">
|
||||
{props.children}
|
||||
</nav>
|
||||
</header>
|
||||
|
@ -14,4 +14,5 @@
|
||||
|
||||
.data-entry-group-body {
|
||||
padding-left: 1rem;
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
|
43
app/src/frontend/building/data-components/data-title.css
Normal file
43
app/src/frontend/building/data-components/data-title.css
Normal file
@ -0,0 +1,43 @@
|
||||
.data-title {
|
||||
margin-top: 1em;
|
||||
margin-bottom: 0.2em;
|
||||
}
|
||||
|
||||
.data-title * {
|
||||
font-size: 0.8333rem;
|
||||
}
|
||||
|
||||
.data-title-text {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.data-title-actions {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.data-title:after {
|
||||
content:"";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
|
||||
.data-title label {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.data-title-actions .icon-button {
|
||||
font-size: 0.8333rem;
|
||||
margin-left: 0.7em;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
.data-title-actions .icon-button input[type=checkbox] {
|
||||
margin: 0;
|
||||
margin-left: 0.3em;
|
||||
padding: 0;
|
||||
vertical-align: middle;
|
||||
}
|
@ -3,6 +3,7 @@ import React from 'react';
|
||||
import Tooltip from '../../components/tooltip';
|
||||
import { CopyProps } from '../data-containers/category-view-props';
|
||||
|
||||
import './data-title.css';
|
||||
|
||||
interface DataTitleProps {
|
||||
title: string;
|
||||
@ -30,22 +31,24 @@ interface DataTitleCopyableProps {
|
||||
const DataTitleCopyable: React.FunctionComponent<DataTitleCopyableProps> = (props) => {
|
||||
return (
|
||||
<div className="data-title">
|
||||
{ props.tooltip? <Tooltip text={ props.tooltip } /> : null }
|
||||
{ (props.copy && props.copy.copying && props.slug && !props.disabled)?
|
||||
<div className="icon-buttons">
|
||||
<label className="icon-button copy">
|
||||
Copy
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={props.copy.copyingKey(props.slug)}
|
||||
onChange={() => props.copy.toggleCopyAttribute(props.slug)}/>
|
||||
</label>
|
||||
</div>
|
||||
: null
|
||||
}
|
||||
<label htmlFor={props.slug}>
|
||||
{ props.title }
|
||||
</label>
|
||||
<div className="data-title-text">
|
||||
<label htmlFor={props.slug}>
|
||||
{ props.title }
|
||||
</label>
|
||||
</div>
|
||||
<div className="data-title-actions icon-buttons">
|
||||
{ (props.copy && props.copy.copying && props.slug && !props.disabled)?
|
||||
<label className="icon-button copy">
|
||||
Copy
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={props.copy.copyingKey(props.slug)}
|
||||
onChange={() => props.copy.toggleCopyAttribute(props.slug)}/>
|
||||
</label>
|
||||
: null
|
||||
}
|
||||
{ props.tooltip? <Tooltip text={ props.tooltip } /> : null }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -1,4 +1,5 @@
|
||||
.verification-container {
|
||||
margin-top: 0.5em;
|
||||
font-size: 0.83333rem;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
@ -262,7 +262,6 @@ const withCopyEdit = (WrappedComponent: React.ComponentType<CategoryViewProps>)
|
||||
className="data-section">
|
||||
<ContainerHeader
|
||||
cat={this.props.cat}
|
||||
backLink={headerBackLink}
|
||||
title={this.props.title}
|
||||
>
|
||||
{
|
||||
|
@ -6,160 +6,94 @@
|
||||
top: 75px;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 95%;
|
||||
width: calc(100% - 40px);
|
||||
border-right: 1px solid #000;
|
||||
z-index: 1001;
|
||||
transition: transform 0.3s;
|
||||
transform: translateX(0);
|
||||
|
||||
width: 65%;
|
||||
min-width: 280px;
|
||||
max-width: 95%;
|
||||
max-width: calc(100vw - 40px);
|
||||
|
||||
border-right: 1px solid #000;
|
||||
}
|
||||
|
||||
.info-container.offscreen {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
.info-container-collapse {
|
||||
position: absolute;
|
||||
right: -32px;
|
||||
top: 2rem;
|
||||
left: 100%;
|
||||
top: 4rem;
|
||||
|
||||
width: 2rem;
|
||||
padding: 2.5rem 0rem;
|
||||
|
||||
border-radius: 0 .25rem .25rem 0;
|
||||
}
|
||||
@media (min-width: 990px){
|
||||
|
||||
@media (min-width: 510px) {
|
||||
.info-container {
|
||||
width: 480px; /* to match .main-header menu width */
|
||||
max-width: 470px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 734px){
|
||||
.info-container {
|
||||
width: 470px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 990px){
|
||||
.info-container.offscreen {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
.info-container-collapse {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.info-container-inner {
|
||||
overflow-y: auto;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0 0 2em;
|
||||
overflow-y: scroll;
|
||||
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data section headers
|
||||
*/
|
||||
.section-header {
|
||||
display: block;
|
||||
position: relative;
|
||||
clear: both;
|
||||
text-decoration: none;
|
||||
color: #222;
|
||||
padding: 0.75rem 0.25rem 0.5rem 0.75rem;
|
||||
z-index: 1000;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
.section-header h2,
|
||||
.section-header .icon-buttons {
|
||||
display: inline-block;
|
||||
}
|
||||
.section-header .h2 {
|
||||
font-size: 1.5rem;
|
||||
margin: 0.25rem 0;
|
||||
}
|
||||
.section-header .icon-buttons {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 7px;
|
||||
padding: 0.7rem 0.5rem 0.5rem 0;
|
||||
}
|
||||
.icon-buttons .icon-button {
|
||||
margin-left: 7px;
|
||||
}
|
||||
|
||||
/**
|
||||
* Icon buttons
|
||||
*/
|
||||
.icon-button {
|
||||
.icon-button {
|
||||
padding: 0;
|
||||
|
||||
display: inline-block;
|
||||
background-color: transparent;
|
||||
font-size: 0.8333rem;
|
||||
|
||||
outline: none;
|
||||
border: none;
|
||||
|
||||
color: #222;
|
||||
vertical-align: top;
|
||||
}
|
||||
.icon-button:hover {
|
||||
color: #222;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
.icon-button.tooltip-hint {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.icon-button svg {
|
||||
margin-left: 0.3em;
|
||||
background-color: transparent;
|
||||
transition: background-color color 0.2s;
|
||||
display: inline-block;
|
||||
font-size: 1.2em;
|
||||
|
||||
color: #222;
|
||||
margin-top: 2px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
padding: 6px;
|
||||
border-radius: 15px;
|
||||
margin: 0 0.05rem;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.svg-inline--fa.fa-w-11,
|
||||
.svg-inline--fa.fa-w-16,
|
||||
.svg-inline--fa.fa-w-18,
|
||||
.svg-inline--fa.fa-w-8 {
|
||||
width: 30px;
|
||||
}
|
||||
.icon-button.edit:active svg,
|
||||
.icon-button.edit:hover svg,
|
||||
.icon-button.view:active svg,
|
||||
.icon-button.view:hover svg {
|
||||
color: rgb(11, 225, 225);
|
||||
}
|
||||
.icon-button.help,
|
||||
.icon-button.copy,
|
||||
.icon-button.history {
|
||||
margin-top: 4px;
|
||||
}
|
||||
.data-section label .icon-buttons .icon-button.copy {
|
||||
margin-top: 0px;
|
||||
}
|
||||
.icon-button.copy:hover,
|
||||
.icon-button.help:hover {
|
||||
color: rgb(0, 81, 255)
|
||||
}
|
||||
.icon-button.tooltip-hint.active svg,
|
||||
.icon-button.tooltip-hint:hover svg {
|
||||
color: rgb(255, 11, 245);
|
||||
}
|
||||
.icon-button.close-edit svg {
|
||||
margin-top: -1px;
|
||||
}
|
||||
.icon-button.close-edit:hover svg {
|
||||
color: rgb(255, 72, 11)
|
||||
}
|
||||
.icon-button.save:hover svg {
|
||||
color: rgb(11, 225, 72);
|
||||
}
|
||||
.data-title .icon-buttons {
|
||||
float: right;
|
||||
}
|
||||
|
||||
/* Back button */
|
||||
.icon-button.back,
|
||||
.icon-button.back:hover {
|
||||
padding: 5px 1px;
|
||||
background-color: transparent;
|
||||
}
|
||||
.icon-button.back:hover svg {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data list sections
|
||||
@ -203,8 +137,6 @@
|
||||
}
|
||||
.data-list dt,
|
||||
.data-section label {
|
||||
display: block;
|
||||
margin: 0.5em 0 0;
|
||||
font-size: 0.8333rem;
|
||||
font-weight: normal;
|
||||
color: #555;
|
||||
|
23
app/src/frontend/components/list-wrapper.tsx
Normal file
23
app/src/frontend/components/list-wrapper.tsx
Normal file
@ -0,0 +1,23 @@
|
||||
import React from 'react';
|
||||
|
||||
interface ListWrapperProps {
|
||||
listType?: 'ul' | 'ol';
|
||||
className?: string;
|
||||
elementClassName?: string;
|
||||
}
|
||||
|
||||
export const ListWrapper: React.FC<ListWrapperProps> = (props) => {
|
||||
|
||||
const ListTag=props.listType ?? 'ol';
|
||||
|
||||
return (
|
||||
<ListTag className={props.className}>
|
||||
{
|
||||
React.Children.map(props.children, (elem) => (
|
||||
<li className={props.elementClassName}>
|
||||
{elem}
|
||||
</li>
|
||||
))
|
||||
}
|
||||
</ListTag>);
|
||||
};
|
@ -4,24 +4,28 @@
|
||||
.tooltip-wrap {
|
||||
float: right;
|
||||
position: relative;
|
||||
top: -3px;
|
||||
right: -4px;
|
||||
}
|
||||
.tooltip-wrap .icon-button svg {
|
||||
margin-top: -2px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
padding-right: 0.3em;
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
text-transform: none;
|
||||
text-align: left;
|
||||
width: 11em;
|
||||
right: 0;
|
||||
top: 27px;
|
||||
top: 100%;
|
||||
opacity: 1;
|
||||
}
|
||||
.tooltip .arrow {
|
||||
right: 7px;
|
||||
right: 0.4em;
|
||||
}
|
||||
|
||||
.tooltip a {
|
||||
color: rgb(255, 11, 245);
|
||||
}
|
||||
|
||||
.icon-button.tooltip-hint.active svg,
|
||||
.icon-button.tooltip-hint:hover svg {
|
||||
color: rgb(255, 11, 245);
|
||||
}
|
@ -6,13 +6,18 @@
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 76px;
|
||||
height: 76px; /* sync with map-container positioning */
|
||||
width: 100%;
|
||||
min-width: 320px; /* to avoid logo line wrap*/
|
||||
text-decoration: none;
|
||||
}
|
||||
@media (min-width: 990px){
|
||||
.main-header {
|
||||
width: 480px; /* to match .info-container menu width */
|
||||
width: 470px;
|
||||
}
|
||||
|
||||
.nav-header {
|
||||
border-right: 1px solid #000;
|
||||
}
|
||||
}
|
||||
.main-header.navbar {
|
||||
@ -25,7 +30,6 @@
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
background: #fff;
|
||||
border-right: 1px solid #000;
|
||||
}
|
||||
.nav-header a {
|
||||
padding: 0;
|
||||
@ -51,7 +55,11 @@
|
||||
transition: transform 0.3s;
|
||||
transform: translateY(0);
|
||||
background: #fff;
|
||||
border-right: 1px solid #000;
|
||||
}
|
||||
@media (min-width: 990px){
|
||||
.navbar-collapse {
|
||||
border-right: 1px solid #000;
|
||||
}
|
||||
}
|
||||
.main-header .navbar-collapse > ul:last-child {
|
||||
padding-bottom: 5rem;
|
||||
|
@ -1,13 +1,15 @@
|
||||
.map-container {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
top: 76px; /* sync with header positioning */
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
min-width: 320px;
|
||||
}
|
||||
@media (min-width: 990px) {
|
||||
.map-container {
|
||||
left: 480px;
|
||||
top: 0;
|
||||
left: 470px;
|
||||
}
|
||||
}
|
||||
.leaflet-container {
|
||||
@ -32,6 +34,7 @@
|
||||
left: 0.5rem;
|
||||
z-index: 1000;
|
||||
padding: 0.5rem 0.75rem;
|
||||
width: 250px;
|
||||
background: #fff;
|
||||
border: 1px solid #fff;
|
||||
border-radius: 4px;
|
||||
|
@ -3,48 +3,62 @@
|
||||
top: 0.5rem;
|
||||
left: 0.5rem;
|
||||
z-index: 1000;
|
||||
max-width:80%;
|
||||
max-width:250px;
|
||||
}
|
||||
.search-box form,
|
||||
.search-box .search-box-results {
|
||||
|
||||
.search-box-pane {
|
||||
max-height: 2.4rem;
|
||||
overflow: hidden;
|
||||
|
||||
border-radius: 4px;
|
||||
background: #fff;
|
||||
box-shadow: 0px 0px 1px 1px #222222;
|
||||
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
}
|
||||
.search-box button {
|
||||
margin-bottom: 0;
|
||||
|
||||
.search-box .collapse-btn {
|
||||
width: 2rem;
|
||||
flex-shrink: 0;
|
||||
line-height: 2.3rem;
|
||||
text-align: center;
|
||||
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
}
|
||||
.search-box .collapse-btn.active {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.search-box input.form-control {
|
||||
flex: 1;
|
||||
padding: 0.1rem 0.1rem;
|
||||
max-width: 157px;
|
||||
}
|
||||
.search-box .btn {
|
||||
padding: 0.25rem 0.2rem;
|
||||
margin: 0.1rem;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.search-box .search-box-results {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
right: 0;
|
||||
left: 2rem;
|
||||
|
||||
margin-top: 0.25rem;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
|
||||
border-radius: 4px;
|
||||
background: #fff;
|
||||
box-shadow: 0px 0px 1px 1px #222222;
|
||||
}
|
||||
.search-box-result {
|
||||
display: block;
|
||||
padding: 0.25rem 0.5rem;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
.collapse-btn {
|
||||
position: absolute;
|
||||
top: 0.5rem;
|
||||
left: 0.5rem;
|
||||
z-index: 1000;
|
||||
background: #fff;
|
||||
border-radius: 2px;
|
||||
box-shadow: 0px 0px 1px 1px #222222;
|
||||
}
|
||||
.search-box .form-control {
|
||||
padding: 0.1rem 0.1rem;
|
||||
width: 180px;
|
||||
}
|
||||
.search-box .btn {
|
||||
padding: 0.25rem 0.2rem;
|
||||
margin-right: 0.1rem;
|
||||
}
|
||||
@media (min-width: 990px) {
|
||||
/* The following is a fix (?) for the truncation of the "Search for postcode" text */
|
||||
.form-inline .form-control {
|
||||
width: 200px;
|
||||
}
|
||||
}
|
||||
}
|
@ -54,11 +54,14 @@ class SearchBox extends Component<SearchBoxProps, SearchBoxState> {
|
||||
|
||||
// Update search term
|
||||
handleChange(e) {
|
||||
const targetValue = e.target.value;
|
||||
|
||||
this.setState({
|
||||
q: e.target.value
|
||||
q: targetValue
|
||||
});
|
||||
// If the ‘clear’ icon has been clicked, clear results list as well
|
||||
if(e.target.value === '') {
|
||||
|
||||
// Clear results if the query is changed sufficiently or deleted
|
||||
if(targetValue === '' || !this.state.q.startsWith(targetValue) ) {
|
||||
this.clearResults();
|
||||
}
|
||||
}
|
||||
@ -137,16 +140,20 @@ class SearchBox extends Component<SearchBoxProps, SearchBoxState> {
|
||||
// On a real mobile device onResize() gets called when the virtual keyboard pops up (e.g. when entering search text)
|
||||
// so be careful what states are changed in this method (i.e. don't collapse the search box here)
|
||||
onResize(e) {
|
||||
this.setState({smallScreen: (e.target.innerWidth < 768)});
|
||||
this.setState({smallScreen: (e.target.innerWidth < 990)});
|
||||
}
|
||||
|
||||
render() {
|
||||
// if the current state is collapsed (and a mobile device) just render the icon
|
||||
if(this.state.collapsedSearch && this.state.smallScreen){
|
||||
return(
|
||||
<div className="collapse-btn" onClick={this.expandSearch}>
|
||||
<SearchIcon />
|
||||
</div>
|
||||
<div className="search-box">
|
||||
<div className="search-box-pane">
|
||||
<div className="collapse-btn active" onClick={this.expandSearch}>
|
||||
<SearchIcon />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -177,22 +184,25 @@ class SearchBox extends Component<SearchBoxProps, SearchBoxState> {
|
||||
: null;
|
||||
return (
|
||||
<div className="search-box" onKeyDown={this.handleKeyPress}>
|
||||
<form onSubmit={this.search} className="form-inline">
|
||||
<div onClick={this.state.smallScreen ? this.expandSearch : null}>
|
||||
<div className="search-box-pane">
|
||||
<div className={`collapse-btn ${this.state.smallScreen ? 'active' : ''}`} onClick={this.state.smallScreen ? this.expandSearch : null}>
|
||||
<SearchIcon/>
|
||||
</div>
|
||||
<input
|
||||
className="form-control"
|
||||
type="search"
|
||||
id="search-box-q"
|
||||
name="q"
|
||||
value={this.state.q}
|
||||
placeholder="Search for a postcode"
|
||||
aria-label="Search for a postcode"
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
<button className="btn btn-outline-dark" type="submit">Search</button>
|
||||
</form>
|
||||
<form onSubmit={this.search} className="form-inline d-flex flex-nowrap">
|
||||
<input
|
||||
className="form-control"
|
||||
type="search"
|
||||
id="search-box-q"
|
||||
name="q"
|
||||
value={this.state.q}
|
||||
placeholder="Type a postcode..."
|
||||
aria-label="Type a postcode..."
|
||||
onChange={this.handleChange}
|
||||
maxLength={8}
|
||||
/>
|
||||
<button className="search-btn btn btn-outline-dark" type="submit">Search</button>
|
||||
</form>
|
||||
</div>
|
||||
{ resultsList }
|
||||
</div>
|
||||
);
|
||||
|
@ -9,9 +9,9 @@
|
||||
margin: 1em 1em;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
flex-grow: 1;
|
||||
height: 4em;
|
||||
}
|
||||
|
||||
.image-row img {
|
||||
@ -19,4 +19,12 @@
|
||||
max-height: 100%;
|
||||
max-width: 100%;
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
.cl-logo {
|
||||
height: 4em;
|
||||
}
|
||||
|
||||
.turing-logo {
|
||||
height: 4em;
|
||||
}
|
@ -32,8 +32,8 @@ const Welcome = () => (
|
||||
Start Colouring Here!
|
||||
</Link>
|
||||
<div className="image-row">
|
||||
<img src="images/logo-cc.jpg" alt="Colouring Cities Research Programme"></img>
|
||||
<img src="images/logo-turing.jpg" alt="Alan Turing Institute"></img>
|
||||
<img className="cl-logo" src="images/logo-cc.jpg" alt="Colouring Cities Research Programme"></img>
|
||||
<img className="turing-logo" src="images/logo-turing.jpg" alt="Alan Turing Institute"></img>
|
||||
</div>
|
||||
<div className="image-row">
|
||||
<img src="images/supporter-logos.png" alt="Colouring London collaborating organisations: The Bartlett UCL, Ordnance Survey, Historic England, Greater London Authority" />
|
||||
|
@ -23,7 +23,7 @@ article {
|
||||
@media (min-width: 990px) {
|
||||
article {
|
||||
top: 0px;
|
||||
left: 480px;
|
||||
left: 470px;
|
||||
}
|
||||
}
|
||||
article section {
|
||||
|
Loading…
Reference in New Issue
Block a user