Initial refactor of jambonz-ui package library (#39)

* Initial refactor of jambonz-ui package library

* Delete public/fonts directory

* Jambonz UI test-app and some refinements

* next lint

* working on jambonz ui docs

* Update package.json

* Update package.json

* Update package.json

* Create package.json

* typescript

* Update components.tsx

* Update components.tsx

* Update utils.ts

* Update icons.ts

* Update components.tsx

* Update components.tsx

* Update icons.ts

* Update components.tsx

* Update _icons.scss

* Update components.tsx

* Update components.tsx

* fix some thangs and compile all

* wrap up the docs

* Update tsconfig.json

* icons refactor

* refine docs

* update readmes

* update readme

* fix props interfaces and test in TS app

* Update components.tsx

* button up some things

* change package name...

* include readme in pkg dist

* use published package
This commit is contained in:
Brandon Lee Kitajchuk
2022-07-01 10:57:32 -07:00
committed by GitHub
parent e783a1d6a3
commit e3cd0edeb6
61 changed files with 1617 additions and 2116 deletions

View File

@@ -11,7 +11,12 @@
"js",
"json",
"bash",
"http"
"http",
"html",
"css",
"jsx",
"sass",
"scss"
],
"plugins": [
"line-numbers",

6
.eslintrc.json Normal file
View File

@@ -0,0 +1,6 @@
{
"extends": "next/core-web-vitals",
"rules": {
"@next/next/no-img-element": "off"
}
}

16
.gitignore vendored
View File

@@ -25,18 +25,14 @@ yarn-error.log*
package-lock.json
# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local
# nextra...
dist
examples
packages
.env*
# jambonz...
/.notes
pkg
css
dist
build
public/fonts
# cypress
/cypress/*

14
.lintstagedrc.js Normal file
View File

@@ -0,0 +1,14 @@
// https://nextjs.org/docs/basic-features/eslint#lint-staged
const path = require('path');
const buildEslintCommand = (filenames) => {
return `next lint --file ${filenames
.map((f) => path.relative(process.cwd(), f))
.join(' --file ')}`;
};
module.exports = {
'src/**/*.{js,jsx,ts,tsx}': [buildEslintCommand],
'pages/**/*.{js,jsx,ts,tsx}': [buildEslintCommand],
};

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2020 Shu Ding
Copyright (c) 2021 Drachtio Communications Services, LLC
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
SOFTWARE.

View File

