diff --git a/.fleek.json b/.fleek.json new file mode 100644 index 0000000..f64430f --- /dev/null +++ b/.fleek.json @@ -0,0 +1,10 @@ +{ + "build": { + "image": "node:16.14", + "command": "npm ci && npm run generate", + "publicDir": "dist", + "environment": { + "SERVER_ENV": "production" + } + } +} diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1b5cf17 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,7 @@ +# Enforce unix newlines +* text eol=lf + +*.png binary +*.jpg binary +*.jpeg binary +*.webp binary diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md new file mode 100644 index 0000000..6f2cc73 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -0,0 +1,22 @@ +--- +name: Report a bug +about: File a bug report +title: '' +labels: bug +assignees: '' + +--- + + diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 4b86d71..2f4e2f5 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,8 +1,8 @@ blank_issues_enabled: false contact_links: - - name: Getting Help on IPFS - url: https://ipfs.io/help - about: All information about how and where to get help on IPFS. - - name: IPFS Official Forum - url: https://discuss.ipfs.io - about: Please post general questions, support requests, and discussions here. + - name: Ecosystem directory website + url: https://filecoinecosystem.io + about: Explore the ecosystem directory to see what projects are already listed + - name: Get in touch with the community + url: https://filecoin.io/slack + about: Join Filecoin community Slack and search available channels diff --git a/.github/ISSUE_TEMPLATE/open-an-issue.md b/.github/ISSUE_TEMPLATE/open-an-issue.md deleted file mode 100644 index 21a15a1..0000000 --- a/.github/ISSUE_TEMPLATE/open-an-issue.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Open an issue -about: Only for actionable issues relevant to this repository. -title: '' -labels: need/triage -assignees: '' - ---- - - diff --git a/.github/ISSUE_TEMPLATE/content-or-feature-suggestion.md b/.github/ISSUE_TEMPLATE/suggestion.md similarity index 69% rename from .github/ISSUE_TEMPLATE/content-or-feature-suggestion.md rename to .github/ISSUE_TEMPLATE/suggestion.md index 1f96022..fde9052 100644 --- a/.github/ISSUE_TEMPLATE/content-or-feature-suggestion.md +++ b/.github/ISSUE_TEMPLATE/suggestion.md @@ -2,18 +2,16 @@ name: Content or feature suggestion about: Have a request for new content, or want to request a new feature for this site? Do it here. -title: "[SUGGESTION] (your title goes here)" +title: '' labels: need/triage assignees: '' --- diff --git a/.github/PULL_REQUEST_TEMPLATE/add-or-edit-project.md b/.github/PULL_REQUEST_TEMPLATE/add-or-edit-project.md new file mode 100644 index 0000000..a89cb75 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/add-or-edit-project.md @@ -0,0 +1,31 @@ +## Project content addition or change + + +#### Purpose + +The purpose of this pull request is to +- [ ] Add a new project +- [ ] Modify an existing project + +_please select one_ + + +#### Description + + + +#### Checklist + +- [ ] I'm affiliated with the project that I'm modifying or adding + +- [ ] I've added content in accordance with the project schema + +- [ ] My project has a suitable icon + +- [ ] I've selected the most appropriate subcategory for my project to fit into + +- [ ] All checks on this pull request pass + +- [ ] I have not modified any other project files + +- [ ] I have performed a self-review of my own additions, and everything looks correct diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml new file mode 100644 index 0000000..10c458e --- /dev/null +++ b/.github/workflows/validation.yml @@ -0,0 +1,83 @@ +name: Validation + +on: + pull_request: + push: + branches: + - main + - develop + +jobs: + json_validation: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Check for new or modified JSON project files + id: check_files + run: | + JSON_COUNT=$(git diff --name-only HEAD^..HEAD | grep -c "content/projects/.*\.json" || true) + echo "::set-output name=count::$JSON_COUNT" + + - name: Configure Node 16 + if: steps.check_files.outputs.count != '0' + uses: actions/setup-node@v2 + with: + node-version: 16 + + - name: Cache npm dependencies + if: steps.check_files.outputs.count != '0' + uses: actions/cache@v2 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + + - name: Install npm dependencies + if: steps.check_files.outputs.count != '0' + run: npm ci + + - name: Set script permissions + if: steps.check_files.outputs.count != '0' + run: chmod +x ./scripts/basic-validation.sh + + - name: Validate JSON files + if: steps.check_files.outputs.count != '0' + run: ./scripts/basic-validation.sh + + schema_validation: + needs: json_validation + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Check if JSON files are modified + id: check_files + run: | + JSON_COUNT=$(git diff --name-only HEAD^..HEAD | grep -c "content/projects/.*\.json" || true) + echo "::set-output name=count::$JSON_COUNT" + + - name: Configure Node 16 + if: steps.check_files.outputs.count != '0' + uses: actions/setup-node@v2 + with: + node-version: 16 + + - name: Install NPM dependencies + if: steps.check_files.outputs.count != '0' + run: npm ci + + - name: Set script permissions + if: steps.check_files.outputs.count != '0' + run: chmod +x ./scripts/schema-validation.sh + + - name: Validate JSON schema + if: steps.check_files.outputs.count != '0' + run: ./scripts/schema-validation.sh diff --git a/.nuxtignore b/.nuxtignore new file mode 100644 index 0000000..54480a1 --- /dev/null +++ b/.nuxtignore @@ -0,0 +1,2 @@ +# ignore v1 _project.vue page +# pages/_project.vue diff --git a/README.md b/README.md index 28d203c..7a59f0f 100644 --- a/README.md +++ b/README.md @@ -1,470 +1,165 @@ -# Filecoin Ecodash +# Filecoin Ecosystem Directory +[![Twitter Follow](https://img.shields.io/twitter/follow/filecoin?style=social)](https://twitter.com/Filecoin) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) ![Validation](https://github.com/filecoin-project/ecodash/actions/workflows/validation.yml/badge.svg?branch=develop) -Interactive ecosystem directory and showcase +An interactive ecosystem directory and showcase, visible on [ecosystem.filecoin.io](https://ecosystem.filecoin.io) -**Just want to add a new project to the IPFS ecosystem directory? [Use this form](https://airtable.com/shrurjLTEsPeNW2Db).** +![Data Programs graph image](static/images/open-graph.png) *** -## Project Add/Change Workflow +## Adding or editing a project -The existing workflow for adding a project to the ecosystem directory, or amending an existing project, is as described below. +This is a public repository, and you can add a new project or amend an existing project by submitting a pull request (PR). Your PR should contain a `json` file in `content/projects/` with your changes. This file must conform to a specific schema, otherwise one of the checks will fail. -### Adding a New Project -- Project info is added to the [master Filecoin project database](https://airtable.com/appAAVcWUtgLMS6PK) in one of two ways: - - Directly in the base as a new row - - By requesting a project's representative fill in the [Filecoin Ecodash Submission Form](https://airtable.com/shrurjLTEsPeNW2Db) -- Once a record is added to the database, a Filecoin core team member reviews the record for accuracy, consistency, typos, etc, as well as determining whether the project should be included in the directory (a decision largely based on project maturity) -- If the project is approved to be included in the directory, directions for adding the data to the repo can be found [here](#transforming-project-data) +Let's go through the steps to adding a new project. Editing a project is a simpler version of the same process, where you do not have to create a new file. -### Amending an Existing Project -- Project info should be amended in the [master Filecoin project database](https://airtable.com/appAAVcWUtgLMS6PK) as a single source of truth -- From there, un-tick and re-tick the `Include in directory?` box to regenerate the JSON -- Replace the JSON and/or images in the repo as indicated in the [instructions](#transforming-project-data) +You can follow these steps by editing directly in Github, or by cloning the repo and editing locally. -*** - -## Generating the Showcase Grid - -To view all projects in the ecosystem directory in a "logo parade" showcase format suitable for including in a slide deck, see the instructions below — this includes how to customize the grid to get the representation that's most useful for you. - -TLDR: https://ecosystem.ipfs.io/showcase/?category=focus is a general-purpose, useful grid if you don't want to build a custom one. - -## Behavior - -- The showcase view is visible in its bare form at [ecosystem.filecoin.io/showcase](https://ecosystem.ipfs.io/showcase) -- It provides a logo-based visual summary of the projects in the app by category -- Each tag within the selected category is assigned a block -- The container for the tag is sized based on whether there's a small, medium, or large quantity of projects within it - -## Customization - -### Category - -Customizing the view is done using GET parameters. You might notice that the base showcase link feels a little empty. - -Adding a target top-level `category` param to showcase solves this issue. Examples: -- [/showcase/?category=industry](https://ecosystem.filecoin.io/showcase/?category=industry) -- [/showcase/?category=focus](https://ecosystem.filecoin.io/showcase/?category=focus) -- [/showcase/?category=benefits](https://ecosystem.filecoin.io/showcase/?category=benefits) - -> Note: This category selection will work for _both_ categories that allow one tag per project (category in which tags are mutually exclusive) and categories that allow multiple tags. - -### Containers - -Instances of this app may have varying quantities of projects. To help the showcase address both large and small ecosystems, there are params that define container limits. These define what the limits are in terms of number of projects that fit into medium, or large containers. - -- `md` minimum projects with a tag to display in a medium container (default is 10, if no value is provided) -- `lg` minimum projects with a tag to display in a large container ((default is 25, if no value is provided) - -Example use case: [/showcase/?category=focus&md=5&lg=15](https://ecosystem.ipfs.io/showcase/?category=focus&md=5&lg=15) - -> Note: The Showcase view is designed to support rows of 5 logos, so setting `lg` and `md` as multiples of 5 is recommended for the ideal visual appearance. - -### Location - -- The showcase path may be redefined in the app's `settings.json` under the key `showcaseBaseRoute` - - Currently implemented as: `"showcaseBaseRoute": "/showcase"` -- The showcase has no links, and is not discoverable by search engines - -*** - -## General Developer Information - -### Deployment - -This repo is currently deployed to Fleek on the following URLs: - -`main` branch: https://ecosystem.filecoin.io/ -`develop` branch: https://filecoin-ecosystem-develop.on.fleek.co/ - -Pushes made to the `main` or `develop` branches of this repo will automatically be reflected in the URLs above. Please allow 2-5 minutes for the application to re-build before seeing changes in your browser. - - -### Server - -**Ports** - -These apply to local development. - -``` -development: 20000 -stable: 20001 -production: 20002 -``` - -**Mode**: `static` - -**Environment Variables** - -``` -NODE_ENV → development|production -SERVER_ENV → development|stable|production -``` - -*** - -## Getting Started - -### A. Get Repo - -In a terminal, run the commands below to get set up - -```bash -# Navigate to directory within which to clone the git repo. A new directory is created within this one called ecosystem-directory -$ cd ~/Desktop - -# Clone the repo -$ git clone git@github.com:filecoin-project/ecosystem-directory.git - -# Enter the repo directory -$ cd ecosystem-directory - -# Add your user information -$ git config user.name "Your Name" -$ git config user.email "your.email@ipfs.io" - -# Install npm dependencies -$ npm ci -``` - -### B. Generating a self-signed SSL certificate - -Used for development in a local environment (such as on your personal computer). You only need to do this once. If you've already done this for a different project, just copy your existing `localhost_cert.pem` and `localhost_key.pem` files from `~/.ssh` into the root directory of this repo and skip the rest of this step. - -1. [Install mkcert and generate certificate](https://github.com/FiloSottile/mkcert) by running the commands below, in that order: - - ```bash - $ cd ~/.ssh - $ brew install mkcert - $ mkcert -install - $ mkcert -key-file localhost_key.pem -cert-file localhost_cert.pem localhost 127.0.0.1 - $ cat localhost_cert.pem > localhost_fullchain.pem - $ cat "$(mkcert -CAROOT)/rootCA.pem" >> localhost_fullchain.pem - ``` - -2. Copy the new `localhost_cert.pem` and `localhost_key.pem` files to the root directory of this repo -3. Start the server and navigate to `https://localhost:` - -### C. Environment variables - -Create a file called `.env` and put it into the root directory of this repo. Add the following environment variables: - -``` -NODE_ENV=development -SERVER_ENV=development -``` - -### D. Start the app - -```bash -$ npm run dev -``` - -*** - -## Project Model - -Below is an outline of the project model. An empty JSON file can be found in `@/content/projects/template.json`. This template file can be duplicated, filled out and renamed to create a new project. It is not necessary to generate a project ID since the filename of each project will serve as a project `slug`. - -### Naming Convention - -This means that file names must be named after project names, and use lowercase and kebab-case. For example, an appropriate project `slug` would be `world-wide-web`, and therefore the corresponding file would be `world-wide-web.json`. It's important to not deviate between the file name and the `name` of the project. - -### Keys - -Keys should be retained when not in use. This ensures that if anyone wants to add to the project, they immediately see all keys available in other projects, rather than searching for the model or accidentally using a data structure that doesn't match the model perfectly. This means empty and type checking is done by the app in a strict fashion. - -- `display`: toggle whether or not to display or hide the project from the results - -- `featured`: toggle whether this appears in the featured slider - -- `sortNumbers`: these labels and numbers will be used in the sort-by filter - -- `logo`: all logos will be in SVG format and must be placed in the `static` directory - -- `name`: name of the product +1. Create a new `json` file in `content/projects/my-project.json`, where `my-project` is the lowercase alphanumeric kebab-case name of your project (for example, a project called "Hello World Labs" would become `hello-world-labs.json`) -- `org`: a product can belong to multiple organizations +2. Copy the contents of the template, found in [`content/project-template.json`](content/project-template.json) (do not change this file, only copy), and add it to your file -- `description`: 2 descriptions are needed. A long description that will be visible on the Project Single page and a short description that is visible in the card format (such as the Featured slider). If none provided, a truncated version of the long description will be used. +3. Replace the content in the file with your project's data (see next section for detailed constraints and limitations) -- `primaryLink`: this is the 1st link found directly under the project description +4. Upload a sqare icon to `static/images/projects` and reference that file name in the `icon` key of your json (only the file name is needed, not the full path) -- `links`: these links will always appear at the top of the **Key Info** section, however, these links could be extended to use elsewhere in the future +5. Create commit your changes and create a pull request against the `main` branch using the pull request template -- `keyInfo`: these key/value pairs will always appear below the links in the **Key Info** section +6. If all checks pass, your PR will be reviewed by a community administrator -- `video`: can be a URL to either a YouTube or Vimeo video, the video must be publicly accessible and embeddable -- `stats`: general statistics with short descriptions, also known as "big numbers" +## Project schema -- `ctaCard`: this card will always be displayed as the last block in the stats section. The button text can be changed in `@/content/pages/project.json` +Each modified `json` file in `content/projects` runs through several CI checks: -- `taxonomies`: the taxonomies contain a `slug` that will match a master taxonomy object (found in: `@/content/pages/general.json`); if none match, this taxonomy and its tags will not be displayed +1. The first checks to ensure that the `json` is syntactically valid +2. The second performs more advanced checks: + - `json` keys and values must match certain criteria (e.g., they exist, meet minimums, maximums, etc.) + - Categories and subcategories must follow the defined taxonomy (defined in `taxonomy.json`) + - Images are sized correctly (< 500px for raster images and 1:1 aspect ratio) -### Schema +In order to pass these checks, you should be aware of the schema, and its contraints. Let's take a look at a sample data structure, pre-filled with some content. -The schema can be found in `@/content/data/project-schema.js` and _must_ be updated if the schema ever changes. The `$setProjectDefaults()` global method (found in `@/plugins/global-methods.js`) uses `project-schema.js` in order to perform type checking. - -```ts +```json { - display: Boolean, - featured: Boolean, - sortNumbers: { - label: Number - }, - logo: { - icon: String, - full: String - }, - name: String, - org: [String], - description: { - short: String, - long: String - }, - primaryCta: { - url: String, - text: String - }, - links: [{ - label: String, - links: [{ - url: String, - text: String - }] - }], - keyInfo: [{ - label: String, - value: String - }], - video: String, - stats: [{ - label: String, - value: String - }], - ctaCard: { - title: String, - description: String, - buttonText: String, - url: String - }, - taxonomies: [{ - slug: String, - tags: [String] - }] -} -``` - -*** - -## Transforming Project Data - -Each project that is to be included in the ecosystem must have a `json` file in `content/projects`, with the project name in `kebab-case`. For instance, `content/projects/foo-bar.json`. - -#### Transferring a Project - -The primary source of truth for the Ecosystem Directory is the [master IPFS project database](https://airtable.com/tblxBjPTzHXiUVZAA/viwpijXTIFraPRkhE?blocks=hide), which has a field `Include in directory?` that indicates whether a project is ready for inclusion. A script has been added there, which converts that ecosystem entry to `json`, per the project model described. This script runs each time a project is checked for inclusion in the Ecosystem Directory. - -#### Inputting a Project - -Alternatively, any of the existing projects in `content/projects` can be copied, and the new `json` file can be altered to create a new project. - -### Process - -When either transferring or inputting a project from a copied `json`, the following process should be observed: - -- Copy the generated JSON output -- Create a new file in `content/projects/.`. with the project name in `kebab-case` as the file name, (with a `.json` extension) -- Make sure the project's contents look correct, and ideally ensure that `json` formatting is preserved, including an empty line at the end of the file - - Using a code editor's prettify function for `json` can correct this -- Download the images (icon and full logo) from the CRM or from the project organization, and place them in `static/images/projects/.` -- Ensure any of the `stat`s (also known as "big numbers") have the correct values, as the CRM script is not good at recognizing where to split the big number -- Pull request the new projec(s) into the repository and use the build preview to see how it looks—or check locally - -_This process could be further automated with a variety of tooling at a later date._ - -*** - -## Analytics - -The following environment variables are required: - -```bash -NODE_ENV= -COUNTLY_APP_KEY= -COUNTLY_SITE_URL= -``` - -The following `nuxt.config.js` entries are required: - -```js -{ - countly: { - debug: Boolean, - disableInDevelopment: Boolean, - suppressErrorLogs: Boolean + "display": true, + "since": 2023, + "icon": "icon-myproject.png", + "name": "My Project", + "org": "Optional Parent Company Name", + "description": "One to several sentences describing your project", + "website": "//myproject.xyz", + "social": [ + { "github": "//github.com/myproject" }, + { "twitter": "//twitter.com/myproject" } + ], + "taxonomy": [ + { + "category": "finance", + "subcategories": [ "leasing-and-staking", "exchanges-and-swaps", "infrastructure-and-other", "bridges-and-oracles" ] + }, + { + "category": "media-and-entertainment", + "subcategories": [ "arts-and-collectibles", "photo-and-video", "music", "gaming", "communication-and-social", "publishing-and-news" ] + }, + { + "category": "tooling-and-productivity", + "subcategories": [ "wallets-identity-and-authentication", "network-explorers-and-reputation", "developer-tools-and-other", "privacy-and-security", "ai-productivity-and-utilities" ] + }, + { + "category": "storage-and-cloud-services", + "subcategories": [ "data-storage-and-management", "data-retrieval", "compute-services", "data-curation-and-monetization", "enterprise-solutions" ] + }, + { + "category": "education-science-and-public-goods", + "subcategories": [ "governance-daos-and-public-goods", "education-and-science" ] + } + ], + "tags": [ "optionally", "include", "some", "tags", "like", "fvm" ] } -} + ``` -Below is a breakdown of all events captured by Countly. - -### → General - -```js -Countly.track_sessions() -Countly.track_pageview() -Countly.track_links() -``` - -### → Segment Chart - -**Segment clicked** +## Project validation rules -`name: ` +#### Global rules -`slug: ` +There are two rules that apply globally to all the fields: -```js -Countly.trackEvent('Segment Chart | Segment Clicked', { label, slug }) -``` +1. Written content should be in English, therefore all content fields accept only `Latin-1` characters +2. If an optional top-level field is not in use, it should still appear in the data structure, but with an empty value, such as `[]` or `""` -**View All button clicked** -`name: ` +#### Field-specific rules -`slug: ` +Next, let's take a look at what each key means and what values they must contain +> _* denotes a required field_ -```js -Countly.trackEvent('Segment Chart | View All Button Clicked', { label, slug }) -``` +- `"display"` * + - This is a boolean + - Should generally be left as `true` -### → Featured Slider +- `"since"` * + - The year the project became part of the ecosystem (i.e., started using Filecoin) + - This should be a number with no quotes, for example `2019` -**Project card clicked** +- `"icon"` * + - A small square icon, typically containing the logo of the project + - Must match an image file uploaded to this repo in `static/images/projects/` + - Must be one of the following file types: `.png` `.gif` `.jpg` `.jpeg` `.svg` `.webp` + - Must be a square image, i.e., an aspect ratio of `1:1` + - In the case of raster images, must not exceed `500px` in dimension (not applicable to SVGs) -`name: ` +- `"name"` * + - The plain text name of the project + - Should not be excessively verbose -`slug: ` +- `"org"` + - The parent organization or company, if one exists + - This field is optional + - If no org is needed, just leave the string empty like `"org": "",` -`from: Home Page | Detail Page` +- `"description"` * + - A short couple of sentences describing the project -```js -Countly.trackEvent('Featured Slider | Project Card Clicked', { name, slug, from }) -``` +- `"website"` * + - A URL to link to the project's website + - Must begin with a web accessible protocol: `http://`, `https://`, or just `//` -### → Events +- `"social"` + - This is an array of objects where a project's social links can be added + - This field is optional + - To leave it empty, just use an empty array like `social: [],` + - Include social links by populating the array with key-value pair objects + - Each object can be a different social link like `{ "github": "//github.com/myproject" }` -**Filter Panel Toggled** +- `"taxonomy"` * + - Select a subcategory for your project to fit into + - Delete all the other subcategories that do not apply to your project + - The category-subcategory pair determines where your project is grouped in the ecosystem explorer + - Do not create any new subcategories, and do not modify top-level category names + - The taxonomy is checked against a source of truth [`taxonomy.js`](content/data/taxonomy.js) -`button: filters | x-icon | done` +- `"tags"` + - An optional array of tags + - Tags must be short strings + - Using the `fvm` tag adds a badge to your project -`state: open | closed` +If in doubt, check out some project files here in [`content/projects`](content/projects) -```js -Countly.trackEvent('Filter Panel Toggled', { button, state }) -``` -**Sort-By Dropdown Toggled** +## Local development quickstart -`state: open | closed` +To get started developing locally -```js -Countly.trackEvent('Sort-By Dropdown Toggled', { state }) -``` +1. Clone the repo `git clone git@github.com:filecoin-project/ecosystem-directory.git` -**Sort-By Option Selected** +2. Install dependencies `npm ci` -`label: ` +3. Run the app in development mode `npm run dev` -`slug: ` +For more advanced developer documentation, see the [administrator docs](/docs/admin.md) -```js -Countly.trackEvent('Sort-By Option Selected', { label, slug }) -``` - -**Pagination Button Clicked** +## Questions -`page: ` - -```js -Countly.trackEvent('Pagination Button Clicked', { page }) -``` - -**Results-Per-Page Dropdown Toggled** - -`state: open | closed` - -```js -Countly.trackEvent('Results-Per-Page Dropdown Toggled', { state }) -``` - -**Results-Per-Page Option Selected** - -`option: ` - -```js -Countly.trackEvent('Results-Per-Page Option Selected', { option }) -``` - -**Grid-List View Toggled** - -`view: list | grid` - -```js -Countly.trackEvent('Grid-List View Toggled', { view }) -``` - -**Filter Chiclet Clicked** - -`tag: all | ` - -`category: ` - -`state: on | off` - -```js -Countly.trackEvent('Filter Chiclet Clicked', { tag, category, state }) -``` - -**Clear Filters Button Clicked** -`count: ` - -```js -Countly.trackEvent('Clear Filters Button Clicked', { count }) -``` - -**Filter Panel Search Input** - -There exists a 500ms debounce function in the search input so as to provide a greater chance of capturing a full rather than partial search query. - -`query: ` - -```js -Countly.trackEvent('Filter Panel Search Input', { query }) -``` - -### → Header/Footer - -Links get automatically tracked by `Countly.track_links()` - -### → 404 - -```js -Countly.trackEvent('404_NOT_FOUND', { - path: this.$route.path, - referrer: document.referrer -}) -``` - -### → Query params - -Track URL entire query param object when interacting with project filtering system. Since every param change is already tracked individually as per the list above, this tracker exists as an added layer for testing. - -`query: Object` - -```js -Countly.trackEvent('Query Param Debug', { query }) -``` +If you have any additional questions, [open an issue](https://github.com/filecoin-project/ecodash/issues/new/choose)! diff --git a/assets/scss/components.scss b/assets/scss/components.scss index 6a63f0d..73548b0 100644 --- a/assets/scss/components.scss +++ b/assets/scss/components.scss @@ -1,253 +1,304 @@ -// ///////////////////////////////////////////////////////////////////// General +// //////////////////////////////////////////////////////////////////////// Hero // ----------------------------------------------------------------------------- -.breadcrumbs { - font-family: 'Suisse Intl Book'; - font-size: $fontSize_Small; - font-weight: $fontWeight_Regular; - letter-spacing: $letter_SpacingRegular; - line-height: $leading_Small; - .breadcrumb-link { - .divider { - font-weight: inherit; - } +.filters-heading { + .display-total { + color: $font_Color_Primary; } } -// ////////////////////////////////////////////////////////////////////// Header +// ///////////////////////////////////////////////////////////////////// Toolbar // ----------------------------------------------------------------------------- -#site-header { - background-color: transparent; +// ------------------------------------------------ [Toggle Button] Filter Panel +#filter-panel-toggle-button { + &.active { + color: white; + background-color: $fill_Dark_Primary; + .svg-icon { + path { + stroke: white; + } + } + } } -#header-hero { - margin-bottom: 1.25rem; - .breadcrumbs { - margin-top: 0; - .breadcrumb-link { - font-weight: $fontWeight_SemiBold; - } +// ------------------------------------------------------------ Sort-By Selector +#sort-by-selector { + .dropdown-root { + background-color: white; } - .index-subheading { - font-family: $font_Primary; - font-size: $fontSize_Medium; - font-weight: $fontWeight_Regular; - letter-spacing: $letter_SpacingRegular; - line-height: $leading_Medium; - width: 75%; - @include medium { - width: 100%; - } + .shadow { + background-color: white; } - &.index-view, - &.filters-view, - &.filters-applied, - &.hero-header { - background-color: unset !important; - h1 { - font-family: $font_Primary; - font-size: $fontSize_ExtraExtraLarge; - font-weight: $fontWeight_SemiBold; - letter-spacing: $letter_SpacingRegular; - line-height: $leading_Small; + .highlighted { + color: white; + background-color: $highlight_Light; + } +} + +// --------------------------------------------- [Toggle Button] List Block View +#list-block-toggle-button { + &:before { + background-color: $fill_Dark_Primary; + } +} + +// //////////////////////////////////////////////////////////////// Filter Panel +// ----------------------------------------------------------------------------- +// --------------------------------------------------------------------- General + +#filter-panel { + .filter-category { + &.heading { + font-family: $font_Secondary; } - .display-total { - font-family: inherit; - font-size: inherit; - font-weight: inherit; - letter-spacing: inherit; - line-height: inherit; + &.sub-heading { + font-family: $font_Primary; } } - &.index-view { - h1 { - margin-top: 4.25rem; - margin-bottom: 1.5rem; +} + +// -------------------------------------------------------------------- Controls +#filter-panel-controls { + font-family: $font_Secondary; + .clear-selected-button, + .done-button { + &:hover { + color: white; + background-color: $highlight_Dark; } } - &.filters-view, - &.filters-applied { - h1 { - margin-top: 3.5rem; - margin-bottom: 1.25rem; - } + .clear-selected-button { + background-color: $fill_Light; + color: $fill_Dark_Primary; + } + .done-button { + color: white; + background-color: $fill_Dark_Primary; } } -// ////////////////////////////////////////////////////////////////////// Footer +// //////////////////////////////////////////////////////////////// Project List // ----------------------------------------------------------------------------- -#site-footer { - background-color: transparent; - .panel-top { - .heading, - .links-heading { - font-family: $font_Primary; - font-size: $fontSize_Large; - font-weight: $fontWeight_SemiBold; - letter-spacing: $letter_SpacingRegular; - line-height: $leading_Large; - } - .links-heading { - margin-bottom: 0.25rem; - } - .subheading, - .navigation-link { - font-family: $font_Primary; - font-size: $fontSize_Medium; - font-weight: $fontWeight_Regular; - letter-spacing: $letter_SpacingRegular; - line-height: $leading_Regular; - } - .navigation-link { - padding: 0.125rem 0; - color: #B5B5B6; +// --------------------------------------------------------------------- General +#project-explorer-container { + .placeholder-results-empty { + background-color: white; + .clear-all-null-results { + background: $site_backgroundColor; &:hover { - opacity: 1 !important; - color: $dodgerBlue; + background-color: $highlight_Dark; } } } - .content-wrapper { - margin: 0 2rem; - @include medium { - margin: 0; - margin-left: 2rem; - } - @include small { - margin: 0; - margin-bottom: 2rem; +} + +#results-per-page-selector { + background-color: white; + .dropdown-list { + background-color: white; + &:after { + background-color: white; } } + .highlighted { + color: white; + background-color: $highlight_Light; + } } -// ///////////////////////////////////////////////////////////////// Footer Form +// //////////////////////////////////////////////////////////////////// Chiclets // ----------------------------------------------------------------------------- -.mailchimp-form { - #mailchimp-form { - .panel-top { - .email, - .submit { - box-shadow: none; - position: relative; - - input { - @include fontSize_Small; - font-family: $font_Secondary; - font-weight: $fontWeight_Regular; - background: none; - box-shadow: none; - height: 30px; - padding: 0 20px; - } +.chiclet-list { + display: flex; + flex-flow: row wrap; + row-gap: 0.75rem; + column-gap: 0.625rem; +} - &:before, - &:after { - content: ''; - position: absolute; - display: block; - width: 100%; - height: 100%; - } +.chiclet { + @include fontSize_Mini; + padding: 0.3125rem 0.75rem; + font-weight: 500; + background-color: $fill_Light; + cursor: pointer; + transition: 250ms ease-out; + &.active-button { + background-color: $fill_Dark_Primary; + color: white; + } + &:hover { + transition: 250ms ease-in; + background-color: $highlight_Dark; + color: white; + } +} - &:before { - @include whiteBorderBack; - background: $cadmiumBlue; - top: -7px; - left: -6px; - z-index: -1; - } +// ///////////////////////////////////////////////////////////////////// Tooltip +// ----------------------------------------------------------------------------- +// Companion mixin: tooltipMobilePosition | found in @/assets/core/utilities.scss +[data-tooltip] { + position: relative; + &:hover { + &:before, + &:after { + transition: 250ms ease-in; + transform: translate(-50%, 0); + opacity: 1; + } + } + &:before, + &:after { + position: absolute; + left: 50%; + transform: translate(-50%, 0.5rem); + pointer-events: none; + opacity: 0; + transition: 250ms ease-out; + } + &:before { + content: ''; + top: calc(100% + 2px); + border-left: 0.5rem solid transparent; + border-right: 0.5rem solid transparent; + border-bottom: 0.375rem solid $fill_Dark_Primary; + } + &:after { + @include fontSize_Mini; + content: attr(data-tooltip); + top: calc(100% + 0.5rem); + background-color: $fill_Dark_Primary; + white-space: nowrap; + padding: 0.5rem 0.75rem; + border-radius: 0.125rem; + } + &[data-tooltip-theme="light"] { + &:before { + border-bottom-color: $fill_Light; + } + &:after { + color: $fill_Dark_Primary; + background-color: $fill_Light; + } + } + &[data-tooltip-theme="dark"] { + &:before { + border-bottom-color: $fill_Dark_Primary; + } + &:after { + color: $fill_Light; + background-color: $fill_Dark_Primary; + } + } +} - &:after { - @include whiteBorderBack; - top: -13px; - left: -11px; - z-index: -2; +// ///////////////////////////////////////////////////////////////// Detail Page +// ----------------------------------------------------------------------------- +// --------------------------------------------------------------------- General +.page-project { + .breadcrumb-link { + color: $highlight_Medium; + } + .company { + font-family: $font_Primary; + } + .ctas { + a { + &.primary-cta { + color: white; + background-color: $fill_Dark_Primary; + &:hover { + background-color: $highlight_Dark; } - } - - .email { - @include whiteBorderBack; - background: $midnight; - - input { - color: $white; - transition: background-color 0.3s ease; - &::placeholder { - color: $white; - opacity: 1; - } - &:hover, &:focus { - background-color: $azure; - } - } + } + } + .card { + &.big-number { + color: $fill_Dark_Primary; + background-color: $fill_Light; + } + &.case-study { + border-color: $fill_Light; + .title, + .description { + color: $fill_Dark_Primary; } - - .submit { - height: 30px; - transition: 250ms ease-out; - &:before, - &:after { - transition: 250ms ease-out; - width: calc(100% - 2px); - } + .cta { + color: $fill_Dark_Primary; + border-color: $fill_Dark_Primary; &:hover { - &:before { - top: -13px; - left: -11px; - } - input { - top: -13px; - left: -11px; - } + background-color: $highlight_Dark; + border-color: $highlight_Dark; } + } + } + } + .statistic, + .title { + font-family: $font_Secondary; + } + .featured-box { + border-color: $border_Color_Medium; + } + // .project-card { + // .thumbnail { + // border-color: $border_Color_Light; + // } + // } +} - input { - @include oceanBlueGradient; - @include whiteBorderBack; - height: 32px; - position: relative; - color: $blackSapphire; - margin-left: 0; - top: 0px; - left: 0px; - transition: 250ms ease-out; - } +// ---------------------------------------------------- Featured Projects Slider +#featured-projects-slider { + input { + &[type=range] { + &::-webkit-slider-runnable-track { + background: $border_Color_Dark; + } + &::-moz-range-track { + background: $border_Color_Dark; + } + &::-ms-fill-lower { + background: $border_Color_Dark; + } + &::-ms-fill-upper { + background: $border_Color_Dark; } } } } -// ////////////////////////////////////////////////////////////// Segment Slider +// ////////////////////////////////////////////////////////////// 404/Error Page // ----------------------------------------------------------------------------- - -#segment-slider-main { - .main-container { - flex-wrap: nowrap; +.error-page { + .breadcrumb-link { + color: $highlight_Medium; } - @include xlarge { - background-color: transparent; - .main-container { - flex-wrap: wrap-reverse; - } - .segments-container { - background-color: inherit; - } + .block-segment { + background-color: $highlight_Medium; } - @include small{ - background-color: $white; - .main-container { - @include oceanBorderGradient; - } + .block-404 { + background-color: $fill_Dark_Primary; } } -#segment-slider-chart { - background-color: transparent; - @include small{ - background-color: $white; +// /////////////////////////////////////////////////////////////// Showcase Page +// ----------------------------------------------------------------------------- +#taxonomy-grid { + .taxonomy { + border-color: rgba($fill_Light, 0.5); + } + .taxonomy-label { + font-family: $font_Primary; + background-color: white; } } +// ////////////////////////////////////////////////////////////////////// Header +// ----------------------------------------------------------------------------- +#site-header { + background-color: transparent; +} + // ///////////////////////////////////////////////////////////// Featured Slider // ----------------------------------------------------------------------------- #section-featured-slider { @@ -520,46 +571,6 @@ } } } - #filter-bar { - height: 1.875rem; - .icon-container { - width: fit-content; - height: fit-content; - left: 10.5px; - top: 50%; - transform: translateY(-50%); - svg { - height: 1rem; - width: 1rem; - line, - circle { - stroke: #BFBFBF; - } - } - } - input { - padding: 8.5px 10.5px; - padding-left: calc(1rem + 21px); - font-family: $font_Primary; - font-weight: $fontWeight_Regular; - letter-spacing: $letter_SpacingRegular; - color: $tundora; - &::placeholder { - font-family: $font_Primary; - font-weight: $fontWeight_Medium; - font-size: $fontSize_Small; - color: $tundora; - opacity: 1; - z-index: 100; - } - &:hover { - background-color: $white; - } - &:focus { - background-color: $white; - } - } - } } .filter-category { @@ -672,54 +683,6 @@ } } -// /////////////////////////////////////////////////////////////// Project Cards -// ----------------------------------------------------------------------------- -.project-card { - &:not(.list-view) { - .content { - margin-bottom: 1rem !important; - } - } - .card-inner-wrapper { - @include oceanBorderGradient; - border-radius: 0 !important; - height: 100%; - } - .thumbnail { - border-radius: 0 !important; - img { - max-width: unset !important; - height: 75px; - } - } - .title { - @include leading_Regular; - font-family: $font_Primary; - font-weight: $fontWeight_Medium; - letter-spacing: $letter_SpacingRegular; - font-size: $fontSize_Regular !important; - margin-bottom: 0.5rem !important; - } - .description { - @include leading_Small; - font-family: $font_Secondary; - font-weight: $fontWeight_Regular; - } - &.list-view { - .title, - .description { - color: $blackSapphire; - } - } - &.block-view { - .title, - .description { - padding: 0 1rem; - color: $white; - } - } -} - // ////////////////////////////////////////////////////////////////// Pagination // ----------------------------------------------------------------------------- #paginated-list-navigation-controls { @@ -799,141 +762,6 @@ } } -// //////////////////////////////////////////////////////////////// Page Project -// ----------------------------------------------------------------------------- -.page-project { - position: relative; - background-color: $projectDetailsGrey !important; - font-family: $font_Primary; - color: $darkGrey; - - &:before { - content: ''; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: radial-gradient(#ffffff 0%, transparent 50%), url("data:image/svg+xml;utf8,"); - opacity: 0.75; - z-index: 0; - } - - [class~="grid"], - [class*="grid-"], - [class*="grid_"], - section { - position: relative; - z-index: 5; - } - - a { - color: $azure; - } - - // //////////////////////////////////// Project Featured Slider [Page Project] - // --------------------------------------------------------------------------- - .featured-box { - border: none !important; - } - - #section-featured-slider { - margin-top: 0 !important; - margin-bottom: 0; - - h3.heading, - div.description { - padding-left: 0.5rem; - font-family: $font_Primary; - letter-spacing: $letter_SpacingRegular; - } - - .heading { - @include fontSize_ExtraLarge; - font-weight: $fontWeight_SemiBold; - line-height: $leading_Regular; - margin-bottom: 0.5rem; - } - - .description { - @include fontSize_Regular; - font-weight: $fontWeight_Regular; - line-height: $leading_Small; - margin-bottom: 2.2rem !important; - } - - .featured-box { - border: none; - padding-top: 3.2rem; - } - - .project-card { - .thumbnail { - border: 0; - background-color: white; - img { - height: 75px; - } - } - .title, - .description { - color: $darkGrey; - } - } - - } - - #slider-line { - width: calc(50% - 1rem) !important; - .dummy-thumb { - position: relative; - top: 1.75rem; - width: 74px; - height: 14px; - z-index: 2; - @include oceanBorderGradient; - border-width: 1px; - background-color: transparent; - transform: unset; - border-radius: 0; - &:before { - content: ''; - position: absolute; - width: calc(100% + 2px); - height: calc(100% + 2px); - top: 1px; - left: 1px; - // @include whiteBorderBack; - @include oceanBlueGradient; - } - &:after { - content: ''; - position: absolute; - width: calc(100% + 2px); - height: calc(100% + 2px); - top: 2px; - left: 2px; - @include whiteBorderBack; - @include oceanBlueGradient; - } - svg { - display: none; - } - } - &:after { - z-index: 1 !important; - top: 2.25rem !important; - border: 1px solid $greyBlue !important; - } - #feature-range-slider { - position: absolute; - &::-webkit-slider-thumb { width: 74px; } - &::-moz-range-thumb { width: 74px; } - &::-ms-thumb { width: 74px; } - } - } - -} // //////////////////////////////////////////////////////////////// Project Info #section-project-info { margin-bottom: 4.3rem !important; diff --git a/assets/scss/grid/README.md b/assets/scss/grid/README.md new file mode 100644 index 0000000..f393517 --- /dev/null +++ b/assets/scss/grid/README.md @@ -0,0 +1,154 @@ +# Gridlex +## Just a Flexbox Grid System + +[![Join the chat at https://gitter.im/devlint/gridlex](https://badges.gitter.im/devlint/gridlex.svg)](https://gitter.im/devlint/gridlex?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +v. 2.7.1 + + +Based on Flexbox (CSS Flexible Box Layout Module), Gridlex is a very simple css grid system to quickly create modern layouts and submodules. + +The concept is simple: you need to wrap your `.col` in a `.grid`. + +### What can we expect? +- Basically each column is the same width as every other cell in the grid. +- But you can add sizing classes to individual columns. +- For responsive designs, you can add classes based on media-queries. +- Top, bottom, or middle. For the grid. And for the columns. +- Grids can be nested. Always. Directly in a column. + +### Sass, CSS? + +**I just wanna use it in my page!** + +To use Gridlex out of the box, call the gridlex.min.css file in your project : + +Via CDN: +```html + +``` +or +```html + +``` +[![](https://data.jsdelivr.com/v1/package/npm/gridlex/badge)](https://www.jsdelivr.com/package/npm/gridlex) + +**I want to include it in my source files!** + +Just include gridlex/src/gridlex.scss +and +update the $gl- vars: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Variable namesDefault value
$gl-colCount:12
$gl-gridName:grid
$gl-colName:col
$gl-attributeName:class
$gl-gutter:1rem
$gl-gutter-vertical:1rem
$gl-mq-width:'max-width'
$gl-mq-list:
(
+         lg: 80em, // max 1280px
+         md: 64em, // max 1024px
+         sm: 48em, // max 768px
+         xs: 36em // up to 576px
+ )
+ +### Install via Npm +npm install gridlex --save + +### Install via Bower +bower install gridlex --save + + +### 3 ways to use Gridlex +**1- The basic. Just add a class `.grid-*` (from -1 to -12)** +```html +
+
...
+
+``` + +**2- The precise. Compose cell by cell (with class like `.col-*`)** +```html +
+
...
+
+``` + +**3- The automatic. Just add number of cells you want in the grid (`.grid > .col`)** +```html +
+
...
+
...
+
+``` + +### Gridlex and media-queries +Because of responsive, you sometimes need to change the size of columns: with this keys as classes you can control your layout by media-queries. + +Columns can be hidden at breakpoints using `_*-0` (e.g. `col-4_md-6_sm-0`) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CSS Media QueryAppliesUsage
@media screen and (max-width: 36rem)Max 576px_xs-*
@media screen and (max-width: 48em)Max 768px_sm-*
@media screen and (max-width: 64em)Max 1024px_md-*
@media screen and (max-width: 80em)Max 1280px_lg-*
+ +See more : http://gridlex.devlint.fr diff --git a/assets/scss/grid/gridlex-2.7.1.scss b/assets/scss/grid/gridlex-2.7.1.scss new file mode 100755 index 0000000..bd44dab --- /dev/null +++ b/assets/scss/grid/gridlex-2.7.1.scss @@ -0,0 +1,8 @@ +/* ========================================================================== + GRIDLEX + Just a Flexbox Grid System - v. 2.7.1 +========================================================================== */ +@import "gridlex-vars"; +@import "gridlex-preprocessing"; +@import "gridlex-mixins"; +@import "gridlex-classes"; \ No newline at end of file diff --git a/assets/scss/grid/gridlex-classes.scss b/assets/scss/grid/gridlex-classes.scss new file mode 100755 index 0000000..03d01f9 --- /dev/null +++ b/assets/scss/grid/gridlex-classes.scss @@ -0,0 +1,182 @@ +@use 'sass:math'; + +//************************ +// CLASSES +//************************ +// GRID +[#{$gl-attributeName}~="#{$gl-gridName}"], +[#{$gl-attributeName}*="#{$gl-gridName}-"], +[#{$gl-attributeName}*="#{$gl-gridName}_"]{ + box-sizing: border-box; + display: flex; + flex-flow: row wrap; + margin: 0 math.div(-$gl-gutter, 2); +} +// COLS +[#{$gl-attributeName}~="#{$gl-colName}"], +[#{$gl-attributeName}*="#{$gl-colName}-"], +[#{$gl-attributeName}*="#{$gl-colName}_"]{ + box-sizing: border-box; + padding: 0 math.div($gl-gutter, 2) $gl-gutter-vertical; + max-width: 100%; +} +// JUST "COL" & "COL_" +[#{$gl-attributeName}~="#{$gl-colName}"], +[#{$gl-attributeName}*="#{$gl-colName}_"]{ + flex: 1 1 0%; +} +// JUST "COL-" +[#{$gl-attributeName}*="#{$gl-colName}-"]{ + flex: none; +} + +// COL & GRID +[#{$gl-attributeName}~="#{$gl-gridName}"][#{$gl-attributeName}~="#{$gl-colName}"], +[#{$gl-attributeName}~="#{$gl-gridName}"][#{$gl-attributeName}*="#{$gl-colName}-"], +[#{$gl-attributeName}~="#{$gl-gridName}"][#{$gl-attributeName}*="#{$gl-colName}_"], +[#{$gl-attributeName}*="#{$gl-gridName}-"][#{$gl-attributeName}~="#{$gl-colName}"], +[#{$gl-attributeName}*="#{$gl-gridName}-"][#{$gl-attributeName}*="#{$gl-colName}-"], +[#{$gl-attributeName}*="#{$gl-gridName}-"][#{$gl-attributeName}*="#{$gl-colName}_"], +[#{$gl-attributeName}*="#{$gl-gridName}_"][#{$gl-attributeName}~="#{$gl-colName}"], +[#{$gl-attributeName}*="#{$gl-gridName}_"][#{$gl-attributeName}*="#{$gl-colName}-"], +[#{$gl-attributeName}*="#{$gl-gridName}_"][#{$gl-attributeName}*="#{$gl-colName}_"]{ + margin: 0; + padding: 0; +} + +/************************ + HELPERS SUFFIXES +*************************/ +// FOR GRID +[#{$gl-attributeName}*="#{$gl-gridName}-"]{ +// No spacing between cols : noGutter + &[#{$gl-attributeName}*="-noGutter"]{ + margin: 0; + > [#{$gl-attributeName}~="#{$gl-colName}"], + > [#{$gl-attributeName}*="#{$gl-colName}-"]{ + padding: 0; + } + } + +// No Wrapping + &[#{$gl-attributeName}*="-noWrap"]{ + flex-wrap: nowrap; + } +// Horizontal alignment on center + &[#{$gl-attributeName}*="-center"]{ + justify-content: center; + } +// Horizontal alignment on right + &[#{$gl-attributeName}*="-right"]{ + justify-content: flex-end; + align-self: flex-end; + margin-left: auto; + } +// Vertical alignment on top + &[#{$gl-attributeName}*="-top"]{ + align-items: flex-start; + } +// Vertical alignment on middle + &[#{$gl-attributeName}*="-middle"]{ + align-items: center; + } +// Vertical alignment on bottom + &[#{$gl-attributeName}*="-bottom"]{ + align-items: flex-end; + } + +// Orders + &[#{$gl-attributeName}*="-reverse"]{ + flex-direction: row-reverse; + } + &[#{$gl-attributeName}*="-column"] { + flex-direction: column; + > [#{$gl-attributeName}*="#{$gl-colName}-"] { + flex-basis: auto; + } + } + &[#{$gl-attributeName}*="-column-reverse"]{ + flex-direction: column-reverse; + } + +// Spaces between and around cols + &[#{$gl-attributeName}*="-spaceBetween"]{ + justify-content: space-between; + } + &[#{$gl-attributeName}*="-spaceAround"]{ + justify-content: space-around; + } + +// Equal heights columns + &[#{$gl-attributeName}*="-equalHeight"] > [#{$gl-attributeName}~="#{$gl-colName}"], + &[#{$gl-attributeName}*="-equalHeight"] > [#{$gl-attributeName}*="#{$gl-colName}-"], + &[#{$gl-attributeName}*="-equalHeight"] > [#{$gl-attributeName}*="#{$gl-colName}_"]{ + align-self: stretch; + > *{ + height: 100%; + } + } +// Removes the padding-bottom + &[#{$gl-attributeName}*="-noBottom"] > [#{$gl-attributeName}~="#{$gl-colName}"], + &[#{$gl-attributeName}*="-noBottom"] > [#{$gl-attributeName}*="#{$gl-colName}-"], + &[#{$gl-attributeName}*="-noBottom"] > [#{$gl-attributeName}*="#{$gl-colName}_"]{ + padding-bottom: 0; + } +} + +// FOR COL +[#{$gl-attributeName}*="#{$gl-colName}-"]{ + &[#{$gl-attributeName}*="-top"]{ + align-self: flex-start; + } + &[#{$gl-attributeName}*="-middle"]{ + align-self: center; + } + &[#{$gl-attributeName}*="-bottom"]{ + align-self: flex-end; + } + &[#{$gl-attributeName}*="-first"]{ + order: -1; + } + &[#{$gl-attributeName}*="-last"]{ + order: 1; + } +} +/************************ + GRID BY NUMBER +*************************/ +@include makeGridByNumber(#{$gl-gridName}); +@each $mq-key, $mq-value in $gl-mq-list { + @include bp(#{$mq-key}) { + //@media #{$mq-value} { + @include makeGridByNumber(_#{$mq-key}); + } +} + +/************************ + COLS SIZES +*************************/ +@include makeCol(#{$gl-colName}); +@include makeOff(off); + + +@each $mq-key, $mq-value in $gl-mq-list { + @include bp(#{$mq-key}) { + @include makeCol(_#{$mq-key}); + @include makeOff(_#{$mq-key}); + @include makeFirstLast(_#{$mq-key}); + } +} + + + +/************************ + HIDING COLS +*************************/ +@each $mq-key, $mq-value in $gl-mq-list { + @include bp(#{$mq-key}) { + [#{$gl-attributeName}*="#{$mq-key}-hidden"] { + display: none; + } + } +} diff --git a/assets/scss/grid/gridlex-mixins.scss b/assets/scss/grid/gridlex-mixins.scss new file mode 100755 index 0000000..0dc1a50 --- /dev/null +++ b/assets/scss/grid/gridlex-mixins.scss @@ -0,0 +1,74 @@ +@use 'sass:math'; + +// Make the breakpoints +@mixin bp($breakpoint) { + $query: map-get($gl-mq-list, $breakpoint); + @if $query != null { + @media ($gl-mq-width: #{nth($query, 1)}) { + @content; + } + } +} + +// Function to generate the grid by number +@mixin makeGridByNumber($grid) +{ + @for $i from 1 through $gl-colCount { + [#{$gl-attributeName}*="#{$grid}-#{$i}"] > [#{$gl-attributeName}~="#{$gl-colName}"], + [#{$gl-attributeName}*="#{$grid}-#{$i}"] > [#{$gl-attributeName}*="#{$gl-colName}-"], + [#{$gl-attributeName}*="#{$grid}-#{$i}"] > [#{$gl-attributeName}*="#{$gl-colName}_"] { + $fraction: math.div(1, $i); + + flex-basis: map-get($gl-colFractions, $fraction); + max-width: map-get($gl-colFractions, $fraction); + } + } +} + +// Function to generate the grid by columns +@mixin makeCol($col) +{ + [#{$gl-attributeName}~="#{$gl-gridName}"], + [#{$gl-attributeName}*="#{$gl-gridName}-"], + [#{$gl-attributeName}*="#{$gl-gridName}_"] { + + @for $i from 1 through $gl-colCount { + > [#{$gl-attributeName}*="#{$col}-#{$i}"]{ flex-basis: map-get($gl-colPortions, $i); max-width: map-get($gl-colPortions, $i); } + } + } +} + +// Function to generate the -first & -last base on mq keys (as _lg-first) +@mixin makeFirstLast($mq) +{ + [#{$gl-attributeName}~="#{$gl-gridName}"], + [#{$gl-attributeName}*="#{$gl-gridName}-"], + [#{$gl-attributeName}*="#{$gl-gridName}_"] { + [#{$gl-attributeName}*="#{$mq}-first"]{ + order: -1; + } + [#{$gl-attributeName}*="#{$mq}-last"]{ + order: 1; + } + } +} + +// Function to generate the offset +@mixin makeOff($off) +{ + [#{$gl-attributeName}~="#{$gl-gridName}"], + [#{$gl-attributeName}*="#{$gl-gridName}-"], + [#{$gl-attributeName}*="#{$gl-gridName}_"] { + @for $i from 0 through $gl-colCount - 1 { + > [data-push-left*="#{$off}-#{$i}"]{ margin-left: map-get($gl-colPortions, $i); } + } + } + + [#{$gl-attributeName}~="#{$gl-gridName}"], + [#{$gl-attributeName}*="#{$gl-gridName}-"], + [#{$gl-attributeName}*="#{$gl-gridName}_"] { + @for $i from 0 through $gl-colCount - 1 { + > [data-push-right*="#{$off}-#{$i}"]{ margin-right: map-get($gl-colPortions, $i); } + } + } +} diff --git a/assets/scss/grid/gridlex-preprocessing.scss b/assets/scss/grid/gridlex-preprocessing.scss new file mode 100755 index 0000000..d2c97b8 --- /dev/null +++ b/assets/scss/grid/gridlex-preprocessing.scss @@ -0,0 +1,21 @@ +@use 'sass:math'; + +// calculate width of one col in % +$gl-colUnit: math.div(100%, $gl-colCount); + +// calculate and store nth portions for grid by columns +$gl-colPortions: ( + 0: 0 +); +@for $i from 1 through $gl-colCount { + $gl-colPortions: map-merge($gl-colPortions, ($i: ($gl-colUnit*$i))); +} + +// calculate and store nth fractions for grid by number +$gl-colFractions: ( + 0: 0 // Avoid division by zero if $i would start at 0 +); +@for $i from 1 through $gl-colCount { + $fraction: math.div(1, $i); + $gl-colFractions: map-merge($gl-colFractions, ($fraction: $fraction * 100%)); +} diff --git a/assets/scss/grid/gridlex-vars.scss b/assets/scss/grid/gridlex-vars.scss new file mode 100755 index 0000000..57addba --- /dev/null +++ b/assets/scss/grid/gridlex-vars.scss @@ -0,0 +1,20 @@ +//************************ +// VARIABLES +//************************ +$gl-colCount: 12 !default; +$gl-gridName: grid !default; +$gl-colName: col !default; +$gl-attributeName: class !default; +$gl-gutter: 1rem !default; // Total left + right +$gl-gutter-vertical: 1rem !default; +$gl-mq-width: 'max-width' !default; + +$gl-mq-list: ( + ulg: 140.625rem, // 2250px + xlg: 90rem, // 1440px + lg: 75rem, // 1200px + md: 64rem, // 1024px + sm: 53.125rem, // 850px + mi: 40rem, // 640px + ti: 25.9375rem // 415px +) !default; diff --git a/assets/scss/main.scss b/assets/scss/main.scss index 2b9539d..7bc42e4 100644 --- a/assets/scss/main.scss +++ b/assets/scss/main.scss @@ -1,3 +1,8 @@ +// /////////////////////////////////////////////////////////////// [Pre] Imports +// ----------------------------------------------------------------------------- +@import 'normalize'; +@import 'grid/gridlex-2.7.1'; + // /////////////////////////////////////////////////////////////////////// Fonts // ----------------------------------------------------------------------------- $fontAssetPath: '~assets/fonts'; @@ -62,14 +67,276 @@ $fontAssetPath: '~assets/fonts'; // ///////////////////////////////////////////////////////////////////// General // ----------------------------------------------------------------------------- html, body { + @include leading_Regular; + padding: 0; + margin: 0; + height: auto; background-color: $blackSapphire; + font-family: $font_Primary; color: $white; + font-size: 16px; + letter-spacing: 0px; letter-spacing: $letter_SpacingRegular; ::-moz-selection { background: $turquoise; color: white; } ::selection { background: $turquoise; color: white; } + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + scroll-behavior: smooth; + &.no-scroll { + overflow-y: hidden; + } + &.no-cursor { + cursor: none; + } +} + +button::-moz-focus-inner, +input[type="reset"]::-moz-focus-inner, +input[type="button"]::-moz-focus-inner, +input[type="submit"]::-moz-focus-inner, +select::-moz-focus-inner, +input[type="file"] > input[type="button"]::-moz-focus-inner { + outline: none !important; +} + +select:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #000; +} + +strong { + font-weight: 500; +} + +a, +ol, +ul, +li, +div, +nav, +pre, +span, +input, +label, +video, +button, +section, +textarea, +figcaption, +select option, +h1, h2, h3, h4, h5, h6, +input[type=tel], +input[type=url], +input[type=text], +input[type=time], +input[type=week], +input[type=date], +input[type=month], +input:not([type]), +input[type=color], +input[type=email], +input[type=number], +input[type=search], +input[type="radio"], +input[type=datetime], +input[type=password], +input[type="submit"], +input[type="checkbox"], +input[type=datetime-local] { + margin: 0; + padding: 0; + border: 0; + border-radius: 0; + outline: none; + box-shadow: none; + font-family: inherit; + font-size: inherit; + background-color: transparent; + box-sizing: border-box; +} + +textarea, +input[type=email], +input[type=month], +input[type=number], +input[type=password], +input[type=search], +input[type=tel], +input[type=text], +input[type=time], +input[type=url], +input[type=week] { + @include placeholder { + opacity: 0.5; + font-family: inherit; + font-size: inherit; + font-weight: inherit; + font-style: inherit; + color: inherit; + } + &:hover, &:active, &:focus { + background-color: transparent; + } +} + +a, +input[type="button"], +button, .button { + outline: none; + &:hover, &:active, &:focus { + outline: none; + background-color: transparent; + } +} + +textarea { + background-color: transparent; + resize: none; + transition: 250ms; + &:active, &:focus, &:hover { + transition: 250ms; + background-color: transparent; + } +} + +ol, ul { + margin: 0; +} + +img { + display: block; + width: 100%; } +a, +button, .button { + font-family: inherit; + color: inherit; + outline: none; + text-decoration: none; + position: relative; + transition: 250ms; + &:active, &:focus, &:hover { + transition: 250ms; + outline: none; + } +} + +.video-wrapper { + position: relative; + padding-bottom: 56.25%; /* 16:9 */ + height: 0; + iframe { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + border: 0; + } +} + +::-webkit-file-upload-button { + cursor: pointer; +} + +.placeholder-section { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + position: relative; + height: 25rem; + margin: 1rem 0; + background-color: $gray300; + color: $gray900; + border-radius: 0.5rem; + font-weight: 600; + &.tiny { + height: 3rem; + } + &.mini { + height: 5rem; + } + &.small { + height: 10rem; + } + &.no-margin { + margin: 0; + } +} + +// /////////////////////////////////////////////////////////////////////// Fonts +// ----------------------------------------------------------------------------- +h1, .h1, +h2, .h2, +h3, .h3, +h4, .h4, +h5, .h5, +h6, .h6, +p, +div, +button { + margin-top: 0; + margin-bottom: 0; + font-weight: normal; +} + +h1, .h1, +h2, .h2, +h3, .h3, +h4, .h4, +h5, .h5, +h6, .h6 { + display: block; + font-family: $font_Secondary; +} + +h1, .h1 { + @include fontSize_ExtraExtraLarge; + @include small { + @include fontSize_ExtraLarge; + } +} + +h2, .h2 { + @include fontSize_ExtraLarge; + @include small { + @include fontSize_Large; + } +} + +h3, .h3 { + @include fontSize_Large; +} + +h4, .h4 { + @include fontSize_Medium; + @include small { + @include fontSize_Regular; + } +} + +h5, .h5 { + @include fontSize_Small; +} + +h6, .h6 { + @include fontSize_Mini; +} + +div, +button, +p, +li { + @include fontSize_Regular; +} + +// ///////////////////////////////////////////////////////////////// Nuxt & Grid +// ----------------------------------------------------------------------------- #__nuxt { + position: relative; + z-index: 2; &:before { content: ''; position: absolute; @@ -84,21 +351,107 @@ html, body { } #__layout { + overflow: hidden; position: relative; z-index: 5; + .master-container { + position: relative; + } +} + +.layout { + position: relative; + z-index: 100; +} + +.page.container { + position: relative; } [class~="grid"], [class*="grid-"], [class*="grid_"] { - padding: 0 4.1665%; + width: $containerWidth; + margin: 0 auto; + @include customMaxMQ ($containerWidth + 4rem) { + padding: 0 4.1665%; + width: 100%; + } + &[class*="-noGutter"] { + margin: 0 auto; + } + &.full { + width: 100%; + padding: 0 0.5rem; + &.maxed { + max-width: 90rem; + } + } + &.no-padding { + padding: 0; + } [class~="grid"], [class*="grid-"], [class*="grid_"] { + width: 100%; padding: 0; } } +// /////////////////////////////////////////////////////////////// Accessibility +// ----------------------------------------------------------------------------- +a, +div, +input, +button, +select, +textarea { + &:focus { + @include focus_BoxShadow_Small; + outline: 0; + } + &.focus-visible:focus:not(:focus-visible) { + box-shadow: none; + outline: 0; + } +} + +a.focus-visible:focus-visible, +a.focus-visible:moz-focusring { + @include focus_BoxShadow_Small; + outline: 0; +} + +button.focus-visible:focus-visible, +button.focus-visible:moz-focusring { + @include focus_BoxShadow_Small; + outline: 0; +} + +div.focus-visible:focus-visible, +div.focus-visible:moz-focusring { + @include focus_BoxShadow_Small; + outline: 0; +} + +input.focus-visible:focus-visible, +input.focus-visible:moz-focusring { + @include focus_BoxShadow_Small; + outline: 0; +} + +select.focus-visible:focus-visible, +select.focus-visible:moz-focusring { + @include focus_BoxShadow_Small; + outline: 0; +} + +textarea.focus-visible:focus-visible, +textarea.focus-visible:moz-focusring { + @include focus_BoxShadow_Small; + outline: 0; +} + // ////////////////////////////////////////////////////////////// [Post] Imports // ----------------------------------------------------------------------------- @import 'components'; diff --git a/assets/scss/normalize.scss b/assets/scss/normalize.scss new file mode 100644 index 0000000..1fe4813 --- /dev/null +++ b/assets/scss/normalize.scss @@ -0,0 +1,254 @@ +////////////////////////////////////////////////////////////////////// Normalize +//------------------------------------------------------------------------------ +// Colors +$yellow: #ff0; +$black: #000; +$silver: #c0c0c0; + +// Fonts +$font_0: sans-serif; +$font_1: monospace; + +// @extend-elements / original selectors / sub, sup +%extend_1 { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +// Original selectors / button, input, optgroup, select, textarea +%extend_2 { + color: inherit; + font: inherit; + margin: 0; +} + +html { + font-family: $font_0; + input[type="button"] { + cursor: pointer; + } + input[disabled] { + cursor: default; + } +} +body { + margin: 0; +} +article { + display: block; +} +aside { + display: block; +} +details { + display: block; +} +figcaption { + display: block; +} +figure { + display: block; + margin: 1em 40px; +} +footer { + display: block; +} +header { + display: block; +} +hgroup { + display: block; +} +main { + display: block; +} +menu { + display: block; +} +nav { + display: block; +} +section { + display: block; +} +summary { + display: block; +} +audio { + display: inline-block; + vertical-align: baseline; + &:not([controls]) { + display: none; + height: 0; + } +} +canvas { + display: inline-block; + vertical-align: baseline; +} +progress { + display: inline-block; + vertical-align: baseline; +} +video { + display: inline-block; + vertical-align: baseline; +} +[hidden] { + display: none; +} +template { + display: none; +} +a { + background-color: transparent; + &:active { + outline: 0; + } + &:hover { + outline: 0; + } +} +abbr[title] { + border-bottom: 1px dotted; +} +b { + font-weight: bold; +} +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +h1 { + font-size: 2em; + margin: 0.67em 0; +} +mark { + background: yellow; + color: $black; +} +small { + font-size: 80%; +} +sub { + @extend %extend_1; + bottom: -0.25em; +} +sup { + @extend %extend_1; + top: -0.5em; +} +img { + border: 0; +} +hr { + // Instead of the line below you could use @include box-sizing($bs) + box-sizing: content-box; + height: 0; +} +pre { + overflow: auto; + font-family: $font_1, $font_1; + font-size: 1em; +} +code { + font-family: $font_1, $font_1; + font-size: 1em; +} +kbd { + font-family: $font_1, $font_1; + font-size: 1em; +} +samp { + font-family: $font_1, $font_1; + font-size: 1em; +} +button { + @extend %extend_2; + overflow: visible; + text-transform: none; + cursor: pointer; +} +input { + @extend %extend_2; + line-height: normal; +} +optgroup { + @extend %extend_2; + font-weight: bold; +} +select { + @extend %extend_2; + text-transform: none; +} +textarea { + @extend %extend_2; + overflow: auto; +} +input[type="reset"] { + cursor: pointer; +} +input[type="submit"] { + cursor: pointer; +} +button[disabled] { + cursor: default; +} +button::-moz-focus-inner { + border: 0; + padding: 0; +} +input::-moz-focus-inner { + border: 0; + padding: 0; +} +input[type="checkbox"] { + // Instead of the line below you could use @include box-sizing($bs) + box-sizing: border-box; + padding: 0; +} +input[type="radio"] { + // Instead of the line below you could use @include box-sizing($bs) + box-sizing: border-box; + padding: 0; +} +input[type="number"]::-webkit-inner-spin-button { + height: auto; +} +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} +input[type="search"] { + // Instead of the line below you could use @include box-sizing($bs) + box-sizing: content-box; +} +input[type="search"]::-webkit-search-cancel-button { +} +input[type="search"]::-webkit-search-decoration { +} +fieldset { + border: 1px solid $silver; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} +legend { + border: 0; + padding: 0; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +td { + padding: 0; +} +th { + padding: 0; +} +svg:not(:root) { + overflow: hidden; +} diff --git a/assets/scss/settings.scss b/assets/scss/settings.scss index ab440e7..ae14402 100644 --- a/assets/scss/settings.scss +++ b/assets/scss/settings.scss @@ -2,7 +2,7 @@ // ----------------------------------------------------------------------------- // -------------------------------------------------------------------- Families $font_Primary: 'SuisseIntl', sans-serif; -$font_Secondary: 'Suisse Intl Mono', sans-serif, monospace; +$font_Secondary: 'SuisseIntl', sans-serif; // --------------------------------------------------------------------- General $containerWidth: 68.75rem; // 1100px @@ -66,6 +66,7 @@ $navigationHeight: 8.25rem; // --------------------------------------------------------------- Border Radius $borderRadius_Small: 0; $borderRadius_Medium: 1px; +$borderRadius_Large: 0.5rem; // //////////////////////////////////////////////////////// Button Layer Spacing $bottomLayerOffsetLeft: -10px; @@ -83,11 +84,16 @@ $font_Color_Primary: $white; $font_Color_Secondary: $tundora; $fill_Dark: $midnight; +$fill_Dark_Primary: black; $fill_Dark_Secondary: $cadmiumBlue; $fill_Light: $white; $fill_Active: $jaguar; $highlight_Light: $dodgerBlue; $highlight_Medium: $dodgerBlue; +$highlight_Dark: $gray800; $border_Color: $white; +$border_Color_Light: $gray200; +$border_Color_Medium: $gray400; +$border_Color_Dark: $gray600; diff --git a/assets/scss/utilities.scss b/assets/scss/utilities.scss index 3ef7d92..eabc792 100644 --- a/assets/scss/utilities.scss +++ b/assets/scss/utilities.scss @@ -1,56 +1,17 @@ // ///////////////////////////////////////////////////////////////////// Imports // ----------------------------------------------------------------------------- +@use 'sass:math'; @import 'variables'; @import 'settings'; - // ////////////////////////////////////////////////////////////////////// Mixins -// --------------------------------------------------------------------- Styling -@mixin shadow1 { - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05), 0 4px 20px rgba(0, 0, 0, 0.05); -} - -@mixin focus_BoxShadow_Small { - box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.5); -} - -@mixin focus_BoxShadow_Regular { - box-shadow: 0 0 0 5px rgba(0, 123, 255, 0.5); -} - -@mixin focus_BoxShadow_Link { - box-shadow: 0 0 0 5px rgba(0, 123, 255, 0.5); - border-radius: 0.125rem; -} - -@mixin selection_Dark { - ::-moz-selection { background: $translucentWhite; color: black; } - ::selection { background: $translucentWhite; color: black; } -} - -@mixin selection_Light { - ::-moz-selection { background: $translucentBlack; color: white; } - ::selection { background: $translucentBlack; color: white; } -} - -@mixin selection_Invisible { - ::-moz-selection { background: transparent; color: transparent; } - ::selection { background: transparent; color: transparent; } -} - -@mixin centerImage { - background-position: center; - background-size: cover; - background-repeat: no-repeat; -} - // --------------------------------------------------------------------- General @mixin optional-at-root($sel) { @at-root #{if(not &, $sel, selector-append(&, $sel))} { @content; } } @mixin placeholder { @include optional-at-root('::-webkit-input-placeholder') { @content; } @include optional-at-root(':-moz-placeholder') { @content; } @include optional-at-root('::-moz-placeholder') { @content; } - @include optional-at-root(':-ms-input-placeholder') { @content; } - @include optional-at-root('::-ms-input-placeholder') { @content; } + @include optional-at-root(':-ms-input-placeholder') { @content; } + @include optional-at-root('::-ms-input-placeholder') { @content; } @include optional-at-root('::placeholder') { @content; } } @@ -62,7 +23,6 @@ @mixin large { @media screen and (max-width: $breakpoint_Large) { @content; } } @mixin xlarge { @media screen and (max-width: $breakpoint_Xlarge) { @content; } } @mixin ultraLarge { @media screen and (max-width: $breakpoint_UltraLarge) { @content; } } -@mixin ultraPlus { @media screen and (min-width: $breakpoint_UltraLarge) { @content; } } @mixin containerMaxMQ { @media screen and (max-width: $containerWidth) { @content; } } @mixin containerMinMQ { @media screen and (max-width: $containerWidthPlusOnePixel) { @content; } } @@ -123,6 +83,57 @@ @mixin leading_ExtraExtraLarge { line-height: $leading_ExtraExtraLarge; } // --------------------------------------------------------------------- Styling + +@mixin gradientText { + background-clip: text; + -moz-background-clip: text; + -webkit-text-fill-color: transparent; + -moz-text-fill-color: transparent; + text-fill-color: transparent; + // IE11 fix + @include IE10and11 { + background: none; + } +} + +@mixin shadow1 { + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05), 0 4px 20px rgba(0, 0, 0, 0.05); +} + +@mixin focus_BoxShadow_Small { + box-shadow: 0 0 0 3px rgba($springGreen, 0.5); +} + +@mixin focus_BoxShadow_Regular { + box-shadow: 0 0 0 5px rgba($springGreen, 0.5); +} + +@mixin focus_BoxShadow_Link { + box-shadow: 0 0 0 5px rgba($springGreen, 0.5); + border-radius: 0.125rem; +} + +@mixin selection_Dark { + ::-moz-selection { background: $translucentWhite; color: black; } + ::selection { background: $translucentWhite; color: black; } +} + +@mixin selection_Light { + ::-moz-selection { background: $translucentBlack; color: white; } + ::selection { background: $translucentBlack; color: white; } +} + +@mixin selection_Invisible { + ::-moz-selection { background: transparent; color: transparent; } + ::selection { background: transparent; color: transparent; } +} + +@mixin centerImage { + background-position: center; + background-size: cover; + background-repeat: no-repeat; +} + @mixin borderRadius_Small { border-radius: $borderRadius_Small; } @mixin borderRadius_Medium { border-radius: $borderRadius_Medium; } @mixin borderRadius_Large { border-radius: $borderRadius_Large; } @@ -132,6 +143,16 @@ font-weight: 700; } +// ------------------------------------------------------------------- Functions +@function toRem($value) { + $remValue: math.div($value, 16) + rem; + @return $remValue; +} + +@function leading($lineHeight, $fontSize) { + @return math.div(math.round(10 * math.div($lineHeight, $fontSize)), 10); +} + // ------------------------------------------------------------------- Animation @mixin animation ($animate...) { $max: length($animate); @@ -190,6 +211,10 @@ background: linear-gradient(75deg, $morningSky, $frostbite); } +@mixin lightOceanGradient { + background: linear-gradient(75deg, #60C1FF, #5DE3F2); +} + // --------------------------------------------------------------------- Borders @mixin oceanBorderGradient { @@ -208,10 +233,8 @@ } // ------------------------------------------------------------ Layered Elements - @mixin tripleLayer { position: relative; - @include whiteBorderFront; border-radius: 0; transform: unset; &:before { diff --git a/assets/scss/variables.scss b/assets/scss/variables.scss index d586785..a52c440 100644 --- a/assets/scss/variables.scss +++ b/assets/scss/variables.scss @@ -15,6 +15,7 @@ $jaguar: #030307; // Black-Blue used for active button states $dodgerBlue: #1890FC; // Blue (used for outbound links) $caribbeanBlue: #36BBD1; // $turquoise used for link $turquoise: #31B4D8; // used for scrollbar +$springGreen: #1DFF5C; // Green highlight $blackSapphire: #07070D; // black used for background $white: #FFFFFF; @@ -26,4 +27,15 @@ $projectDetailsGrey: #F9F9F9; $greyBlue: #C7D9EA; $tooltipBlue: #052437; -$tooltipShadow: #889FAA; \ No newline at end of file +$tooltipShadow: #889FAA; + +$gray50: #FAFAFA; +$gray100: #F5F5F5; +$gray200: #EEEEEE; +$gray300: #E0E0E0; +$gray400: #BDBDBD; +$gray500: #9E9E9E; +$gray600: #757575; +$gray700: #616161; +$gray800: #424242; +$gray900: #212121; diff --git a/components/CardListBlock.vue b/components/CardListBlock.vue new file mode 100644 index 0000000..bae09c1 --- /dev/null +++ b/components/CardListBlock.vue @@ -0,0 +1,210 @@ + + + + + diff --git a/components/CopyrightLogo.vue b/components/CopyrightLogo.vue new file mode 100644 index 0000000..83ef8a6 --- /dev/null +++ b/components/CopyrightLogo.vue @@ -0,0 +1,18 @@ + + + diff --git a/components/DropdownSelector.vue b/components/DropdownSelector.vue index e5709ce..feb673c 100644 --- a/components/DropdownSelector.vue +++ b/components/DropdownSelector.vue @@ -1,11 +1,9 @@