feat: add case studies

This commit is contained in:
2021-02-01 23:38:41 +00:00
parent 718910f442
commit add7c35a26
63 changed files with 924 additions and 214 deletions

View File

@@ -23,14 +23,6 @@ module.exports = {
{ {
title: "Tiling", title: "Tiling",
to: "/services/tiling" to: "/services/tiling"
},
{
title: "Electrics",
to: "/services/electrics"
},
{
title: "Carpentry",
to: "/services/carpentry"
} }
] ]
}, },

115
package-lock.json generated
View File

@@ -1134,6 +1134,15 @@
"to-fast-properties": "^2.0.0" "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": { "@emotion/babel-plugin": {
"version": "11.1.2", "version": "11.1.2",
"resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.1.2.tgz", "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", "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
"integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" "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": { "@emotion/memoize": {
"version": "0.7.4", "version": "0.7.4",
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", "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": { "@emotion/unitless": {
"version": "0.7.5", "version": "0.7.5",
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", "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", "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==" "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": { "babel-plugin-transform-react-remove-prop-types": {
"version": "0.4.24", "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", "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": { "caniuse-api": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", "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": { "css-color-names": {
"version": "0.0.4", "version": "0.0.4",
"resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz",
@@ -5635,6 +5683,16 @@
"fastparse": "^1.1.2" "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": { "css-tree": {
"version": "1.0.0-alpha.37", "version": "1.0.0-alpha.37",
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", "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": { "exif-parser": {
"version": "0.1.12", "version": "0.1.12",
"resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz",
@@ -15423,6 +15486,15 @@
"source-map": "^0.7.3" "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": { "react-is": {
"version": "16.13.1", "version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "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", "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" "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": { "react-refresh": {
"version": "0.8.3", "version": "0.8.3",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz",
@@ -17506,6 +17589,38 @@
"inline-style-parser": "0.1.1" "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": { "stylehacks": {
"version": "4.0.3", "version": "4.0.3",
"resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz",

View File

@@ -17,6 +17,7 @@
] ]
}, },
"dependencies": { "dependencies": {
"@browniebroke/gatsby-image-gallery": "^4.0.2",
"@emotion/react": "^11.1.4", "@emotion/react": "^11.1.4",
"@emotion/styled": "^11.0.0", "@emotion/styled": "^11.0.0",
"@fontsource/cooper-hewitt": "^4.1.0", "@fontsource/cooper-hewitt": "^4.1.0",

View 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>
);
}

View File

@@ -5,7 +5,8 @@ import { css } from "@emotion/react";
const Container = styled.header` const Container = styled.header`
position: relative; position: relative;
height: 50vh; height: 50vh;
color: white; min-height: 280px;
color: var(--color-white);
${props => props.avoidNav && `margin-top: 40px;`} ${props => props.avoidNav && `margin-top: 40px;`}
`; `;
@@ -47,6 +48,8 @@ export default function Header({
map, map,
position = "middle middle", position = "middle middle",
avoidNav, avoidNav,
variant,
swap,
children children
}) { }) {
const [posY, posX] = position.split(" "); const [posY, posX] = position.split(" ");

View File

@@ -55,7 +55,8 @@ export default function Heading({
return ( return (
<Container <Container
size={sizes[el]} size={sizes[el]}
shadowSize={shadowSizes[size]} el={el}
shadowSize={el === "h1" ? shadowSizes[size] : 0}
shadowColor={shadowColors[color]} shadowColor={shadowColors[color]}
{...other} {...other}
> >

View File

@@ -1,6 +1,7 @@
export { default as Button } from "./button"; export { default as Button } from "./button";
export { default as Card } from "./card"; export { default as Card } from "./card";
export { default as Content } from "./content"; export { default as Content } from "./content";
export { default as CustomGallery } from "./custom-gallery";
export { default as CustomSlick } from "./custom-slick"; export { default as CustomSlick } from "./custom-slick";
export { default as Footer } from "./footer"; export { default as Footer } from "./footer";
export { default as Grid } from "./grid"; 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 Nav } from "./nav";
export { default as ReviewSummary } from "./review-summary"; export { default as ReviewSummary } from "./review-summary";
export { default as Section } from "./section"; export { default as Section } from "./section";
export { default as Table } from "./table";
export { default as Text } from "./text"; export { default as Text } from "./text";
export { default as Tile } from "./tile"; export { default as Tile } from "./tile";

21
src/components/table.js Normal file
View 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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 919 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 843 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 953 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 960 KiB

BIN
src/images/bathroom.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 MiB

BIN
src/images/tiling-cs1a.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

BIN
src/images/tiling-cs1b.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 657 KiB

BIN
src/images/tiling-cs1c.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 KiB

BIN
src/images/tiling-cs1d.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 736 KiB

BIN
src/images/tiling-cs2a.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

BIN
src/images/tiling-cs2b.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

BIN
src/images/tiling-cs2c.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 868 KiB

BIN
src/images/tiling-cs2d.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 879 KiB

BIN
src/images/tiling-cs2e.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

BIN
src/images/tiling.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 670 KiB

View File

@@ -6,6 +6,7 @@ import { css, Global } from "@emotion/react";
import "@fontsource/cooper-hewitt/400.css"; import "@fontsource/cooper-hewitt/400.css";
import "@fontsource/cooper-hewitt/400-italic.css"; import "@fontsource/cooper-hewitt/400-italic.css";
import "@fontsource/cooper-hewitt/700.css"; import "@fontsource/cooper-hewitt/700.css";
import "@browniebroke/gatsby-image-gallery/dist/style.css";
const GlobalStyles = css` const GlobalStyles = css`
:root { :root {

View File

@@ -19,9 +19,9 @@ export default function Index({ data }) {
export const query = graphql` export const query = graphql`
query { query {
headerImage: file(relativePath: { eq: "bathroom.png" }) { headerImage: file(relativePath: { eq: "banner_bathroom.jpg" }) {
childImageSharp { childImageSharp {
fluid(maxWidth: 1920, quality: 100) { fluid(maxWidth: 1920, quality: 90) {
...GatsbyImageSharpFluid_withWebp ...GatsbyImageSharpFluid_withWebp
} }
} }

View File

@@ -50,9 +50,9 @@ export default function Index({ data }) {
export const query = graphql` export const query = graphql`
query { query {
headerImage: file(relativePath: { eq: "bathroom3.png" }) { headerImage: file(relativePath: { eq: "banner_bathroom.jpg" }) {
childImageSharp { childImageSharp {
fluid(maxWidth: 1920, quality: 100) { fluid(maxWidth: 1920, quality: 90) {
...GatsbyImageSharpFluid_withWebp ...GatsbyImageSharpFluid_withWebp
} }
} }

View File

@@ -6,6 +6,7 @@ import {
Button, Button,
Grid, Grid,
Header, Header,
Heading,
Icon, Icon,
IconWithContent, IconWithContent,
InputText, InputText,
@@ -14,9 +15,10 @@ import {
Section, Section,
Text Text
} from "../components"; } from "../components";
import Phone from "../icons/phone.svg";
import Envelope from "../icons/envelope.svg";
import CheckCircle from "../icons/check-circle.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 => const encodeData = data =>
Object.keys(data) Object.keys(data)
@@ -53,15 +55,45 @@ export default function Index({ data }) {
<Layout location="/contact"> <Layout location="/contact">
<Header <Header
image={data.headerImage.childImageSharp.fluid} 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> </Header>
<Section> <Section>
<Grid columns={[1, 2]} breakpoints={["40rem"]}> <Grid columns={[1, 2]} breakpoints={["40rem"]}>
<div> <div>
<Text>Get in touch with us</Text> <IconWithContent>
<Text textStyle="italic">More info here</Text> <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> <IconWithContent>
<Icon color="dark" size="lg"> <Icon color="dark" size="lg">
<Phone /> <Phone />
@@ -93,7 +125,7 @@ export default function Index({ data }) {
<Text color="dark" size="lg"> <Text color="dark" size="lg">
Thank you for contacting us Thank you for contacting us
</Text> </Text>
<Text color="dark" size="md"> <Text color="dark" size="lg">
We will be in touch shortly We will be in touch shortly
</Text> </Text>
</> </>
@@ -163,9 +195,9 @@ export default function Index({ data }) {
export const query = graphql` export const query = graphql`
query { query {
headerImage: file(relativePath: { eq: "bathroom4.png" }) { headerImage: file(relativePath: { eq: "banner_bathroom.jpg" }) {
childImageSharp { childImageSharp {
fluid(maxWidth: 1920, quality: 100) { fluid(maxWidth: 1920, quality: 90) {
...GatsbyImageSharpFluid_withWebp ...GatsbyImageSharpFluid_withWebp
} }
} }

View File

@@ -58,21 +58,7 @@ export default function Index({ data }) {
image={data.tilingImage.childImageSharp.fluid} image={data.tilingImage.childImageSharp.fluid}
heading={<Heading el="h3">Tiling</Heading>} heading={<Heading el="h3">Tiling</Heading>}
> >
Our tiling is primo! We can install many different styles
</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!
</Card> </Card>
</Grid> </Grid>
</Section> </Section>
@@ -165,37 +151,23 @@ export default function Index({ data }) {
export const query = graphql` export const query = graphql`
query { query {
headerImage: file(relativePath: { eq: "bathroom.png" }) { headerImage: file(relativePath: { eq: "banner_bathroom.jpg" }) {
childImageSharp { childImageSharp {
fluid(maxWidth: 1920, quality: 100) { fluid(maxWidth: 1920, quality: 90) {
...GatsbyImageSharpFluid_withWebp ...GatsbyImageSharpFluid_withWebp
} }
} }
} }
bathroomImage: file(relativePath: { eq: "service_bathroom.png" }) { bathroomImage: file(relativePath: { eq: "bathroom.jpg" }) {
childImageSharp { childImageSharp {
fluid(maxWidth: 480, quality: 100) { fluid(maxWidth: 480, maxHeight: 320, quality: 90) {
...GatsbyImageSharpFluid_withWebp ...GatsbyImageSharpFluid_withWebp
} }
} }
} }
tilingImage: file(relativePath: { eq: "service_tiling.png" }) { tilingImage: file(relativePath: { eq: "tiling.jpg" }) {
childImageSharp { childImageSharp {
fluid(maxWidth: 480, quality: 100) { fluid(maxWidth: 480, maxHeight: 320, quality: 90) {
...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) {
...GatsbyImageSharpFluid_withWebp ...GatsbyImageSharpFluid_withWebp
} }
} }

View File

@@ -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
}
}
}
}
`;

View 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
}
}
}
}
}
`;

View 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
}
}
}
}
}
`;

View 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
}
}
}
}
}
`;

View 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
}
}
}
}
}
`;

View 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
}
}
}
}
}
`;

View 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
}
}
}
}
}
`;

View File

@@ -7,7 +7,7 @@ export default function Index({ data }) {
return ( return (
<Layout location="/services"> <Layout location="/services">
<Header image={data.headerImage.childImageSharp.fluid}> <Header image={data.headerImage.childImageSharp.fluid}>
<h1>Services</h1> <Heading shadow="xl-white">Services</Heading>
</Header> </Header>
<Section> <Section>
<Grid columns={[1, 2]}> <Grid columns={[1, 2]}>
@@ -23,21 +23,7 @@ export default function Index({ data }) {
image={data.tilingImage.childImageSharp.fluid} image={data.tilingImage.childImageSharp.fluid}
heading={<Heading el="h3">Tiling</Heading>} heading={<Heading el="h3">Tiling</Heading>}
> >
Our tiling is primo! We can install many different styles
</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!
</Card> </Card>
</Grid> </Grid>
</Section> </Section>
@@ -47,37 +33,23 @@ export default function Index({ data }) {
export const query = graphql` export const query = graphql`
query { query {
headerImage: file(relativePath: { eq: "floor_tiles.png" }) { headerImage: file(relativePath: { eq: "banner_bathroom.jpg" }) {
childImageSharp { childImageSharp {
fluid(maxWidth: 1920, quality: 100) { fluid(maxWidth: 1920, quality: 90) {
...GatsbyImageSharpFluid_withWebp ...GatsbyImageSharpFluid_withWebp
} }
} }
} }
bathroomImage: file(relativePath: { eq: "service_bathroom.png" }) { bathroomImage: file(relativePath: { eq: "bathroom.jpg" }) {
childImageSharp { childImageSharp {
fluid(maxWidth: 480, quality: 100) { fluid(maxWidth: 480, maxHeight: 320, quality: 90) {
...GatsbyImageSharpFluid_withWebp ...GatsbyImageSharpFluid_withWebp
} }
} }
} }
tilingImage: file(relativePath: { eq: "service_tiling.png" }) { tilingImage: file(relativePath: { eq: "tiling.jpg" }) {
childImageSharp { childImageSharp {
fluid(maxWidth: 480, quality: 100) { fluid(maxWidth: 480, maxHeight: 320, quality: 90) {
...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) {
...GatsbyImageSharpFluid_withWebp ...GatsbyImageSharpFluid_withWebp
} }
} }

View 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
}
}
}
}
}
`;

View 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
}
}
}
}
}
`;

View 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
}
}
}
}
}
`;