@@ -25,10 +25,10 @@ Clone this repository and install [yarn](https://yarnpkg.com/getting-started/ins
### Commands
- `yarn install`
- `yarn`
- Installs node packages
- Installs [husky](https://typicode.github.io/husky/) for git `pre-commit` hooks
- Husky will run `yarn build` before a git commit and stop the commit if `lint` or `build` fails
- Husky will run `yarn lint-staged` and `yarn build` to ensure staged code is sound
- `yarn dev`
- Serves local dev at [localhost:3000](http://localhost:3000)
- `yarn lint`
@@ -39,7 +39,33 @@ Clone this repository and install [yarn](https://yarnpkg.com/getting-started/ins
- `yarn build && yarn export`
- Create a static production export for any static deploy target
### Testing
## Jambonz UI library
Head on over to the [jambonz-ui](https://github.com/jambonz/jambonz-ui) repo for full documentation. Also check out the [jambonz-ui docs](https://jambonz.org/docs/jambonz-ui/getting-started/) as a more in-depth resource.
### UI Design
This app is being composed in the manor of `module > component > element`, wherein a page is a module which is made up of components that are comprised of elements. We are using [Next.js](https://nextjs.org) [SASS](https://nextjs.org/learn/basics/assets-metadata-css/css-styling) located in the `src/styles` directory and loaded globally in [pages/_app.js](/pages/_app.js). JS components are in the `src/components` directory. The `jambonz-ui` component library consists of reusable design element components.
### Styling
We are using the [BEM](http://getbem.com/) style for our CSS/SASS system. Please review current implementations in `src/styles` and take the time to understand the BEM style in order to properly name and design your components styling.
### Typography
You should always use the reusable components from the `jambonz-ui` component library. These typographic components implement our type-scale for our design system. When styling pages in which we want to adjust or tweak the type-scale you should always use the `mixins` provided in the SASS. This ensures when we decide to break out of our standard type-scale implementation for any given element(s) we retain a harmonious nature to our type sizing as it retains its responsive nature provided by the `mixins`. A perfect example of how we have already done this is for the `_text-layout` page(s) wherein we've chosen to have the `p` element implement the `ms()` mixin and likewise the `li` element(s) implementing the `ms()` mixin as well.
## Static page data
We are using static data with [yamljs](https://www.npmjs.com/package/yamljs) and [Next.js static props](https://nextjs.org/docs/basic-features/data-fetching#getstaticprops-static-generation). Data files are located in the `data` directory. There's a JS data utility in `lib/data.js` that provides a method for "fetching" the static data for use with a Next.js pages async `getStaticProps` SSR method.
## Markdown data
The project is generating some dynamic layouts with markdown files using static file JS utilities alongside Next.js static paths/props system. We are leveraging their [catch-all](https://nextjs.org/docs/routing/dynamic-routes#optional-catch-all-routes) dynamic routes logic. Example located at `pages/docs/[[...slug]].js`. The markdown files are in the `markdown` directory organized by subfolders. The markdown navigation structure is controlled in the relevant page YAML data located in the `data` directory for each `markdown` subfolder. You can create markdown files at will but they will not render in the sidebar nav until they are also added to the nav structure in the relevant `data` file. For example, the markdown files for the developer docs are located at `markdown/docs/...` and the YAML data for this layout is located at `data/docs.yml`.
We are using [remark](https://github.com/remarkjs/remark), [remark-html](https://github.com/remarkjs/remark-html) and [remark-gfm](https://github.com/remarkjs/remark-gfm) as well as [gray-matter](https://github.com/jonschlinkert/gray-matter) for parsing the docs markdown files. Code syntax highlighting is done with [prismjs](https://prismjs.com) and the associative babel config is in the `.babelrc` file. It's important to leave the preset in this file that merges our config with `next/babel` so Next.js works properly.
## Testing
*Note cypress test suite is still a work in progress*
@@ -50,34 +76,3 @@ Cypress specs are located at `cypress/integration/...`. The source of truth stat
* A `pretest` script runs and generates the JSON fixtures for Cypress
* The Cypress tests are run in headless mode
* A `posttest` script runs and performs cleanup on the Cypress fixtures
### Packages
Packages being used prominently in this apps source code are:
* [classnames](https://www.npmjs.com/package/classnames)
* [nanoid](https://www.npmjs.com/package/nanoid#react)
## Jambonz UI library
This app is being composed in the manor of `module > component > element`, wherein a page is a module which is made up of components that are comprised of elements. We are using [Next.js](https://nextjs.org) [SASS](https://nextjs.org/learn/basics/assets-metadata-css/css-styling) located in the `styles` directory and loaded globally in [pages/_app.js](/pages/_app.js). A generally simple BEM CSS module naming convention is being used prominently. JS components are in the `components` directory. The `jambonz-ui` component library consists of reusable design element components.
You can view examples of the Jambonz UI component elements on this page [here](https://jambonz.org/jambonz-ui).
### Jambonz Styling
We are using the [BEM](http://getbem.com/) style for our CSS/SASS system. Please review current implementations in `src/styles` and take the time to understand the BEM style in order to properly name and design your components styling.
### Jambonz Typography
You should always use the reusable components from the `jambonz-ui` component library. These typographic components implement our type-scale for our design system. When styling pages in which we want to adjust or tweak the type-scale you should always use the `mixins` provided in the SASS. This ensures when we decide to break out of our standard type-scale implementation for any given element(s) we retain a harmonious nature to our type sizing as it retains its responsive nature provided by the `mixins`. A perfect example of how we have already done this is for the `docs` page(s) wherein we've chosen to have the `h1` element implement the `h2()` mixin and likewise the `h2` element to implement the `h3()` mixin. We even have the `li` element(s) implementing the `ms()` mixin.
## Static page data
We are using static data with [yamljs](https://www.npmjs.com/package/yamljs) and [Next.js static props](https://nextjs.org/docs/basic-features/data-fetching#getstaticprops-static-generation). Data files are located in the `data` directory. There's a JS data utility in `lib/data.js` that provides a method for "fetching" the static data for use with a Next.js pages async `getStaticProps` SSR method.
## Jambonz markdown data
The project is generating some dynamic layouts with markdown files using static file JS utilities alongside Next.js static paths/props system. We are leveraging their [catch-all](https://nextjs.org/docs/routing/dynamic-routes#optional-catch-all-routes) dynamic routes logic. Example located at `pages/docs/[[...slug]].js`. The markdown files are in the `markdown` directory organized by subfolders. The markdown navigation structure is controlled in the relevant page YAML data located in the `data` directory for each `markdown` subfolder. You can create markdown files at will but they will not render in the sidebar nav until they are also added to the nav structure in the relevant `data` file. For example, the markdown files for the developer docs are located at `markdown/docs/...` and the YAML data for this layout is located at `data/docs.yml`.
We are using [remark](https://github.com/remarkjs/remark), [remark-html](https://github.com/remarkjs/remark-html) and [remark-gfm](https://github.com/remarkjs/remark-gfm) as well as [gray-matter](https://github.com/jonschlinkert/gray-matter) for parsing the docs markdown files. Code syntax highlighting is done with [prismjs](https://prismjs.com) and the associative babel config is in the `.babelrc` file. It's important to leave the preset in this file that merges our config with `next/babel` so Next.js works properly.

View File

@@ -111,6 +111,22 @@ navi:
-
path: nodejs-sdk
title: Introduction to the Node.js SDK
-
path: jambonz-ui
title: Jambonz UI
pages:
-
path: getting-started
title: Getting started
-
path: fonts-and-icons
title: Fonts and icons
-
path: styles
title: Styles
-
path: components
title: Components
-
path: release-notes
title: Release Notes

View File

@@ -0,0 +1,162 @@
# Components
The UI library would not be complete without some atomic components for use in your jambonz apps. Currently there are components for normalized typography, iconography and buttons. As jambonz frontend development continues to mature new use cases will become viable candidates to incorporate into this UI kit—form elements being the most notable upcoming candidates. To see all the components in action, visually in one place you can go [here](/jambonz-ui/).
The component library requires that some JS peer dependencies are met in your jambonz app. The component library itself is also written in [TypeScript](https://www.typescriptlang.org/) so it supports jambonz apps also using TypeScript.
```json
"peerDependencies": {
"react": ">=18.2.0",
"react-dom": ">=18.2.0",
"react-feather": ">=2.0.9"
}
```
##### Using components
You can import available components from the package into your jambonz app JS.
```jsx
import { ButtonGroup, Button, Icon } from 'jambonz-ui';
function MyComponent() {
return (
<ButtonGroup className="pad">
<Button mainStyle="pill">
<Icons.GitHub />
<span>github.com/jambonz</span>
</Button>
<Button mainStyle="pill">
<Icons.GitHub />
<span>github.com/drachtio</span>
</Button>
</ButtonGroup>
);
}
```
##### Button with Link
The `Button` component takes a few props that are specific to rendering a link element, `<a>`, with button styles. If you just need a button, you can ignore these props. But if you would like links to be styled like buttons (CTAs) and you want them to route within the [React](https://reactjs.org/) context you can do that. The distinction between which one has to do with passing either the `to` or the `href` props that are passed on to the `Link` component in question.
Using the `Link` prop with [react-router-dom](https://reactrouter.com/docs/en/v6/components/link).
```jsx
import { Link } from 'react-router-dom';
import { Button } from 'jambonz-ui';
function MyComponent() {
return (
<Button
as={Link}
to="/someurl/"
subStyle="dark">
Some text
</Button>
);
}
```
Using the `Link` prop with [next/link](https://nextjs.org/docs/api-reference/next/link) for [Next.js](https://nextjs.org/).
```jsx
import Link from 'next/link';
import { Button } from 'jambonz-ui';
function MyComponent() {
return (
<Button
as={Link}
href="/someurl/"
subStyle="dark">
Some text
</Button>
);
}
```
##### Importing your icon set
By default the UI library doesn't import any icons from [feathericons](https://feathericons.com/), however it declares [react-feather](https://github.com/feathericons/react-feather) as a peer dependency. This means you can import just the icons you are using in your jambonz app. This allows for [tree-shaking](https://developer.mozilla.org/en-US/docs/Glossary/Tree_shaking) to take effect and ensures we don't load extra bloat into our dist JS that isn't explicitly used. The `Icon` component renders a stylized design icon with many visual variations.
You can see how we import the feather icons used on this site [here](https://github.com/jambonz/next-static-site/blob/main/src/components/icons.js). But for a quick reference here is a compressed example.
First we create a module in our jambonz app and import the icons we would like to use and export them for use in the rest of the app.
```jsx
import {
X,
Lock,
Send,
Menu,
Phone,
Heart,
ExternalLink,
// ...
} from 'react-feather';
export const Icons = {
X,
Lock,
Send,
Menu,
Phone,
Heart,
ExternalLink,
// ...
};
export default Icons;
```
Then we can use these icons both `inline` and with the `Icon` component for stylized designer icons.
```jsx
import { Icons, Heart } from './my-icons';
import { Icon } from 'jambonz-ui';
function MyComponent() {
return (
<>
<Icon mainStyle="pill" subStyle="dark">
<Icons.Heart />
</Icon>
<Link href="https://www.behance.net/gallery/60530395/Objectivity-Free-Font-Family">
<a className="i" target="_blank">
<span>design</span>
<Icons.ExternalLink />
</a>
</Link>
</>
);
}
```
###### Atomic components
| Component | Props |
|-----------|-------|
| Icon | `{ children, subStyle, mainStyle, ...rest }` |
| IconGroup | `{ children, className, set }` |
| Button | `{ children, to, href, as, subStyle, mainStyle, ...rest }` |
| ButtonGroup | `{ children, className }` |
###### Typography components
| Component | Props |
|-----------|-------|
| H1 | `{ children, ...rest }` |
| H2 | `{ children, ...rest }` |
| H3 | `{ children, ...rest }` |
| H4 | `{ children, ...rest }` |
| H5 | `{ children, ...rest }` |
| H6 | `{ children, ...rest }` |
| P | `{ children, ...rest }` |
| M | `{ children }` |
| MS | `{ children }` |
| MXS | `{ children }` |
<p class="flex">
<a href="/docs/jambonz-ui/styles/">Prev: Styles</a>
<span>&nbsp;</span>
</p>

View File

@@ -0,0 +1,75 @@
# Fonts and icons
The point of the Jambonz UI library is for jambonz apps to be "on brand" and share a cohesive foundational design DNA. With that in mind, the official font family for jambonz is called [Objectivity](https://www.behance.net/gallery/60530395/Objectivity-Free-Font-Family). Objectivity is a free, open-source font available for download online. The UI kit provides the font files already optimized for web use in the `woff` format. Jambonz doesn't utilize every member of the font family but you can view the full font specimen [here](https://www.fontsquirrel.com/fonts/objectivity).
##### Available fonts for web use:
| Font | File | SASS Variable |
|------|------|---------------|
| Objectivity Regular | `objectivity-regular-webfont.woff(2)` | `$font-regular` |
| Objectivity Regular Slanted | `objectivity-regularslanted-webfont.woff(2)` | `$font-regular-italic` |
| Objectivity Medium | `objectivity-medium-webfont.woff(2)` | `$font-medium` |
| Objectivity Medium Slanted | `objectivity-mediumslanted-webfont.woff(2)` | `$font-medium-italic` |
| Objectivity Bold | `objectivity-bold-webfont.woff(2)` | `$font-bold` |
| Objectivity Bold Slanted | `objectivity-boldslanted-webfont.woff(2)` | `$font-bold-italic` |
##### Loading the fonts
Fonts can be copied from the package to your static public directory. This can be done manually, at installation time or during app bundling depending on your preference. The package provides a singular `public` directory that consists of all static assets: CSS, JS and fonts. You can literally just copy these assets into your jambonz applications static directory if you want to.
##### Examples
For this [Next.js](https://nextjs.org/) app you're on right now we do this with the `postinstall` script in the `package.json` file. We are also opting to ignore the `fonts` directory inside of `public` since the fonts are always copied during `install` which works locally and in CI.
```json
{
"scripts": {
"postinstall": "rm -rf public/fonts && cp -R ./node_modules/jambonz-ui/public/fonts ./public/fonts"
}
}
```
Of course you can serve them statically in development and bundle them at build time if you're using a tool like [webpack](https://webpack.js.org/). See the documentation on [devServer](https://webpack.js.org/configuration/dev-server/#devserverstatic) and check out the [copy-webpack-plugin](https://www.npmjs.com/package/copy-webpack-plugin) for resources on how to handle this. Beyond this the expectation is that you have a good handle on how you can get the static fonts into your jambonz app.
Example of dev server config:
```js
module.exports = {
// ...
devServer: {
static: [path.resolve(__dirname, 'node_modules/jambonz-ui/public')],
},
};
```
Example of copy plugin config:
```js
module.exports = {
// ...
plugins: [
new CopyWebpackPlugin({
patterns: [
{
from: path.resolve(__dirname, 'node_modules/jambonz-ui/public'),
// If you would like to omit the CSS/JS and only copy fonts
globOptions: {
ignore: ['**/css/**', '**/js/**'],
},
},
],
}),
],
};
```
##### Feather icons
Jambonz UI utilizes [feathericons](https://feathericons.com/), an open-source icon library available in many formats for implemention into frontend stacks. Feather has 280+ available icons and the UI library is designed to work with [react-feather](https://github.com/feathericons/react-feather). By default the UI library doesn't import any icons from feather, however it declares `react-feather` as a peer dependency. This means you can import just the icons you are using in your jambonz app. This allows for [tree-shaking](https://developer.mozilla.org/en-US/docs/Glossary/Tree_shaking) to take effect and ensures we don't load extra bloat into our dist JS that isn't explicitly used. There is an [Icon component](/docs/jambonz-ui/components/) that renders a stylized design icon with many visual variations.
You can see how we import the feather icons used on this site [here](https://github.com/jambonz/next-static-site/blob/main/src/components/icons.js).
<p class="flex">
<a href="/docs/jambonz-ui/getting-started/">Prev: Getting started</a>
<a href="/docs/jambonz-ui/styles/">Next: Styles</a>
</p>

View File

@@ -0,0 +1,30 @@
# Jambonz UI
The Jambonz UI library is a minimal, light-weight UI design package for developing frontends for jambonz apps. It's a kit-of-parts including fonts, a small set of CSS styles, a source set of SASS styles and JavaScript components. Whether you're developing a custom dev stack with tools like [webpack](https://webpack.js.org/) or using a framework (like [vite](https://vitejs.dev/)) you should have no issues utilizing the resources available in the Jambonz UI library package. You can view the available UI elements from the library on this site [here](/jambonz-ui/). Also—this site is using the UI library!
What this is not is an overopinionated UI framework. Jambonz UI aims to provide foundational design materials like colors, fonts and typography as well as [atomic design](https://bradfrost.com/blog/post/atomic-web-design/) materials like buttons, icons etc. Currently the library is very lean but is expected to grow thoughtfully as jambonz frontend development continues to mature along this line of thinking.
A primary goal of the library is to have a small footprint. Current sizes:
| Output format | CSS size | JS size |
|---------------|----------|---------|
| Minified and Gzipped | `2 KB` | `614 bytes` |
| Minified | `10 KB` | `2 KB` |
| Compiled | `14 KB` | `4 KB` |
##### Installation
Installing the package is easy. You can use any typical package manager for frontend stacks.
```shell
npm install jambonz-ui # or yarn add jambonz-ui
```
##### General usage
The UI kit can be used in any typical way we pull things into our modern frontend stacks. You can import the CSS, SASS and JS directly into your specific target entry points for bundling or you can load them statically the good-old-fashioned way. For the latter the package provides a singular `public` directory that consists of all static assets: CSS, JS and fonts. You can literally just copy these assets into your jambonz applications static directory if you want to. This is also handy for serving extra static assets during development with tools like [webpack-dev-server](https://webpack.js.org/configuration/dev-server/) and also for copying just the raw static assets at build time when bundling.
<p class="flex">
<span>&nbsp;</span>
<a href="/docs/jambonz-ui/fonts-and-icons/">Next: Fonts and icons</a>
</p>

View File

@@ -0,0 +1,83 @@
# Styles
Jambonz UI styles are provided a couple of ways. The raw source for the styles is [SASS]() so if you're also using SASS you have the beneficial ability to directly import either all the UI SASS or just the variables and mixins for use extending the UI kit in your jambonz app. If you import all the SASS you don't need to use the raw CSS anywhere in your app. The imported SASS will compile into your final CSS output.
##### Loading the CSS
You can load the raw CSS directly into your app with a `<link>` tag if you prefer that method. It is provided compiled, minified and minified + gzipped. Assuming you've copied the CSS from the `public` directory provided with the package into your own static directory and renamed it `jambonz-ui.css`:
```html
<!-- loading the minified CSS -->
<link rel="stylesheet" href="/css/jambonz-ui.css" />
```
You can also import the CSS directly into your jambonz app entry point (JS) as most bundlers support extraction for this file type:
```js
import 'jambonz-ui/public/css/styles.css';
```
##### Available CSS selectors
Most of the styles are utilized directly by the [components](/dacs/jambonz-ui/components/) so you're better off just using those. These are the basic utility styles that can be used in an ad-hoc manor in your jambonz apps.
| CSS selector | Application |
|--------------|-------------|
| `bg--jambonz` | Applies main brand color as element `background-color` |
| `bg--black` | Applies color as element `background-color` |
| `bg--charcoal` | Applies color as element `background-color` |
| `bg--grey` | Applies color as element `background-color` |
| `bg--pink` | Applies color as element `background-color` |
| `bg--blue` | Applies color as element `background-color` |
| `bg--purple` | Applies color as element `background-color` |
| `bg--teal` | Applies color as element `background-color` |
| `color--jambonz` | Applies main brand color as element `color` |
| `color--blue` | Applies color as element `color` |
| `color--purple` | Applies color as element `color` |
| `color--teal` | Applies color as element `color` |
| `wrap` | Center contains content with a `max-width` and default left/right `padding` |
| `wrap-text` | Flex center justifies text—combine with a `max-width` |
| `pad` | Applies normalized top/bottom `padding` |
| `pad-b` | Applies normalized bottom `padding` |
| `pad-t` | Applies normalized top `padding` |
| `i` | Inline icon wrapper—normalizes display of `Icon` alongside text |
That `i` class is pretty useful. Here's an example of how it's used on this site to inline an icon with some text.
```jsx
<Link href="https://www.behance.net/gallery/60530395/Objectivity-Free-Font-Family">
<a className="i" target="_blank">
<span>design</span>
<Icons.ExternalLink />
</a>
</Link>
```
##### Loading in SASS
As mentioned you can import either the whole kit or just the variables and mixins. If you're already using SASS for your jambonz app the recommendation would be to just import the whole thing and not worry about managing another CSS import target anywhere in your frontend stack.
```scss
// This imports the entire SASS lib
@import 'jambonz-ui/src/styles/index.scss';
// This imports just the mixins and variables
@import 'jambonz-ui/src/styles/_vars.scss';
@import 'jambonz-ui/src/styles/_mixins.scss';
```
##### Available SASS variables
A more comprehensive table of available variables here is coming soon. For now the easiest place to visualize this is in the source file for the variables [here](https://github.com/jambonz/next-static-site/tree/main/jambonz-ui/src/styles/_vars.scss).
##### Available SASS mixins
A more comprehensive table of available mixins here is coming soon. For now the easiest place to visualize this is in the source file for the mixins [here](https://github.com/jambonz/next-static-site/tree/main/jambonz-ui/src/styles/_mixins.scss).
<p class="flex">
<a href="/docs/jambonz-ui/icons/">Prev: Icons</a>
<a href="/docs/jambonz-ui/components/">Next: Components</a>
</p>

View File

@@ -5,19 +5,26 @@
"main": "index.js",
"scripts": {
"prepare": "husky install",
"postinstall": "rm -rf public/fonts && cp -R ./node_modules/jambonz-ui/public/fonts ./public/fonts",
"dev": "next",
"lint": "next lint",
"start": "next start",
"build": "next build",
"export": "next export",
"pretest": "node cypress/scripts/fixtures.js",
"test": "cypress run --headless --browser chrome",
"posttest": "rm -rf cypress/fixtures",
"lint": "eslint src/components src/lib pages --ext js"
"posttest": "rm -rf cypress/fixtures"
},
"author": "Jambonz Developers",
"contributors": [
{
"name": "Brandon Lee Kitajchuk",
"email": "bk@kitajchuk.com",
"url": "https://www.kitajchuk.com"
}
],
"license": "MIT",
"dependencies": {
"classnames": "^2.2.6",
"jambonz-ui": "^0.0.2",
"nanoid": "^3.1.22",
"next": "^12.1.4",
"next-plugin-preact": "^3.0.6",
@@ -26,7 +33,7 @@
"prismjs": "^1.23.0",
"react": "npm:@preact/compat",
"react-dom": "npm:@preact/compat",
"react-feather": "^2.0.9",
"react-feather": "^2.0.10",
"react-ssr-prepass": "npm:preact-ssr-prepass"
},
"devDependencies": {
@@ -34,13 +41,8 @@
"babel-plugin-prismjs": "^2.0.1",
"cypress": "^7.7.0",
"env-cmd": "^10.1.0",
"eslint": "^7.26.0",
"eslint-config-react-app": "^6.0.0",
"eslint-plugin-flowtype": "^5.7.2",
"eslint-plugin-import": "^2.23.4",
"eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-react": "^7.24.0",
"eslint-plugin-react-hooks": "^4.2.0",
"eslint": "8.18.0",
"eslint-config-next": "12.1.6",
"gray-matter": "^4.0.2",
"husky": "^6.0.0",
"lint-staged": "^12.4.1",
@@ -52,58 +54,7 @@
"yamljs": "^0.3.0"
},
"lint-staged": {
"*.js": "yarn lint"
},
"eslintConfig": {
"settings": {
"react": {
"version": "detect"
}
},
"env": {
"browser": true,
"es2021": true,
"node": true
},
"extends": [
"eslint:recommended",
"plugin:react/recommended",
"react-app"
],
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 12,
"sourceType": "module"
},
"plugins": [
"react"
],
"rules": {
"react/prop-types": "off",
"react/react-in-jsx-scope": "off",
"jsx-a11y/anchor-is-valid": "off",
"jsx-a11y/alt-text": "off",
"indent": [
"error",
2
],
"quotes": [
"error",
"single"
],
"semi": [
"error",
"always"
]
},
"ignorePatterns": [
"**/node_modules/*",
"**/out/*",
"**/.next/*",
"next.config.js",
"**/cypress/*"
]
"src/**/*.js": "yarn lint",
"pages/**/*.js": "yarn lint"
}
}

View File

@@ -1,6 +1,5 @@
import Layout from '../src/components/layout';
import { Hero } from '../src/components/jambonz-ui';
import { getData } from '../src/lib/data';
import Layout, { Hero } from '../src/components/layout';
export default function Page404({ data }) {
return (

View File

@@ -1,5 +1,5 @@
import '../src/styles/global.scss';
export default function App({Component, pageProps}) {
export default function App({ Component, pageProps }) {
return <Component {...pageProps} />;
}

View File

@@ -1,6 +1,5 @@
import { useEffect } from 'react';
import Prism from 'prismjs';
import { useEffect } from 'react';
import Layout from '../../src/components/layout';
import Markdown from '../../src/components/markdown';

View File

@@ -1,10 +1,14 @@
import { nanoid } from 'nanoid';
import classNames from 'classnames';
import { useState, useEffect, useRef } from 'react';
import Link from 'next/link';
import { nanoid } from 'nanoid';
import { useState, useEffect, useRef } from 'react';
import { Icon, Button, H4, H3, H2, P, MS, classNames, IconGroup } from 'jambonz-ui';
import Layout from '../src/components/layout';
import { Latest, Hero, Icon, Button, H4, H3, H2, P, MS, normalizeSubtext, normalizeSlug, useMobileMedia } from '../src/components/jambonz-ui';
import { getData } from '../src/lib/data';
import { Icons } from '../src/components/icons';
import { useMobileMedia } from '../src/components/hooks';
import Layout, { Latest, Hero } from '../src/components/layout';
import { normalizeSubtext, normalizeSlug } from '../src/components/utils';
function Tech({data}) {
return (
@@ -92,7 +96,7 @@ function Dilemma({data}) {
<div className="dilemma__table__title" onClick={() => handleToggle(slug)}>
{table.logo ? <img src={table.logo} width="128" height="42" alt="jambonz" /> : <P><strong>{table.title}</strong></P>}
<span className="dilemma__table__toggle" >
{isActiveToggle ? <Icon name="ChevronUp" /> : <Icon name="ChevronDown" />}
{isActiveToggle ? <Icons.ChevronUp /> : <Icons.ChevronDown />}
</span>
</div>
<div className={classNames(pointsClasses)}>
@@ -101,10 +105,11 @@ function Dilemma({data}) {
'dilemma__table__point': true,
[point.icon.toLowerCase()]: true,
};
const SvgIcon = Icons[point.icon];
return (
<div key={nanoid()} className={classNames(classes)}>
<Icon name={point.icon} />
<SvgIcon />
<MS>
{normalizeSubtext(point.text).map((text) => {
return <div key={nanoid()}>{text}</div>;
@@ -133,11 +138,16 @@ function BYO({data}) {
<div className="byo__subtext">
<H3 className="h5">{data.subtext}</H3>
</div>
<div className="byo__icons icons">
<IconGroup className="byo__icons">
{data.icons.map((icon) => {
return <Icon key={nanoid()} name={icon} mainStyle="fill" />;
const SvgIcon = Icons[icon];
return (
<Icon key={nanoid()} mainStyle="fill">
<SvgIcon />
</Icon>
);
})}
</div>
</IconGroup>
<div className="byo__comment">
<H4 className="h5">
{/* Use dangerouslySetInnerHTML to render inline link from YAML data */}
@@ -145,7 +155,7 @@ function BYO({data}) {
</H4>
</div>
<div className="byo__cta">
<Button href={data.url} subStyle="dark">{data.cta}</Button>
<Button as={Link} href={data.url} subStyle="dark">{data.cta}</Button>
</div>
</div>
</section>

View File

@@ -1,104 +1,100 @@
import Link from 'next/link';
import Layout from '../src/components/layout';
import Icons from '../src/components/icons';
import { P, M, MS, MXS, H1, H2, H3, H4, H5, H6, Button, Icon, Hero } from '../src/components/jambonz-ui';
import { P, M, MS, MXS, H1, H2, H3, H4, H5, H6, Icon, Button, IconGroup, ButtonGroup } from 'jambonz-ui';
import { getData } from '../src/lib/data';
import { Icons } from '../src/components/icons';
import Layout, { Hero } from '../src/components/layout';
export default function JambonzUI({ data }) {
const pageData = data['jambonz-ui'];
return (
<Layout siteData={data.site}>
<div className="jambonz-ui">
{/* High-level design information */}
<Hero subStyle="jambonz-ui" altStyle="pink">
<div className="wrap">
<H1>
<div>Jambonz UI</div>
<div>&nbsp;</div>
</H1>
<H2 className="h5">
<div><strong>font</strong></div>
<div>Objectivity (os, large family16 styles)</div>
<div>
<Link href="https://www.behance.net/gallery/60530395/Objectivity-Free-Font-Family">
<a className="i" target="_blank">
<span>design</span>
<Icon name="ExternalLink" />
</a>
</Link>
</div>
<div>
<Link href="https://www.fontsquirrel.com/fonts/objectivity">
<a className="i" target="_blank">
<span>specimen</span>
<Icon name="ExternalLink" />
</a>
</Link>
</div>
<div>&nbsp;</div>
<div><strong>icons</strong></div>
<div>Feather (os, large set286 icons)</div>
<div>
<Link href="https://feathericons.com">
<a className="i" target="_blank">
<span>specimen</span>
<Icon name="ExternalLink" />
</a>
</Link>
</div>
<div>
<Link href="https://github.com/feathericons/react-feather">
<a className="i" target="_blank">
<span>react-feather</span>
<Icon name="ExternalLink" />
</a>
</Link>
</div>
</H2>
</div>
</Hero>
{/* Show black background style */}
{/* High-level design information */}
<Hero subStyle="jambonz-ui" altStyle="pink">
<div className="wrap">
<H1>
<div>Jambonz UI</div>
<div>&nbsp;</div>
</H1>
<H2 className="h5">
<div><strong>font</strong></div>
<div>Objectivity (os, large family16 styles)</div>
<div>
<Link href="https://www.behance.net/gallery/60530395/Objectivity-Free-Font-Family">
<a className="i" target="_blank">
<span>design</span>
<Icons.ExternalLink />
</a>
</Link>
</div>
<div>
<Link href="https://www.fontsquirrel.com/fonts/objectivity">
<a className="i" target="_blank">
<span>specimen</span>
<Icons.ExternalLink />
</a>
</Link>
</div>
<div>&nbsp;</div>
<div><strong>icons</strong></div>
<div>Feather (os, large set286 icons)</div>
<div>
<Link href="https://feathericons.com">
<a className="i" target="_blank">
<span>specimen</span>
<Icons.ExternalLink />
</a>
</Link>
</div>
<div>
<Link href="https://github.com/feathericons/react-feather">
<a className="i" target="_blank">
<span>react-feather</span>
<Icons.ExternalLink />
</a>
</Link>
</div>
</H2>
</div>
</Hero>
<div className="kit-of-parts">
<div className="pad bg--black">
<div className="wrap">
<div className="wrap-text">
<H1>H1: {pageData.text}</H1>
<H1>H1: {data['jambonz-ui'].text}</H1>
</div>
</div>
</div>
<div className="wrap">
<div className="wrap-text pad">
<H2>H2: {pageData.text}</H2>
<H2>H2: {data['jambonz-ui'].text}</H2>
</div>
</div>
{/* Show pink background style */}
<div className="pad bg--pink">
<div className="wrap">
<div className="wrap-text">
<H3>H3: {pageData.text}</H3>
<H3>H3: {data['jambonz-ui'].text}</H3>
</div>
</div>
</div>
<div className="wrap">
<div className="wrap-text pad">
<H4>H4: {pageData.text}</H4>
<H4>H4: {data['jambonz-ui'].text}</H4>
</div>
</div>
{/* Show grey background style */}
<div className="pad bg--grey">
<div className="wrap">
<div className="wrap-text">
<H5>H5: {pageData.text}</H5>
<H5>H5: {data['jambonz-ui'].text}</H5>
</div>
</div>
</div>
<div className="wrap">
<div className="wrap-text pad">
<H6>H6: {pageData.text}</H6>
<H6>H6: {data['jambonz-ui'].text}</H6>
</div>
<div className="wrap-text pad">
<P>P: {pageData.text}</P>
<P>P: {data['jambonz-ui'].text}</P>
</div>
<div className="wrap-text pad">
<P>P: With a <strong>strong</strong> element</P>
@@ -113,80 +109,109 @@ export default function JambonzUI({ data }) {
<P>P: <span className="color--blue">With</span> <span className="color--teal">colored</span> <span className="color--purple">text</span></P>
</div>
<div className="wrap-text pad">
<M>M: {pageData.text}</M>
<M>M: {data['jambonz-ui'].text}</M>
</div>
<div className="wrap-text pad">
<MS>MS: {pageData.text}</MS>
<MS>MS: {data['jambonz-ui'].text}</MS>
</div>
<div className="wrap-text pad">
<MXS>MXS: {pageData.text}</MXS>
<MXS>MXS: {data['jambonz-ui'].text}</MXS>
</div>
</div>
<div className="wrap">
<div className="pad">
<div className="icons icons--set">
<IconGroup set>
{Object.keys(Icons).map((icon) => {
return <Icon key={icon} mainStyle="fill" name={icon} />;
const SvgIcon = Icons[icon];
return (
<Icon key={icon} mainStyle="fill">
<SvgIcon />
</Icon>
);
})}
</div>
</IconGroup>
</div>
<div className="pad">
<div className="icons icons--set">
<Icon mainStyle="fill" subStyle="dark" name="MapPin" />
<Icon mainStyle="fill" subStyle="purple" name="MapPin" />
<Icon mainStyle="fill" subStyle="teal" name="MapPin" />
<Icon mainStyle="fill" subStyle="blue" name="MapPin" />
</div>
<IconGroup set>
<Icon mainStyle="fill" subStyle="dark">
<Icons.MapPin />
</Icon>
<Icon mainStyle="fill" subStyle="purple">
<Icons.MapPin />
</Icon>
<Icon mainStyle="fill" subStyle="teal">
<Icons.MapPin />
</Icon>
<Icon mainStyle="fill" subStyle="blue">
<Icons.MapPin />
</Icon>
</IconGroup>
</div>
<div className="pad">
<div className="icons icons--set">
<Icon mainStyle="pill" subStyle="dark" name="Heart" />
<Icon mainStyle="pill" subStyle="purple" name="Heart" />
<Icon mainStyle="pill" subStyle="teal" name="Heart" />
<Icon mainStyle="pill" subStyle="blue" name="Heart" />
<Icon mainStyle="pill" name="Heart" />
</div>
<IconGroup set>
<Icon mainStyle="pill" subStyle="dark">
<Icons.Heart />
</Icon>
<Icon mainStyle="pill" subStyle="purple">
<Icons.Heart />
</Icon>
<Icon mainStyle="pill" subStyle="teal">
<Icons.Heart />
</Icon>
<Icon mainStyle="pill" subStyle="blue">
<Icons.Heart />
</Icon>
<Icon mainStyle="pill">
<Icons.Heart />
</Icon>
</IconGroup>
</div>
<div className="pad">
<img src="/svg/drachtio.svg" width="313" height="71" alt="drachtio" />
</div>
<div className="pad">
<Button href="/regions/?redirect=login" mainStyle="login">Log In</Button>
<Button mainStyle="login">Log In</Button>
</div>
</div>
<div className="bg--charcoal">
<div className="pad">
<Button href="/regions/?redirect=login" mainStyle="login" subStyle="white">Log In</Button>
<Icon mainStyle="pill" subStyle="white">
<Icons.Heart />
</Icon>
</div>
</div>
<div className="bg--charcoal">
<div className="pad">
<Button mainStyle="login" subStyle="white">Log In</Button>
</div>
</div>
<div className="wrap">
<div className="btns pad">
<Button href="/regions/?redirect=register">Sign up for free</Button>
<Button href="/regions/?redirect=register" subStyle="dark">Get started for free</Button>
</div>
<div className="btns pad">
<Button href="/regions/?redirect=register" subStyle="purple">Do it</Button>
<Button href="/regions/?redirect=register" subStyle="teal">Do it</Button>
<Button href="/regions/?redirect=register" subStyle="blue">Do it</Button>
</div>
<ButtonGroup className="pad">
<Button>Sign up for free</Button>
<Button subStyle="dark">Get started for free</Button>
</ButtonGroup>
<ButtonGroup className="pad">
<Button subStyle="purple">Do it</Button>
<Button subStyle="teal">Do it</Button>
<Button subStyle="blue">Do it</Button>
</ButtonGroup>
</div>
<div className="bg--jambonz">
<div className="pad">
<Button href="mailto:support@jambonz.org?subject=Jambonz Support" subStyle="light" target="_blank">support@jambonz.org</Button>
<Button subStyle="light">support@jambonz.org</Button>
</div>
</div>
<div className="wrap">
<div className="btns pad">
<Button href="https://github.com/jambonz" target="_blank" mainStyle="pill">
<Icon name="GitHub" />
<ButtonGroup className="pad">
<Button mainStyle="pill">
<Icons.GitHub />
<span>github.com/jambonz</span>
</Button>
<Button href="https://github.com/drachtio" target="_blank" mainStyle="pill">
<Icon name="GitHub" />
<Button mainStyle="pill">
<Icons.GitHub />
<span>github.com/drachtio</span>
</Button>
</div>
</ButtonGroup>
<div className="pad">
<Button href="mailto:support@jambonz.org?subject=Additional Services Support" mainStyle="pill" subStyle="jambonz" target="_blank">
<Icon name="Send" />
<Button mainStyle="pill" subStyle="jambonz">
<Icons.Send />
<span>Contact us</span>
</Button>
</div>

View File

@@ -1,6 +1,5 @@
import { useEffect } from 'react';
import Prism from 'prismjs';
import { useEffect } from 'react';
import Layout from '../../src/components/layout';
import Markdown from '../../src/components/markdown';

View File

@@ -1,10 +1,15 @@
import { nanoid } from 'nanoid';
import Link from 'next/link';
import { nanoid } from 'nanoid';
import { Icon, Button, H2, P } from 'jambonz-ui';
import Layout from '../src/components/layout';
import { Hero, Icon, Button, H2, P, normalizeSubtext } from '../src/components/jambonz-ui';
import { getData } from '../src/lib/data';
import { Icons } from '../src/components/icons';
import Layout, { Hero } from '../src/components/layout';
import { normalizeSubtext } from '../src/components/utils';
function Structure({data}) {
const CtaIcon = Icons[data.cta.icon];
return (
<section className="structure">
<div className="wrap structure__text">
@@ -16,8 +21,8 @@ function Structure({data}) {
</div>
<div className="wrap structure__cta">
<P>{data.cta.text}</P>
<Button href={`${data.cta.url}?subject=Additional Services Support`} target="_blank" mainStyle="pill" subStyle="jambonz">
<Icon name={data.cta.icon} />
<Button as={Link} href={`${data.cta.url}?subject=Additional Services Support`} target="_blank" mainStyle="pill" subStyle="jambonz">
<CtaIcon />
<span>{data.cta.cta}</span>
</Button>
</div>
@@ -26,6 +31,7 @@ function Structure({data}) {
}
function Services({data}) {
const SvgIcon = Icons[data.icon];
return (
<section className="bg--pink services pad">
<div className="wrap services__wrap">
@@ -39,7 +45,7 @@ function Services({data}) {
<P>
<a className="i" href={`${data.url}?subject=${service.title} Support`} target="_blank" rel="noreferrer">
<strong>{service.title}</strong>
<Icon name="ExternalLink" />
<Icons.ExternalLink />
</a>
</P>
<P>{service.text}</P>
@@ -48,8 +54,8 @@ function Services({data}) {
})}
</div>
<div className="services__cta">
<Button href={`${data.url}?subject=Additional Services Support`} target="_blank" mainStyle="pill" subStyle="jambonz">
<Icon name={data.icon} />
<Button as={Link} href={`${data.url}?subject=Additional Services Support`} target="_blank" mainStyle="pill" subStyle="jambonz">
<SvgIcon />
<span>{data.cta}</span>
</Button>
</div>

View File

@@ -1,5 +1,4 @@
import Layout from '../src/components/layout';
import { Hero, TextLayout } from '../src/components/jambonz-ui';
import Layout, { Hero, TextLayout } from '../src/components/layout';
import { getData, getParsedMarkdown } from '../src/lib/data';
import path from 'path';

View File

@@ -1,10 +1,12 @@
import Link from 'next/link';
import { useRouter } from 'next/router';
import { nanoid } from 'nanoid';
import Layout from '../src/components/layout';
import { Hero, Icon, P } from '../src/components/jambonz-ui';
import { nanoid } from 'nanoid';
import { Icon, P } from 'jambonz-ui';
import { getData } from '../src/lib/data';
import { Icons } from '../src/components/icons';
import Layout, { Hero } from '../src/components/layout';
function Regions({ data }) {
const router = useRouter();
@@ -14,11 +16,14 @@ function Regions({ data }) {
<section className="regions">
{data.regions.map((region) => {
const href = (redirect === 'login') ? region.url : region.altUrl;
const SvgIcon = Icons[region.icon];
return (
<div key={nanoid()} className="wrap regions__wrap">
<div className="regions__icon">
<Icon name={region.icon} subStyle={region.color} mainStyle="fill" />
<Icon subStyle={region.color} mainStyle="fill">
<SvgIcon />
</Icon>
</div>
<div className="regions__title">
<P className={`med color--${region.color}`}>
@@ -30,7 +35,7 @@ function Regions({ data }) {
<Link href={href}>
<a className="i" title={`jambonz ${region.title}`}>
<span className="regions__text">{region.text}</span>
<Icon name="ExternalLink" />
<Icons.ExternalLink />
</a>
</Link>
</P>

View File

@@ -1,5 +1,4 @@
import Layout from '../src/components/layout';
import { Hero, TextLayout } from '../src/components/jambonz-ui';
import Layout, { Hero, TextLayout } from '../src/components/layout';
import { getData, getParsedMarkdown } from '../src/lib/data';
import path from 'path';

View File

@@ -1,8 +1,11 @@
import { nanoid } from 'nanoid';
import Link from 'next/link';
import { nanoid } from 'nanoid';
import { Icon, Button, H3, H2, P, ButtonGroup } from 'jambonz-ui';
import Layout from '../src/components/layout';
import { Hero, Icon, Button, H3, H2, P } from '../src/components/jambonz-ui';
import { getData } from '../src/lib/data';
import { Icons } from '../src/components/icons';
import Layout, { Hero } from '../src/components/layout';
function Facts({data}) {
return (
@@ -10,9 +13,12 @@ function Facts({data}) {
<div className="wrap facts__wrap">
<div className="facts__items">
{data.map((fact) => {
const FactIcon = Icons[fact.icon];
return (
<div key={nanoid()} className="facts__item">
<Icon name={fact.icon} mainStyle="fill" />
<Icon mainStyle="fill">
<FactIcon />
</Icon>
<div className="facts__text">
<P className="h5"><strong>{fact.title}</strong></P>
<P>{fact.text}</P>
@@ -38,25 +44,26 @@ function OS({data}) {
<div className="os__subtext">
<H3 className="h5">{data.subtext}</H3>
</div>
<div className="btns os__btns">
<ButtonGroup className="os__btns">
{data.buttons.map((button) => {
const BtnIcon = Icons[button.icon];
return (
<Button key={nanoid()} href={button.url} target="_blank" mainStyle="pill">
<Icon name={button.icon} />
<Button as={Link} key={nanoid()} href={button.url} target="_blank" mainStyle="pill">
<BtnIcon />
<span>{button.text}</span>
</Button>
);
})}
</div>
</ButtonGroup>
<div className="os__logo">
<img src={data.logo} width="313" height="71" alt="drachtio" />
<Button href="https://github.com/sponsors/drachtio/" target="_blank" mainStyle="pill" subStyle="jambonz">
<Icon name="Heart" />
<Button as={Link} href="https://github.com/sponsors/drachtio/" target="_blank" mainStyle="pill" subStyle="jambonz">
<Icons.Heart />
<span>Sponsor</span>
</Button>
</div>
<div className="os__cta">
<Button href={data.url} subStyle="dark" >{data.cta}</Button>
<Button as={Link} href={data.url} subStyle="dark" >{data.cta}</Button>
</div>
</div>
</section>

View File

@@ -1,9 +1,10 @@
import { nanoid } from 'nanoid';
import classNames from 'classnames';
import Link from 'next/link';
import { Button, useActiveNavi, rSlash } from './jambonz-ui';
import { nanoid } from 'nanoid';
import { Button, classNames } from 'jambonz-ui';
import { rSlash } from './utils';
import { useActiveNavi } from './hooks';
function FooterItem({ obj }) {
const activeNavi = useActiveNavi();
@@ -42,7 +43,7 @@ export default function Footer({ siteData }) {
</ul>
</div>
<div className="foot__support">
<Button href={`mailto:${siteData.footer.email}?subject=Jambonz Support`} target="_blank" subStyle="light">
<Button as={Link} href={`mailto:${siteData.footer.email}?subject=Jambonz Support`} target="_blank" subStyle="light">
{siteData.footer.email}
</Button>
</div>

36
src/components/hooks.js Normal file
View File

@@ -0,0 +1,36 @@
import { useRouter } from 'next/router';
import { useState, useEffect, useCallback } from 'react';
import { rSlash } from './utils';
export function useActiveNavi() {
const router = useRouter();
const cleanPath = router.asPath.replace(rSlash, '').split('/')[0];
return cleanPath;
}
export function useMobileMedia() {
const [mobile, setMobile] = useState(false);
const handleMedia = useCallback((e) => {
setMobile(e.matches);
}, [setMobile]);
useEffect(() => {
const str = window.getComputedStyle(document.documentElement);
const qry = str.getPropertyValue('--mobile-media');
const mql = window.matchMedia(`(max-width: ${qry})`);
mql.addEventListener('change', handleMedia);
setMobile(mql.matches);
return function cleanup() {
mql.removeEventListener('change', handleMedia);
};
}, [handleMedia, setMobile]);
return mobile;
}

View File

@@ -1,4 +1,3 @@
// Icons dictionary of just what we're using
import {
X,
Lock,

View File

@@ -1,220 +0,0 @@
import classNames from 'classnames';
import { nanoid } from 'nanoid';
import { useState, useEffect, useCallback } from 'react';
import Icons from './icons';
import Link from 'next/link';
import { useRouter } from 'next/router';
export const rSlash = /^\/|\/$/g;
// Normalize how we work with the subtext as an array[]
export function normalizeSubtext(subtext) {
if (!Array.isArray(subtext)) {
subtext = [subtext];
}
return subtext;
}
// Simple method to normalize string as slug
export function normalizeSlug(key) {
return String(key.toLowerCase()).split(' ').join('-');
}
export function useActiveNavi() {
const router = useRouter();
const cleanPath = router.asPath.replace(rSlash, '').split('/')[0];
return cleanPath;
}
// Normalize for our mobile media query
export function useMobileMedia() {
const [mobile, setMobile] = useState(false);
const handleMedia = useCallback((e) => {
setMobile(e.matches);
}, [setMobile]);
useEffect(() => {
const str = window.getComputedStyle(document.documentElement);
const qry = str.getPropertyValue('--mobile-media');
const mql = window.matchMedia(`(max-width: ${qry})`);
mql.addEventListener('change', handleMedia);
setMobile(mql.matches);
return function cleanup() {
mql.removeEventListener('change', handleMedia);
};
}, [handleMedia, setMobile]);
return mobile;
}
export function H1({ children, ...rest }) {
return <h1 {...rest}>{children}</h1>;
}
export function H2({ children, ...rest }) {
return <h2 {...rest}>{children}</h2>;
}
export function H3({ children, ...rest }) {
return <h3 {...rest}>{children}</h3>;
}
export function H4({ children, ...rest }) {
return <h4 {...rest}>{children}</h4>;
}
export function H5({ children, ...rest }) {
return <h5 {...rest}>{children}</h5>;
}
export function H6({ children, ...rest }) {
return <h6 {...rest}>{children}</h6>;
}
export function P({ children, ...rest }) {
return <p {...rest}>{children}</p>;
}
export function M({ children }) {
return <div className="m">{children}</div>;
}
export function MS({ children }) {
return <div className="ms">{children}</div>;
}
export function MXS({ children }) {
return <div className="mxs">{children}</div>;
}
export function Latest({ data }) {
const classes = {
'latest': true,
[`latest--${data.label}`]: true,
'pad': true,
'bg--pink': true,
};
return (
<section className={classNames(classes)}>
<div className="wrap latest__wrap">
<div className="latest__headline">
<H2>{data.headline}</H2>
</div>
<div className="latest__subtext">
<H3 className="h5">
{/* Use dangerouslySetInnerHTML to render inline links from YAML data */}
{normalizeSubtext(data.subtext).map((subtext) => {
return <div key={nanoid()} dangerouslySetInnerHTML={{ __html: subtext }} />;
})}
</H3>
</div>
</div>
</section>
);
}
export function Hero({ data = {}, subStyle, altStyle, children }) {
const classes = {
'hero': true,
'pad': true,
};
if (subStyle) {
classes[`hero--${subStyle}`] = true;
}
if (altStyle) {
classes[`hero--${altStyle}`] = true;
}
return (
<section className={classNames(classes)}>
<div className="wrap hero__wrap">
{data.headline && (
<div className="hero__headline">
<H1>{data.headline}</H1>
</div>
)}
{data.subtext && (
<div className="hero__subtext">
<H2 className="h5">
{normalizeSubtext(data.subtext).map((subtext) => {
return <div key={nanoid()}>{subtext}</div>;
})}
</H2>
</div>
)}
{data.cta && (
<div className="hero__cta">
<Button href={data.url}>{data.cta}</Button>
</div>
)}
{children}
</div>
</section>
);
}
// Extra {props} get passed to the <a> element
export function Button({ children, href, mainStyle = 'fill', subStyle = null, ...props }) {
const classes = {
'btn': true,
[`btn--${mainStyle}`]: true,
};
if (subStyle) {
classes[`btn--${mainStyle}--${subStyle}`] = true;
}
return (
<Link href={href}>
<a {...props} className={classNames(classes)}>{children}</a>
</Link>
);
}
// Extra {props} get passed to the feather Component
// See react-feather for all 286 icons available
// https://github.com/feathericons/react-feather
export function Icon({ name, mainStyle = 'inline', subStyle = null, ...props }) {
const Component = Icons[name];
const classes = {
'icon': true,
[`icon--${mainStyle}`]: true,
};
if (subStyle) {
classes[`icon--${mainStyle}--${subStyle}`] = true;
}
if (!Component) {
return null;
}
// Stylized icon
if (mainStyle !== 'inline') {
return (
<div className={classNames(classes)}>
<Component {...props} />
</div>
);
}
// Inline icon
return <Component {...props} />;
}
export function TextLayout({ data, name }) {
return (
<div className={`text-layout text-layout--${name}`}>
<div className="text-layout__wrap" dangerouslySetInnerHTML={{ __html: data.contentHtml }} />
</div>
);
}

View File

@@ -1,10 +1,14 @@
import Head from 'next/head';
import Link from 'next/link';
import { nanoid } from 'nanoid';
import { classNames, H1, H2, H3, Button } from 'jambonz-ui';
import Navi from './navi';
import Footer from './footer';
import { normalizeSubtext } from './utils';
function Banner({ data }) {
export function Banner({ data }) {
return (
<div className="banner">
<Link href={data.link}>
@@ -14,6 +18,83 @@ function Banner({ data }) {
);
}
export function Latest({ data }) {
const classes = {
'latest': true,
[`latest--${data.label}`]: true,
'pad': true,
'bg--pink': true,
};
return (
<section className={classNames(classes)}>
<div className="wrap latest__wrap">
<div className="latest__headline">
<H2>{data.headline}</H2>
</div>
<div className="latest__subtext">
<H3 className="h5">
{/* Use dangerouslySetInnerHTML to render inline links from YAML data */}
{normalizeSubtext(data.subtext).map((subtext) => {
return <div key={nanoid()} dangerouslySetInnerHTML={{ __html: subtext }} />;
})}
</H3>
</div>
</div>
</section>
);
}
export function Hero({ data = {}, subStyle, altStyle, children }) {
const classes = {
'hero': true,
'pad': true,
};
if (subStyle) {
classes[`hero--${subStyle}`] = true;
}
if (altStyle) {
classes[`hero--${altStyle}`] = true;
}
return (
<section className={classNames(classes)}>
<div className="wrap hero__wrap">
{data.headline && (
<div className="hero__headline">
<H1>{data.headline}</H1>
</div>
)}
{data.subtext && (
<div className="hero__subtext">
<H2 className="h5">
{normalizeSubtext(data.subtext).map((subtext) => {
return <div key={nanoid()}>{subtext}</div>;
})}
</H2>
</div>
)}
{data.cta && (
<div className="hero__cta">
<Button as={Link} href={data.url}>{data.cta}</Button>
</div>
)}
{children}
</div>
</section>
);
}
export function TextLayout({ data, name }) {
return (
<div className={`text-layout text-layout--${name}`}>
<div className="text-layout__wrap" dangerouslySetInnerHTML={{ __html: data.contentHtml }} />
</div>
);
}
export default function Layout({ children, siteData, title = 'jambonz' }) {
return (
<>

View File

@@ -1,12 +1,12 @@
import { useState } from 'react';
import { nanoid } from 'nanoid';
import classNames from 'classnames';
import Link from 'next/link';
import { useRouter } from 'next/router';
import { Icon, TextLayout } from './jambonz-ui';
import { useState } from 'react';
import { nanoid } from 'nanoid';
import { classNames, Icon } from 'jambonz-ui';
import { Icons } from './icons';
import { TextLayout } from './layout';
function MarkdownSidebar({scope, data}) {
const router = useRouter();
@@ -51,7 +51,7 @@ function MarkdownSidebar({scope, data}) {
return (
<li key={nanoid()} className="markdown__item">
<div className="m markdown__label" onClick={() => handleToggle(item.path)}>
{isActiveToggle ? <Icon name="ChevronDown" /> : <Icon name="ChevronRight" />}
{isActiveToggle ? <Icons.ChevronDown /> : <Icons.ChevronRight />}
<strong>{item.title}</strong>
</div>
<ul className={classNames(subClasses)}>

View File

@@ -1,10 +1,12 @@
import { useState } from 'react';
import { nanoid } from 'nanoid';
import classNames from 'classnames';
import Link from 'next/link';
import { Button, Icon, useMobileMedia, useActiveNavi, rSlash } from './jambonz-ui';
import { nanoid } from 'nanoid';
import { useState } from 'react';
import { Button, Icon, classNames } from 'jambonz-ui';
import { Icons } from './icons';
import { rSlash } from './utils';
import { useMobileMedia, useActiveNavi } from './hooks';
function NaviItem({obj}) {
const activeNavi = useActiveNavi();
@@ -37,12 +39,14 @@ function NaviMobile({ active, handler, siteData }) {
<div className={classNames(classes)}>
<div className="navi__mobile__head">
<div className="navi__mobile__login">
<Button href={siteData.navi.login.link} mainStyle="login" subStyle="white" onClick={handler}>
<Button as={Link} href={siteData.navi.login.link} mainStyle="login" subStyle="white" onClick={handler}>
{siteData.navi.login.label}
</Button>
</div>
<div className="navi__mobile__icon" onClick={handler}>
<Icon mainStyle="fill" subStyle="white" name="X" />
<Icon mainStyle="fill" subStyle="white">
<Icons.X />
</Icon>
</div>
</div>
<ul className="navi__mobile__links">
@@ -57,7 +61,7 @@ function NaviMobile({ active, handler, siteData }) {
})}
</ul>
<div className="navi__mobile__support">
<Button href={`mailto:${siteData.footer.email}`} target="_blank" subStyle="light">
<Button as={Link} href={`mailto:${siteData.footer.email}`} target="_blank" subStyle="light">
{siteData.footer.email}
</Button>
</div>
@@ -97,10 +101,12 @@ export default function Navi({ siteData }) {
})}
</ul>
<div className="navi__icon" onClick={handleNavi}>
<Icon mainStyle="fill" name="Menu" />
<Icon mainStyle="fill">
<Icons.Menu />
</Icon>
</div>
<div className="navi__login">
<Button href={siteData.navi.login.link} mainStyle="login">
<Button as={Link} href={siteData.navi.login.link} mainStyle="login">
{siteData.navi.login.label}
</Button>
</div>

15
src/components/utils.js Normal file
View File

@@ -0,0 +1,15 @@
export const rSlash = /^\/|\/$/g;
// Normalize how we work with the subtext as an array[]
export function normalizeSubtext(subtext) {
if (!Array.isArray(subtext)) {
subtext = [subtext];
}
return subtext;
}
// Simple method to normalize string as slug
export function normalizeSlug(key) {
return String(key.toLowerCase()).split(' ').join('-');
}

View File

@@ -1,3 +1,9 @@
/**
* These utils are for Next.js Static Generation (SSG) at build time
* They are used with Next.js `getStaticProps` and `getStaticPaths`
* https://nextjs.org/docs/basic-features/pages#static-generation-recommended
*/
const fs = require('fs');
const path = require('path');
const yamljs = require('yamljs');
@@ -8,6 +14,18 @@ const remarkGfm = require('remark-gfm');
const dataDir = path.join(process.cwd(), 'data');
const markdownDir = path.join(process.cwd(), 'markdown');
function _slugify(str) {
return str.toString().toLowerCase().trim()
// Replace & with "and"
.replace( /&/g, "-and-" )
// Replace spaces, non-word characters and dashes with a single dash (-)
.replace( /[\s\W-]+/g, "-" )
// Replace leading trailing slashes with an empty string - nothing
.replace( /^[-]+|[-]+$/g, "" );
}
/**
* For accessibility issues we can "fix" our limitations with markdown and remark-html
* The ideal solution would be to comb over every markdown file and fix our headings...
@@ -17,11 +35,8 @@ const markdownDir = path.join(process.cwd(), 'markdown');
*/
function _normalizeHTML(html) {
return html
.replace(/<(h[1-6])>/g, (m, p1) => {
return `<div class="${p1}">`;
})
.replace(/<\/(h[1-6])>/g, (m, p1) => {
return '</div>';
.replace(/<(h[1-6])>(.*?)(<\/(h[1-6])>)/g, (m, p1, p2, p3) => {
return `<div class="${p1}" id="${p1}-${_slugify(p2)}">${p2}</div>`;
});
}

View File

@@ -1,34 +0,0 @@
.bg--jambonz {
background-color: $jambonz;
color: $white;
}
.bg--black {
background-color: $black;
color: $white;
}
.bg--charcoal {
background-color: $charcoal;
color: $white;
}
.bg--grey {
background-color: $grey;
}
.bg--pink {
background-color: $pink;
}
.bg--blue {
background-color: $blue;
}
.bg--purple {
background-color: $purple;
}
.bg--teal {
background-color: $teal;
}

View File

@@ -1,187 +0,0 @@
.btn {
font-size: $m-size;
line-height: 1;
padding: 23px 64px 21px;
background-color: $jambonz;
color: $white;
text-decoration: none;
border-radius: 30px;
display: inline-block;
transition: background-color $base-dur $base-ease,
border-color $base-dur $base-ease,
color $base-dur $base-ease;
@include font-bold();
&:hover {
background-color: mix($pink, $jambonz, $mix-amount);
}
@media (max-width: $width-tablet-2) {
font-size: $ms-size;
}
// @note: Consideration on stopping type reduction here
// @media (max-width: $width-mobile) {
// font-size: $mxs-size;
// }
&--login {
font-family: $font-medium;
font-size: $ms-size;
background-color: transparent;
border: 2px solid $jambonz;
color: $jambonz;
padding: 10px 26px;
&:hover {
background-color: $jambonz;
color: $white;
}
&--white {
color: $white;
border-color: $white;
&:hover {
background-color: $white;
color: $charcoal;
}
}
@media (max-width: $width-tablet-2) {
font-size: $mxs-size;
}
}
&--fill {
&--dark {
background-color: $charcoal;
&:hover {
background-color: mix($white, $charcoal, $mix-amount);
}
}
&--purple {
background-color: $purple;
&:hover {
background-color: mix($white, $purple, $mix-amount);
}
}
&--teal {
background-color: $teal;
&:hover {
background-color: mix($white, $teal, $mix-amount);
}
}
&--blue {
background-color: $blue;
&:hover {
background-color: mix($white, $blue, $mix-amount);
}
}
&--light {
background-color: $white;
color: $jambonz;
&:hover {
background-color: mix($grey-light, $white, $mix-amount);
}
}
}
&--pill {
font-family: $font-regular;
background-color: transparent;
border: 2px solid $charcoal;
color: $charcoal;
padding: 18px 32px 17px;
&:hover {
background-color: $charcoal;
color: $white;
}
@media (max-width: $width-mobile) {
padding: 15px 32px 16px;
}
svg, span {
display: inline-block;
vertical-align: middle;
}
svg {
margin-right: 16px;
width: 18px;
height: 18px;
@media (max-width: $width-tablet-2) {
margin-right: 12px;
width: 16px;
height: 16px;
}
@media (max-width: $width-mobile) {
margin-right: 10px;
width: 14px;
height: 14px;
}
}
&--jambonz {
border-color: $jambonz;
color: $jambonz;
&:hover {
background-color: $jambonz;
color: $white;
svg {
stroke: $white;
}
}
svg {
stroke: $jambonz;
}
}
}
}
.btn:not(.btn--pill, .btn--login) {
@media (max-width: $width-tablet-2) {
padding: 18px 46px;
}
}
.btns {
margin: 0 -2.2222222222vw;
display: flex;
align-items: center;
justify-content: center;
@media (max-width: $width-mobile) {
flex-direction: column;
}
.btn {
margin: 0 2.2222222222vw;
&:not(:first-child) {
@media (max-width: $width-mobile) {
margin-top: 16px;
}
}
@media (max-width: $width-mobile) {
margin: 0;
}
}
}

View File

@@ -1,50 +0,0 @@
@font-face {
font-family: $font-regular;
src: url('/fonts/objectivity-regular-webfont.woff2') format('woff2'),
url('/fonts/objectivity-regular-webfont.woff') format('woff');
font-weight: normal;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: $font-regular-italic;
src: url('/fonts/objectivity-regularslanted-webfont.woff2') format('woff2'),
url('/fonts/objectivity-regularslanted-webfont.woff') format('woff');
font-weight: normal;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: $font-medium;
src: url('/fonts/objectivity-medium-webfont.woff2') format('woff2'),
url('/fonts/objectivity-medium-webfont.woff') format('woff');
font-weight: normal;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: $font-medium-italic;
src: url('/fonts/objectivity-mediumslanted-webfont.woff2') format('woff2'),
url('/fonts/objectivity-mediumslanted-webfont.woff') format('woff');
font-weight: normal;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: $font-bold;
src: url('/fonts/objectivity-bold-webfont.woff2') format('woff2'),
url('/fonts/objectivity-bold-webfont.woff') format('woff');
font-weight: normal;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: $font-bold-italic;
src: url('/fonts/objectivity-boldslanted-webfont.woff2') format('woff2'),
url('/fonts/objectivity-boldslanted-webfont.woff') format('woff');
font-weight: normal;
font-style: normal;
font-display: swap;
}

View File

@@ -1,125 +0,0 @@
svg {
transition: stroke $base-dur $base-ease;
}
.icon {
display: inline-block;
background-color: $jambonz;
width: $icon-size-1;
height: $icon-size-1;
border-radius: 100%;
position: relative;
@media (max-width: $width-mobile) {
width: $icon-size-2;
height: $icon-size-2;
}
svg {
stroke: $white;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 22px;
height: 22px;
@media (max-width: $width-mobile) {
width: 18px;
height: 18px;
}
}
&--pill {
background-color: transparent;
border: 2px solid $jambonz;
svg {
stroke: $jambonz;
}
&--dark {
border: 2px solid $charcoal;
svg {
stroke: $charcoal;
}
}
&--blue {
border: 2px solid $blue;
svg {
stroke: $blue;
}
}
&--teal {
border: 2px solid $teal;
svg {
stroke: $teal;
}
}
&--purple {
border: 2px solid $purple;
svg {
stroke: $purple;
}
}
}
&--fill {
&--purple {
background-color: $purple;
}
&--blue {
background-color: $blue;
}
&--teal {
background-color: $teal;
}
&--dark {
background-color: $charcoal;
}
&--white {
background-color: $white;
svg {
stroke: $charcoal;
}
}
}
}
.icons {
margin: 0 -16px;
@media (max-width: $width-mobile) {
margin: 0 -8px;
}
.icon {
margin: 0 16px;
@media (max-width: $width-mobile) {
margin: 0 8px;
}
}
&--set {
.icon {
margin: 16px;
@media (max-width: $width-mobile) {
margin: 8px;
}
}
}
}

View File

@@ -1,36 +1,3 @@
/******************************************************************************
* Main container wrap
*******************************************************************************/
.wrap {
max-width: calc(#{$width-max} + #{$width-padding} * 2);
width: 100%;
margin: 0 auto;
padding-left: $width-padding;
padding-right: $width-padding;
}
.pad {
padding-top: 96px;
padding-bottom: 96px;
@media (max-width: $width-tablet-1) {
padding-top: 64px;
padding-bottom: 64px;
}
img {
display: inline-block;
}
}
.pad-b {
padding-bottom: 96px;
@media (max-width: $width-tablet-1) {
padding-bottom: 64px;
}
}
/******************************************************************************
* Above the fold
*******************************************************************************/

View File

@@ -1,182 +1,3 @@
/******************************************************************************
* Mixins
*******************************************************************************/
@mixin font-bold() {
font-family: $font-bold;
font-weight: normal;
em {
font-family: $font-bold-italic;
}
}
@mixin font-medium() {
font-family: $font-medium;
em {
font-family: $font-medium-italic;
}
}
@mixin h1() {
font-size: $h1-size;
line-height: 1.33;
letter-spacing: -0.06px;
@include font-bold();
@media (max-width: $width-tablet-1) {
font-size: $h2-size;
}
@media (max-width: $width-tablet-2) {
font-size: $h3-size;
}
@media (max-width: $width-mobile) {
font-size: $h4-size;
}
}
@mixin h2() {
font-size: $h2-size;
line-height: 1.35;
letter-spacing: -0.05px;
@include font-bold();
@media (max-width: $width-tablet-1) {
font-size: $h3-size;
}
@media (max-width: $width-tablet-2) {
font-size: $h4-size;
}
@media (max-width: $width-mobile) {
font-size: $h5-size;
}
}
@mixin h3() {
font-size: $h3-size;
line-height: 1.33;
letter-spacing: -0.05px;
@include font-bold();
@media (max-width: $width-tablet-1) {
font-size: $h4-size;
}
@media (max-width: $width-tablet-2) {
font-size: $h5-size;
}
@media (max-width: $width-mobile) {
font-size: $h6-size;
}
}
@mixin h4 () {
font-size: $h4-size;
line-height: 1.5;
letter-spacing: -0.04px;
@include font-medium();
@media (max-width: $width-tablet-1) {
font-size: $h5-size;
}
@media (max-width: $width-tablet-2) {
font-size: $h6-size;
}
@media (max-width: $width-mobile) {
font-size: $p-size;
}
}
@mixin h5() {
font-size: $h5-size;
line-height: 1.67;
letter-spacing: -0.03px;
@include font-medium();
span {
color: $jambonz;
}
@media (max-width: $width-tablet-1) {
font-size: $h6-size;
}
@media (max-width: $width-tablet-2) {
font-size: $p-size;
}
// @note: Consideration on stopping type reduction here
// @media (max-width: $width-mobile) {
// font-size: $m-size;
// }
}
@mixin h6() {
font-size: $h6-size;
line-height: 1.8;
letter-spacing: -0.03px;
@include font-medium();
@media (max-width: $width-tablet-1) {
font-size: $p-size;
}
@media (max-width: $width-tablet-2) {
font-size: $m-size;
}
// @note: Consideration on stopping type reduction here
// @media (max-width: $width-mobile) {
// font-size: $ms-size;
// }
}
@mixin p() {
font-size: $p-size;
line-height: 1.9;
@media (max-width: $width-tablet-2) {
font-size: $m-size;
}
// @note: Consideration on stopping type reduction here
@media (max-width: $width-mobile) {
font-size: $ms-size;
}
}
@mixin m() {
font-size: $m-size;
line-height: 1.9;
// @note: Consideration on stopping type reduction here?
@media (max-width: $width-tablet-1) {
font-size: $ms-size;
}
}
@mixin ms () {
font-size: $ms-size;
line-height: 2;
// @note: Consideration on stopping type reduction here
// @media (max-width: $width-tablet-1) {
// font-size: $mxs-size;
// }
}
@mixin mxs() {
font-size: $mxs-size;
line-height: 2;
}
@mixin cta() {
margin-top: 96px;

View File

@@ -1,82 +0,0 @@
/******************************************************************************
* CSS Reset
* Add / Remove / Tweak this for your project.
* The philosophy behind the CSS Reset is personal application customization.
*
* This approach is preferred over options like Normalize, which make way
* too many assumptions and apply styles on top of the basic property resets.
*
* Though this CSS Reset is very basic and has not been updated in quite some
* time, since 2011, it serves as a great starting point.
*
* Know what you are resetting and have piloted conrtol of your web app ;-)
*
*
* http://meyerweb.com/eric/tools/css/reset/
* v2.0 | 20110126
* License: none (public domain)
*******************************************************************************/
/**
* Intentionally removed elements
* sup
*/
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font: inherit;
font-size: 100%;
vertical-align: baseline;
}
html {
line-height: 1;
box-sizing: border-box;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
a {
color: inherit;
text-decoration: none;
}
ol, ul {
list-style: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
caption, th, td {
text-align: left;
font-weight: normal;
vertical-align: middle;
}
q, blockquote {
quotes: none;
}
q:before, q:after, blockquote:before, blockquote:after {
content: "";
content: none;
}
a img {
border: none;
}
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section, summary, main {
display: block;
}
img {
max-width: 100%;
height: auto;
}

View File

@@ -96,6 +96,7 @@
code:not([class*="language-"]) {
font-family: $font-mono;
font-size: 13px;
color: $jambonz;
}
}
}

View File

@@ -1,125 +0,0 @@
html,
body {
font-family: $font-regular;
letter-spacing: -0.02px;
color: $charcoal;
}
a {
color: $jambonz;
text-decoration: none;
transition: color $base-dur $base-ease;
}
/*
* Buttons have their own inline svg/span styles
* This className lets us inline a flat icon with text
*/
.i {
svg, span, strong {
display: inline;
vertical-align: middle;
}
svg:last-child {
margin-left: 8px;
}
svg:first-child {
margin-right: 8px;
}
/*
* Using React Feather
* https://github.com/feathericons/react-feather
* Default size is 24x24 for SVG icons
* Sizing can be passed in component JS as in:
* <Icon size={18} name="GitHub" />
* However the inline, in-text SVG icons need to be
* responsive with the text scaling so some CSS
* can achieve the desired result in this case:
* e.g. <span>text</span><Icon name="ExternalLink" />
*
*/
svg {
@media (max-width: $width-tablet-1) {
width: 20px;
height: 20px;
}
@media (max-width: $width-tablet-2) {
width: 18px;
height: 18px;
}
// @note: Consideration on stopping type reduction here
// @media (max-width: $width-mobile) {
// width: 16px;
// height: 16px;
// }
}
}
strong {
@include font-bold();
}
em {
font-family: $font-regular-italic;
}
.h1, h1 {
@include h1();
}
.h2, h2 {
@include h2();
}
.h3, h3 {
@include h3();
}
.h4, h4 {
@include h4();
}
.h5, h5 {
@include h5();
}
.h6, h6 {
@include h6();
}
.p, p {
@include p();
}
.m {
@include m();
}
.ms {
@include ms();
}
.mxs {
@include mxs();
}
.med {
@include font-medium();
}
.color--teal {
color: $teal;
}
.color--blue {
color: $blue;
}
.color--purple {
color: $purple;
}

View File

@@ -1,6 +1,6 @@
/******************************************************************************
* Special mobile layout width
* Utilized in src/components/jambonz-ui: useMobileMedia
* Utilized in src/components/hooks: useMobileMedia
*******************************************************************************/
:root {
--mobile-media: 896px;
@@ -8,69 +8,8 @@
$mobile-width: 896px;
/******************************************************************************
* Colors
*******************************************************************************/
$black: #000;
$white: #fff;
$charcoal: #231f20;
$grey: #f8f8f8;
$grey-light: mix($white, $charcoal, 75%);
$jambonz: #da1c5c;
$pink: #fff3f6;
$purple: #9662b2;
$teal: #30beb0;
$blue: #006dff;
$green: #008a1a;
$red: #e10e22;
$mix-amount: 25%;
/******************************************************************************
* Font family
*******************************************************************************/
$font-regular: 'objectivityregular';
$font-regular-italic: 'objectivityregular_slanted';
$font-medium: 'objectivitymedium';
$font-medium-italic: 'objectivitymedium_slanted';
$font-bold: 'objectivitybold';
$font-bold-italic: 'objectivitybold_slanted';
$font-mono: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
/******************************************************************************
* Font sizes
*******************************************************************************/
$h1-size: 3rem;
$h2-size: 2.5rem;
$h3-size: 2.25rem;
$h4-size: 2rem;
$h5-size: 1.5rem;
$h6-size: 1.25rem;
$p-size: 1.125rem;
$m-size: 1rem;
$ms-size: 0.875rem;
$mxs-size: 0.75rem;
/******************************************************************************
* Icon sizes
*******************************************************************************/
$icon-size-1: $h1-size;
$icon-size-2: $h2-size;
$icon-size-3: $h3-size;
/******************************************************************************
* Sizes
*******************************************************************************/
$navi-index: 999;
$navi-height: 76px;
$width-max: 1440px;
$width-tablet-1: 1024px;
$width-tablet-2: 768px;
$width-mobile: 640px;
$width-small: 480px;
$width-padding: 4.4444444444vw;
/******************************************************************************
* Animation / transitions
*******************************************************************************/
$base-dur: 200ms;
$base-ease: ease;
$navi-height: 76px;

View File

@@ -1,39 +1,14 @@
/******************************************************************************
* Variables / Mixins
* jambonz-ui
*******************************************************************************/
@import 'jambonz-ui/src/styles/index.scss';
/******************************************************************************
* Local Vars / Mixins
*******************************************************************************/
@import 'vars.scss';
@import 'mixins.scss';
/******************************************************************************
* Reset
*******************************************************************************/
@import 'reset.scss';
/******************************************************************************
* Fonts
*******************************************************************************/
@import 'fonts.scss';
/******************************************************************************
* Typography
*******************************************************************************/
@import 'typography.scss';
/******************************************************************************
* Buttons
*******************************************************************************/
@import 'buttons.scss';
/******************************************************************************
* Icons
*******************************************************************************/
@import 'icons.scss';
/******************************************************************************
* Backgrounds
*******************************************************************************/
@import 'backgrounds.scss';
/******************************************************************************
* Layout
*******************************************************************************/
@@ -57,5 +32,5 @@
@import 'pages/home.scss';
@import 'pages/why.scss';
@import 'pages/pricing.scss';
@import 'pages/jambonz-ui.scss';
@import 'pages/regions.scss'
@import 'pages/regions.scss';
@import 'pages/kit-of-parts.scss';

View File

@@ -1,46 +1,44 @@
.jambonz-ui {
.kit-of-parts {
text-align: center;
.wrap-text {
display: flex;
justify-content: center;
h1 {
max-width: 1024px;
}
h2 {
max-width: 950px;
}
h3 {
max-width: 860px;
}
h4 {
max-width: 875px;
}
h5 {
max-width: 768px;
}
h6 {
max-width: 640px;
}
p {
max-width: 640px;
}
.m, .ms {
.m,
.ms {
max-width: 500px;
}
.mxs {
max-width: 380px;
}
> div {
margin: 0 auto;
}

1445
yarn.lock

File diff suppressed because it is too large Load Diff