feat: add case studies
@@ -23,14 +23,6 @@ module.exports = {
|
||||
{
|
||||
title: "Tiling",
|
||||
to: "/services/tiling"
|
||||
},
|
||||
{
|
||||
title: "Electrics",
|
||||
to: "/services/electrics"
|
||||
},
|
||||
{
|
||||
title: "Carpentry",
|
||||
to: "/services/carpentry"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
115
package-lock.json
generated
@@ -1134,6 +1134,15 @@
|
||||
"to-fast-properties": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"@browniebroke/gatsby-image-gallery": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@browniebroke/gatsby-image-gallery/-/gatsby-image-gallery-4.0.2.tgz",
|
||||
"integrity": "sha512-kP6vxq4PkI2Lf6pHngcwdHY2pIm16K3eKYt99GnEOYSpucIbKUoar5WmZFSg3wWXc/48SiDzPpkp2yYuAsYZFw==",
|
||||
"requires": {
|
||||
"react-image-lightbox": "^5.1.1",
|
||||
"styled-components": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"@emotion/babel-plugin": {
|
||||
"version": "11.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.1.2.tgz",
|
||||
@@ -1206,6 +1215,14 @@
|
||||
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
|
||||
"integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow=="
|
||||
},
|
||||
"@emotion/is-prop-valid": {
|
||||
"version": "0.8.8",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz",
|
||||
"integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==",
|
||||
"requires": {
|
||||
"@emotion/memoize": "0.7.4"
|
||||
}
|
||||
},
|
||||
"@emotion/memoize": {
|
||||
"version": "0.7.4",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz",
|
||||
@@ -1264,6 +1281,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@emotion/stylis": {
|
||||
"version": "0.8.5",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz",
|
||||
"integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ=="
|
||||
},
|
||||
"@emotion/unitless": {
|
||||
"version": "0.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz",
|
||||
@@ -3532,6 +3554,22 @@
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-remove-graphql-queries/-/babel-plugin-remove-graphql-queries-2.13.0.tgz",
|
||||
"integrity": "sha512-6sL3JVKDa3OjXtmBYrr467BnQeUjNI7p2dy+aBwbB8WqChHLJOFh5+lxfzC0z/7hBehqmWpBV7xHfZdIP1lAzQ=="
|
||||
},
|
||||
"babel-plugin-styled-components": {
|
||||
"version": "1.12.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-1.12.0.tgz",
|
||||
"integrity": "sha512-FEiD7l5ZABdJPpLssKXjBUJMYqzbcNzBowfXDCdJhOpbhWiewapUaY+LZGT8R4Jg2TwOjGjG4RKeyrO5p9sBkA==",
|
||||
"requires": {
|
||||
"@babel/helper-annotate-as-pure": "^7.0.0",
|
||||
"@babel/helper-module-imports": "^7.0.0",
|
||||
"babel-plugin-syntax-jsx": "^6.18.0",
|
||||
"lodash": "^4.17.11"
|
||||
}
|
||||
},
|
||||
"babel-plugin-syntax-jsx": {
|
||||
"version": "6.18.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
|
||||
"integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY="
|
||||
},
|
||||
"babel-plugin-transform-react-remove-prop-types": {
|
||||
"version": "0.4.24",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz",
|
||||
@@ -4551,6 +4589,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"camelize": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz",
|
||||
"integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs="
|
||||
},
|
||||
"caniuse-api": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz",
|
||||
@@ -5511,6 +5554,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"css-color-keywords": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",
|
||||
"integrity": "sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU="
|
||||
},
|
||||
"css-color-names": {
|
||||
"version": "0.0.4",
|
||||
"resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz",
|
||||
@@ -5635,6 +5683,16 @@
|
||||
"fastparse": "^1.1.2"
|
||||
}
|
||||
},
|
||||
"css-to-react-native": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.0.0.tgz",
|
||||
"integrity": "sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ==",
|
||||
"requires": {
|
||||
"camelize": "^1.0.0",
|
||||
"css-color-keywords": "^1.0.0",
|
||||
"postcss-value-parser": "^4.0.2"
|
||||
}
|
||||
},
|
||||
"css-tree": {
|
||||
"version": "1.0.0-alpha.37",
|
||||
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz",
|
||||
@@ -7391,6 +7449,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"exenv": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz",
|
||||
"integrity": "sha1-KueOhdmJQVhnCwPUe+wfA72Ru50="
|
||||
},
|
||||
"exif-parser": {
|
||||
"version": "0.1.12",
|
||||
"resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz",
|
||||
@@ -15423,6 +15486,15 @@
|
||||
"source-map": "^0.7.3"
|
||||
}
|
||||
},
|
||||
"react-image-lightbox": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/react-image-lightbox/-/react-image-lightbox-5.1.1.tgz",
|
||||
"integrity": "sha512-GprldD8AqpRb2hsOdns3sI7Xeo9hJlcybDxuli4RB+ml1J/GaFaUuRkT/7IrTLv2+4vkR74ahz2LD0HOUHI7wA==",
|
||||
"requires": {
|
||||
"prop-types": "^15.6.2",
|
||||
"react-modal": "^3.8.1"
|
||||
}
|
||||
},
|
||||
"react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
@@ -15433,6 +15505,17 @@
|
||||
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
||||
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
||||
},
|
||||
"react-modal": {
|
||||
"version": "3.12.1",
|
||||
"resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.12.1.tgz",
|
||||
"integrity": "sha512-WGuXn7Fq31PbFJwtWmOk+jFtGC7E9tJVbFX0lts8ZoS5EPi9+WWylUJWLKKVm3H4GlQ7ZxY7R6tLlbSIBQ5oZA==",
|
||||
"requires": {
|
||||
"exenv": "^1.2.0",
|
||||
"prop-types": "^15.5.10",
|
||||
"react-lifecycles-compat": "^3.0.0",
|
||||
"warning": "^4.0.3"
|
||||
}
|
||||
},
|
||||
"react-refresh": {
|
||||
"version": "0.8.3",
|
||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz",
|
||||
@@ -17506,6 +17589,38 @@
|
||||
"inline-style-parser": "0.1.1"
|
||||
}
|
||||
},
|
||||
"styled-components": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.2.1.tgz",
|
||||
"integrity": "sha512-sBdgLWrCFTKtmZm/9x7jkIabjFNVzCUeKfoQsM6R3saImkUnjx0QYdLwJHBjY9ifEcmjDamJDVfknWm1yxZPxQ==",
|
||||
"requires": {
|
||||
"@babel/helper-module-imports": "^7.0.0",
|
||||
"@babel/traverse": "^7.4.5",
|
||||
"@emotion/is-prop-valid": "^0.8.8",
|
||||
"@emotion/stylis": "^0.8.4",
|
||||
"@emotion/unitless": "^0.7.4",
|
||||
"babel-plugin-styled-components": ">= 1",
|
||||
"css-to-react-native": "^3.0.0",
|
||||
"hoist-non-react-statics": "^3.0.0",
|
||||
"shallowequal": "^1.1.0",
|
||||
"supports-color": "^5.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"requires": {
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"stylehacks": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz",
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@browniebroke/gatsby-image-gallery": "^4.0.2",
|
||||
"@emotion/react": "^11.1.4",
|
||||
"@emotion/styled": "^11.0.0",
|
||||
"@fontsource/cooper-hewitt": "^4.1.0",
|
||||
|
||||
15
src/components/custom-gallery.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import React from "react";
|
||||
import Gallery from "@browniebroke/gatsby-image-gallery";
|
||||
import styled from "@emotion/styled";
|
||||
|
||||
const Container = styled.div`
|
||||
padding: 0 15px; // Offset negative margin in Gallery
|
||||
`;
|
||||
|
||||
export default function CustomGallery({ ...other }) {
|
||||
return (
|
||||
<Container>
|
||||
<Gallery {...other} />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
@@ -5,7 +5,8 @@ import { css } from "@emotion/react";
|
||||
const Container = styled.header`
|
||||
position: relative;
|
||||
height: 50vh;
|
||||
color: white;
|
||||
min-height: 280px;
|
||||
color: var(--color-white);
|
||||
${props => props.avoidNav && `margin-top: 40px;`}
|
||||
`;
|
||||
|
||||
@@ -47,6 +48,8 @@ export default function Header({
|
||||
map,
|
||||
position = "middle middle",
|
||||
avoidNav,
|
||||
variant,
|
||||
swap,
|
||||
children
|
||||
}) {
|
||||
const [posY, posX] = position.split(" ");
|
||||
|
||||
@@ -55,7 +55,8 @@ export default function Heading({
|
||||
return (
|
||||
<Container
|
||||
size={sizes[el]}
|
||||
shadowSize={shadowSizes[size]}
|
||||
el={el}
|
||||
shadowSize={el === "h1" ? shadowSizes[size] : 0}
|
||||
shadowColor={shadowColors[color]}
|
||||
{...other}
|
||||
>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
export { default as Button } from "./button";
|
||||
export { default as Card } from "./card";
|
||||
export { default as Content } from "./content";
|
||||
export { default as CustomGallery } from "./custom-gallery";
|
||||
export { default as CustomSlick } from "./custom-slick";
|
||||
export { default as Footer } from "./footer";
|
||||
export { default as Grid } from "./grid";
|
||||
@@ -18,5 +19,6 @@ export { default as NavLink } from "./nav-link";
|
||||
export { default as Nav } from "./nav";
|
||||
export { default as ReviewSummary } from "./review-summary";
|
||||
export { default as Section } from "./section";
|
||||
export { default as Table } from "./table";
|
||||
export { default as Text } from "./text";
|
||||
export { default as Tile } from "./tile";
|
||||
|
||||
21
src/components/table.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import React from "react";
|
||||
import styled from "@emotion/styled";
|
||||
|
||||
const CustomTable = styled.table`
|
||||
margin-bottom: var(--spacing-y-md);
|
||||
border-collapse: collapse;
|
||||
|
||||
td {
|
||||
padding: var(--spacing-y-xs) var(--spacing-x-sm);
|
||||
border: 1px solid var(--color-dark-grey);
|
||||
}
|
||||
|
||||
td:first-of-type {
|
||||
font-weight: 700;
|
||||
text-align: right;
|
||||
}
|
||||
`;
|
||||
|
||||
export default function Table({ children }) {
|
||||
return <CustomTable>{children}</CustomTable>;
|
||||
}
|
||||
3
src/icons/team.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512">
|
||||
<path fill="currentColor" d="M96 224c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm448 0c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm32 32h-64c-17.6 0-33.5 7.1-45.1 18.6 40.3 22.1 68.9 62 75.1 109.4h66c17.7 0 32-14.3 32-32v-32c0-35.3-28.7-64-64-64zm-256 0c61.9 0 112-50.1 112-112S381.9 32 320 32 208 82.1 208 144s50.1 112 112 112zm76.8 32h-8.3c-20.8 10-43.9 16-68.5 16s-47.6-6-68.5-16h-8.3C179.6 288 128 339.6 128 403.2V432c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48v-28.8c0-63.6-51.6-115.2-115.2-115.2zm-223.7-13.4C161.5 263.1 145.6 256 128 256H64c-35.3 0-64 28.7-64 64v32c0 17.7 14.3 32 32 32h65.9c6.3-47.4 34.9-87.3 75.2-109.4z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 803 B |
BIN
src/images/banner_bathroom.jpg
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
src/images/banner_tiling.jpg
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
src/images/bathroom-cs1a.jpg
Normal file
|
After Width: | Height: | Size: 166 KiB |
BIN
src/images/bathroom-cs1b.jpg
Normal file
|
After Width: | Height: | Size: 192 KiB |
BIN
src/images/bathroom-cs1c.jpg
Normal file
|
After Width: | Height: | Size: 172 KiB |
BIN
src/images/bathroom-cs1d.jpg
Normal file
|
After Width: | Height: | Size: 214 KiB |
BIN
src/images/bathroom-cs1e.jpg
Normal file
|
After Width: | Height: | Size: 160 KiB |
BIN
src/images/bathroom-cs2a.jpg
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
src/images/bathroom-cs2b.jpg
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
src/images/bathroom-cs2c.jpg
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
src/images/bathroom-cs3a.jpg
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
src/images/bathroom-cs3b.jpg
Normal file
|
After Width: | Height: | Size: 919 KiB |
BIN
src/images/bathroom-cs3c.jpg
Normal file
|
After Width: | Height: | Size: 843 KiB |
BIN
src/images/bathroom-cs4a.jpg
Normal file
|
After Width: | Height: | Size: 113 KiB |
BIN
src/images/bathroom-cs4b.jpg
Normal file
|
After Width: | Height: | Size: 152 KiB |
BIN
src/images/bathroom-cs4c.jpg
Normal file
|
After Width: | Height: | Size: 157 KiB |
BIN
src/images/bathroom-cs5a.jpg
Normal file
|
After Width: | Height: | Size: 953 KiB |
BIN
src/images/bathroom-cs5b.jpg
Normal file
|
After Width: | Height: | Size: 960 KiB |
BIN
src/images/bathroom.jpg
Normal file
|
After Width: | Height: | Size: 386 KiB |
|
Before Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 3.0 MiB |
|
Before Width: | Height: | Size: 1.8 MiB |
|
Before Width: | Height: | Size: 2.2 MiB |
|
Before Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 3.8 MiB |
|
Before Width: | Height: | Size: 9.0 MiB |
|
Before Width: | Height: | Size: 5.1 MiB |
|
Before Width: | Height: | Size: 3.7 MiB |
BIN
src/images/tiling-cs1a.jpg
Normal file
|
After Width: | Height: | Size: 1.8 MiB |
BIN
src/images/tiling-cs1b.jpg
Normal file
|
After Width: | Height: | Size: 657 KiB |
BIN
src/images/tiling-cs1c.jpg
Normal file
|
After Width: | Height: | Size: 900 KiB |
BIN
src/images/tiling-cs1d.jpg
Normal file
|
After Width: | Height: | Size: 736 KiB |
BIN
src/images/tiling-cs2a.jpg
Normal file
|
After Width: | Height: | Size: 2.5 MiB |
BIN
src/images/tiling-cs2b.jpg
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
src/images/tiling-cs2c.jpg
Normal file
|
After Width: | Height: | Size: 868 KiB |
BIN
src/images/tiling-cs2d.jpg
Normal file
|
After Width: | Height: | Size: 879 KiB |
BIN
src/images/tiling-cs2e.jpg
Normal file
|
After Width: | Height: | Size: 2.6 MiB |
BIN
src/images/tiling.jpg
Normal file
|
After Width: | Height: | Size: 670 KiB |
@@ -6,6 +6,7 @@ import { css, Global } from "@emotion/react";
|
||||
import "@fontsource/cooper-hewitt/400.css";
|
||||
import "@fontsource/cooper-hewitt/400-italic.css";
|
||||
import "@fontsource/cooper-hewitt/700.css";
|
||||
import "@browniebroke/gatsby-image-gallery/dist/style.css";
|
||||
|
||||
const GlobalStyles = css`
|
||||
:root {
|
||||
|
||||
@@ -19,9 +19,9 @@ export default function Index({ data }) {
|
||||
|
||||
export const query = graphql`
|
||||
query {
|
||||
headerImage: file(relativePath: { eq: "bathroom.png" }) {
|
||||
headerImage: file(relativePath: { eq: "banner_bathroom.jpg" }) {
|
||||
childImageSharp {
|
||||
fluid(maxWidth: 1920, quality: 100) {
|
||||
fluid(maxWidth: 1920, quality: 90) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,9 +50,9 @@ export default function Index({ data }) {
|
||||
|
||||
export const query = graphql`
|
||||
query {
|
||||
headerImage: file(relativePath: { eq: "bathroom3.png" }) {
|
||||
headerImage: file(relativePath: { eq: "banner_bathroom.jpg" }) {
|
||||
childImageSharp {
|
||||
fluid(maxWidth: 1920, quality: 100) {
|
||||
fluid(maxWidth: 1920, quality: 90) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
Button,
|
||||
Grid,
|
||||
Header,
|
||||
Heading,
|
||||
Icon,
|
||||
IconWithContent,
|
||||
InputText,
|
||||
@@ -14,9 +15,10 @@ import {
|
||||
Section,
|
||||
Text
|
||||
} from "../components";
|
||||
import Phone from "../icons/phone.svg";
|
||||
import Envelope from "../icons/envelope.svg";
|
||||
import CheckCircle from "../icons/check-circle.svg";
|
||||
import Envelope from "../icons/envelope.svg";
|
||||
import Phone from "../icons/phone.svg";
|
||||
import Team from "../icons/team.svg";
|
||||
|
||||
const encodeData = data =>
|
||||
Object.keys(data)
|
||||
@@ -53,15 +55,45 @@ export default function Index({ data }) {
|
||||
<Layout location="/contact">
|
||||
<Header
|
||||
image={data.headerImage.childImageSharp.fluid}
|
||||
position="middle right"
|
||||
position="bottom right"
|
||||
>
|
||||
<h1>Get in touch</h1>
|
||||
<Heading shadow="xl-white">
|
||||
<em>Get in</em> touch
|
||||
</Heading>
|
||||
</Header>
|
||||
<Section>
|
||||
<Grid columns={[1, 2]} breakpoints={["40rem"]}>
|
||||
<div>
|
||||
<Text>Get in touch with us</Text>
|
||||
<Text textStyle="italic">More info here</Text>
|
||||
<IconWithContent>
|
||||
<Icon color="dark" size="lg">
|
||||
<Team />
|
||||
</Icon>
|
||||
<Text color="dark" size="lg">
|
||||
The team
|
||||
</Text>
|
||||
</IconWithContent>
|
||||
<ul>
|
||||
<li>
|
||||
<Text>
|
||||
Nicholas Day - <em>Sales and Marketing Manager</em>
|
||||
</Text>
|
||||
</li>
|
||||
<li>
|
||||
<Text>
|
||||
Daniel Costea - <em>Project Director</em>
|
||||
</Text>
|
||||
</li>
|
||||
<li>
|
||||
<Text>
|
||||
Maria Antonia - <em>After Sales Manager</em>
|
||||
</Text>
|
||||
</li>
|
||||
<li>
|
||||
<Text>
|
||||
Harry Jackson - <em>Design and Consultation Manager</em>
|
||||
</Text>
|
||||
</li>
|
||||
</ul>
|
||||
<IconWithContent>
|
||||
<Icon color="dark" size="lg">
|
||||
<Phone />
|
||||
@@ -93,7 +125,7 @@ export default function Index({ data }) {
|
||||
<Text color="dark" size="lg">
|
||||
Thank you for contacting us
|
||||
</Text>
|
||||
<Text color="dark" size="md">
|
||||
<Text color="dark" size="lg">
|
||||
We will be in touch shortly
|
||||
</Text>
|
||||
</>
|
||||
@@ -163,9 +195,9 @@ export default function Index({ data }) {
|
||||
|
||||
export const query = graphql`
|
||||
query {
|
||||
headerImage: file(relativePath: { eq: "bathroom4.png" }) {
|
||||
headerImage: file(relativePath: { eq: "banner_bathroom.jpg" }) {
|
||||
childImageSharp {
|
||||
fluid(maxWidth: 1920, quality: 100) {
|
||||
fluid(maxWidth: 1920, quality: 90) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,21 +58,7 @@ export default function Index({ data }) {
|
||||
image={data.tilingImage.childImageSharp.fluid}
|
||||
heading={<Heading el="h3">Tiling</Heading>}
|
||||
>
|
||||
Our tiling is primo!
|
||||
</Card>
|
||||
<Card
|
||||
to="/services/electrics"
|
||||
image={data.electricsImage.childImageSharp.fluid}
|
||||
heading={<Heading el="h3">Electrics</Heading>}
|
||||
>
|
||||
Bring some light to your next project
|
||||
</Card>
|
||||
<Card
|
||||
to="/services/carpentry"
|
||||
image={data.carpentryImage.childImageSharp.fluid}
|
||||
heading={<Heading el="h3">Carpentry</Heading>}
|
||||
>
|
||||
Our woodworking is sharp!
|
||||
We can install many different styles
|
||||
</Card>
|
||||
</Grid>
|
||||
</Section>
|
||||
@@ -165,37 +151,23 @@ export default function Index({ data }) {
|
||||
|
||||
export const query = graphql`
|
||||
query {
|
||||
headerImage: file(relativePath: { eq: "bathroom.png" }) {
|
||||
headerImage: file(relativePath: { eq: "banner_bathroom.jpg" }) {
|
||||
childImageSharp {
|
||||
fluid(maxWidth: 1920, quality: 100) {
|
||||
fluid(maxWidth: 1920, quality: 90) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
}
|
||||
}
|
||||
bathroomImage: file(relativePath: { eq: "service_bathroom.png" }) {
|
||||
bathroomImage: file(relativePath: { eq: "bathroom.jpg" }) {
|
||||
childImageSharp {
|
||||
fluid(maxWidth: 480, quality: 100) {
|
||||
fluid(maxWidth: 480, maxHeight: 320, quality: 90) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
}
|
||||
}
|
||||
tilingImage: file(relativePath: { eq: "service_tiling.png" }) {
|
||||
tilingImage: file(relativePath: { eq: "tiling.jpg" }) {
|
||||
childImageSharp {
|
||||
fluid(maxWidth: 480, quality: 100) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
}
|
||||
}
|
||||
electricsImage: file(relativePath: { eq: "service_electrics.png" }) {
|
||||
childImageSharp {
|
||||
fluid(maxWidth: 480, quality: 100) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
}
|
||||
}
|
||||
carpentryImage: file(relativePath: { eq: "service_carpentry.png" }) {
|
||||
childImageSharp {
|
||||
fluid(maxWidth: 480, quality: 100) {
|
||||
fluid(maxWidth: 480, maxHeight: 320, quality: 90) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
import React from "react";
|
||||
import { graphql } from "gatsby";
|
||||
import Img from "gatsby-image";
|
||||
import styled from "@emotion/styled";
|
||||
import Layout from "../../layout";
|
||||
import { Grid, Header, Section, Text } from "../../components";
|
||||
|
||||
const FullWidth = styled.div`
|
||||
grid-column: 1 / 3;
|
||||
`;
|
||||
|
||||
export default function Index({ data }) {
|
||||
return (
|
||||
<Layout location="/services/bathrooms">
|
||||
<Header image={data.headerImage.childImageSharp.fluid}>
|
||||
<h1>Bathrooms</h1>
|
||||
</Header>
|
||||
<Section heading="We build bespoke bathrooms">
|
||||
<Grid columns={[1, 2]} breakpoints={["40em"]}>
|
||||
<div>
|
||||
<Text>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
|
||||
eiusmod tempor incididunt ut labore et dolore magna aliqua. Sed
|
||||
risus ultricies tristique nulla aliquet enim tortor. Laoreet id
|
||||
donec ultrices tincidunt arcu non sodales. Eu ultrices vitae
|
||||
auctor eu augue ut lectus arcu bibendum. Egestas diam in arcu
|
||||
cursus euismod quis. Suspendisse potenti nullam ac tortor vitae
|
||||
purus faucibus ornare suspendisse.
|
||||
</Text>
|
||||
</div>
|
||||
<div>
|
||||
<Img fluid={data.image1.childImageSharp.fluid} />
|
||||
</div>
|
||||
<FullWidth>
|
||||
<Text>
|
||||
Lacus sed turpis tincidunt id aliquet. Faucibus ornare suspendisse
|
||||
sed nisi lacus sed viverra tellus in. In hac habitasse platea
|
||||
dictumst. Dolor sit amet consectetur adipiscing. Facilisis magna
|
||||
etiam tempor orci eu lobortis elementum. Sed enim ut sem viverra
|
||||
aliquet. Leo vel fringilla est ullamcorper eget nulla facilisi
|
||||
etiam. Sem integer vitae justo eget. Vitae elementum curabitur
|
||||
vitae nunc sed velit dignissim sodales. Felis imperdiet proin
|
||||
fermentum leo vel orci porta non. Donec et odio pellentesque diam
|
||||
volutpat commodo sed egestas. Cursus in hac habitasse platea
|
||||
dictumst quisque sagittis. Proin fermentum leo vel orci porta non
|
||||
pulvinar.
|
||||
</Text>
|
||||
</FullWidth>
|
||||
<div>
|
||||
<Img fluid={data.image2.childImageSharp.fluid} />
|
||||
</div>
|
||||
<div>
|
||||
<Text>
|
||||
Arcu dictum varius duis at consectetur. Blandit volutpat maecenas
|
||||
volutpat blandit. Varius morbi enim nunc faucibus a pellentesque
|
||||
sit amet. Mattis pellentesque id nibh tortor id aliquet lectus.
|
||||
Venenatis a condimentum vitae sapien pellentesque habitant morbi
|
||||
tristique.
|
||||
</Text>
|
||||
</div>
|
||||
<FullWidth>
|
||||
<Text>
|
||||
Commodo viverra maecenas accumsan lacus vel facilisis volutpat est
|
||||
velit. Consequat nisl vel pretium lectus quam id leo in vitae.
|
||||
Phasellus faucibus scelerisque eleifend donec. Ultricies mi quis
|
||||
hendrerit dolor magna eget est lorem ipsum. Vitae tempus quam
|
||||
pellentesque nec nam aliquam sem. Nulla at volutpat diam ut
|
||||
venenatis tellus in metus vulputate. Faucibus in ornare quam
|
||||
viverra. Neque ornare aenean euismod elementum nisi quis eleifend
|
||||
quam adipiscing. Egestas maecenas pharetra convallis posuere morbi
|
||||
leo. Proin nibh nisl condimentum id venenatis a condimentum vitae
|
||||
sapien.
|
||||
</Text>
|
||||
<Text>
|
||||
Phasellus egestas tellus rutrum tellus pellentesque eu. Facilisi
|
||||
nullam vehicula ipsum a. Eget lorem dolor sed viverra. Nulla
|
||||
facilisi nullam vehicula ipsum a arcu. Orci a scelerisque purus
|
||||
semper. Sed tempus urna et pharetra pharetra. Ac turpis egestas
|
||||
integer eget aliquet. Dui id ornare arcu odio. At volutpat diam ut
|
||||
venenatis tellus in metus vulputate. Eu nisl nunc mi ipsum
|
||||
faucibus vitae aliquet nec. Pharetra vel turpis nunc eget lorem.
|
||||
Duis tristique sollicitudin nibh sit amet. Id nibh tortor id
|
||||
aliquet lectus. Sed vulputate mi sit amet mauris commodo. Amet est
|
||||
placerat in egestas. Tincidunt id aliquet risus feugiat in ante
|
||||
metus dictum at. Vitae auctor eu augue ut lectus arcu bibendum at
|
||||
varius. Viverra justo nec ultrices dui sapien eget. Nisl
|
||||
condimentum id venenatis a. Nec dui nunc mattis enim ut tellus.
|
||||
</Text>
|
||||
</FullWidth>
|
||||
</Grid>
|
||||
</Section>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
export const query = graphql`
|
||||
query {
|
||||
headerImage: file(relativePath: { eq: "bathroom2.png" }) {
|
||||
childImageSharp {
|
||||
fluid(maxWidth: 1920, quality: 100) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
}
|
||||
}
|
||||
image1: file(relativePath: { eq: "bathroom3.png" }) {
|
||||
childImageSharp {
|
||||
fluid(maxWidth: 640, quality: 100) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
}
|
||||
}
|
||||
image2: file(relativePath: { eq: "bathroom4.png" }) {
|
||||
childImageSharp {
|
||||
fluid(maxWidth: 640, quality: 100) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
86
src/pages/services/bathrooms/case-study-1.js
Normal file
@@ -0,0 +1,86 @@
|
||||
import React from "react";
|
||||
import { graphql } from "gatsby";
|
||||
import Layout from "../../../layout";
|
||||
import {
|
||||
CustomGallery,
|
||||
Header,
|
||||
Heading,
|
||||
Section,
|
||||
Table,
|
||||
Text
|
||||
} from "../../../components";
|
||||
|
||||
export default function Index({ data }) {
|
||||
const images = data.images.nodes.map(node => node.childImageSharp);
|
||||
return (
|
||||
<Layout location="/services/bathrooms/case-study-1">
|
||||
<Header image={images[0].full}>
|
||||
<Heading shadow="xl-black">Modern Bathroom</Heading>
|
||||
<Text size="lg">Maldon, Essex</Text>
|
||||
</Header>
|
||||
<Section>
|
||||
<Table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Key features</td>
|
||||
<td>Damp proofing, Tiling, Alcove lighting</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Price</td>
|
||||
<td>£4,900</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Time taken</td>
|
||||
<td>X days</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Date</td>
|
||||
<td>Jan 2099</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</Table>
|
||||
<Text>
|
||||
This medium sized bathroom in Maldon, Essex came with very few design
|
||||
problems. The old bathroom was completely stripped out to a shell. The
|
||||
bathroom showed small signs of damp which was easily rectified with a
|
||||
waterproof membrane inserted within the shower walls.
|
||||
</Text>
|
||||
<Text>
|
||||
The client decided to replace the old bath with a large walk-in
|
||||
shower. Client chose to have a false ceiling installed with spot
|
||||
lights and an alcove with electrics and lighting was fitted to give
|
||||
the bathroom a warm feeling.
|
||||
</Text>
|
||||
<Text>
|
||||
We stripped out the old bathroom and disposed of all rubbish. We
|
||||
tiled, plastered and painted the floor and walls, installed the new
|
||||
bathroom with tiling, plastering, painting and all electrical works.
|
||||
</Text>
|
||||
<Text>Total price for labour and building materials: £4,900.</Text>
|
||||
</Section>
|
||||
<Section heading="Gallery" variant="primary">
|
||||
<CustomGallery images={images} />
|
||||
</Section>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
export const query = graphql`
|
||||
query {
|
||||
images: allFile(
|
||||
filter: { relativePath: { regex: "/bathroom-cs1(.*).jpg$/" } }
|
||||
sort: { fields: relativePath }
|
||||
) {
|
||||
nodes {
|
||||
childImageSharp {
|
||||
thumb: fluid(maxWidth: 256, maxHeight: 256, quality: 80) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
full: fluid(maxWidth: 1280, quality: 90) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
82
src/pages/services/bathrooms/case-study-2.js
Normal file
@@ -0,0 +1,82 @@
|
||||
import React from "react";
|
||||
import { graphql } from "gatsby";
|
||||
import Layout from "../../../layout";
|
||||
import {
|
||||
CustomGallery,
|
||||
Header,
|
||||
Heading,
|
||||
Section,
|
||||
Table,
|
||||
Text
|
||||
} from "../../../components";
|
||||
|
||||
export default function Index({ data }) {
|
||||
const images = data.images.nodes.map(node => node.childImageSharp);
|
||||
return (
|
||||
<Layout location="/services/bathrooms/case-study-2">
|
||||
<Header image={images[0].full}>
|
||||
<Heading shadow="xl-black">Compact Bathroom</Heading>
|
||||
<Text size="lg">Hackney, London</Text>
|
||||
</Header>
|
||||
<Section>
|
||||
<Table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Key features</td>
|
||||
<td>Damp proofing, Recessed shower mixer</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Price</td>
|
||||
<td>£4,000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Time taken</td>
|
||||
<td>X days</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Date</td>
|
||||
<td>Jan 2099</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</Table>
|
||||
<Text>Very small bathroom in a block of flats In Hackney, E9.</Text>
|
||||
<Text>
|
||||
Existing bathroom was extremely old. We stripped the bathroom back to
|
||||
the shell and addressed damp issues.
|
||||
</Text>
|
||||
<Text>
|
||||
Client went with our suggestion of using two different wall tiles.
|
||||
</Text>
|
||||
<Text>
|
||||
Shower mixer was inserted in to wall to give the bathroom a modern,
|
||||
minimal feel.
|
||||
</Text>
|
||||
<Text>Bathroom went from old and dated to fresh and modern.</Text>
|
||||
<Text>Total price for labour and materials: £4,000.</Text>
|
||||
</Section>
|
||||
<Section heading="Gallery" variant="primary">
|
||||
<CustomGallery images={images} />
|
||||
</Section>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
export const query = graphql`
|
||||
query {
|
||||
images: allFile(
|
||||
filter: { relativePath: { regex: "/bathroom-cs2(.*).jpg$/" } }
|
||||
sort: { fields: relativePath }
|
||||
) {
|
||||
nodes {
|
||||
childImageSharp {
|
||||
thumb: fluid(maxWidth: 256, maxHeight: 256, quality: 80) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
full: fluid(maxWidth: 1280, quality: 90) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
82
src/pages/services/bathrooms/case-study-3.js
Normal file
@@ -0,0 +1,82 @@
|
||||
import React from "react";
|
||||
import { graphql } from "gatsby";
|
||||
import Layout from "../../../layout";
|
||||
import {
|
||||
CustomGallery,
|
||||
Header,
|
||||
Heading,
|
||||
Section,
|
||||
Table,
|
||||
Text
|
||||
} from "../../../components";
|
||||
|
||||
export default function Index({ data }) {
|
||||
const images = data.images.nodes.map(node => node.childImageSharp);
|
||||
return (
|
||||
<Layout location="/services/bathrooms/case-study-3">
|
||||
<Header image={images[0].full}>
|
||||
<Heading shadow="xl-black">Modest Shower Room</Heading>
|
||||
<Text size="lg">Location unknown</Text>
|
||||
</Header>
|
||||
<Section>
|
||||
<Table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Key features</td>
|
||||
<td>Accessible shower, False ceiling with spot lights</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Price</td>
|
||||
<td>£4,300</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Time taken</td>
|
||||
<td>X days</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Date</td>
|
||||
<td>Jan 2099</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</Table>
|
||||
<Text>
|
||||
Medium sized bathroom for an elderly lady who had trouble getting in
|
||||
and out of the bath.
|
||||
</Text>
|
||||
<Text>
|
||||
Complete refurbishment, bathroom was 20 years old and showed signs of
|
||||
damp. Completely stripped out old bathroom, disposed of all rubbish
|
||||
and lefy to air out with windows open for 3 days
|
||||
</Text>
|
||||
<Text>
|
||||
New bathroom installed with a fresh look and easy to maintain. 4 spot
|
||||
lights installed in false ceiling.
|
||||
</Text>
|
||||
<Text>Total price for labour and materials: £4,300.</Text>
|
||||
</Section>
|
||||
<Section heading="Gallery" variant="primary">
|
||||
<CustomGallery images={images} />
|
||||
</Section>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
export const query = graphql`
|
||||
query {
|
||||
images: allFile(
|
||||
filter: { relativePath: { regex: "/bathroom-cs3(.*).jpg$/" } }
|
||||
sort: { fields: relativePath }
|
||||
) {
|
||||
nodes {
|
||||
childImageSharp {
|
||||
thumb: fluid(maxWidth: 256, maxHeight: 256, quality: 80) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
full: fluid(maxWidth: 1280, quality: 90) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
78
src/pages/services/bathrooms/case-study-4.js
Normal file
@@ -0,0 +1,78 @@
|
||||
import React from "react";
|
||||
import { graphql } from "gatsby";
|
||||
import Layout from "../../../layout";
|
||||
import {
|
||||
CustomGallery,
|
||||
Header,
|
||||
Heading,
|
||||
Section,
|
||||
Table,
|
||||
Text
|
||||
} from "../../../components";
|
||||
|
||||
export default function Index({ data }) {
|
||||
const images = data.images.nodes.map(node => node.childImageSharp);
|
||||
return (
|
||||
<Layout location="/services/bathrooms/case-study-4">
|
||||
<Header image={images[0].full}>
|
||||
<Heading shadow="xl-black">Period with a Modern Twist</Heading>
|
||||
<Text size="lg">Hampstead, London</Text>
|
||||
</Header>
|
||||
<Section>
|
||||
<Table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Key features</td>
|
||||
<td>Period features with modern twist</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Price</td>
|
||||
<td>£7,800</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Time taken</td>
|
||||
<td>X days</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Date</td>
|
||||
<td>Jan 2099</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</Table>
|
||||
<Text>
|
||||
A complete refurbishment in a three bedroom house in Hampstead,
|
||||
London.
|
||||
</Text>
|
||||
<Text>
|
||||
Existing bathroom was more than 20 years old. We completely stripped
|
||||
out the old bathroom and disposed of all rubbish.
|
||||
</Text>
|
||||
<Text>Client went for a Victorian style with a modern twist</Text>
|
||||
<Text>Total price for labour and materials: £7,800.</Text>
|
||||
</Section>
|
||||
<Section heading="Gallery" variant="primary">
|
||||
<CustomGallery images={images} />
|
||||
</Section>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
export const query = graphql`
|
||||
query {
|
||||
images: allFile(
|
||||
filter: { relativePath: { regex: "/bathroom-cs4(.*).jpg$/" } }
|
||||
sort: { fields: relativePath }
|
||||
) {
|
||||
nodes {
|
||||
childImageSharp {
|
||||
thumb: fluid(maxWidth: 256, maxHeight: 256, quality: 80) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
full: fluid(maxWidth: 1280, quality: 90) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
81
src/pages/services/bathrooms/case-study-5.js
Normal file
@@ -0,0 +1,81 @@
|
||||
import React from "react";
|
||||
import { graphql } from "gatsby";
|
||||
import Layout from "../../../layout";
|
||||
import {
|
||||
CustomGallery,
|
||||
Header,
|
||||
Heading,
|
||||
Section,
|
||||
Table,
|
||||
Text
|
||||
} from "../../../components";
|
||||
|
||||
export default function Index({ data }) {
|
||||
const images = data.images.nodes.map(node => node.childImageSharp);
|
||||
return (
|
||||
<Layout location="/services/bathrooms/case-study-5">
|
||||
<Header image={images[0].full}>
|
||||
<Heading shadow="xl-black">En-suite</Heading>
|
||||
<Text size="lg">Chelmsford, Essex</Text>
|
||||
</Header>
|
||||
<Section>
|
||||
<Table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Key features</td>
|
||||
<td>Feature wall with alcove shelf</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Price</td>
|
||||
<td>£6,400</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Time taken</td>
|
||||
<td>X days</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Date</td>
|
||||
<td>Jan 2099</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</Table>
|
||||
<Text>
|
||||
2 bedroom flat Chelmsford. An en-suite bathroom. The existing bathroom
|
||||
was 10 years old and very dated.
|
||||
</Text>
|
||||
<Text>
|
||||
Client went for fairly cheap products and tiles to keep within their
|
||||
budget.
|
||||
</Text>
|
||||
<Text>
|
||||
Service included stripping out old bathroom and disposing of all
|
||||
rubbish, supplying and fitting everything.
|
||||
</Text>
|
||||
<Text>Total price for labour and materials: £6,400.</Text>
|
||||
</Section>
|
||||
<Section heading="Gallery" variant="primary">
|
||||
<CustomGallery images={images} />
|
||||
</Section>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
export const query = graphql`
|
||||
query {
|
||||
images: allFile(
|
||||
filter: { relativePath: { regex: "/bathroom-cs5(.*).jpg$/" } }
|
||||
sort: { fields: relativePath }
|
||||
) {
|
||||
nodes {
|
||||
childImageSharp {
|
||||
thumb: fluid(maxWidth: 256, maxHeight: 256, quality: 80) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
full: fluid(maxWidth: 1280, quality: 90) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
105
src/pages/services/bathrooms/index.js
Normal file
@@ -0,0 +1,105 @@
|
||||
import React from "react";
|
||||
import { graphql } from "gatsby";
|
||||
import Layout from "../../../layout";
|
||||
import {
|
||||
Card,
|
||||
Grid,
|
||||
Header,
|
||||
Heading,
|
||||
Section,
|
||||
Text
|
||||
} from "../../../components";
|
||||
|
||||
export default function Index({ data }) {
|
||||
return (
|
||||
<Layout location="/services/bathrooms">
|
||||
<Header image={data.headerImage.childImageSharp.fluid}>
|
||||
<Heading shadow="xl-white">Bathrooms</Heading>
|
||||
</Header>
|
||||
<Section heading="We build bespoke bathrooms">
|
||||
<Text>
|
||||
It's more than likely the most important room in your house and one of
|
||||
the biggest investments you will ever make. We offer a professional
|
||||
design service and an expert installation service. All our tradesman
|
||||
are vetted and handpicked based on their skills within their chosen
|
||||
fields.
|
||||
</Text>
|
||||
<Text>
|
||||
With over 30 years experience in bathroom installation we will help
|
||||
you choose the perfect bathroom for your home. We can complete your
|
||||
whole bathroom installation including electrics, plastering, plumbing
|
||||
and paint and decorating.
|
||||
</Text>
|
||||
<Text>
|
||||
If you want a high quality bathroom you have come to the right place.
|
||||
</Text>
|
||||
<Text>
|
||||
We provide an initial consultation followed by a competitive quote.
|
||||
</Text>
|
||||
</Section>
|
||||
<Section heading="Case studies" variant="primary">
|
||||
<Grid columns={[1, 2, 3]} breakpoints={["25em", "50em"]}>
|
||||
<Card
|
||||
to="/services/bathrooms/case-study-1"
|
||||
image={data.images.nodes[0].childImageSharp.fluid}
|
||||
heading={<Heading el="h3">Modern Bathroom</Heading>}
|
||||
>
|
||||
Maldon, Essex
|
||||
</Card>
|
||||
<Card
|
||||
to="/services/bathrooms/case-study-2"
|
||||
image={data.images.nodes[1].childImageSharp.fluid}
|
||||
heading={<Heading el="h3">Compact Bathroom</Heading>}
|
||||
>
|
||||
Hackney, London
|
||||
</Card>
|
||||
<Card
|
||||
to="/services/bathrooms/case-study-3"
|
||||
image={data.images.nodes[2].childImageSharp.fluid}
|
||||
heading={<Heading el="h3">Modest Shower Room</Heading>}
|
||||
>
|
||||
Location unknown
|
||||
</Card>
|
||||
<Card
|
||||
to="/services/bathrooms/case-study-4"
|
||||
image={data.images.nodes[3].childImageSharp.fluid}
|
||||
heading={<Heading el="h3">Period with a Modern Twist</Heading>}
|
||||
>
|
||||
Hampstead, London
|
||||
</Card>
|
||||
<Card
|
||||
to="/services/bathrooms/case-study-5"
|
||||
image={data.images.nodes[4].childImageSharp.fluid}
|
||||
heading={<Heading el="h3">En-suite</Heading>}
|
||||
>
|
||||
Chelmsford, Essex
|
||||
</Card>
|
||||
</Grid>
|
||||
</Section>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
export const query = graphql`
|
||||
query {
|
||||
headerImage: file(relativePath: { eq: "banner_bathroom.jpg" }) {
|
||||
childImageSharp {
|
||||
fluid(maxWidth: 1920, quality: 90) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
}
|
||||
}
|
||||
images: allFile(
|
||||
filter: { relativePath: { regex: "/bathroom-cs(.*)a.jpg$/" } }
|
||||
sort: { fields: relativePath }
|
||||
) {
|
||||
nodes {
|
||||
childImageSharp {
|
||||
fluid(maxWidth: 640, maxHeight: 480, quality: 90) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -7,7 +7,7 @@ export default function Index({ data }) {
|
||||
return (
|
||||
<Layout location="/services">
|
||||
<Header image={data.headerImage.childImageSharp.fluid}>
|
||||
<h1>Services</h1>
|
||||
<Heading shadow="xl-white">Services</Heading>
|
||||
</Header>
|
||||
<Section>
|
||||
<Grid columns={[1, 2]}>
|
||||
@@ -23,21 +23,7 @@ export default function Index({ data }) {
|
||||
image={data.tilingImage.childImageSharp.fluid}
|
||||
heading={<Heading el="h3">Tiling</Heading>}
|
||||
>
|
||||
Our tiling is primo!
|
||||
</Card>
|
||||
<Card
|
||||
to="/services/electrics"
|
||||
image={data.electricsImage.childImageSharp.fluid}
|
||||
heading={<Heading el="h3">Electrics</Heading>}
|
||||
>
|
||||
Bring some light to your next project
|
||||
</Card>
|
||||
<Card
|
||||
to="/services/carpentry"
|
||||
image={data.carpentryImage.childImageSharp.fluid}
|
||||
heading={<Heading el="h3">Carpentry</Heading>}
|
||||
>
|
||||
Our woodworking is sharp!
|
||||
We can install many different styles
|
||||
</Card>
|
||||
</Grid>
|
||||
</Section>
|
||||
@@ -47,37 +33,23 @@ export default function Index({ data }) {
|
||||
|
||||
export const query = graphql`
|
||||
query {
|
||||
headerImage: file(relativePath: { eq: "floor_tiles.png" }) {
|
||||
headerImage: file(relativePath: { eq: "banner_bathroom.jpg" }) {
|
||||
childImageSharp {
|
||||
fluid(maxWidth: 1920, quality: 100) {
|
||||
fluid(maxWidth: 1920, quality: 90) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
}
|
||||
}
|
||||
bathroomImage: file(relativePath: { eq: "service_bathroom.png" }) {
|
||||
bathroomImage: file(relativePath: { eq: "bathroom.jpg" }) {
|
||||
childImageSharp {
|
||||
fluid(maxWidth: 480, quality: 100) {
|
||||
fluid(maxWidth: 480, maxHeight: 320, quality: 90) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
}
|
||||
}
|
||||
tilingImage: file(relativePath: { eq: "service_tiling.png" }) {
|
||||
tilingImage: file(relativePath: { eq: "tiling.jpg" }) {
|
||||
childImageSharp {
|
||||
fluid(maxWidth: 480, quality: 100) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
}
|
||||
}
|
||||
electricsImage: file(relativePath: { eq: "service_electrics.png" }) {
|
||||
childImageSharp {
|
||||
fluid(maxWidth: 480, quality: 100) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
}
|
||||
}
|
||||
carpentryImage: file(relativePath: { eq: "service_carpentry.png" }) {
|
||||
childImageSharp {
|
||||
fluid(maxWidth: 480, quality: 100) {
|
||||
fluid(maxWidth: 480, maxHeight: 320, quality: 90) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
}
|
||||
|
||||
50
src/pages/services/tiling/case-study-1.js
Normal file
@@ -0,0 +1,50 @@
|
||||
import React from "react";
|
||||
import { graphql } from "gatsby";
|
||||
import Layout from "../../../layout";
|
||||
import {
|
||||
CustomGallery,
|
||||
Header,
|
||||
Heading,
|
||||
Section,
|
||||
Text
|
||||
} from "../../../components";
|
||||
|
||||
export default function Index({ data }) {
|
||||
const images = data.images.nodes.map(node => node.childImageSharp);
|
||||
return (
|
||||
<Layout location="/services/tiling/case-study-1">
|
||||
<Header image={images[0].full}>
|
||||
<Heading shadow="xl-black">Under Floor Heating</Heading>
|
||||
<Text size="lg">Location unknown</Text>
|
||||
</Header>
|
||||
<Section>
|
||||
<Text>
|
||||
<em>Case study info needed</em>
|
||||
</Text>
|
||||
</Section>
|
||||
<Section heading="Gallery" variant="primary">
|
||||
<CustomGallery images={images} />
|
||||
</Section>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
export const query = graphql`
|
||||
query {
|
||||
images: allFile(
|
||||
filter: { relativePath: { regex: "/tiling-cs1(.*).jpg$/" } }
|
||||
sort: { fields: relativePath }
|
||||
) {
|
||||
nodes {
|
||||
childImageSharp {
|
||||
thumb: fluid(maxWidth: 256, maxHeight: 256, quality: 80) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
full: fluid(maxWidth: 1280, quality: 90) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
65
src/pages/services/tiling/case-study-2.js
Normal file
@@ -0,0 +1,65 @@
|
||||
import React from "react";
|
||||
import { graphql } from "gatsby";
|
||||
import Layout from "../../../layout";
|
||||
import {
|
||||
CustomGallery,
|
||||
Header,
|
||||
Heading,
|
||||
Section,
|
||||
Text
|
||||
} from "../../../components";
|
||||
|
||||
export default function Index({ data }) {
|
||||
const images = data.images.nodes.map(node => node.childImageSharp);
|
||||
return (
|
||||
<Layout location="/services/tiling/case-study-2">
|
||||
<Header image={images[0].full}>
|
||||
<Heading shadow="xl-black">Ceramic Floor Tiles</Heading>
|
||||
<Text size="lg">Brentwood, Essex</Text>
|
||||
</Header>
|
||||
<Section>
|
||||
<Text>
|
||||
The client needed 19m<sup>2</sup> of ceramic floor tiles at short
|
||||
notice.
|
||||
</Text>
|
||||
<Text>
|
||||
We first applied self leveling compound as the concrete floor was
|
||||
quite uneven. After 2 days to allow for the compound to completely
|
||||
dry, we returned to install the tiles.
|
||||
</Text>
|
||||
<Text>
|
||||
The installation was completed in one day and the client was able to
|
||||
continue with the kitchen installation the following day.
|
||||
</Text>
|
||||
<Text>
|
||||
The client provided the ceramic floor tiles and we provided the,
|
||||
levelling compound, adhesive and grout.
|
||||
</Text>
|
||||
<Text>Total price for labour and materials: £1,100.</Text>
|
||||
</Section>
|
||||
<Section heading="Gallery" variant="primary">
|
||||
<CustomGallery images={images} />
|
||||
</Section>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
export const query = graphql`
|
||||
query {
|
||||
images: allFile(
|
||||
filter: { relativePath: { regex: "/tiling-cs2(.*).jpg$/" } }
|
||||
sort: { fields: relativePath }
|
||||
) {
|
||||
nodes {
|
||||
childImageSharp {
|
||||
thumb: fluid(maxWidth: 256, maxHeight: 256, quality: 80) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
full: fluid(maxWidth: 1280, quality: 90) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
71
src/pages/services/tiling/index.js
Normal file
@@ -0,0 +1,71 @@
|
||||
import React from "react";
|
||||
import { graphql } from "gatsby";
|
||||
import Layout from "../../../layout";
|
||||
import {
|
||||
Card,
|
||||
Grid,
|
||||
Header,
|
||||
Heading,
|
||||
Section,
|
||||
Text
|
||||
} from "../../../components";
|
||||
|
||||
export default function Index({ data }) {
|
||||
return (
|
||||
<Layout location="/services/tiling">
|
||||
<Header image={data.headerImage.childImageSharp.fluid}>
|
||||
<Heading shadow="xl-white">Tiling</Heading>
|
||||
</Header>
|
||||
<Section heading="We specialise in floor tiling">
|
||||
<Text>
|
||||
We can install both floor and wall tiles, including ceramic, natural
|
||||
stone, marble, quartz, porcelain and mosaic tiles.
|
||||
</Text>
|
||||
<Text>
|
||||
Our elite team of 3 stonemasons and 3 tilers has a combined total of
|
||||
112 years of experience within the industry.
|
||||
</Text>
|
||||
</Section>
|
||||
<Section heading="Case studies" variant="primary">
|
||||
<Grid columns={[1, 2]} breakpoints={["30em"]}>
|
||||
<Card
|
||||
to="/services/tiling/case-study-1"
|
||||
image={data.images.nodes[0].childImageSharp.fluid}
|
||||
heading={<Heading el="h3">Under Floor Heating</Heading>}
|
||||
>Location unknown</Card>
|
||||
<Card
|
||||
to="/services/tiling/case-study-2"
|
||||
image={data.images.nodes[1].childImageSharp.fluid}
|
||||
heading={<Heading el="h3">Ceramic Floor Tiles</Heading>}
|
||||
>
|
||||
Brentwood, Essex
|
||||
</Card>
|
||||
</Grid>
|
||||
</Section>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
export const query = graphql`
|
||||
query {
|
||||
headerImage: file(relativePath: { eq: "banner_tiling.jpg" }) {
|
||||
childImageSharp {
|
||||
fluid(maxWidth: 1920, quality: 90) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
}
|
||||
}
|
||||
images: allFile(
|
||||
filter: { relativePath: { regex: "/tiling-cs(.*)a.jpg$/" } }
|
||||
sort: { fields: relativePath }
|
||||
) {
|
||||
nodes {
|
||||
childImageSharp {
|
||||
fluid(maxWidth: 640, maxHeight: 480, quality: 90) {
|
||||
...GatsbyImageSharpFluid_withWebp
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||