mirror of
https://github.com/kremalicious/portfolio.git
synced 2025-01-03 18:35:00 +01:00
resume tweaks, markdown summaries
This commit is contained in:
parent
f44e0557ed
commit
9d5e33b146
@ -19,7 +19,7 @@
|
|||||||
- [💍 One data file to rule all pages](#-one-data-file-to-rule-all-pages)
|
- [💍 One data file to rule all pages](#-one-data-file-to-rule-all-pages)
|
||||||
- [🐱 GitHub repositories](#-github-repositories)
|
- [🐱 GitHub repositories](#-github-repositories)
|
||||||
- [💅 Theme switcher](#-theme-switcher)
|
- [💅 Theme switcher](#-theme-switcher)
|
||||||
- [🗂 Resume](#-resume)
|
- [🗂 JSON Resume](#-json-resume)
|
||||||
- [🏆 SEO component](#-seo-component)
|
- [🏆 SEO component](#-seo-component)
|
||||||
- [📇 Client-side vCard creation](#-client-side-vcard-creation)
|
- [📇 Client-side vCard creation](#-client-side-vcard-creation)
|
||||||
- [💫 Page transitions](#-page-transitions)
|
- [💫 Page transitions](#-page-transitions)
|
||||||
@ -77,14 +77,14 @@ If you want to know how, have a look at the respective components:
|
|||||||
- [`src/components/molecules/ThemeSwitch.jsx`](src/components/molecules/ThemeSwitch.jsx)
|
- [`src/components/molecules/ThemeSwitch.jsx`](src/components/molecules/ThemeSwitch.jsx)
|
||||||
- [`src/hooks/use-dark-mode.jsx`](src/hooks/use-dark-mode.jsx)
|
- [`src/hooks/use-dark-mode.jsx`](src/hooks/use-dark-mode.jsx)
|
||||||
|
|
||||||
### 🗂 Resume
|
### 🗂 JSON Resume
|
||||||
|
|
||||||
Resume page based on [JSON Resume](https://jsonresume.org) standard.
|
Resume page based on [JSON Resume](https://jsonresume.org) standard. Most metadata and social profiles are defined in [`content/resume.json`](content/resume.json) and used throughout the site.
|
||||||
|
|
||||||
If you want to know how, have a look at the respective components:
|
If you want to know how, have a look at the respective components:
|
||||||
|
|
||||||
- [`src/pages/resume.jsx`](src/pages/resume.jsx)
|
|
||||||
- [`content/resume.json`](content/resume.json)
|
- [`content/resume.json`](content/resume.json)
|
||||||
|
- [`src/pages/resume.jsx`](src/pages/resume.jsx)
|
||||||
- [`src/hooks/use-resume.js`](src/hooks/use-resume.js)
|
- [`src/hooks/use-resume.js`](src/hooks/use-resume.js)
|
||||||
|
|
||||||
### 🏆 SEO component
|
### 🏆 SEO component
|
||||||
|
@ -34,7 +34,6 @@
|
|||||||
],
|
],
|
||||||
"location": {
|
"location": {
|
||||||
"city": "Berlin",
|
"city": "Berlin",
|
||||||
"country": "Germany",
|
|
||||||
"countryCode": "DE"
|
"countryCode": "DE"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -44,7 +43,7 @@
|
|||||||
"position": "Lead UI Designer & Developer",
|
"position": "Lead UI Designer & Developer",
|
||||||
"website": "https://oceanprotocol.com",
|
"website": "https://oceanprotocol.com",
|
||||||
"startDate": "2017-01-01",
|
"startDate": "2017-01-01",
|
||||||
"summary": "Leading the UI design & development of Ocean Protocol, iterating on a components-based UI design system spanning all of Ocean Protocol's web properties. Additionally, I conceptualize, execute and iterate on the creative and visual direction of the Ocean Protocol brand.",
|
"summary": "Leading the UI design & development of Ocean Protocol's user interfaces, iterating on a components-based UI design system spanning all of Ocean Protocol's web properties. \n\nConceptualize, execute and iterate on the creative and visual direction of the Ocean Protocol brand.\n\nAs a core developer leading the execution of [multiple user interfaces](/oceanprotocol) and core components.",
|
||||||
"highlights": ["Started the company"]
|
"highlights": ["Started the company"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -53,7 +52,7 @@
|
|||||||
"website": "https://bigchaindb.com",
|
"website": "https://bigchaindb.com",
|
||||||
"startDate": "2016-12-01",
|
"startDate": "2016-12-01",
|
||||||
"endDate": "2018-12-31",
|
"endDate": "2018-12-31",
|
||||||
"summary": "Leading the UI design & development of all BigchainDB web properties. I created the initial BigchainDB brand and further conceptualized, executed and iterated on the creative and visual direction of BigchainDB. This included creating and iterating on a components-based UI design system for all of BigchainDB's web properties.",
|
"summary": "Leading the UI design & development of all BigchainDB web properties. I created the initial BigchainDB brand and further conceptualized, executed and iterated on the creative and visual direction of BigchainDB. This included creating and iterating on a components-based UI design system for all of [BigchainDB's user interfaces](/bigchaindb).",
|
||||||
"highlights": ["Started the company"]
|
"highlights": ["Started the company"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -71,7 +70,7 @@
|
|||||||
"website": "https://chartmogul.com",
|
"website": "https://chartmogul.com",
|
||||||
"startDate": "2015-07-15",
|
"startDate": "2015-07-15",
|
||||||
"endDate": "2017-02-01",
|
"endDate": "2017-02-01",
|
||||||
"summary": "Co-designing and leading the UI design & development of various ChartMogul web properties. This included the creation of a components-based UI design system and implementing it across all web touch points. Besides designing and implementing new features, I maintained the front-end of the ChartMogul application and implemented the UI design system by refactoring most of its front-end codebase.",
|
"summary": "Co-designing and leading the UI design & development of various [ChartMogul web properties](/chartmogul). This included the creation of a components-based UI design system and implementing it across all web touch points.\n\nBesides designing and implementing new features, I maintained the front-end of the ChartMogul application and implemented the UI design system by refactoring most of its front-end codebase.",
|
||||||
"highlights": ["Started the company"]
|
"highlights": ["Started the company"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -80,7 +79,7 @@
|
|||||||
"website": "https://sharethemeal.org",
|
"website": "https://sharethemeal.org",
|
||||||
"startDate": "2014-10-01",
|
"startDate": "2014-10-01",
|
||||||
"endDate": "2015-06-01",
|
"endDate": "2015-06-01",
|
||||||
"summary": "...",
|
"summary": "[app and website](/sharethemeal)",
|
||||||
"highlights": ["Started the company"]
|
"highlights": ["Started the company"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -89,21 +88,21 @@
|
|||||||
"website": "https://ezeep.com",
|
"website": "https://ezeep.com",
|
||||||
"startDate": "2012-01-01",
|
"startDate": "2012-01-01",
|
||||||
"endDate": "2014-09-01",
|
"endDate": "2014-09-01",
|
||||||
"summary": "Creating an unprecedented, market-leading & award-winning user experience around printing based on the principles of emotional design way ahead of all competitors. This included defining the product based on user & market research in an iterative process and designing & building ezeep’s numerous touch points, like the web app, web site, desktop apps for Windows & Mac OS X and apps for iOS & Android. On top of that I created the corporate identity and a consistent visual branding including the logo."
|
"summary": "Creating an unprecedented, market-leading & award-winning user experience around printing based on the principles of emotional design way ahead of all competitors.\n\nThis included defining the product based on user & market research in an iterative process and designing & building [ezeep’s numerous touch points](/ezeep), like the web app, web site, desktop apps for Windows & Mac OS X and apps for iOS & Android.\n\nOn top of that I created the corporate identity and a consistent visual branding, including the logo."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"company": "Martin Luther University Halle-Wittenberg",
|
"company": "Martin Luther University Halle-Wittenberg",
|
||||||
"position": "UI/UX Designer & Front End Developer",
|
"position": "UI/UX Designer & Front End Developer",
|
||||||
"startDate": "2009-02-01",
|
"startDate": "2009-02-01",
|
||||||
"endDate": "2012-01-01",
|
"endDate": "2012-01-01",
|
||||||
"summary": "Conceptualizing & implementing numerous in-house and public facing interfaces for thousands of students and staff. Additionally, conceptualizing, creating and maintaining the blog network & community for all students & staff."
|
"summary": "Conceptualizing & implementing [numerous in-house and public facing interfaces](/unihalle) for thousands of students and staff. Additionally, conceptualizing, creating and maintaining the blog network & community for all students & staff."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"company": "Harz University of Applied Sciences",
|
"company": "Harz University of Applied Sciences",
|
||||||
"position": "Consultant & Teacher",
|
"position": "Consultant & Teacher",
|
||||||
"startDate": "2011-02-01",
|
"startDate": "2011-02-01",
|
||||||
"endDate": "2011-05-01",
|
"endDate": "2011-05-01",
|
||||||
"summary": "Conceptualizing a web design & development university seminar and building a responsive & fluid grid framework with a basic HTML/CSS template for students of Media Informatics at the Harz University of Applied Sciences to learn and use."
|
"summary": "Conceptualizing a web design & development university seminar and building a [responsive & fluid grid framework](https://github.com/kremalicious/hsresponsive) with a basic HTML/CSS template for students of Media Informatics at the Harz University of Applied Sciences to learn and use."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"company": "Martin Luther University Halle-Wittenberg",
|
"company": "Martin Luther University Halle-Wittenberg",
|
||||||
@ -144,7 +143,7 @@
|
|||||||
{
|
{
|
||||||
"institution": "Martin Luther University Halle-Wittenberg",
|
"institution": "Martin Luther University Halle-Wittenberg",
|
||||||
"area": "Media/Communication Science & Art History",
|
"area": "Media/Communication Science & Art History",
|
||||||
"studyType": "Bachelor",
|
"studyType": "Bachelor of Arts",
|
||||||
"startDate": "2008-01-01",
|
"startDate": "2008-01-01",
|
||||||
"endDate": "2012-01-01"
|
"endDate": "2012-01-01"
|
||||||
},
|
},
|
||||||
@ -160,7 +159,8 @@
|
|||||||
{
|
{
|
||||||
"title": "German Design Award",
|
"title": "German Design Award",
|
||||||
"date": "2015-11-01",
|
"date": "2015-11-01",
|
||||||
"awarder": "ezeep GmbH"
|
"awarder": "ezeep GmbH",
|
||||||
|
"summary": "Nominated in the category _Interactive User Experience (Excellent Communications Design)_"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "CeBIT Preview Award",
|
"title": "CeBIT Preview Award",
|
||||||
@ -225,13 +225,13 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"languages": [
|
"languages": [
|
||||||
{
|
|
||||||
"language": "German",
|
|
||||||
"fluency": "Native speaker"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"language": "English",
|
"language": "English",
|
||||||
"fluency": "Advanced speaker"
|
"fluency": "Advanced speaker"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"language": "German",
|
||||||
|
"fluency": "Native speaker"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const remark = require('remark')
|
const remark = require('remark')
|
||||||
const markdown = require('remark-parse')
|
const parse = require('remark-parse')
|
||||||
const html = require('remark-html')
|
const html = require('remark-html')
|
||||||
const axios = require('axios')
|
const axios = require('axios')
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
@ -111,7 +111,7 @@ exports.onCreateNode = ({ node, actions }) => {
|
|||||||
let descriptionHtml
|
let descriptionHtml
|
||||||
|
|
||||||
remark()
|
remark()
|
||||||
.use(markdown, { gfm: true, commonmark: true, pedantic: true })
|
.use(parse, { gfm: true, commonmark: true, pedantic: true })
|
||||||
.use(html)
|
.use(html)
|
||||||
.process(descriptionWithLineBreaks, (err, file) => {
|
.process(descriptionWithLineBreaks, (err, file) => {
|
||||||
if (err) throw Error('Could not transform project description')
|
if (err) throw Error('Could not transform project description')
|
||||||
|
276
jest/__fixtures__/resume.json
Normal file
276
jest/__fixtures__/resume.json
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
{
|
||||||
|
"contentJson": {
|
||||||
|
"basics": {
|
||||||
|
"name": "Matthias Kretschmann",
|
||||||
|
"label": "Designer & Developer",
|
||||||
|
"picture": {
|
||||||
|
"childImageSharp": {
|
||||||
|
"fixed": {
|
||||||
|
"aspectRatio": 1,
|
||||||
|
"width": 256,
|
||||||
|
"height": 256,
|
||||||
|
"src": "/static/b45f45aa8d98d4e4019a242d38f2f248/c296b/avatar.jpg",
|
||||||
|
"srcSet": "/static/b45f45aa8d98d4e4019a242d38f2f248/c296b/avatar.jpg 1x,\n/static/b45f45aa8d98d4e4019a242d38f2f248/28b3a/avatar.jpg 1.5x,\n/static/b45f45aa8d98d4e4019a242d38f2f248/72cad/avatar.jpg 2x",
|
||||||
|
"srcWebp": "/static/b45f45aa8d98d4e4019a242d38f2f248/59c88/avatar.webp",
|
||||||
|
"srcSetWebp": "/static/b45f45aa8d98d4e4019a242d38f2f248/59c88/avatar.webp 1x,\n/static/b45f45aa8d98d4e4019a242d38f2f248/bd640/avatar.webp 1.5x,\n/static/b45f45aa8d98d4e4019a242d38f2f248/b957b/avatar.webp 2x",
|
||||||
|
"originalName": "avatar.jpg"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"email": "m@kretschmann.io",
|
||||||
|
"website": "https://matthiaskretschmann.com",
|
||||||
|
"summary": "",
|
||||||
|
"profiles": [
|
||||||
|
{
|
||||||
|
"network": "Blog",
|
||||||
|
"url": "https://kremalicious.com",
|
||||||
|
"username": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"network": "Twitter",
|
||||||
|
"url": "https://twitter.com/kremalicious",
|
||||||
|
"username": "kremalicious"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"network": "GitHub",
|
||||||
|
"url": "https://github.com/kremalicious",
|
||||||
|
"username": "kremalicious"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"network": "Dribbble",
|
||||||
|
"url": "https://dribbble.com/kremalicious",
|
||||||
|
"username": "kremalicious"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"network": "Keybase",
|
||||||
|
"url": "https://keybase.io/kremalicious",
|
||||||
|
"username": "kremalicious"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"location": {
|
||||||
|
"city": "Berlin",
|
||||||
|
"countryCode": "DE"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"education": [
|
||||||
|
{
|
||||||
|
"institution": "Self-taught",
|
||||||
|
"area": "UI Design & Web Development",
|
||||||
|
"studyType": "Autodidactic",
|
||||||
|
"startDate": "1999-01-01",
|
||||||
|
"endDate": "2004-01-01"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"institution": "Martin Luther University Halle-Wittenberg",
|
||||||
|
"area": "Media/Communication Science & Art History",
|
||||||
|
"studyType": "Bachelor of Arts",
|
||||||
|
"startDate": "2008-01-01",
|
||||||
|
"endDate": "2012-01-01"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"institution": "Martin Luther University Halle-Wittenberg",
|
||||||
|
"area": "Political Science & Sociology",
|
||||||
|
"studyType": "Magister Artium",
|
||||||
|
"startDate": "2006-01-01",
|
||||||
|
"endDate": "2008-01-01"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"languages": [
|
||||||
|
{
|
||||||
|
"language": "English",
|
||||||
|
"fluency": "Advanced speaker"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"language": "German",
|
||||||
|
"fluency": "Native speaker"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"skills": [
|
||||||
|
{
|
||||||
|
"name": "Design",
|
||||||
|
"level": "Master",
|
||||||
|
"keywords": [
|
||||||
|
"Product Design",
|
||||||
|
"Service Design",
|
||||||
|
"Interface Design",
|
||||||
|
"User Experience Design",
|
||||||
|
"Communication Design",
|
||||||
|
"Interaction Design",
|
||||||
|
"Information Architecture",
|
||||||
|
"Icon Design",
|
||||||
|
"Web Design",
|
||||||
|
"Typography",
|
||||||
|
"Design management"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Web Development",
|
||||||
|
"level": "Master",
|
||||||
|
"keywords": [
|
||||||
|
"HTML",
|
||||||
|
"CSS",
|
||||||
|
"Javascript",
|
||||||
|
"Node.js",
|
||||||
|
"npm ecosystem",
|
||||||
|
"SASS/SCSS",
|
||||||
|
"Less",
|
||||||
|
"Stylus",
|
||||||
|
"Gulp",
|
||||||
|
"Gatsby",
|
||||||
|
"React",
|
||||||
|
"Styled Components",
|
||||||
|
"JAMstack"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "General Software Development",
|
||||||
|
"level": "Master",
|
||||||
|
"keywords": [
|
||||||
|
"Git",
|
||||||
|
"GitHub",
|
||||||
|
"Bash",
|
||||||
|
"UNIX",
|
||||||
|
"Agile: Kanban & Scrum",
|
||||||
|
"Prototyping",
|
||||||
|
"Incremental"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "DevOps",
|
||||||
|
"level": "Intermediate",
|
||||||
|
"keywords": [
|
||||||
|
"AWS",
|
||||||
|
"Now",
|
||||||
|
"Serverless",
|
||||||
|
"Cloudflare",
|
||||||
|
"NGINX",
|
||||||
|
"Apache"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"work": [
|
||||||
|
{
|
||||||
|
"company": "Ocean Protocol Foundation",
|
||||||
|
"position": "Lead UI Designer & Developer",
|
||||||
|
"website": "https://oceanprotocol.com",
|
||||||
|
"startDate": "2017-01-01",
|
||||||
|
"endDate": null,
|
||||||
|
"summary": "Leading the UI design & development of Ocean Protocol's user interfaces, iterating on a components-based UI design system spanning all of Ocean Protocol's web properties. \n\nConceptualize, execute and iterate on the creative and visual direction of the Ocean Protocol brand.\n\nAs a core developer leading the execution of [multiple user interfaces](/oceanprotocol) and core components.",
|
||||||
|
"highlights": ["Started the company"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"company": "BigchainDB GmbH",
|
||||||
|
"position": "Lead UI Designer & Developer",
|
||||||
|
"website": "https://bigchaindb.com",
|
||||||
|
"startDate": "2016-12-01",
|
||||||
|
"endDate": "2018-12-31",
|
||||||
|
"summary": "Leading the UI design & development of all BigchainDB web properties. I created the initial BigchainDB brand and further conceptualized, executed and iterated on the creative and visual direction of BigchainDB. This included creating and iterating on a components-based UI design system for all of [BigchainDB's user interfaces](/bigchaindb).",
|
||||||
|
"highlights": ["Started the company"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"company": "ascribe GmbH",
|
||||||
|
"position": "UI Designer & Developer",
|
||||||
|
"website": "https://ascribe.io",
|
||||||
|
"startDate": "2016-01-01",
|
||||||
|
"endDate": "2017-12-31",
|
||||||
|
"summary": "Description...",
|
||||||
|
"highlights": ["Started the company"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"company": "ChartMogul Ltd.",
|
||||||
|
"position": "Lead UI Engineer",
|
||||||
|
"website": "https://chartmogul.com",
|
||||||
|
"startDate": "2015-07-15",
|
||||||
|
"endDate": "2017-02-01",
|
||||||
|
"summary": "Co-designing and leading the UI design & development of various [ChartMogul web properties](/chartmogul). This included the creation of a components-based UI design system and implementing it across all web touch points.\n\nBesides designing and implementing new features, I maintained the front-end of the ChartMogul application and implemented the UI design system by refactoring most of its front-end codebase.",
|
||||||
|
"highlights": ["Started the company"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"company": "UN World Food Programme/ShareTheMeal",
|
||||||
|
"position": "UI Engineer",
|
||||||
|
"website": "https://sharethemeal.org",
|
||||||
|
"startDate": "2014-10-01",
|
||||||
|
"endDate": "2015-06-01",
|
||||||
|
"summary": "[app and website](/sharethemeal)",
|
||||||
|
"highlights": ["Started the company"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"company": "ezeep GmbH",
|
||||||
|
"position": "Lead Designer & Front End Developer",
|
||||||
|
"website": "https://ezeep.com",
|
||||||
|
"startDate": "2012-01-01",
|
||||||
|
"endDate": "2014-09-01",
|
||||||
|
"summary": "Creating an unprecedented, market-leading & award-winning user experience around printing based on the principles of emotional design way ahead of all competitors.\n\nThis included defining the product based on user & market research in an iterative process and designing & building [ezeep’s numerous touch points](/ezeep), like the web app, web site, desktop apps for Windows & Mac OS X and apps for iOS & Android.\n\nOn top of that I created the corporate identity and a consistent visual branding, including the logo.",
|
||||||
|
"highlights": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"company": "Martin Luther University Halle-Wittenberg",
|
||||||
|
"position": "UI/UX Designer & Front End Developer",
|
||||||
|
"website": null,
|
||||||
|
"startDate": "2009-02-01",
|
||||||
|
"endDate": "2012-01-01",
|
||||||
|
"summary": "Conceptualizing & implementing [numerous in-house and public facing interfaces](/unihalle) for thousands of students and staff. Additionally, conceptualizing, creating and maintaining the blog network & community for all students & staff.",
|
||||||
|
"highlights": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"company": "Harz University of Applied Sciences",
|
||||||
|
"position": "Consultant & Teacher",
|
||||||
|
"website": null,
|
||||||
|
"startDate": "2011-02-01",
|
||||||
|
"endDate": "2011-05-01",
|
||||||
|
"summary": "Conceptualizing a web design & development university seminar and building a [responsive & fluid grid framework](https://github.com/kremalicious/hsresponsive) with a basic HTML/CSS template for students of Media Informatics at the Harz University of Applied Sciences to learn and use.",
|
||||||
|
"highlights": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"company": "Martin Luther University Halle-Wittenberg",
|
||||||
|
"position": "Consultant & Teacher",
|
||||||
|
"website": null,
|
||||||
|
"startDate": "2011-02-01",
|
||||||
|
"endDate": "2011-05-01",
|
||||||
|
"summary": "Conceptualizing a WordPress-based web design university seminar and building a minimal starting theme for students of media & communication science at the MLU Halle-Wittenberg to learn and use.",
|
||||||
|
"highlights": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"company": "Shortmoves",
|
||||||
|
"position": "Web Designer & Developer",
|
||||||
|
"website": null,
|
||||||
|
"startDate": "2009-01-01",
|
||||||
|
"endDate": "2010-01-01",
|
||||||
|
"summary": "Creating & managing the web presence and marketing material of the International Shortfilm Festival Shortmoves in Halle (Saale), Germany.",
|
||||||
|
"highlights": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"company": "Agentur Ahron",
|
||||||
|
"position": "Co-Founder & Photojournalist & Photographer",
|
||||||
|
"website": null,
|
||||||
|
"startDate": "2005-01-01",
|
||||||
|
"endDate": "2008-12-31",
|
||||||
|
"summary": "Co-founded and built up a photo agency from the ground up and worked as a photographer ranging from journalistic works for news agencies & newspapers to photographic work for private clients.",
|
||||||
|
"highlights": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"company": "Freelance",
|
||||||
|
"position": "Designer & Developer",
|
||||||
|
"website": null,
|
||||||
|
"startDate": "2004-01-01",
|
||||||
|
"endDate": null,
|
||||||
|
"summary": "Numerous projects and clients as a UI/UX Designer, Front End Developer, Icon Designer & Photographer.",
|
||||||
|
"highlights": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"awards": [
|
||||||
|
{
|
||||||
|
"title": "German Design Award",
|
||||||
|
"date": "2015-11-01",
|
||||||
|
"awarder": "ezeep GmbH",
|
||||||
|
"summary": "Nominated in the category _Interactive User Experience (Excellent Communications Design)_"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "CeBIT Preview Award",
|
||||||
|
"date": "2013-11-01",
|
||||||
|
"awarder": "ezeep GmbH",
|
||||||
|
"summary": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@ -49,8 +49,10 @@
|
|||||||
"react-helmet": "^5.2.1",
|
"react-helmet": "^5.2.1",
|
||||||
"react-pose": "^4.0.10",
|
"react-pose": "^4.0.10",
|
||||||
"remark": "^11.0.2",
|
"remark": "^11.0.2",
|
||||||
|
"remark-breaks": "^1.0.3",
|
||||||
"remark-html": "^10.0.0",
|
"remark-html": "^10.0.0",
|
||||||
"remark-parse": "^7.0.2",
|
"remark-parse": "^7.0.2",
|
||||||
|
"remark-react": "^6.0.0",
|
||||||
"shortid": "^2.2.15",
|
"shortid": "^2.2.15",
|
||||||
"suncalc": "^1.8.0",
|
"suncalc": "^1.8.0",
|
||||||
"vcf": "^2.0.6"
|
"vcf": "^2.0.6"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Helmet from 'react-helmet'
|
import Helmet from 'react-helmet'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { useMeta } from '../../hooks/use-meta'`
|
import { useMeta } from '../../hooks/use-meta'
|
||||||
import { useResume } from '../../hooks/use-resume'
|
import { useResume } from '../../hooks/use-resume'
|
||||||
|
|
||||||
const MetaTags = ({ title, description, url, image, meta }) => {
|
const MetaTags = ({ title, description, url, image, meta }) => {
|
||||||
@ -10,33 +10,34 @@ const MetaTags = ({ title, description, url, image, meta }) => {
|
|||||||
({ network }) => network === 'Twitter'
|
({ network }) => network === 'Twitter'
|
||||||
)[0].username
|
)[0].username
|
||||||
|
|
||||||
const MetaTags = ({ title, description, url, image, meta }) => (
|
return (
|
||||||
<Helmet
|
<Helmet
|
||||||
defaultTitle={`${meta.title.toLowerCase()} { ${meta.tagline.toLowerCase()} }`}
|
defaultTitle={`${meta.title.toLowerCase()} { ${meta.tagline.toLowerCase()} }`}
|
||||||
titleTemplate={`%s // ${meta.title.toLowerCase()} { ${meta.tagline.toLowerCase()} }`}
|
titleTemplate={`%s // ${meta.title.toLowerCase()} { ${meta.tagline.toLowerCase()} }`}
|
||||||
title={title}
|
title={title}
|
||||||
>
|
>
|
||||||
<html lang="en" />
|
<html lang="en" />
|
||||||
|
|
||||||
{/* General tags */}
|
{/* General tags */}
|
||||||
<meta name="description" content={description} />
|
<meta name="description" content={description} />
|
||||||
<meta name="image" content={`${meta.url}${image}`} />
|
<meta name="image" content={`${meta.url}${image}`} />
|
||||||
<link rel="canonical" href={url} />
|
<link rel="canonical" href={url} />
|
||||||
|
|
||||||
{/* OpenGraph tags */}
|
{/* OpenGraph tags */}
|
||||||
<meta property="og:url" content={url} />
|
<meta property="og:url" content={url} />
|
||||||
<meta property="og:title" content={title} />
|
<meta property="og:title" content={title} />
|
||||||
<meta property="og:description" content={description} />
|
<meta property="og:description" content={description} />
|
||||||
<meta property="og:image" content={`${meta.url}${image}`} />
|
<meta property="og:image" content={`${meta.url}${image}`} />
|
||||||
|
|
||||||
{/* Twitter Card tags */}
|
{/* Twitter Card tags */}
|
||||||
<meta name="twitter:card" content="summary_large_image" />
|
<meta name="twitter:card" content="summary_large_image" />
|
||||||
<meta name="twitter:creator" content={twitterHandle} />
|
<meta name="twitter:creator" content={twitterHandle} />
|
||||||
<meta name="twitter:title" content={title} />
|
<meta name="twitter:title" content={title} />
|
||||||
<meta name="twitter:description" content={description} />
|
<meta name="twitter:description" content={description} />
|
||||||
<meta name="twitter:image" content={`${meta.url}${image}`} />
|
<meta name="twitter:image" content={`${meta.url}${image}`} />
|
||||||
</Helmet>
|
</Helmet>
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
MetaTags.propTypes = {
|
MetaTags.propTypes = {
|
||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
|
@ -7,7 +7,6 @@ import { useResume } from '../../hooks/use-resume'
|
|||||||
export default function Vcard() {
|
export default function Vcard() {
|
||||||
const metaYaml = useMeta()
|
const metaYaml = useMeta()
|
||||||
const { basics } = useResume()
|
const { basics } = useResume()
|
||||||
const data = useStaticQuery(query)
|
|
||||||
const photoSrc = basics.picture.childImageSharp.fixed.src
|
const photoSrc = basics.picture.childImageSharp.fixed.src
|
||||||
const { name, label, email, profiles } = basics
|
const { name, label, email, profiles } = basics
|
||||||
|
|
||||||
@ -56,6 +55,12 @@ export const downloadVcard = (vcard, meta) => {
|
|||||||
|
|
||||||
export const constructVcard = async (dataUrl, meta) => {
|
export const constructVcard = async (dataUrl, meta) => {
|
||||||
const contact = new vCard()
|
const contact = new vCard()
|
||||||
|
const blog = meta.profiles.filter(({ network }) => network === 'Blog')[0].url
|
||||||
|
const twitter = meta.profiles.filter(
|
||||||
|
({ network }) => network === 'Twitter'
|
||||||
|
)[0].url
|
||||||
|
const github = meta.profiles.filter(({ network }) => network === 'GitHub')[0]
|
||||||
|
.url
|
||||||
|
|
||||||
// stripping this data out of base64 string is required
|
// stripping this data out of base64 string is required
|
||||||
// for vcard to actually display the image for whatever reason
|
// for vcard to actually display the image for whatever reason
|
||||||
@ -66,9 +71,9 @@ export const constructVcard = async (dataUrl, meta) => {
|
|||||||
contact.set('email', meta.email)
|
contact.set('email', meta.email)
|
||||||
contact.set('nickname', 'kremalicious')
|
contact.set('nickname', 'kremalicious')
|
||||||
contact.set('url', meta.url, { type: 'Portfolio' })
|
contact.set('url', meta.url, { type: 'Portfolio' })
|
||||||
contact.add('url', meta.social.Blog, { type: 'Blog' })
|
contact.add('url', blog, { type: 'Blog' })
|
||||||
contact.add('x-socialprofile', meta.social.Twitter, { type: 'twitter' })
|
contact.add('x-socialprofile', twitter, { type: 'twitter' })
|
||||||
contact.add('x-socialprofile', meta.social.GitHub, { type: 'GitHub' })
|
contact.add('x-socialprofile', github, { type: 'GitHub' })
|
||||||
|
|
||||||
const vcard = contact.toString('3.0')
|
const vcard = contact.toString('3.0')
|
||||||
|
|
||||||
|
@ -3,10 +3,12 @@ import PropTypes from 'prop-types'
|
|||||||
import posed from 'react-pose'
|
import posed from 'react-pose'
|
||||||
import { moveInTop } from '../atoms/Transitions'
|
import { moveInTop } from '../atoms/Transitions'
|
||||||
import Icon from '../atoms/Icon'
|
import Icon from '../atoms/Icon'
|
||||||
import { useMeta } from '../../hooks/use-meta'
|
|
||||||
import { useResume } from '../../hooks/use-resume'
|
import { useResume } from '../../hooks/use-resume'
|
||||||
import styles from './Networks.module.scss'
|
import styles from './Networks.module.scss'
|
||||||
|
|
||||||
|
const linkClasses = key =>
|
||||||
|
key === 'Email' ? `u-email ${styles.link}` : `u-url ${styles.link}`
|
||||||
|
|
||||||
const NetworkLink = ({ name, url }) => (
|
const NetworkLink = ({ name, url }) => (
|
||||||
<a
|
<a
|
||||||
className={linkClasses(name)}
|
className={linkClasses(name)}
|
||||||
@ -24,25 +26,22 @@ NetworkLink.propTypes = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function Networks({ small, hide }) {
|
export default function Networks({ small, hide }) {
|
||||||
const { social } = useMeta()
|
const { basics } = useResume()
|
||||||
if (hide) return null
|
if (hide) return null
|
||||||
|
|
||||||
const Animation = posed.aside(moveInTop)
|
const Animation = posed.aside(moveInTop)
|
||||||
|
|
||||||
const linkClasses = key =>
|
|
||||||
key === 'Email' ? `u-email ${styles.link}` : `u-url ${styles.link}`
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Animation className={small ? styles.small : styles.networks}>
|
<Animation className={small ? styles.small : styles.networks}>
|
||||||
<NetworkLink name={'Email'} url={`mailto:${basics.email}`} />
|
<NetworkLink name={'Email'} url={`mailto:${basics.email}`} />
|
||||||
|
|
||||||
{profiles.map(profile => (
|
{basics.profiles.map(profile => (
|
||||||
<NetworkLink
|
<NetworkLink
|
||||||
key={profile.network}
|
key={profile.network}
|
||||||
name={profile.network}
|
name={profile.network}
|
||||||
url={profile.url}
|
url={profile.url}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</Animation>
|
</Animation>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -18,9 +18,13 @@ export default function Header({ minimal, isResume }) {
|
|||||||
return (
|
return (
|
||||||
<header className={minimal ? styles.minimal : styles.header}>
|
<header className={minimal ? styles.minimal : styles.header}>
|
||||||
<ThemeSwitch />
|
<ThemeSwitch />
|
||||||
<LogoUnit minimal={minimal} isResume={isResume} />
|
{!isResume && (
|
||||||
<Networks hide={minimal} />
|
<>
|
||||||
<Availability hide={minimal && !availability.status} />
|
<LogoUnit minimal={minimal} isResume={isResume} />
|
||||||
|
<Networks hide={minimal} />
|
||||||
|
<Availability hide={minimal && !availability.status} />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</header>
|
</header>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ const query = graphql`
|
|||||||
tagline
|
tagline
|
||||||
description
|
description
|
||||||
url
|
url
|
||||||
email
|
|
||||||
img {
|
img {
|
||||||
childImageSharp {
|
childImageSharp {
|
||||||
resize(width: 980) {
|
resize(width: 980) {
|
||||||
@ -15,21 +14,6 @@ const query = graphql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
avatar {
|
|
||||||
childImageSharp {
|
|
||||||
resize {
|
|
||||||
src
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
social {
|
|
||||||
Mail
|
|
||||||
Blog
|
|
||||||
Twitter
|
|
||||||
GitHub
|
|
||||||
Dribbble
|
|
||||||
Keybase
|
|
||||||
}
|
|
||||||
availability {
|
availability {
|
||||||
status
|
status
|
||||||
available
|
available
|
||||||
|
@ -23,7 +23,6 @@ const query = graphql`
|
|||||||
}
|
}
|
||||||
location {
|
location {
|
||||||
city
|
city
|
||||||
country
|
|
||||||
countryCode
|
countryCode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,6 +51,12 @@ const query = graphql`
|
|||||||
summary
|
summary
|
||||||
highlights
|
highlights
|
||||||
}
|
}
|
||||||
|
awards {
|
||||||
|
title
|
||||||
|
date
|
||||||
|
awarder
|
||||||
|
summary
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
18
src/hooks/use-resume.test.js
Normal file
18
src/hooks/use-resume.test.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { render } from '@testing-library/react'
|
||||||
|
import { useStaticQuery } from 'gatsby'
|
||||||
|
import { useResume } from './use-resume'
|
||||||
|
import data from '../../jest/__fixtures__/resume.json'
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
useStaticQuery.mockImplementationOnce(() => ({ ...data }))
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('useResume', () => {
|
||||||
|
it('renders correctly', () => {
|
||||||
|
const { basics } = useResume()
|
||||||
|
const { container } = render(<div>{basics.name}</div>)
|
||||||
|
|
||||||
|
expect(container.textContent).toBe(data.contentJson.basics.name)
|
||||||
|
})
|
||||||
|
})
|
@ -1,14 +1,43 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
import remark from 'remark'
|
||||||
|
import remark2react from 'remark-react'
|
||||||
|
import parse from 'remark-parse'
|
||||||
|
import html from 'remark-html'
|
||||||
|
import breaks from 'remark-breaks'
|
||||||
import styles from './ResumeItem.module.scss'
|
import styles from './ResumeItem.module.scss'
|
||||||
|
|
||||||
export default function ResumeItem({ workPlace, eduPlace }) {
|
export const markdownOutput = text =>
|
||||||
const title = workPlace ? workPlace.company : eduPlace.institution
|
remark()
|
||||||
const subTitle = workPlace ? workPlace.position : eduPlace.area
|
.use(parse, { gfm: true, commonmark: true, pedantic: true })
|
||||||
const text = workPlace ? workPlace.summary : eduPlace.studyType
|
.use(html)
|
||||||
const { startDate, endDate } = workPlace || eduPlace
|
.use(breaks)
|
||||||
|
.use(remark2react)
|
||||||
|
.processSync(text).contents
|
||||||
|
|
||||||
const dateStart = new Date(startDate).getFullYear()
|
export default function ResumeItem({ workPlace, eduPlace, award }) {
|
||||||
|
const title = workPlace
|
||||||
|
? workPlace.company
|
||||||
|
: award
|
||||||
|
? award.title
|
||||||
|
: eduPlace.institution
|
||||||
|
const subTitle = workPlace
|
||||||
|
? workPlace.position
|
||||||
|
: award
|
||||||
|
? award.awarder
|
||||||
|
: eduPlace.area
|
||||||
|
const text = workPlace
|
||||||
|
? workPlace.summary
|
||||||
|
: award && award.summary
|
||||||
|
? award.summary
|
||||||
|
: eduPlace
|
||||||
|
? eduPlace.studyType
|
||||||
|
: null
|
||||||
|
const { startDate, endDate, date } = workPlace || eduPlace || award
|
||||||
|
|
||||||
|
const dateStart = date
|
||||||
|
? new Date(date).getFullYear()
|
||||||
|
: new Date(startDate).getFullYear()
|
||||||
const dateEnd = endDate && new Date(endDate).getFullYear()
|
const dateEnd = endDate && new Date(endDate).getFullYear()
|
||||||
const isSameYear = dateStart === dateEnd
|
const isSameYear = dateStart === dateEnd
|
||||||
|
|
||||||
@ -16,13 +45,15 @@ export default function ResumeItem({ workPlace, eduPlace }) {
|
|||||||
<div className={styles.resumeItem}>
|
<div className={styles.resumeItem}>
|
||||||
<span className={styles.time}>
|
<span className={styles.time}>
|
||||||
{dateStart}
|
{dateStart}
|
||||||
{dateEnd ? !isSameYear && `–${dateEnd}` : '–present'}{' '}
|
{dateEnd
|
||||||
|
? !isSameYear && `–${dateEnd}`
|
||||||
|
: !date
|
||||||
|
? '–present'
|
||||||
|
: null}{' '}
|
||||||
</span>
|
</span>
|
||||||
<h4 className={styles.title}>{title}</h4>
|
<h4 className={styles.title}>{title}</h4>
|
||||||
<h5 className={styles.subTitle}>{subTitle}</h5>
|
<h5 className={styles.subTitle}>{subTitle}</h5>
|
||||||
<p>
|
{text && markdownOutput(text)}
|
||||||
<em>{text}</em>
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -41,5 +72,11 @@ ResumeItem.propTypes = {
|
|||||||
institution: PropTypes.string.isRequired,
|
institution: PropTypes.string.isRequired,
|
||||||
area: PropTypes.string.isRequired,
|
area: PropTypes.string.isRequired,
|
||||||
studyType: PropTypes.string
|
studyType: PropTypes.string
|
||||||
|
}),
|
||||||
|
award: PropTypes.shape({
|
||||||
|
date: PropTypes.string.isRequired,
|
||||||
|
title: PropTypes.string.isRequired,
|
||||||
|
awarder: PropTypes.string.isRequired,
|
||||||
|
summary: PropTypes.string
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -4,22 +4,27 @@
|
|||||||
padding-bottom: $spacer * 3;
|
padding-bottom: $spacer * 3;
|
||||||
padding-left: $spacer;
|
padding-left: $spacer;
|
||||||
position: relative;
|
position: relative;
|
||||||
border-left: 1px solid $brand-grey-light;
|
border-left: 1px solid rgba($brand-grey-light, 0.25);
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
content: '';
|
content: '';
|
||||||
display: block;
|
display: block;
|
||||||
width: 1rem;
|
width: $font-size-small;
|
||||||
height: 1rem;
|
height: $font-size-small;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: $brand-grey-light;
|
background: $brand-grey-light;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: -0.5rem;
|
left: -($font-size-small / 2);
|
||||||
|
top: 0.1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
p:last-child {
|
p:last-child {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
|
@ -7,7 +7,8 @@ import styles from './index.module.scss'
|
|||||||
import ResumeItem from './ResumeItem'
|
import ResumeItem from './ResumeItem'
|
||||||
|
|
||||||
export default function Resume() {
|
export default function Resume() {
|
||||||
const { basics, education, languages, work } = useResume()
|
const { basics, education, languages, work, awards } = useResume()
|
||||||
|
const { name, label, email, website, location } = basics
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -16,25 +17,25 @@ export default function Resume() {
|
|||||||
<div className={styles.resume}>
|
<div className={styles.resume}>
|
||||||
<header>
|
<header>
|
||||||
<p>Résumé</p>
|
<p>Résumé</p>
|
||||||
<h1 className={styles.title}>{basics.name}</h1>
|
<h1 className={styles.title}>{name}</h1>
|
||||||
<h2 className={styles.label}>{basics.label}</h2>
|
<h2 className={styles.label}>{label}</h2>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<ul className={styles.contact}>
|
<ul className={styles.contact}>
|
||||||
<li>
|
<li>
|
||||||
<a href={basics.website}>
|
<a href={website}>
|
||||||
<LinkIcon type="website" />
|
<LinkIcon type="website" />
|
||||||
{basics.website.replace('https://', '')}
|
Portfolio
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<LinkIcon type="Email" />
|
<LinkIcon type="Email" />
|
||||||
{basics.email}
|
<a href={`mailto:${email}`}>Email</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<LinkIcon type="Info" />
|
<LinkIcon type="Info" />
|
||||||
{basics.location.city}
|
{location.city}, {location.countryCode}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<LinkIcon type="Info" />
|
<LinkIcon type="Info" />
|
||||||
@ -56,6 +57,15 @@ export default function Resume() {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3 className={styles.subTitle}>Awards</h3>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{awards.map(award => (
|
||||||
|
<ResumeItem key={shortid.generate()} award={award} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h3 className={styles.subTitle}>Education</h3>
|
<h3 className={styles.subTitle}>Education</h3>
|
||||||
</div>
|
</div>
|
||||||
|
@ -46,13 +46,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: $screen-md) {
|
@media (min-width: $screen-md) {
|
||||||
margin-top: $spacer * 2;
|
margin-top: $spacer * 2.25;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.subTitle {
|
.subTitle {
|
||||||
font-size: $font-size-h3;
|
font-size: $font-size-h3;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
margin-top: -($spacer / 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media print {
|
@media print {
|
||||||
|
Loading…
Reference in New Issue
Block a user