modif comtabilite

This commit is contained in:
2019-01-16 16:23:31 +01:00
parent 6b741a9666
commit 9312edc3ae
1844 changed files with 158848 additions and 55874 deletions
+1
View File
@@ -0,0 +1 @@
node_modules
+15
View File
@@ -1,3 +1,18 @@
# v2.0.0
## 09/30/2018
1. [](#new)
* Completely rewritten to be much more flexible
* New _class_ based problems architecture for unified problem definition and reporting
* New `onProblemsInitialized()` plugin event for 3rd party plugins to add their own problem checks
* New more intuitive theme based on Spectre.css to display problems
* Storage of problem state to allow for displaying in admin plugin
* Now with 3 states `critical`, `warning`, and `notice`. Only critical will stop the site working.
* Added some new PHP module checks
* Added a new `umask` permission check
1. [](#improved)
* Implemented extra image checks [#17](https://github.com/getgrav/grav-plugin-problems/pull/17)
# v1.4.7
## 05/16/2017
+40 -39
View File
@@ -1,6 +1,6 @@
# Grav Problems Plugin
![Problems](assets/readme_1.png)
![Problems](assets/readme_1.jpg)
`Problems` is a [Grav](http://github.com/getgrav/grav) Plugin and allows to detect issues.
@@ -26,7 +26,7 @@ You should now have all the plugin files under
/your/site/grav/user/plugins/problems
>> NOTE: This plugin is a modular component for Grav which requires [Grav](http://github.com/getgrav/grav), the [Error](https://github.com/getgrav/grav-plugin-error) and [Problems](https://github.com/getgrav/grav-plugin-problems) plugins, and a theme to be installed in order to operate.
> NOTE: This plugin is a modular component for Grav which requires [Grav](http://github.com/getgrav/grav), the [Error](https://github.com/getgrav/grav-plugin-error) and [Problems](https://github.com/getgrav/grav-plugin-problems) plugins, and a theme to be installed in order to operate.
# Usage
@@ -34,28 +34,35 @@ You should now have all the plugin files under
`Problems` checks for the following common issues:
| Check | Description |
| :---------------------------------- | :-------------------------------------------------------------------------------------------------------- |
| Apache `mod_rewrite` | Checks to ensure `mod_rewrite` is enabled if you are running an Apache server. |
| PHP Version | Checks to make sure the PHP version being run by the server meets or exceeds Grav's minimum requirements. |
| PHP GD (Image Manipulation Library) | Checks to make sure that PHP GD is installed. |
| PHP Curl (Data Transfer Library) | Checks to make sure that PHP Curl is installed. |
| PHP OpenSSL (Secure Sockets Library) | Checks to make sure that PHP OpenSSL is installed. |
| PHP Mbstring (Multibyte String Library) | Checks to make sure that PHP Mbstring is installed. |
| .htaccess | Checks to make sure that there is an `.htaccess` file in Grav's root directory. |
| `bin/*` executable | Checks that all the files in the `bin/` folder are exectuable. |
| Cache | Checks the `/cache` folder's existence and verifies that it is writeable. |
| Logs | Checks the `/logs` folder's existence and verifies that it is writeable. |
| Images | Checks the `/images` folder's existence and verifies that it is writeable. |
| Assets | Checks the `/assets` folder's existence and verifies that it is writeable. |
| System | Checks the `/system` folder's existence. |
| Data | Checks the `/user/data` folder's existence and verifies that it is writeable. |
| Pages | Checks the `/user/images` folder's existence. |
| Config | Checks the `/user/config` folder's existence. |
| Error | Checks to make sure the **Error** plugin is installed in `/user/plugins/error`. |
| Plugins | Checks the `/user/plugins` folder's existence. |
| Themes | Checks the `/user/themes` folder's existence. |
| Vendor | Checks the `/vendor` folder's existence. |
| Check | Description |
| :-------------- | :-------------------------------------------------------------------------------- |
| Apache | `mod_rewrite` is enabled if you are running an Apache server. |
| PHP Version | PHP version being run by the server meets or exceeds Grav's minimum requirements. |
| PHP Modules | PHP GD library is installed. |
| | PHP Curl library is installed. |
| | PHP Ctype library is installed |
| | PHP Dom is library installed |
| | PHP OpenSSL library is installed |
| | PHP XML library is installed |
| | PHP Zip library is installed |
| | PHP Exif library is installed if Exif support is enabled |
| | PHP OpenSSL library is installed. |
| | PHP Mbstring library is installed. |
| Essential Files | `.htaccess` file in Grav's root directory. |
| | Checks that all the files in the `bin/` folder are exectuable. |
| | `/cache` folder's existence and verifies that it is writeable. |
| | `/logs` folder's existence and verifies that it is writeable. |
| | `/images` folder's existence and verifies that it is writeable. |
| | `/assets` folder's existence and verifies that it is writeable. |
| | `/system` folder's existence. |
| | `/tmp` folder's existence. |
| | `/user/data` folder's existence and verifies that it is writeable. |
| | `/user/images` folder's existence. |
| | `/user/config` folder's existence. |
| | **Error** plugin is installed in `/user/plugins/error`. |
| | `/user/plugins` folder's existence. |
| | `/user/themes` folder's existence. |
| | `/vendor` folder's existence. |
If an issue is discovered, you will be greeted with a page that lists these checks and whether or not your install passed or failed them. Green checks mean it passed, and a red x indicates that the there is something amiss with the item.
@@ -65,25 +72,19 @@ If a change is caught and the cache is refreshed, the plugin will loop through i
`Problems` gets also triggered if any fatal exception is caught.
# Updating
# CLI Command
As development for the Problems plugin continues, new versions may become available that add additional features and functionality, improve compatibility with newer Grav releases, and generally provide a better user experience. Updating Problems is easy, and can be done through Grav's GPM system, as well as manually.
Problems 2.0 comes with a handy CLI command so you can run the checks at any time
## GPM Update (Preferred)
```bash
bin/plugin problems check
```
The simplest way to update this plugin is via the [Grav Package Manager (GPM)](http://learn.getgrav.org/advanced/grav-gpm). You can do this with this by navigating to the root directory of your Grav install using your system's Terminal (also called command line) and typing the following:
You should see some output like this:
bin/gpm update problems
This command will check your Grav install to see if your Problems plugin is due for an update. If a newer release is found, you will be asked whether or not you wish to update. To continue, type `y` and hit enter. The plugin will automatically update and clear Grav's cache.
![](assets/cli.png)
## Manual Update
# Extending Plugins
Manually updating Problems is pretty simple. Here is what you will need to do to get this done:
* Delete the `your/site/user/plugins/problems` directory.
* Download the new version of the Problems plugin from either [GitHub](https://github.com/getgrav/grav-plugin-problems) or [GetGrav.org](http://getgrav.org/downloads/plugins#extras).
* Unzip the zip file in `your/site/user/plugins` and rename the resulting folder to `problems`.
* Clear the Grav cache. The simplest way to do this is by going to the root Grav directory in terminal and typing `bin/grav clear-cache`.
> Note: Any changes you have made to any of the files listed under this directory will also be removed and replaced by the new set. Any files located elsewhere (for example a YAML settings file placed in `user/config/plugins`) will remain intact.
You can also extend the problems plugin via the `onProblemsInitialized()` event. The event includes an array of Problems. Simply create your own Problems class that extends the `Grav\Plugin\Problems\Base\Problem` class and add it to the array.
Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

+11
View File
@@ -0,0 +1,11 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid" width="95.7" height="83.6" viewBox="0 0 47.85 41.8">
<defs>
<style>
.cls-1 {
fill: #000;
fill-rule: evenodd;
}
</style>
</defs>
<path d="M47.557,21.555 L37.591,32.529 C37.394,32.746 37.124,32.856 36.853,32.856 C36.614,32.856 36.374,32.770 36.183,32.597 C35.776,32.225 35.746,31.596 36.116,31.188 L45.472,20.884 L36.116,10.585 C35.746,10.177 35.776,9.547 36.183,9.176 C36.591,8.806 37.221,8.836 37.591,9.243 L47.556,20.212 C47.901,20.593 47.902,21.173 47.557,21.555 ZM18.874,41.119 C18.744,41.552 18.349,41.830 17.920,41.830 C17.825,41.830 17.729,41.816 17.633,41.788 C17.106,41.629 16.807,41.073 16.965,40.546 L28.923,0.648 C29.082,0.120 29.639,-0.175 30.164,-0.022 C30.691,0.137 30.991,0.694 30.832,1.221 L18.874,41.119 ZM11.614,32.594 C11.423,32.768 11.183,32.853 10.944,32.853 C10.673,32.853 10.403,32.743 10.206,32.527 L0.241,21.558 C-0.104,21.176 -0.105,20.596 0.241,20.215 L10.206,9.240 C10.576,8.833 11.207,8.803 11.614,9.173 C12.021,9.545 12.051,10.174 11.681,10.582 L2.325,20.886 L11.681,31.184 C12.051,31.592 12.021,32.223 11.614,32.594 Z" class="cls-1"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" viewBox="0 0 504 140" clip-rule="evenodd"><path d="M235.83 71.56h-7.98c-1.2 0-2.2 1-2.2 2.2V89.1l-.15.13c-4.7 3.96-10.64 6.14-16.72 6.14-14.36 0-26.04-11.68-26.04-26.04s11.68-26.04 26.04-26.04c5.58 0 10.92 1.76 15.44 5.1.87.66 2.1.57 2.86-.2l5.7-5.7c.44-.44.67-1.05.63-1.68-.02-.62-.32-1.2-.82-1.6-6.76-5.35-15.2-8.3-23.8-8.3-21.18 0-38.42 17.23-38.42 38.4 0 21.2 17.24 38.42 38.42 38.42 10.93 0 21.4-4.7 28.7-12.9.35-.4.55-.93.55-1.47v-19.6c0-1.22-.98-2.2-2.2-2.2M502.8 34.44c-.4-.6-1.1-.98-1.84-.98h-8.7c-.87 0-1.66.52-2 1.32l-24.5 56.84-24.9-56.85c-.36-.8-1.15-1.3-2.02-1.3h-8.72c-.74 0-1.44.36-1.84.98-.4.62-.48 1.4-.17 2.1l30.2 68.85c.34.8 1.13 1.32 2 1.32h11c.88 0 1.67-.53 2.02-1.33l29.66-68.87c.3-.68.22-1.47-.2-2.1"/><path d="M388.68 34.77c-.35-.8-1.14-1.32-2-1.32h-11c-.88 0-1.67.53-2.02 1.33L344 103.64c-.3.68-.22 1.47.18 2.08.4.62 1.1 1 1.84 1h8.7c.86 0 1.66-.53 2-1.33l24.5-56.86 24.9 56.86c.36.8 1.15 1.32 2.02 1.32h8.72c.74 0 1.44-.38 1.84-1 .4-.62.47-1.4.17-2.1l-30.2-68.85zM309.2 81.52l.47-.22c8.68-4.2 14.28-13.1 14.28-22.67 0-13.88-11.3-25.18-25.17-25.18H266.9c-1.2 0-2.2 1-2.2 2.2v68.86c0 1.23 1 2.22 2.2 2.22h8c1.2 0 2.2-1 2.2-2.2V45.8h21.68c7.05 0 12.8 5.75 12.8 12.8 0 5.9-4 11-9.73 12.42-1.04.26-2.07.4-3.07.4h-7.98c-.83 0-1.6.46-1.96 1.2-.38.73-.3 1.62.2 2.3l22.6 30.87c.42.58 1.08.92 1.78.92h9.9c.84 0 1.6-.47 1.97-1.2.37-.75.3-1.64-.2-2.3l-15.9-21.7zM107.2 80.97c-7.26-4.8-11.4-8.85-15.02-16.1-2.47 4.97-8.24 12.37-17.96 18.2-4.86 15.1-27.96 44-35.43 39.9-2.22-1.2-2.64-2.8-2.15-4.45.54-4.13 9.08-13.62 9.08-13.62s.18 2 2.92 6.18c-3.6-11.2 5.96-25.03 8.5-29.73 3.98-1.27 4.27-6.4 4.27-6.4.26-7.9-3.28-13.63-6.7-17.05 2.46 3 3.25 7.54 3.37 11.7v.02c0 .47 0 .93 0 1.4-.12 3.43-1.16 8.18-3.38 8.18v.03c-2.28-.1-5.1.4-7.63 1.18l-5.6 1.34s2.98-.13 4.6 1.25c-1.8 2.9-5.78 6.53-10.22 8.58-6.45 3-8.3-2.96-5.03-6.84.8-.94 1.62-1.74 2.38-2.4-.5-.5-.8-1.2-.88-2.06 0 0 0 0 0-.02-.46-1.97-.2-4.54 2.6-8.62.54-.86 1.2-1.75 2-2.65.02-.04.04-.07.07-.1.03-.04.07-.08.1-.12.02-.02.04-.04.06-.06.2-.23.42-.45.64-.67 3.34-3.4 8.6-6.96 16.9-10.15C64.4 43.68 67.94 41 67.94 41c1.07-1.1 2.94-2.45 3.63-2.8-5.05-8.77-6.07-21.15-4.75-24.5-.1.2-.2.38-.3.57.5-1.14.83-1.5 1.34-2.1 1.38-1.64 6.06-2.5 7.74.96.9 1.84 1.06 4.23 1.03 6.02-3.7-.2-7.06 4.04-7.06 4.04s3.07-1.46 6.88-1.5c0 0 1 .9 2.28 2.56-1.7 3.2-4.52 10.02-2.5 17.16.35 1.4.86 2.62 1.5 3.65.02.05.04.1.07.14.05.07.1.13.14.2 3.37 5.06 9.54 5.66 9.54 5.66-2.9-1.45-5.27-3.76-6.8-6.56-.82-1.5-1.3-2.77-1.6-3.77-1.64-6.3.77-10 2.14-12.47 3.17-4.9 8.95-7.9 15.15-7.18 8.72 1 14.97 8.86 13.98 17.57-.6 5.32-3.78 9.72-8.15 12.12 1.05 2.84-.07 6.28-.07 6.28 2.64 3.32 2.76 5.23 2.67 7-3.36-.55-6.62 1.7-6.62 1.7s6.48-1.53 10.24 1.82c2.44 2.64 4.08 5 5.05 6.77 1.4 2.5 7.86 2.68 7.12 7.2-.74 4.5-5.68 4.53-13.4-.57M69.56 0C31.15 0 0 31.15 0 69.57c0 38.42 31.15 69.57 69.57 69.57 38.42 0 69.57-31.15 69.57-69.57C139.14 31.15 108 0 69.57 0M73.8 51.7c.8-.82.8-2.14 0-2.95-.82-.82-2.14-.82-2.95 0-.82.8-.82 2.13 0 2.94.8.8 2.13.8 2.95 0M66.45 53.15c-.82.8-.82 2.13 0 2.95.8.8 2.13.8 2.94 0 .8-.82.8-2.14 0-2.95-.82-.8-2.14-.8-2.95 0"/><path d="M79.23 54.23c-1.27-1.27-3.34-1.27-4.6 0l-2.72 2.7c-1.27 1.3-1.27 3.35 0 4.63l3 2.97c1.26 1.28 3.32 1.28 4.6 0l2.7-2.7c1.28-1.28 1.28-3.35 0-4.62l-2.97-2.97zM95.76 41.44c-2.15-2.57 1.87-7.25 4.4-4.46 4.64 5.15-2.25 7.04-4.4 4.46m9.24 2.7c3.45-6.56-1.42-10.4-4.77-13.53-5.36-5.03-10.7-7.2-16.8-.23-6.1 6.98-2.24 15.07 3.35 19.06 5.58 4 14.78 1.25 18.22-5.3"/></svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

+5
View File
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 96 84" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
<path d="M87.98,42.724C87.976,42.728 87.976,42.734 87.974,42.736L53.094,81.456C51.634,83.092 49.664,83.998 47.552,83.998C47.55,83.998 47.55,83.998 47.548,83.998C45.438,83.998 43.468,83.09 42.006,81.448L7.138,42.736C7.134,42.732 7.132,42.728 7.13,42.724C-2.46,32.94 -2.44,17.092 7.202,7.34C11.886,2.606 18.114,-0.002 24.74,-0.002C31.364,-0.002 37.594,2.606 42.278,7.34C42.286,7.348 42.288,7.358 42.294,7.364C42.302,7.372 42.312,7.374 42.32,7.382L47.552,12.99L52.79,7.382C52.798,7.374 52.808,7.372 52.816,7.364C52.822,7.356 52.824,7.348 52.832,7.34C57.516,2.606 63.746,-0.002 70.37,-0.002C76.996,-0.002 83.224,2.606 87.91,7.34C97.542,17.092 97.562,32.942 87.98,42.724ZM85.098,10.164C81.166,6.188 75.934,3.998 70.37,3.998C64.822,3.998 59.604,6.178 55.672,10.136L48.998,17.28C48.984,17.294 48.964,17.3 48.95,17.314C48.934,17.33 48.928,17.35 48.912,17.366C48.792,17.48 48.646,17.544 48.508,17.622C48.436,17.664 48.374,17.726 48.298,17.756C48.058,17.854 47.806,17.908 47.552,17.908C47.298,17.908 47.046,17.854 46.806,17.756C46.73,17.726 46.67,17.664 46.596,17.624C46.458,17.546 46.314,17.48 46.192,17.366C46.176,17.35 46.17,17.33 46.156,17.314C46.14,17.3 46.122,17.294 46.106,17.28L39.456,10.152C35.522,6.184 30.298,3.998 24.74,3.998C19.176,3.998 13.946,6.188 10.01,10.164C1.884,18.386 1.884,31.76 10.01,39.978C10.022,39.99 10.026,40.008 10.038,40.02C10.048,40.032 10.064,40.034 10.074,40.048L44.95,78.768C45.66,79.564 46.58,79.996 47.55,79.996L47.552,79.996C48.524,79.996 49.446,79.564 50.15,78.774L85.036,40.048C85.046,40.036 85.06,40.032 85.07,40.022C85.082,40.008 85.086,39.992 85.098,39.98C93.218,31.76 93.218,18.386 85.098,10.164Z" style="fill:rgb(235,82,66);"/>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 360 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

+1 -1
View File
@@ -1,5 +1,5 @@
name: Problems
version: 1.4.7
version: 2.0.0
description: Detects and reports problems found in the site.
icon: exclamation-circle
author:
@@ -0,0 +1,53 @@
<?php
namespace Grav\Plugin\Problems;
use Grav\Plugin\Problems\Base\Problem;
class Apache extends Problem
{
public function __construct()
{
$this->id = 'Apache Modules';
$this->class = get_class($this);
$this->order = 1;
$this->level = Problem::LEVEL_CRITICAL;
$this->status = true;
$this->help = 'https://learn.getgrav.org/basics/requirements#apache-requirements';
}
public function process()
{
// Perform some Apache checks
if (strpos(php_sapi_name(), 'apache') !== false && function_exists('apache_get_modules')) {
$require_apache_modules = ['mod_rewrite'];
$apache_modules = apache_get_modules();
$apache_errors = [];
$apache_success = [];
foreach ((array) $require_apache_modules as $module) {
if (in_array($module, $apache_modules)) {
$apache_success[$module] = 'module required but not enabled';
} else {
$apache_errors[$module] = 'module is not installed or enabled';
}
}
if (empty($apache_errors)) {
$this->status = true;
$this->msg = 'All modules look good!';
} else {
$this->status = false;
$this->msg = 'There were problems with required modules:';
}
$this->details = ['errors' => $apache_errors, 'success' => $apache_success];
} else {
$this->msg = 'Apache not installed, skipping...';
}
return $this;
}
}
@@ -0,0 +1,85 @@
<?php
namespace Grav\Plugin\Problems\Base;
class Problem implements \JsonSerializable
{
const LEVEL_CRITICAL = 'critical';
const LEVEL_WARNING = 'warning';
const LEVEL_NOTICE = 'notice';
protected $id;
protected $order;
protected $level;
protected $status;
protected $msg;
protected $details;
protected $help;
protected $class;
public function __contstruct($data = null)
{
if (!is_null($data)) {
$this->load($data);
}
}
public function load($data) {
$this->set_object_vars($data);
}
public function process() {
return $this;
}
public function getId() {
return $this->id;
}
public function getOrder() {
return $this->order;
}
public function getLevel() {
return $this->level;
}
public function getStatus() {
return $this->status;
}
public function getMsg() {
return $this->msg;
}
public function getDetails()
{
return $this->details;
}
public function getHelp()
{
return $this->help;
}
public function getClass()
{
return $this->class;
}
public function toArray()
{
return get_object_vars($this);
}
public function jsonSerialize()
{
$this->toArray();
}
protected function set_object_vars($object, array $vars) {
$has = get_object_vars($object);
foreach ($has as $name => $oldValue) {
$object->$name = isset($vars[$name]) ? $vars[$name] : NULL;
}
}
}
@@ -0,0 +1,119 @@
<?php
namespace Grav\Plugin\Problems\Base;
use Grav\Common\Cache;
use Grav\Common\Grav;
use RocketTheme\Toolbox\Event\Event;
class ProblemChecker
{
const PROBLEMS_PREFIX = 'problem-check-';
protected $problems = [];
protected $status_file;
public function __construct()
{
/** @var Cache $cache */
$cache = Grav::instance()['cache'];
$this->status_file = CACHE_DIR . $this::PROBLEMS_PREFIX . $cache->getKey() . '.json';
}
public function load()
{
if ($this->statusFileExists()) {
$json = file_get_contents($this->status_file);
$data = json_decode($json, true);
foreach ($data as $problem) {
$class = $problem['class'];
$this->problems[] = new $class($problem);
}
}
}
public function getStatusFile()
{
return $this->status_file;
}
public function statusFileExists()
{
return file_exists($this->status_file);
}
public function storeStatusFile()
{
$problems = $this->getProblemsSerializable();
$json = json_encode($problems);
file_put_contents($this->status_file, $json);
}
public function check($problems_dir)
{
$problems = [];
$problems_found = false;
foreach (new \DirectoryIterator($problems_dir) as $file) {
if ($file->isDot() || $file->isDir()) {
continue;
}
$classname = 'Grav\\Plugin\\Problems\\' . $file->getBasename('.php');
/** @var Problem $problem */
$problem = new $classname();
$problems[$problem->getId()] = $problem;
}
// Fire event to allow other plugins to add problems
Grav::instance()->fireEvent('onProblemsInitialized', new Event(['problems' => $problems]));
// Get the problems in order
usort($problems, function($a, $b) {
return $b->getOrder() - $a->getOrder();
});
// run the process methods in new order
foreach ($problems as $problem) {
$problem->process();
if ($problem->getStatus() === false && $problem->getLevel() === Problem::LEVEL_CRITICAL) {
$problems_found = true;
}
}
$this->problems = $problems;
return $problems_found;
}
public function getProblems()
{
if (empty($this->problems)) {
$this->check();
}
$problems = $this->problems;
// Put the failed ones first
usort($problems, function($a, $b) {
return $a->getStatus() - $b->getStatus();
});
return $problems;
}
public function getProblemsSerializable()
{
if (empty($this->problems)) {
$this->getProblems();
}
$problems = [];
foreach ($this->problems as $problem) {
$problems[] = $problem->toArray();
}
return $problems;
}
}
@@ -0,0 +1,65 @@
<?php
namespace Grav\Plugin\Problems;
use Grav\Plugin\Problems\Base\Problem;
class EssentialFolders extends Problem
{
public function __construct()
{
$this->id = 'Essential Folders';
$this->class = get_class($this);
$this->order = 100;
$this->level = Problem::LEVEL_CRITICAL;
$this->status = false;
$this->help = 'https://learn.getgrav.org/basics/folder-structure';
}
public function process()
{
$essential_folders = [
'backup' => true,
'cache' => true,
'logs' => true,
'images' => true,
'assets' => true,
'system' => false,
'user/data' => true,
'user/pages' => false,
'user/config' => false,
'user/plugins/error' => false,
'user/plugins' => false,
'user/themes' => false,
'vendor' => false,
'tmp' => true,
];
// Check for essential files & perms
$file_errors = [];
$file_success = [];
foreach ($essential_folders as $file => $check_writable) {
$file_path = ROOT_DIR . $file;
if (!file_exists($file_path)) {
$file_errors[$file_path] = 'does not exist';
} elseif ($check_writable && !is_writable($file_path)) {
$file_errors[$file_path] = 'exists but is <strong>not writeable</strong>';
} else {
$file_success[$file_path] = 'exists and is writable';
}
}
if (empty($file_errors)) {
$this->status = true;
$this->msg = 'All folders look good!';
} else {
$this->status = false;
$this->msg = 'There were problems with required folders:';
}
$this->details = ['errors' => $file_errors, 'success' => $file_success];
return $this;
}
}
@@ -0,0 +1,132 @@
<?php
namespace Grav\Plugin\Problems;
use Grav\Common\Grav;
use Grav\Plugin\Problems\Base\Problem;
class PHPModules extends Problem
{
public function __construct()
{
$this->id = 'PHP Modules';
$this->class = get_class($this);
$this->order = 101;
$this->level = Problem::LEVEL_CRITICAL;
$this->status = false;
$this->help = 'https://learn.getgrav.org/basics/requirements#php-requirements';
}
public function process()
{
$modules_errors = [];
$modules_success = [];
// Check for PHP CURL library
$msg = "PHP Curl (Data Transfer Library) is %s installed";
if (function_exists('curl_version')) {
$modules_success['curl'] = sprintf($msg, 'successfully');
} else {
$modules_errors['curl'] = sprintf($msg, 'required but not');
}
// Check for PHP Ctype library
$msg = "PHP Ctype is %s installed";
if (function_exists('ctype_print')) {
$modules_success['ctype'] = sprintf($msg, 'successfully');
} else {
$modules_errors['ctype'] = sprintf($msg, 'required but not');
}
// Check for PHP Dom library
$msg = "PHP DOM is %s installed";
if (class_exists('DOMDocument')) {
$modules_success['dom'] = sprintf($msg, 'successfully');
} else {
$modules_errors['dom'] = sprintf($msg, 'required but not');
}
// Check for GD library
$msg = "PHP GD (Image Manipulation Library) is %s installed";
if (defined('GD_VERSION') && function_exists('gd_info')) {
$msg = $modules_success['gd'] = sprintf($msg, 'successfully');
// Extra checks for Image support
$ginfo = gd_info();
$gda = array("PNG Support", "JPEG Support", "FreeType Support", "GIF Read Support");
$gda_msg = '';
$problems_found = false;
foreach ($gda as $image_type) {
if (!$ginfo[$image_type]) {
$problems_found = true;
$gda_msg = "missing $image_type, but is ";
break;
}
}
if ($problems_found) {
$msg .= ' but missing ' . $gda_msg;
}
$modules_success['gd'] = $msg;
} else {
$modules_errors['gd'] = sprintf($msg, 'required but not');
}
// Check for PHP MbString library
$msg = "PHP Mbstring (Multibyte String Library) is %s installed";
if (extension_loaded('mbstring')) {
$modules_success['mbstring'] = sprintf($msg, 'successfully');
} else {
$modules_errors['mbstring'] = sprintf($msg, 'required but not');
}
// Check for PHP Open SSL library
$msg = "PHP OpenSSL (Secure Sockets Library) is %s installed";
if (extension_loaded('openssl') && defined('OPENSSL_VERSION_TEXT')) {
$modules_success['openssl'] = sprintf($msg, 'successfully');
} else {
$modules_errors['openssl'] = sprintf($msg, 'required but not');
}
// Check for PHP XML library
$msg = "PHP XML Library is %s installed";
if (extension_loaded('xml')) {
$modules_success['xml'] = sprintf($msg, 'successfully');
} else {
$modules_errors['xml'] = sprintf($msg, 'required but not');
}
// Check for PHP Zip library
$msg = "PHP Zip extension is %s installed";
if (extension_loaded('zip')) {
$modules_success['zip'] = sprintf($msg, 'successfully');
} else {
$modules_errors['zip'] = sprintf($msg, 'required but not');
}
// Check Exif if enabled
if (Grav::instance()['config']->get('system.media.auto_metadata_exif')) {
$msg = "PHP Exif (Exchangeable Image File Format) is %s installed";
if (extension_loaded('exif')) {
$modules_success['exif'] = sprintf($msg, 'successfully');
} else {
$modules_errors['exif'] = sprintf($msg, 'required but not');
}
}
if (empty($modules_errors)) {
$this->status = true;
$this->msg = 'All modules look good!';
} else {
$this->status = false;
$this->msg = 'There were problems with required modules:';
}
$this->details = ['errors' => $modules_errors, 'success' => $modules_success];
return $this;
}
}
@@ -0,0 +1,35 @@
<?php
namespace Grav\Plugin\Problems;
use Grav\Plugin\Problems\Base\Problem;
class PHPVersion extends Problem
{
public function __construct()
{
$this->id = 'PHP Minimum Version';
$this->class = get_class($this);
$this->order = 102;
$this->level = Problem::LEVEL_CRITICAL;
$this->status = false;
$this->help = 'https://getgrav.org/blog/raising-php-requirements-2018';
}
public function process()
{
$min_php_version = defined('GRAV_PHP_MIN') ? GRAV_PHP_MIN : '5.6.4';
$your_php_version = phpversion();
$msg = "Your PHP <strong>%s</strong> is %s than the minimum of <strong>%s</strong> required";
// Check PHP version
if (version_compare($your_php_version, $min_php_version, '<')) {
$this->msg = sprintf($msg, $your_php_version, 'less', $min_php_version);
} else {
$this->msg = sprintf($msg, $your_php_version, 'greater', $min_php_version);
$this->status = true;
}
return $this;
}
}
@@ -0,0 +1,34 @@
<?php
namespace Grav\Plugin\Problems;
use Grav\Plugin\Problems\Base\Problem;
class Permissions extends Problem
{
public function __construct()
{
$this->id = 'Permissions Setup';
$this->class = get_class($this);
$this->order = -1;
$this->level = Problem::LEVEL_WARNING;
$this->status = false;
$this->help = 'https://learn.getgrav.org/troubleshooting/permissions';
}
public function process()
{
umask($umask = umask(022));
$msg = "Your default file umask is <strong>%s</strong> which %s";
if (($umask & 2) !== 2) {
$this->msg = sprintf($msg, decoct($umask), 'is potentially dangerous');
$this->status = false;
} else {
$this->msg = sprintf($msg, decoct($umask), 'looks good!');
$this->status = true;
}
return $this;
}
}
+105
View File
@@ -0,0 +1,105 @@
<?php
namespace Grav\Plugin\Console;
use Grav\Common\Grav;
use Grav\Console\ConsoleCommand;
use Grav\Plugin\Problems\Base\ProblemChecker;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Helper\TableCell;
use Symfony\Component\Console\Helper\TableSeparator;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Style\SymfonyStyle;
/**
* Class ProblemsCommand
*
* @package Grav\Plugin\Console
*/
class CheckCommand extends ConsoleCommand
{
/**
*
*/
protected function configure()
{
$this
->setName("check")
->setDescription("Check Problems")
->setHelp('The <info>problems command</info> allows you display any potential problems with your Grav setup')
;
}
/**
* @return int|null|void
*/
protected function serve()
{
/** @var use new SymfonyStyle helper $io */
$io = new SymfonyStyle($this->input, $this->output);
$plugin_dir = realpath(__DIR__ . '/..');
$problems_dir = $plugin_dir . '/classes/Problems';
require $plugin_dir . '/vendor/autoload.php';
$checker = new ProblemChecker();
$checker->check($problems_dir);
$problems = $checker->getProblems();
$io->title('Grav Problems');
$table = new Table($this->output);
$table->setStyle('default');
$headers = ['ID', 'Status', 'Level', 'Message'];
$rows = [];
foreach ($problems as $problem) {
$rows[] = new TableSeparator();
$rows[] = [
$problem->getStatus() ? $problem->getID() : '<red>' . $problem->getId() . '</red>' ,
$problem->getStatus() ? '<green>success</green>' : '<red>error</red>',
$problem->getLevel() == 'critical' ? '<red>' . $problem->getLevel() . '</red>' : '<yellow>' .$problem->getLevel() . '</yellow>',
strip_tags($problem->getMsg()),
];
$details = $problem->getDetails();
if (is_array($details)) {
$errors_row = [];
$success_row = [];
if (isset($details['errors'])) {
foreach ($details['errors'] as $key => $value) {
$errors_row[] = "<red>✗</red> <yellow>{$key}{$value}</yellow>";
}
}
if (isset($details['success'])) {
foreach ($details['success'] as $key => $value) {
$success_row[] = "<green>✔</green> {$key}{$value}";
}
}
foreach($errors_row as $e_row) {
$rows[] = ['', new TableCell($e_row, array('colspan' => 3)), ];
}
foreach($success_row as $e_row) {
$rows[] = ['', new TableCell($e_row, array('colspan' => 3)), ];
}
}
}
if (!empty($rows)) {
$table->setHeaders($headers);
$table->setRows($rows);
$table->render();
} else {
$io->text('did not find anything to check...');
}
}
}
+7
View File
@@ -0,0 +1,7 @@
{
"autoload": {
"psr-4": {
"Grav\\Plugin\\": "classes/"
}
}
}
-71
View File
@@ -1,71 +0,0 @@
section#body {
padding-top: 3rem;
}
ul.problems {
list-style: none;
padding: 0;
margin-top: 3rem;
}
ul.problems li {
margin-bottom: 1rem;
padding: 1rem;
}
ul.problems li.success {
background: #F1F9F1;
border-left: 5px solid #5CB85C;
color: #3d8b3d;
}
ul.problems li.error {
background: #FDF7F7;
border-left: 5px solid #D9534F;
color: #b52b27;
}
ul.problems li.info {
background: #F4F8FA;
border-left: 5px solid #5bc0de;
color: #28a1c5;
}
ul.problems .fa {
font-size: 3rem;
vertical-align: middle;
margin-left: 1rem;
display: block;
float: left;
}
ul.problems p {
display: block;
margin: 0.5rem 0.5rem 0.5rem 5rem;
}
.button.big {
font-size: 1.2rem;
}
.center {
text-align: center;
}
.underline {
text-decoration: underline;
}
.clearfix:after {
visibility: hidden;
display: block;
font-size: 0;
content: " ";
clear: both;
height: 0;
}
.clearfix { display: inline-block; }
/* start commented backslash hack \*/
* html .clearfix { height: 1%; }
.clearfix { display: block; }
/* close commented backslash hack */
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-762
View File
@@ -1,762 +0,0 @@
@import url(//fonts.googleapis.com/css?family=Montserrat:400|Raleway:300,400,600|Inconsolata);
#header #logo h3, #header #navbar ul, #header #navbar .panel-activation, #footer p {
position: relative;
top: 50%;
-webkit-transform: translateY(-50%);
-moz-transform: translateY(-50%);
-o-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%); }
.button, .button-secondary {
display: inline-block;
padding: 7px 20px; }
html, body {
height: 100%; }
body {
background: white;
color: #444444;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; }
a {
color: #1bb3e9; }
a:hover {
color: #0e6e90; }
b, strong, label, th {
font-weight: 600; }
#container {
min-height: 100%;
position: relative; }
.fullwidth #body {
padding-left: 0;
padding-right: 0; }
#body {
padding-top: 8rem;
padding-bottom: 11rem; }
.default-animation, #body, #header, #header #logo h3, .modular .showcase .button {
-webkit-transition: all 0.5s ease;
-moz-transition: all 0.5s ease;
transition: all 0.5s ease; }
.padding-horiz, .fullwidth #header, .fullwidth #breadcrumbs, .fullwidth .blog-header, .fullwidth .blog-content-item, .fullwidth .blog-content-list, .fullwidth ul.pagination, .fullwidth #body > .modular-row, #body, #header, #footer {
padding-left: 7rem;
padding-right: 7rem; }
@media only all and (max-width: 59.938rem) {
.padding-horiz, .fullwidth #header, .fullwidth #breadcrumbs, .fullwidth .blog-header, .fullwidth .blog-content-item, .fullwidth .blog-content-list, .fullwidth ul.pagination, .fullwidth #body > .modular-row, #body, #header, #footer {
padding-left: 4rem;
padding-right: 4rem; } }
@media only all and (max-width: 47.938rem) {
.padding-horiz, .fullwidth #header, .fullwidth #breadcrumbs, .fullwidth .blog-header, .fullwidth .blog-content-item, .fullwidth .blog-content-list, .fullwidth ul.pagination, .fullwidth #body > .modular-row, #body, #header, #footer {
padding-left: 1rem;
padding-right: 1rem; } }
.padding-vert {
padding-top: 3rem;
padding-bottom: 3rem; }
#header {
position: fixed;
z-index: 10;
width: 100%;
height: 5rem;
background-color: rgba(255, 255, 255, 0.9);
box-shadow: 0 0.05rem 1rem rgba(0, 0, 0, 0.15); }
#header.scrolled {
height: 3rem;
background-color: rgba(255, 255, 255, 0.9) !important;
box-shadow: 0 0.05rem 1rem rgba(0, 0, 0, 0.15) !important; }
#header.scrolled #logo h3 {
color: #444444 !important;
font-size: 1.6rem !important; }
#header.scrolled #logo a {
color: #444444 !important; }
#header.scrolled #navbar a {
color: #1bb3e9 !important; }
#header.scrolled #navbar a:before, #header.scrolled #navbar a:after {
background-color: #1bb3e9 !important; }
#header > .grid, #header #logo, #header #navbar {
height: 100%; }
#header #logo {
float: left; }
#header #logo h3 {
font-size: 2rem;
line-height: 2rem;
margin: 0;
text-transform: uppercase; }
#header #logo h3 a {
color: #444444; }
#header #navbar {
font-size: 0.9rem; }
#header #navbar ul {
display: inline-block;
margin: 0;
list-style: none;
float: right; }
#header #navbar ul li {
float: left;
position: relative; }
#header #navbar ul li a {
font-family: "Montserrat", "Helvetica", "Tahoma", "Geneva", "Arial", sans-serif;
display: inline-block;
padding: 0.1rem 0.8rem; }
#header #navbar ul li a:before, #header #navbar ul li a:after {
content: "";
position: absolute;
width: 100%;
height: 1px;
bottom: 0;
left: 0;
background-color: #1bb3e9;
visibility: hidden;
-webkit-transform: scaleX(0);
-moz-transform: scaleX(0);
-ms-transform: scaleX(0);
-o-transform: scaleX(0);
transform: scaleX(0);
-webkit-transition: all 0.2s ease;
-moz-transition: all 0.2s ease;
transition: all 0.2s ease; }
#header #navbar ul li a:hover:before {
visibility: visible;
-webkit-transform: scaleX(0.75);
-moz-transform: scaleX(0.75);
-ms-transform: scaleX(0.75);
-o-transform: scaleX(0.75);
transform: scaleX(0.75); }
#header #navbar ul li.active a:after {
top: 0;
visibility: visible;
-webkit-transform: scaleX(0.75);
-moz-transform: scaleX(0.75);
-ms-transform: scaleX(0.75);
-o-transform: scaleX(0.75);
transform: scaleX(0.75); }
@media only all and (max-width: 59.938rem) {
#header #navbar ul {
display: none; } }
#header #navbar .panel-activation {
display: none;
font-size: 2rem;
cursor: pointer;
float: right; }
@media only all and (max-width: 59.938rem) {
#header #navbar .panel-activation {
display: inline-block; } }
.header-image.fullwidth #body {
padding-left: 0;
padding-right: 0; }
.header-image.fullwidth #body > .listing-row {
padding-left: 7rem;
padding-right: 7rem; }
.header-image .listing-row:last-child {
margin-bottom: 2rem; }
.header-image #body > .blog-header {
margin-top: -9.5rem;
padding-top: 9rem; }
.header-image #breadcrumbs {
margin-top: 1rem; }
.header-image #header {
background-color: rgba(255, 255, 255, 0);
box-shadow: none; }
.header-image #header #logo h3, .header-image #header #logo a {
color: white; }
.header-image #header a, .header-image #header .menu-btn {
color: white; }
.header-image #header a:before, .header-image #header a:after {
background-color: rgba(255, 255, 255, 0.7) !important; }
#footer {
position: absolute;
background: #333;
height: 6rem;
right: 0;
bottom: 0;
left: 0;
color: #999;
text-align: center; }
#footer a:hover {
color: #fff; }
#footer .totop {
position: absolute;
bottom: 5rem;
text-align: center;
left: 0;
right: 0; }
#footer .totop span {
font-size: 1.7rem;
line-height: 2.5rem;
background: #333;
width: 3rem;
height: 2rem;
border-radius: 3px;
display: inline-block;
text-align: top; }
#footer p {
margin: 0; }
#footer p .fa {
color: #fff; }
body {
font-family: "Raleway", "Helvetica", "Tahoma", "Geneva", "Arial", sans-serif;
font-weight: 400; }
h1, h2, h3, h4, h5, h6 {
font-family: "Montserrat", "Helvetica", "Tahoma", "Geneva", "Arial", sans-serif;
font-weight: 400;
text-rendering: optimizeLegibility;
letter-spacing: -0px; }
h1 {
font-size: 3.2rem; }
@media only all and (max-width: 47.938rem) {
h1 {
font-size: 2.5rem;
line-height: 1.2;
margin-bottom: 2.5rem; } }
@media only all and (min-width: 48rem) and (max-width: 59.938rem) {
h2 {
font-size: 2.1rem; } }
@media only all and (max-width: 47.938rem) {
h2 {
font-size: 2rem; } }
@media only all and (min-width: 48rem) and (max-width: 59.938rem) {
h3 {
font-size: 1.7rem; } }
@media only all and (max-width: 47.938rem) {
h3 {
font-size: 1.6rem; } }
@media only all and (min-width: 48rem) and (max-width: 59.938rem) {
h4 {
font-size: 1.35rem; } }
@media only all and (max-width: 47.938rem) {
h4 {
font-size: 1.25rem; } }
h1 {
text-align: center;
letter-spacing: -3px; }
h2 {
letter-spacing: -2px; }
h3 {
letter-spacing: -1px; }
h1 + h2 {
margin: -2rem 0 2rem 0;
font-size: 2rem;
line-height: 1;
text-align: center;
font-family: "Raleway", "Helvetica", "Tahoma", "Geneva", "Arial", sans-serif;
font-weight: 300; }
@media only all and (min-width: 48rem) and (max-width: 59.938rem) {
h1 + h2 {
font-size: 1.6rem; } }
@media only all and (max-width: 47.938rem) {
h1 + h2 {
font-size: 1.5rem; } }
h2 + h3 {
margin: 0.5rem 0 2rem 0;
font-size: 2rem;
line-height: 1;
text-align: center;
font-family: "Raleway", "Helvetica", "Tahoma", "Geneva", "Arial", sans-serif;
font-weight: 300; }
@media only all and (min-width: 48rem) and (max-width: 59.938rem) {
h2 + h3 {
font-size: 1.6rem; } }
@media only all and (max-width: 47.938rem) {
h2 + h3 {
font-size: 1.5rem; } }
blockquote {
border-left: 10px solid #f0f2f4; }
blockquote p {
font-size: 1.1rem;
color: #999; }
blockquote cite {
display: block;
text-align: right;
color: #666;
font-size: 1.2rem; }
blockquote > blockquote > blockquote {
margin: 0; }
blockquote > blockquote > blockquote p {
padding: 15px;
display: block;
font-size: 1rem;
margin-top: 0rem;
margin-bottom: 0rem; }
blockquote > blockquote > blockquote > p {
margin-left: -71px;
border-left: 10px solid #F0AD4E;
background: #FCF8F2;
color: #df8a13; }
blockquote > blockquote > blockquote > blockquote > p {
margin-left: -94px;
border-left: 10px solid #D9534F;
background: #FDF7F7;
color: #b52b27; }
blockquote > blockquote > blockquote > blockquote > blockquote > p {
margin-left: -118px;
border-left: 10px solid #5BC0DE;
background: #F4F8FA;
color: #28a1c5; }
blockquote > blockquote > blockquote > blockquote > blockquote > blockquote > p {
margin-left: -142px;
border-left: 10px solid #5CB85C;
background: #F1F9F1;
color: #3d8b3d; }
code,
kbd,
pre,
samp {
font-family: "Inconsolata", monospace; }
code {
background: #f9f2f4;
color: #9c1d3d; }
pre {
padding: 2rem;
background: #f6f6f6;
border: 1px solid #dddddd;
border-radius: 3px; }
pre code {
color: #237794;
background: inherit; }
hr {
border-bottom: 4px solid #f0f2f4; }
.page-title {
margin-top: -25px;
padding: 25px;
float: left;
clear: both;
background: #1bb3e9;
color: white; }
fieldset {
border: 1px solid #dddddd; }
textarea, input[type="email"], input[type="number"], input[type="password"], input[type="search"], input[type="tel"], input[type="text"], input[type="url"], input[type="color"], input[type="date"], input[type="datetime"], input[type="datetime-local"], input[type="month"], input[type="time"], input[type="week"], select[multiple=multiple] {
background-color: white;
border: 1px solid #dddddd;
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.06); }
textarea:hover, input[type="email"]:hover, input[type="number"]:hover, input[type="password"]:hover, input[type="search"]:hover, input[type="tel"]:hover, input[type="text"]:hover, input[type="url"]:hover, input[type="color"]:hover, input[type="date"]:hover, input[type="datetime"]:hover, input[type="datetime-local"]:hover, input[type="month"]:hover, input[type="time"]:hover, input[type="week"]:hover, select[multiple=multiple]:hover {
border-color: #c4c4c4; }
textarea:focus, input[type="email"]:focus, input[type="number"]:focus, input[type="password"]:focus, input[type="search"]:focus, input[type="tel"]:focus, input[type="text"]:focus, input[type="url"]:focus, input[type="color"]:focus, input[type="date"]:focus, input[type="datetime"]:focus, input[type="datetime-local"]:focus, input[type="month"]:focus, input[type="time"]:focus, input[type="week"]:focus, select[multiple=multiple]:focus {
border-color: #1bb3e9;
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.06), 0 0 5px rgba(21, 163, 214, 0.7); }
.form-field .required {
color: #F3443F;
font-size: 3rem;
line-height: 3rem;
vertical-align: top;
height: 1.5rem;
display: inline-block; }
form .buttons {
text-align: center; }
form input {
font-weight: 400; }
table {
border: 1px solid #eaeaea; }
th {
background: #f7f7f7;
padding: 0.5rem; }
td {
padding: 0.5rem;
border: 1px solid #eaeaea; }
.button {
background: white;
color: #1bb3e9;
border: 1px solid #1bb3e9;
border-radius: 3px; }
.button:hover {
background: #1bb3e9;
color: white; }
.button:active {
box-shadow: 0 1px 0 #118ab5; }
.button-secondary {
background: white;
color: #f6635e;
border: 1px solid #f6635e;
border-radius: 3px; }
.button-secondary:hover {
background: #f6635e;
color: white; }
.button-secondary:active {
box-shadow: 0 1px 0 #f32b24; }
.bullets {
margin: 1.7rem 0;
margin-left: -0.85rem;
margin-right: -0.85rem;
overflow: auto; }
.bullet {
float: left;
padding: 0 0.85rem; }
.two-column-bullet {
width: 50%; }
@media only all and (max-width: 47.938rem) {
.two-column-bullet {
width: 100%; } }
.three-column-bullet {
width: 33.33333%; }
@media only all and (max-width: 47.938rem) {
.three-column-bullet {
width: 100%; } }
.four-column-bullet {
width: 25%; }
@media only all and (max-width: 47.938rem) {
.four-column-bullet {
width: 100%; } }
.bullet-icon {
float: left;
background: #1bb3e9;
padding: 0.875rem;
width: 3.5rem;
height: 3.5rem;
border-radius: 50%;
color: white;
font-size: 1.75rem;
text-align: center; }
.bullet-icon-1 {
background: #1bb3e9; }
.bullet-icon-2 {
background: #1be9da; }
.bullet-icon-3 {
background: #d5e91b; }
.bullet-content {
margin-left: 4.55rem; }
#panel {
color: white; }
#panel .navigation {
list-style: none;
padding: 0; }
#panel .navigation li {
padding: 0.5rem 1rem;
border-bottom: 1px solid #404040;
font-weight: 600; }
#panel .navigation li.active {
background: #fff; }
#panel .navigation li.active a {
color: #444444; }
#panel .navigation li.active a:hover {
color: #444444; }
#panel .navigation li:last-child {
border-bottom: 0; }
#panel .navigation li a:hover {
color: white; }
/* Menu Appearance */
.pushy {
position: fixed;
width: 250px;
height: 100%;
top: 0;
z-index: 9999;
background: #333333;
overflow: auto;
-webkit-overflow-scrolling: touch;
/* enables momentum scrolling in iOS overflow elements */ }
/* Menu Movement */
.pushy-left {
-webkit-transform: translate3d(-250px, 0, 0);
-moz-transform: translate3d(-250px, 0, 0);
-ms-transform: translate3d(-250px, 0, 0);
-o-transform: translate3d(-250px, 0, 0);
transform: translate3d(-250px, 0, 0); }
.pushy-open {
-webkit-transform: translate3d(0, 0, 0);
-moz-transform: translate3d(0, 0, 0);
-ms-transform: translate3d(0, 0, 0);
-o-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0); }
.container-push, .push-push {
-webkit-transform: translate3d(250px, 0, 0);
-moz-transform: translate3d(250px, 0, 0);
-ms-transform: translate3d(250px, 0, 0);
-o-transform: translate3d(250px, 0, 0);
transform: translate3d(250px, 0, 0); }
/* Menu Transitions */
.pushy, #container, .push {
-webkit-transition: -webkit-transform 0.2s cubic-bezier(0.16, 0.68, 0.43, 0.99);
-moz-transition: -moz-transform 0.2s cubic-bezier(0.16, 0.68, 0.43, 0.99);
transition: transform 0.2s cubic-bezier(0.16, 0.68, 0.43, 0.99);
/* improves performance issues on mobile*/
-webkit-perspective: 1000; }
/* Site Overlay */
.site-overlay {
display: none; }
.pushy-active .site-overlay {
display: block;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 250px;
z-index: 9999; }
.blog-header {
padding-top: 2rem;
padding-bottom: 2rem; }
.blog-header.blog-header-image {
background-size: cover;
background-position: center; }
.blog-header.blog-header-image h1, .blog-header.blog-header-image h2 {
color: white; }
.blog-header h1 {
font-size: 4rem;
margin-top: 0; }
@media only all and (min-width: 48rem) and (max-width: 59.938rem) {
.blog-header h1 {
font-size: 3rem; } }
@media only all and (max-width: 47.938rem) {
.blog-header h1 {
font-size: 2.5rem;
line-height: 1.2;
margin-bottom: 2.5rem; } }
.blog-header + .blog-content {
padding-top: 3rem; }
.list-item {
border-bottom: 1px solid #eeeeee;
margin-bottom: 3rem; }
.list-item:last-child {
border-bottom: 0; }
.list-item .list-blog-header {
position: relative; }
.list-item .list-blog-header h4 {
margin-bottom: 0.5rem; }
.list-item .list-blog-header h4 a {
color: #444444; }
.list-item .list-blog-header h4 a:hover {
color: #1bb3e9; }
.list-item .list-blog-header img {
display: block;
margin-top: 1rem;
border-radius: 3px; }
.list-item .list-blog-date {
float: right;
text-align: center; }
.list-item .list-blog-date span {
display: block;
font-size: 1.75rem;
font-weight: 600;
line-height: 110%; }
.list-item .list-blog-date em {
display: block;
border-top: 1px solid #eeeeee;
font-style: normal;
text-transform: uppercase; }
.blog-content-item .list-blog-padding > p:nth-child(2) {
font-size: 1.2rem; }
.tags a {
display: inline-block;
font-size: 0.8rem;
border: 1px solid #1bb3e9;
border-radius: 3px;
padding: 0.1rem 0.4rem;
margin-bottom: 0.2rem;
text-transform: uppercase; }
.archives {
padding: 0;
list-style: none; }
.archives li {
border-bottom: 1px solid #eeeeee;
line-height: 2rem; }
.archives li:last-child {
border-bottom: 0; }
.syndicate a {
margin-bottom: 1rem; }
div#breadcrumbs {
padding-left: 0; }
#sidebar {
padding-left: 3rem; }
@media only all and (max-width: 47.938rem) {
#sidebar {
padding-left: 0; } }
#sidebar .sidebar-content {
margin-bottom: 3rem; }
#sidebar .sidebar-content h4 {
margin-bottom: 1rem; }
#sidebar .sidebar-content p, #sidebar .sidebar-content ul {
margin-top: 1rem; }
ul.pagination {
margin: 0 0 3rem;
text-align: left; }
#error {
text-align: center;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
padding-bottom: 6rem; }
#error h1 {
font-size: 5rem; }
#error p {
margin: 1rem 0; }
.modular.header-image #body > .showcase {
margin-top: -9.5rem;
padding-top: 9rem; }
.modular.header-image #header {
background-color: rgba(255, 255, 255, 0);
box-shadow: none; }
.modular.header-image #header #logo h3 {
color: white; }
.modular.header-image #header #navbar a {
color: white; }
.modular .showcase {
padding-top: 4rem;
padding-bottom: 4rem;
background-color: #666;
background-size: cover;
background-attachment: fixed;
background-position: center;
text-align: center;
color: white; }
.modular .showcase h1 {
font-size: 4rem;
margin-top: 0; }
@media only all and (min-width: 48rem) and (max-width: 59.938rem) {
.modular .showcase h1 {
font-size: 3rem; } }
@media only all and (max-width: 47.938rem) {
.modular .showcase h1 {
font-size: 2.5rem;
line-height: 1.2;
margin-bottom: 2.5rem; } }
.modular .showcase .button {
color: white;
padding: 0.7rem 2rem;
margin-top: 2rem;
background: rgba(255, 255, 255, 0);
border: 1px solid white;
border-radius: 3px;
box-shadow: none;
font-size: 1.3rem; }
.modular .showcase .button:hover {
background: rgba(255, 255, 255, 0.2); }
.modular .features {
padding: 3rem 0;
text-align: center; }
.modular .features:after {
content: "";
display: table;
clear: both; }
.modular .features h2 {
margin: 0;
line-height: 100%; }
.modular .features p {
margin: 1rem 0;
font-size: 1.2rem; }
@media only all and (max-width: 47.938rem) {
.modular .features p {
font-size: 1rem; } }
.modular .features .feature-items {
margin-top: 2rem; }
.modular .features .feature {
display: block;
float: left;
width: 25%;
vertical-align: top;
margin-top: 2rem;
margin-bottom: 1rem; }
@media only all and (max-width: 47.938rem) {
.modular .features .feature {
width: 100%; } }
.modular .features .feature i.fa {
font-size: 2rem;
color: #1bb3e9; }
.modular .features .feature h4 {
margin: 0;
font-size: 1.1rem; }
.modular .features .feature p {
display: inline-block;
font-size: 1rem;
margin: 0.2rem 0 1rem; }
.modular .features.big {
text-align: center; }
.modular .features.big .feature {
width: 50%; }
.modular .features.big i.fa {
font-size: 3rem;
float: left; }
.modular .features.big .feature-content {
padding-right: 2rem; }
.modular .features.big .feature-content.push {
margin-left: 5rem; }
.modular .features.big .feature-content h4 {
font-size: 1.3rem;
text-align: left; }
.modular .features.big .feature-content p {
padding: 0;
text-align: left; }
.callout {
background: #f6f6f6;
padding: 3rem 0.938rem; }
.callout .align-left {
float: left;
margin-right: 2rem; }
.callout .align-right {
float: right;
margin-left: 2rem; }
.callout img {
border-radius: 3px; }
.modular .modular-row:last-child {
margin-bottom: 2rem; }
/*# sourceMappingURL=template.css.map */
+39
View File
@@ -0,0 +1,39 @@
var gulp = require('gulp');
var sass = require('gulp-sass');
var cleancss = require('gulp-clean-css');
var csscomb = require('gulp-csscomb');
var rename = require('gulp-rename');
var autoprefixer = require('gulp-autoprefixer');
var sourcemaps = require('gulp-sourcemaps');
// configure the paths
var watch_dir = './scss/*.scss';
var src_dir = './scss/*.scss';
var dest_dir = './css';
var paths = {
source: src_dir
};
gulp.task('watch', function() {
gulp.watch(watch_dir, ['build']);
});
gulp.task('build', function() {
gulp.src(paths.source)
.pipe(sourcemaps.init())
.pipe(sass({outputStyle: 'compact', precision: 10})
.on('error', sass.logError)
)
.pipe(sourcemaps.write())
.pipe(autoprefixer())
.pipe(gulp.dest(dest_dir))
.pipe(csscomb())
.pipe(cleancss())
.pipe(rename({
suffix: '.min'
}))
.pipe(gulp.dest(dest_dir));
});
gulp.task('default', ['build']);
+15
View File
@@ -0,0 +1,15 @@
{
"project":"grav-plugin-problems",
"platforms":{
"grav":{
"nodes":{
"plugin":[
{
"source":"/",
"destination":"/user/plugins/problems"
}
]
}
}
}
}
-28
View File
@@ -1,28 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Grav Problems</title>
<meta name="description" content="Grav is an easy to use, yet powerful, open source flat-file CMS">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="%%PROBLEMS_URL%%/css/template.css" type="text/css" />
<link rel="stylesheet" href="%%PROBLEMS_URL%%/css/problems.css" type="text/css" />
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css" rel="stylesheet">
</head>
<body id="top" class="">
<div id="container">
<section id="body" class="">
<h1>Issues Found</h1>
<h2>Please <strong>Review</strong> and <strong>Resolve</strong> before continuing...</h2>
<p class="center">
<a href="%%BASE_URL%%" class="button big"><i class="fa fa-refresh"></i> Reload Page</a>
</p>
<ul class="problems">
%%PROBLEMS%%
</ul>
</section>
</div>
</body>
</html>
File diff suppressed because it is too large Load Diff
+45
View File
@@ -0,0 +1,45 @@
{
"name": "spectre.css",
"version": "0.5.1",
"homepage": "http://picturepan2.github.io/spectre",
"author": "Yan Zhu <picturepan2@hotmail.com>",
"description": "Spectre.css: a lightweight, responsive and modern CSS framework",
"main": "docs/dist/spectre.css",
"repository": {
"type": "git",
"url": "https://github.com/picturepan2/spectre.git"
},
"license": "MIT",
"keywords": [
"css",
"framework",
"flexbox",
"responsive",
"mobile-friendly",
"front-end",
"sass",
"modern"
],
"bugs": {
"url": "https://github.com/picturepan2/spectre/issues"
},
"devDependencies": {
"gulp": "^3.9.1",
"gulp-autoprefixer": "latest",
"gulp-clean-css": "^3.9.4",
"gulp-csscomb": "^3.0.8",
"gulp-rename": "^1.2.2",
"gulp-sass": "^4.0.1"
},
"browserslist": [
"last 4 Chrome versions",
"Edge >= 12",
"Firefox ESR",
"last 4 Safari versions",
"last 4 Opera versions",
"Explorer >= 10"
],
"dependencies": {
"gulp-sourcemaps": "^2.6.4"
}
}
+35 -271
View File
@@ -1,15 +1,15 @@
<?php
namespace Grav\Plugin;
use Grav\Common\Cache;
use Grav\Common\Plugin;
use Grav\Common\Uri;
use Grav\Plugin\Problems\Base\ProblemChecker;
class ProblemsPlugin extends Plugin
{
protected $results = array();
protected $check;
protected $checker;
protected $problems = [];
/**
* @return array
@@ -25,12 +25,11 @@ class ProblemsPlugin extends Plugin
public function onFatalException()
{
if ($this->isAdmin()) {
$this->active = false;
return;
}
// Run through potential issues
if ($this->problemChecker()) {
if ($this->problemsFound()) {
$this->renderProblems();
}
}
@@ -38,295 +37,60 @@ class ProblemsPlugin extends Plugin
public function onPluginsInitialized()
{
if ($this->isAdmin()) {
$this->active = false;
return;
}
/** @var Cache $cache */
$cache = $this->grav['cache'];
$validated_prefix = 'problem-check-';
require __DIR__ . '/vendor/autoload.php';
$this->checker = new ProblemChecker();
$this->check = CACHE_DIR . $validated_prefix . $cache->getKey();
if (!file_exists($this->check)) {
if (!$this->checker->statusFileExists()) {
// If no issues remain, save a state file in the cache
if (!$this->problemChecker()) {
if (!$this->problemsFound()) {
// delete any existing validated files
foreach (new \GlobIterator(CACHE_DIR . $validated_prefix . '*') as $fileInfo) {
foreach (new \GlobIterator(CACHE_DIR . ProblemChecker::PROBLEMS_PREFIX . '*') as $fileInfo) {
@unlink($fileInfo->getPathname());
}
// create a file in the cache dir so it only runs on cache changes
touch($this->check);
$this->checker->storeStatusFile();
} else {
$this->renderProblems();
}
}
}
protected function renderProblems()
private function renderProblems()
{
$theme = 'antimatter';
/** @var Uri $uri */
$uri = $this->grav['uri'];
$baseUrlRelative = $uri->rootUrl(false);
$themeUrl = $baseUrlRelative . '/' . USER_PATH . basename(THEMES_DIR) . '/' . $theme;
$problemsUrl = $baseUrlRelative . '/user/plugins/problems';
$html = file_get_contents(__DIR__ . '/html/problems.html');
/** @var \Twig_Environment $twig */
$twig = $this->getTwig();
/**
* Process the results, ignore the statuses passed as $ignore_status
*
* @param $results
* @param $ignore_status
*/
$processResults = function ($results, $ignore_status) {
$problems = '';
foreach ($results as $key => $result) {
if ($key == 'files' || $key == 'apache' || $key == 'execute') {
foreach ($result as $key_text => $value_text) {
foreach ($value_text as $status => $text) {
if ($status == $ignore_status) continue;
$problems .= $this->getListRow($status, '<b>' . $key_text . '</b> ' . $text);
}
}
} else {
foreach ($result as $status => $text) {
if ($status == $ignore_status) continue;
$problems .= $this->getListRow($status, $text);
}
}
}
return $problems;
};
// First render the errors
$problems = $processResults($this->results, 'success');
// Then render the successful checks
$problems .= $processResults($this->results, 'error');
$html = str_replace('%%BASE_URL%%', $baseUrlRelative, $html);
$html = str_replace('%%THEME_URL%%', $themeUrl, $html);
$html = str_replace('%%PROBLEMS_URL%%', $problemsUrl, $html);
$html = str_replace('%%PROBLEMS%%', $problems, $html);
echo $html;
http_response_code(500);
exit();
}
protected function getListRow($status, $text)
{
if ($status == 'error') {
$icon = 'fa-times';
} elseif ($status == 'info') {
$icon = 'fa-info';
} else {
$icon = 'fa-check';
}
$output = "\n";
$output .= '<li class="' . $status . ' clearfix"><i class="fa fa-fw '. $icon . '"></i><p>'. $text . '</p></li>';
return $output;
}
protected function problemChecker()
{
$min_php_version = defined('GRAV_PHP_MIN') ? GRAV_PHP_MIN : '5.4.0';
$problems_found = false;
$essential_files = [
'cache' => true,
'logs' => true,
'images' => true,
'assets' => true,
'system' => false,
'user/data' => true,
'user/pages' => false,
'user/config' => false,
'user/plugins/error' => false,
'user/plugins' => false,
'user/themes' => false,
'vendor' => false
$data = [
'problems' => $this->problems,
'base_url' => $baseUrlRelative = $uri->rootUrl(false),
'problems_url' => $baseUrlRelative . '/user/plugins/problems',
];
if (version_compare(GRAV_VERSION, '0.9.27', ">=")) {
$essential_files['backup'] = true;
$backup_folder = ROOT_DIR . 'backup';
// try to create backup folder if missing
if (!file_exists($backup_folder)) {
@mkdir($backup_folder, 0770);
}
}
echo $twig->render('problems.html.twig', $data);
http_response_code(500);
exit();
}
if (version_compare(GRAV_VERSION, '1.1.4', ">=")) {
$essential_files['tmp'] = true;
$tmp_folder = ROOT_DIR . 'tmp';
// try to create tmp folder if missing
if (!file_exists($tmp_folder)) {
@mkdir($tmp_folder, 0770);
}
}
private function problemsFound()
{
$status = $this->checker->check(__DIR__ . '/classes/Problems');
$this->problems = $this->checker->getProblems();
return $status;
}
// Perform some Apache checks
if (strpos(php_sapi_name(), 'apache') !== false) {
private function getTwig()
{
$loader = new \Twig_Loader_Filesystem(__DIR__ . '/templates');
$twig = new \Twig_Environment($loader, ['debug' => true]);
$twig->addExtension(New \Twig_Extension_Debug());
$require_apache_modules = ['mod_rewrite'];
$apache_modules = apache_get_modules();
$apache_status = [];
foreach ($require_apache_modules as $module) {
if (in_array($module, $apache_modules)) {
$apache_module_adjective = ' Apache module is enabled';
$apache_module_status = 'success';
} else {
$problems_found = true;
$apache_module_adjective = ' Apache module is not installed or enabled';
$apache_module_status = 'error';
}
$apache_status[$module] = [$apache_module_status => $apache_module_adjective];
}
if (sizeof($apache_status) > 0) {
$this->results['apache'] = $apache_status;
}
}
// Check PHP version
if (version_compare(phpversion(), $min_php_version, '<')) {
$problems_found = true;
$php_version_adjective = 'lower';
$php_version_status = 'error';
} else {
$php_version_adjective = 'greater';
$php_version_status = 'success';
}
$this->results['php'] = [$php_version_status => 'Your PHP version (' . phpversion() . ') is '. $php_version_adjective . ' than the minimum required: <b>' . $min_php_version . '</b> - <a href="http://getgrav.org/blog/changing-php-requirements-to-5.5">Additional Information</a>'];
// Check for GD library
if (defined('GD_VERSION') && function_exists('gd_info')) {
$gd_adjective = '';
$gd_status = 'success';
} else {
$problems_found = true;
$gd_adjective = 'not ';
$gd_status = 'error';
}
$this->results['gd'] = [$gd_status => 'PHP GD (Image Manipulation Library) is '. $gd_adjective . 'installed'];
// Check for PHP CURL library
if (function_exists('curl_version')) {
$curl_adjective = '';
$curl_status = 'success';
} else {
$problems_found = true;
$curl_adjective = 'not ';
$curl_status = 'error';
}
$this->results['curl'] = [$curl_status => 'PHP Curl (Data Transfer Library) is '. $curl_adjective . 'installed'];
// Check for PHP Open SSL library
if (extension_loaded('openssl') && defined('OPENSSL_VERSION_TEXT')) {
$ssl_adjective = '';
$ssl_status = 'success';
} else {
$problems_found = true;
$ssl_adjective = 'not ';
$ssl_status = 'error';
}
$this->results['ssl'] = [$ssl_status => 'PHP OpenSSL (Secure Sockets Library) is '. $ssl_adjective . 'installed'];
// Check for PHP XML library
if (extension_loaded('xml')) {
$xml_adjective = '';
$xml_status = 'success';
} else {
$problems_found = true;
$xml_adjective = 'not ';
$xml_status = 'error';
}
$this->results['xml'] = [$xml_status => 'PHP XML Library is '. $xml_adjective . 'installed'];
// Check for PHP MbString library
if (extension_loaded('mbstring')) {
$mbstring_adjective = '';
$mbstring_status = 'success';
} else {
$problems_found = true;
$mbstring_adjective = 'not ';
$mbstring_status = 'error';
}
$this->results['mbstring'] = [$mbstring_status => 'PHP Mbstring (Multibyte String Library) is '. $mbstring_adjective . 'installed'];
// Check Exif if enabled
if ($this->grav['config']->get('system.media.auto_metadata_exif')) {
if(extension_loaded('exif')) {
$exif_adjective = '';
$exif_status = 'success';
} else {
$problems_found = true;
$exif_adjective = 'not ';
$exif_status = 'error';
}
$this->results['exif'] = [$exif_status => 'PHP Exif (Exchangeable Image File Format) is '. $exif_adjective . 'installed'];
}
// Check for PHP Zip library
if (extension_loaded('zip')) {
$zip_adjective = '';
$zip_status = 'success';
} else {
$problems_found = true;
$zip_adjective = 'not ';
$zip_status = 'error';
}
$this->results['zip'] = [$zip_status => 'PHP Zip extension is '. $zip_adjective . 'installed'];
// Check for essential files & perms
$file_problems = [];
foreach ($essential_files as $file => $check_writable) {
$file_path = ROOT_DIR . $file;
$is_dir = false;
if (!file_exists($file_path)) {
$problems_found = true;
$file_status = 'error';
$file_adjective = 'does not exist';
} else {
$file_status = 'success';
$file_adjective = 'exists';
$is_writeable = is_writable($file_path);
$is_dir = is_dir($file_path);
if ($check_writable) {
if (!$is_writeable) {
$file_status = 'error';
$problems_found = true;
$file_adjective .= ' but is <b class="underline">not writeable</b>';
} else {
$file_adjective .= ' and <b class="underline">is writeable</b>';
}
}
}
$file_problems[$file_path] = [$file_status => $file_adjective];
}
if (sizeof($file_problems) > 0) {
$this->results['files'] = $file_problems;
}
return $problems_found;
return $twig;
}
}
@@ -0,0 +1,38 @@
// Accordions
.accordion {
input:checked ~,
&[open] {
& .accordion-header {
.icon {
transform: rotate(90deg);
}
}
& .accordion-body {
max-height: 50rem;
}
}
.accordion-header {
display: block;
padding: $unit-1 $unit-2;
.icon {
transition: all .2s ease;
}
}
.accordion-body {
margin-bottom: $layout-spacing;
max-height: 0;
overflow: hidden;
transition: max-height .2s ease;
}
}
// Remove default details marker in Webkit
summary.accordion-header {
&::-webkit-details-marker {
display: none;
}
}
@@ -0,0 +1,20 @@
// Animations
@keyframes loading {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
@keyframes slide-down {
0% {
opacity: 0;
transform: translateY(-$unit-8);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
+38
View File
@@ -0,0 +1,38 @@
// Optimized for East Asian CJK
:lang(zh),
:lang(zh-Hans) {
font-family: $cjk-zh-hans-font-family;
}
:lang(zh-Hant) {
font-family: $cjk-zh-hant-font-family;
}
:lang(ja) {
font-family: $cjk-jp-font-family;
}
:lang(ko) {
font-family: $cjk-ko-font-family;
}
:lang(zh),
:lang(ja),
.cjk {
ins,
u {
border-bottom: $border-width solid;
text-decoration: none;
}
del + del,
del + s,
ins + ins,
ins + u,
s + del,
s + s,
u + ins,
u + u {
margin-left: .125em;
}
}
@@ -0,0 +1,47 @@
// Autocomplete
.form-autocomplete {
position: relative;
.form-autocomplete-input {
align-content: flex-start;
display: flex;
flex-wrap: wrap;
height: auto;
min-height: $unit-8;
padding: $unit-h;
&.is-focused {
@include control-shadow();
border-color: $primary-color;
}
.form-input {
border-color: transparent;
box-shadow: none;
display: inline-block;
flex: 1 0 auto;
height: $unit-6;
line-height: $unit-4;
margin: $unit-h;
width: auto;
}
}
.menu {
left: 0;
position: absolute;
top: 100%;
width: 100%;
}
&.autocomplete-oneline {
.form-autocomplete-input {
flex-wrap: nowrap;
overflow-x: auto;
}
.chip {
flex: 1 0 auto;
}
}
}
+77
View File
@@ -0,0 +1,77 @@
// Avatars
.avatar {
@include avatar-base();
background: $primary-color;
border-radius: 50%;
color: rgba($light-color, .85);
display: inline-block;
font-weight: 300;
line-height: 1.25;
margin: 0;
position: relative;
vertical-align: middle;
&.avatar-xs {
@include avatar-base($unit-4);
}
&.avatar-sm {
@include avatar-base($unit-6);
}
&.avatar-lg {
@include avatar-base($unit-12);
}
&.avatar-xl {
@include avatar-base($unit-16);
}
img {
border-radius: 50%;
height: 100%;
position: relative;
width: 100%;
z-index: $zindex-0;
}
.avatar-icon,
.avatar-presence {
background: $bg-color-light;
bottom: 14.64%;
height: 50%;
padding: $border-width-lg;
position: absolute;
right: 14.64%;
transform: translate(50%, 50%);
width: 50%;
z-index: $zindex-0 + 1;
}
.avatar-presence {
background: $gray-color;
box-shadow: 0 0 0 $border-width-lg $light-color;
border-radius: 50%;
height: .5em;
width: .5em;
&.online {
background: $success-color;
}
&.busy {
background: $error-color;
}
&.away {
background: $warning-color;
}
}
&[data-initial]::before {
color: currentColor;
content: attr(data-initial);
left: 50%;
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
z-index: $zindex-0;
}
}
+60
View File
@@ -0,0 +1,60 @@
// Badges
.badge {
position: relative;
white-space: nowrap;
&[data-badge],
&:not([data-badge]) {
&::after {
background: $primary-color;
background-clip: padding-box;
border-radius: .5rem;
box-shadow: 0 0 0 .1rem $bg-color-light;
color: $light-color;
content: attr(data-badge);
display: inline-block;
transform: translate(-.05rem, -.5rem);
}
}
&[data-badge] {
&::after {
font-size: $font-size-sm;
height: .9rem;
line-height: 1;
min-width: .9rem;
padding: .1rem .2rem;
text-align: center;
white-space: nowrap;
}
}
&:not([data-badge]),
&[data-badge=""] {
&::after {
height: 6px;
min-width: 6px;
padding: 0;
width: 6px;
}
}
// Badges for Buttons
&.btn {
&::after {
position: absolute;
top: 0;
right: 0;
transform: translate(50%, -50%);
}
}
// Badges for Avatars
&.avatar {
&::after {
position: absolute;
top: 14.64%;
right: 14.64%;
transform: translate(50%, -50%);
z-index: $zindex-1;
}
}
}
+71
View File
@@ -0,0 +1,71 @@
// Bars
.bar {
background: $bg-color-dark;
border-radius: $border-radius;
display: flex;
flex-wrap: nowrap;
height: $unit-4;
width: 100%;
&.bar-sm {
height: $unit-1;
}
// TODO: attr() support
.bar-item {
background: $primary-color;
color: $light-color;
display: block;
font-size: $font-size-sm;
flex-shrink: 0;
line-height: $unit-4;
height: 100%;
position: relative;
text-align: center;
width: 0;
&:first-child {
border-bottom-left-radius: $border-radius;
border-top-left-radius: $border-radius;
}
&:last-child {
border-bottom-right-radius: $border-radius;
border-top-right-radius: $border-radius;
flex-shrink: 1;
}
}
}
// Slider bar
.bar-slider {
height: $border-width-lg;
margin: $layout-spacing 0;
position: relative;
.bar-item {
left: 0;
padding: 0;
position: absolute;
&:not(:last-child):first-child {
background: $bg-color-dark;
z-index: $zindex-0;
}
}
.bar-slider-btn {
background: $primary-color;
border: 0;
border-radius: 50%;
height: $unit-3;
padding: 0;
position: absolute;
right: 0;
top: 50%;
transform: translate(50%, -50%);
width: $unit-3;
&:active {
box-shadow: 0 0 0 .1rem $primary-color;
}
}
}
+44
View File
@@ -0,0 +1,44 @@
// Base
*,
*::before,
*::after {
box-sizing: inherit;
}
html {
box-sizing: border-box;
font-size: $html-font-size;
line-height: $html-line-height;
-webkit-tap-highlight-color: transparent;
}
body {
background: $body-bg;
color: $body-font-color;
font-family: $body-font-family;
font-size: $font-size;
overflow-x: hidden;
text-rendering: optimizeLegibility;
}
a {
color: $link-color;
outline: none;
text-decoration: none;
&:focus {
@include control-shadow();
}
&:focus,
&:hover,
&:active,
&.active {
color: $link-color-dark;
text-decoration: underline;
}
&:visited {
color: $link-color-light;
}
}
@@ -0,0 +1,29 @@
// Breadcrumbs
.breadcrumb {
list-style: none;
margin: $unit-1 0;
padding: $unit-1 0;
.breadcrumb-item {
color: $gray-color-dark;
display: inline-block;
margin: 0;
padding: $unit-1 0;
&:not(:last-child) {
margin-right: $unit-1;
a {
color: $gray-color-dark;
}
}
&:not(:first-child) {
&::before {
color: $gray-color-light;
content: "/";
padding-right: $unit-2;
}
}
}
}
+195
View File
@@ -0,0 +1,195 @@
// Buttons
.btn {
@include control-transition();
appearance: none;
background: $bg-color-light;
border: $border-width solid $primary-color;
border-radius: $border-radius;
color: $primary-color;
cursor: pointer;
display: inline-block;
font-size: $font-size;
height: $control-size;
line-height: $line-height;
outline: none;
padding: $control-padding-y $control-padding-x;
text-align: center;
text-decoration: none;
user-select: none;
vertical-align: middle;
white-space: nowrap;
&:focus {
@include control-shadow();
}
&:focus,
&:hover {
background: $secondary-color;
border-color: $primary-color-dark;
text-decoration: none;
}
&:active,
&.active {
background: $primary-color-dark;
border-color: darken($primary-color-dark, 5%);
color: $light-color;
text-decoration: none;
&.loading {
&::after {
border-bottom-color: $light-color;
border-left-color: $light-color;
}
}
}
&[disabled],
&:disabled,
&.disabled {
cursor: default;
opacity: .5;
pointer-events: none;
}
// Button Primary
&.btn-primary {
background: $primary-color;
border-color: $primary-color-dark;
color: $light-color;
&:focus,
&:hover {
background: darken($primary-color-dark, 2%);
border-color: darken($primary-color-dark, 5%);
color: $light-color;
}
&:active,
&.active {
background: darken($primary-color-dark, 4%);
border-color: darken($primary-color-dark, 7%);
color: $light-color;
}
&.loading {
&::after {
border-bottom-color: $light-color;
border-left-color: $light-color;
}
}
}
// Button Colors
&.btn-success {
@include button-variant($success-color);
}
&.btn-error {
@include button-variant($error-color);
}
&.btn-warning {
@include button-variant($warning-color);
}
// Button Link
&.btn-link {
background: transparent;
border-color: transparent;
color: $link-color;
&:focus,
&:hover,
&:active,
&.active {
color: $link-color-dark;
}
}
// Button Sizes
&.btn-sm {
font-size: $font-size-sm;
height: $control-size-sm;
padding: $control-padding-y-sm $control-padding-x-sm;
}
&.btn-lg {
font-size: $font-size-lg;
height: $control-size-lg;
padding: $control-padding-y-lg $control-padding-x-lg;
}
// Button Block
&.btn-block {
display: block;
width: 100%;
}
// Button Action
&.btn-action {
width: $control-size;
padding-left: 0;
padding-right: 0;
&.btn-sm {
width: $control-size-sm;
}
&.btn-lg {
width: $control-size-lg;
}
}
// Button Clear
&.btn-clear {
background: transparent;
border: 0;
color: currentColor;
height: $unit-4;
line-height: $unit-4;
margin-left: $unit-1;
margin-right: -2px;
opacity: 1;
padding: 0;
text-decoration: none;
width: $unit-4;
&:hover {
opacity: .95;
}
&::before {
content: "\2715";
}
}
}
// Button groups
.btn-group {
display: inline-flex;
flex-wrap: wrap;
.btn {
flex: 1 0 auto;
&:first-child:not(:last-child) {
border-bottom-right-radius: 0;
border-top-right-radius: 0;
}
&:not(:first-child):not(:last-child) {
border-radius: 0;
margin-left: -$border-width;
}
&:last-child:not(:first-child) {
border-bottom-left-radius: 0;
border-top-left-radius: 0;
margin-left: -$border-width;
}
&:focus,
&:hover,
&:active,
&.active {
z-index: $zindex-0;
}
}
&.btn-group-block {
display: flex;
.btn {
flex: 1 0 0;
}
}
}
+222
View File
@@ -0,0 +1,222 @@
// Calendars
.calendar {
border: $border-width solid $border-color;
border-radius: $border-radius;
display: block;
min-width: 280px;
.calendar-nav {
align-items: center;
background: $bg-color;
border-top-left-radius: $border-radius;
border-top-right-radius: $border-radius;
display: flex;
font-size: $font-size-lg;
padding: $layout-spacing;
}
.calendar-header,
.calendar-body {
display: flex;
flex-wrap: wrap;
justify-content: center;
padding: $layout-spacing 0;
.calendar-date {
flex: 0 0 14.28%; // 7 calendar-items each row
max-width: 14.28%;
}
}
.calendar-header {
background: $bg-color;
border-bottom: $border-width solid $border-color;
color: $gray-color;
font-size: $font-size-sm;
text-align: center;
}
.calendar-body {
color: $gray-color-dark;
}
.calendar-date {
border: 0;
padding: $unit-1;
.date-item {
@include control-transition();
appearance: none;
background: transparent;
border: $border-width solid transparent;
border-radius: 50%;
color: $gray-color-dark;
cursor: pointer;
font-size: $font-size-sm;
height: $unit-7;
line-height: $unit-5;
outline: none;
padding: $unit-h;
position: relative;
text-align: center;
text-decoration: none;
vertical-align: middle;
white-space: nowrap;
width: $unit-7;
&.date-today {
border-color: $secondary-color-dark;
color: $primary-color;
}
&:focus {
@include control-shadow();
}
&:focus,
&:hover {
background: $secondary-color-light;
border-color: $secondary-color-dark;
color: $primary-color;
text-decoration: none;
}
&:active,
&.active {
background: $primary-color-dark;
border-color: darken($primary-color-dark, 5%);
color: $light-color;
}
// Calendar badge support
&.badge {
&::after {
position: absolute;
top: 3px;
right: 3px;
transform: translate(50%, -50%);
}
}
}
.date-item,
.calendar-event {
&:disabled,
&.disabled {
cursor: default;
opacity: .25;
pointer-events: none;
}
}
&.prev-month,
&.next-month {
.date-item,
.calendar-event {
opacity: .25;
}
}
}
.calendar-range {
position: relative;
&::before {
background: $secondary-color;
content: "";
height: $unit-7;
left: 0;
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
}
&.range-start {
&::before {
left: 50%;
}
}
&.range-end {
&::before {
right: 50%;
}
}
&.range-start,
&.range-end {
.date-item {
background: $primary-color-dark;
border-color: darken($primary-color-dark, 5%);
color: $light-color;
}
}
.date-item {
color: $primary-color;
}
}
// Calendars size
&.calendar-lg {
.calendar-body {
padding: 0;
.calendar-date {
border-bottom: $border-width solid $border-color;
border-right: $border-width solid $border-color;
display: flex;
flex-direction: column;
height: 5.5rem;
padding: 0;
&:nth-child(7n) {
border-right: 0;
}
&:nth-last-child(-n+7) {
border-bottom: 0;
}
}
}
.date-item {
align-self: flex-end;
height: $unit-7;
margin-right: $layout-spacing-sm;
margin-top: $layout-spacing-sm;
}
.calendar-range {
&::before {
top: 19px;
}
&.range-start {
&::before {
left: auto;
width: 19px;
}
}
&.range-end {
&::before {
right: 19px;
}
}
}
.calendar-events {
flex-grow: 1;
line-height: 1;
overflow-y: auto;
padding: $layout-spacing-sm;
}
.calendar-event {
border-radius: $border-radius;
font-size: $font-size-sm;
display: block;
margin: $unit-h auto;
overflow: hidden;
padding: 3px 4px;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
+43
View File
@@ -0,0 +1,43 @@
// Cards
.card {
background: $bg-color-light;
border: $border-width solid $border-color;
border-radius: $border-radius;
display: flex;
flex-direction: column;
.card-header,
.card-body,
.card-footer {
padding: $layout-spacing-lg;
padding-bottom: 0;
&:last-child {
padding-bottom: $layout-spacing-lg;
}
}
.card-body {
flex: 1 1 auto;
}
.card-image {
padding-top: $layout-spacing-lg;
&:first-child {
padding-top: 0;
img {
border-top-left-radius: $border-radius;
border-top-right-radius: $border-radius;
}
}
&:last-child {
img {
border-bottom-left-radius: $border-radius;
border-bottom-right-radius: $border-radius;
}
}
}
}
+126
View File
@@ -0,0 +1,126 @@
// Carousels
.carousel {
background: $bg-color;
display: block;
overflow: hidden;
position: relative;
width: 100%;
-webkit-overflow-scrolling: touch;
z-index: $zindex-0;
.carousel-container {
height: 100%;
left: 0;
position: relative;
&::before {
content: "";
display: block;
padding-bottom: 56.25%;
}
.carousel-item {
animation: carousel-slideout 1s ease-in-out 1;
height: 100%;
left: 0;
margin: 0;
opacity: 0;
position: absolute;
top: 0;
width: 100%;
&:hover {
.item-prev,
.item-next {
opacity: 1;
}
}
}
.item-prev,
.item-next {
background: rgba($gray-color-light, .25);
border-color: rgba($gray-color-light, .5);
color: $gray-color-light;
opacity: 0;
position: absolute;
top: 50%;
transition: all .4s ease;
transform: translateY(-50%);
z-index: $zindex-1;
}
.item-prev {
left: 1rem;
}
.item-next {
right: 1rem;
}
}
.carousel-locator {
&:nth-of-type(1):checked ~ .carousel-container .carousel-item:nth-of-type(1),
&:nth-of-type(2):checked ~ .carousel-container .carousel-item:nth-of-type(2),
&:nth-of-type(3):checked ~ .carousel-container .carousel-item:nth-of-type(3),
&:nth-of-type(4):checked ~ .carousel-container .carousel-item:nth-of-type(4) {
animation: carousel-slidein .75s ease-in-out 1;
opacity: 1;
z-index: $zindex-1;
}
&:nth-of-type(1):checked ~ .carousel-nav .nav-item:nth-of-type(1),
&:nth-of-type(2):checked ~ .carousel-nav .nav-item:nth-of-type(2),
&:nth-of-type(3):checked ~ .carousel-nav .nav-item:nth-of-type(3),
&:nth-of-type(4):checked ~ .carousel-nav .nav-item:nth-of-type(4) {
color: $gray-color-light;
}
}
.carousel-nav {
bottom: $layout-spacing;
display: flex;
justify-content: center;
left: 50%;
position: absolute;
transform: translateX(-50%);
width: 10rem;
z-index: $zindex-1;
.nav-item {
color: rgba($gray-color-light, .5);
display: block;
flex: 1 0 auto;
height: $unit-8;
margin: $unit-1;
max-width: 2.5rem;
position: relative;
&::before {
background: currentColor;
content: "";
display: block;
height: $unit-h;
position: absolute;
top: .5rem;
width: 100%;
}
}
}
}
@keyframes carousel-slidein {
0% {
transform: translateX(100%);
}
100% {
transform: translateX(0);
}
}
@keyframes carousel-slideout {
0% {
opacity: 1;
transform: translateX(0);
}
100% {
opacity: 1;
transform: translateX(-50%);
}
}
+30
View File
@@ -0,0 +1,30 @@
// Chips
.chip {
align-items: center;
background: $bg-color-dark;
border-radius: 5rem;
color: $gray-color-dark;
display: inline-flex;
font-size: 90%;
height: $unit-6;
line-height: $unit-4;
margin: $unit-h;
max-width: 100%;
padding: $unit-1 $unit-2;
text-decoration: none;
vertical-align: middle;
&.active {
background: $primary-color;
color: $light-color;
}
.avatar {
margin-left: -$unit-2;
margin-right: $unit-1;
}
.btn-clear {
transform: scale(.75);
}
}
+31
View File
@@ -0,0 +1,31 @@
// Codes
code {
@include label-base();
@include label-variant($code-color, lighten($code-color, 42.5%));
font-size: 85%;
}
.code {
border-radius: $border-radius;
color: $body-font-color;
position: relative;
&::before {
color: $gray-color;
content: attr(data-lang);
font-size: $font-size-sm;
position: absolute;
right: $layout-spacing;
top: $unit-h;
}
code {
background: $bg-color;
color: inherit;
display: block;
line-height: 1.5;
overflow-x: auto;
padding: 1rem;
width: 100%;
}
}
@@ -0,0 +1,115 @@
// Image comparison slider
// Credit: http://codepen.io/solipsistacp/pen/Gpmaq
.comparison-slider {
height: 50vh;
overflow: hidden;
position: relative;
width: 100%;
-webkit-overflow-scrolling: touch;
.comparison-before,
.comparison-after {
height: 100%;
left: 0;
margin: 0;
overflow: hidden;
position: absolute;
top: 0;
img {
height: 100%;
object-fit: cover;
object-position: left center;
position: absolute;
width: 100%;
}
}
.comparison-before {
width: 100%;
z-index: 1;
.comparison-label {
right: $unit-4;
}
}
.comparison-after {
max-width: 100%;
min-width: 0;
z-index: 2;
&::before {
background: transparent;
content: "";
cursor: default;
height: 100%;
left: 0;
position: absolute;
right: $unit-4;
top: 0;
z-index: $zindex-0;
}
&::after {
background: currentColor;
border-radius: 50%;
box-shadow: 0 -5px, 0 5px;
color: $light-color;
content: "";
height: 3px;
position: absolute;
right: $unit-2;
top: 50%;
transform: translate(50%, -50%);
width: 3px;
}
.comparison-label {
left: $unit-4;
}
}
.comparison-resizer {
animation: first-run 1.5s 1 ease-in-out;
cursor: ew-resize;
height: $unit-4;
left: 0;
max-width: 100%;
min-width: $unit-4;
opacity: 0;
outline: none;
position: relative;
resize: horizontal;
top: 50%;
transform: translateY(-50%) scaleY(30);
width: 0;
}
.comparison-label {
background: rgba($dark-color, .5);
bottom: $unit-4;
color: $light-color;
padding: $unit-1 $unit-2;
position: absolute;
user-select: none;
}
}
@keyframes first-run {
0% {
width: 0;
}
25% {
width: $unit-12;
}
50% {
width: $unit-4;
}
75% {
width: $unit-6;
}
100% {
width: 0;
}
}
@@ -0,0 +1,36 @@
// Dropdown
.dropdown {
display: inline-block;
position: relative;
.menu {
animation: slide-down .15s ease 1;
display: none;
left: 0;
max-height: 50vh;
overflow-y: auto;
position: absolute;
top: 100%;
}
&.dropdown-right {
.menu {
left: auto;
right: 0;
}
}
&.active .menu,
.dropdown-toggle:focus + .menu,
.menu:hover {
display: block;
}
// Fix dropdown-toggle border radius in button groups
.btn-group {
.dropdown-toggle:nth-last-child(2) {
border-bottom-right-radius: $border-radius;
border-top-right-radius: $border-radius;
}
}
}
+21
View File
@@ -0,0 +1,21 @@
// Empty states (or Blank slates)
.empty {
background: $bg-color;
border-radius: $border-radius;
color: $gray-color-dark;
text-align: center;
padding: $unit-16 $unit-8;
.empty-icon {
margin-bottom: $layout-spacing-lg;
}
.empty-title,
.empty-subtitle {
margin: $layout-spacing auto;
}
.empty-action {
margin-top: $layout-spacing-lg;
}
}
+37
View File
@@ -0,0 +1,37 @@
// Filters
// The number of filter options
$filter-number: 8 !default;
%filter-checked-nav {
background: $primary-color;
color: $light-color;
}
%filter-checked-body {
display: none;
}
.filter {
.filter-nav {
margin: $layout-spacing 0;
}
.filter-body {
display: flex;
flex-wrap: wrap;
}
.filter-tag {
@for $i from 0 through ($filter-number) {
&#tag-#{$i}:checked ~ .filter-nav .chip[for="tag-#{$i}"] {
@extend %filter-checked-nav;
}
}
@for $i from 1 through ($filter-number) {
&#tag-#{$i}:checked ~ .filter-body .filter-item:not([data-tag~="tag-#{$i}"]) {
@extend %filter-checked-body;
}
}
}
}
+545
View File
@@ -0,0 +1,545 @@
// Forms
.form-group {
&:not(:last-child) {
margin-bottom: $layout-spacing;
}
}
fieldset {
margin-bottom: $layout-spacing-lg;
}
legend {
font-size: $font-size-lg;
font-weight: 500;
margin-bottom: $layout-spacing-lg;
}
// Form element: Label
.form-label {
display: block;
line-height: $line-height;
padding: $control-padding-y + $border-width 0;
&.label-sm {
font-size: $font-size-sm;
padding: $control-padding-y-sm + $border-width 0;
}
&.label-lg {
font-size: $font-size-lg;
padding: $control-padding-y-lg + $border-width 0;
}
}
// Form element: Input
.form-input {
@include control-transition();
appearance: none;
background: $bg-color-light;
background-image: none;
border: $border-width solid $border-color-dark;
border-radius: $border-radius;
color: $body-font-color;
display: block;
font-size: $font-size;
height: $control-size;
line-height: $line-height;
max-width: 100%;
outline: none;
padding: $control-padding-y $control-padding-x;
position: relative;
width: 100%;
&:focus {
@include control-shadow();
border-color: $primary-color;
}
&::placeholder {
color: $gray-color;
}
// Input sizes
&.input-sm {
font-size: $font-size-sm;
height: $control-size-sm;
padding: $control-padding-y-sm $control-padding-x-sm;
}
&.input-lg {
font-size: $font-size-lg;
height: $control-size-lg;
padding: $control-padding-y-lg $control-padding-x-lg;
}
&.input-inline {
display: inline-block;
vertical-align: middle;
width: auto;
}
// Input types
&[type="file"] {
height: auto;
}
}
// Form element: Textarea
textarea.form-input {
height: auto;
}
// Form element: Input hint
.form-input-hint {
color: $gray-color;
font-size: $font-size-sm;
margin-top: $unit-1;
.has-success &,
.is-success + & {
color: $success-color;
}
.has-error &,
.is-error + & {
color: $error-color;
}
}
// Form element: Select
.form-select {
appearance: none;
border: $border-width solid $border-color-dark;
border-radius: $border-radius;
color: inherit;
font-size: $font-size;
height: $control-size;
line-height: $line-height;
outline: none;
padding: $control-padding-y $control-padding-x;
vertical-align: middle;
width: 100%;
&[size],
&[multiple] {
height: auto;
option {
padding: $unit-h $unit-1;
}
}
&:not([multiple]):not([size]) {
background: #fff url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%204%205'%3E%3Cpath%20fill='%23667189'%20d='M2%200L0%202h4zm0%205L0%203h4z'/%3E%3C/svg%3E") no-repeat right .35rem center/.4rem .5rem;
padding-right: $control-icon-size + $control-padding-x;
}
&:focus {
@include control-shadow();
border-color: $primary-color;
}
&::-ms-expand {
display: none;
}
// Select sizes
&.select-sm {
font-size: $font-size-sm;
height: $control-size-sm;
padding: $control-padding-y-sm ($control-icon-size + $control-padding-x-sm) $control-padding-y-sm $control-padding-x-sm;
}
&.select-lg {
font-size: $font-size-lg;
height: $control-size-lg;
padding: $control-padding-y-lg ($control-icon-size + $control-padding-x-lg) $control-padding-y-lg $control-padding-x-lg;
}
}
// Form Icons
.has-icon-left,
.has-icon-right {
position: relative;
.form-icon {
height: $control-icon-size;
margin: 0 $control-padding-y;
position: absolute;
top: 50%;
transform: translateY(-50%);
width: $control-icon-size;
z-index: $zindex-0 + 1;
}
}
.has-icon-left {
.form-icon {
left: $border-width;
}
.form-input {
padding-left: $control-icon-size + $control-padding-y * 2;
}
}
.has-icon-right {
.form-icon {
right: $border-width;
}
.form-input {
padding-right: $control-icon-size + $control-padding-y * 2;
}
}
// Form element: Checkbox and Radio
.form-checkbox,
.form-radio,
.form-switch {
display: block;
line-height: $line-height;
margin: ($control-size - $control-size-sm) / 2 0;
min-height: 1.2rem;
padding: (($control-size-sm - $line-height) / 2) $control-padding-x (($control-size-sm - $line-height) / 2) ($control-icon-size + $control-padding-x);
position: relative;
input {
clip: rect(0, 0, 0, 0);
height: 1px;
margin: -1px;
overflow: hidden;
position: absolute;
width: 1px;
&:focus + .form-icon {
@include control-shadow();
border-color: $primary-color;
}
&:checked + .form-icon {
background: $primary-color;
border-color: $primary-color;
}
}
.form-icon {
@include control-transition();
border: $border-width solid $border-color-dark;
cursor: pointer;
display: inline-block;
position: absolute;
}
// Input checkbox, radio and switch sizes
&.input-sm {
font-size: $font-size-sm;
margin: 0;
}
&.input-lg {
font-size: $font-size-lg;
margin: ($control-size-lg - $control-size-sm) / 2 0;
}
}
.form-checkbox,
.form-radio {
.form-icon {
background: $bg-color-light;
height: $control-icon-size;
left: 0;
top: ($control-size-sm - $control-icon-size) / 2;
width: $control-icon-size;
}
input {
&:active + .form-icon {
background: $bg-color-dark;
}
}
}
.form-checkbox {
.form-icon {
border-radius: $border-radius;
}
input {
&:checked + .form-icon {
&::before {
background-clip: padding-box;
border: $border-width-lg solid $light-color;
border-left-width: 0;
border-top-width: 0;
content: "";
height: 12px;
left: 50%;
margin-left: -4px;
margin-top: -8px;
position: absolute;
top: 50%;
transform: rotate(45deg);
width: 8px;
}
}
&:indeterminate + .form-icon {
background: $primary-color;
border-color: $primary-color;
&::before {
background: $bg-color-light;
content: "";
height: 2px;
left: 50%;
margin-left: -5px;
margin-top: -1px;
position: absolute;
top: 50%;
width: 10px;
}
}
}
}
.form-radio {
.form-icon {
border-radius: 50%;
}
input {
&:checked + .form-icon {
&::before {
background: $bg-color-light;
border-radius: 50%;
content: "";
height: 4px;
left: 50%;
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
width: 4px;
}
}
}
}
// Form element: Switch
.form-switch {
padding-left: ($unit-8 + $control-padding-x);
.form-icon {
background: $gray-color-light;
background-clip: padding-box;
border-radius: $unit-2 + $border-width;
height: $unit-4 + $border-width * 2;
left: 0;
top: ($control-size-sm - $unit-4) / 2 - $border-width;
width: $unit-8;
&::before {
@include control-transition();
background: $bg-color-light;
border-radius: 50%;
content: "";
display: block;
height: $unit-4;
left: 0;
position: absolute;
top: 0;
width: $unit-4;
}
}
input {
&:checked + .form-icon {
&::before {
left: 14px;
}
}
&:active + .form-icon {
&::before {
background: $bg-color;
}
}
}
}
// Form element: Input groups
.input-group {
display: flex;
.input-group-addon {
background: $bg-color;
border: $border-width solid $border-color-dark;
border-radius: $border-radius;
line-height: $line-height;
padding: $control-padding-y $control-padding-x;
white-space: nowrap;
&.addon-sm {
font-size: $font-size-sm;
padding: $control-padding-y-sm $control-padding-x-sm;
}
&.addon-lg {
font-size: $font-size-lg;
padding: $control-padding-y-lg $control-padding-x-lg;
}
}
.form-input,
.form-select {
flex: 1 1 auto;
width: 1%;
}
.input-group-btn {
z-index: $zindex-0;
}
.form-input,
.form-select,
.input-group-addon,
.input-group-btn {
&:first-child:not(:last-child) {
border-bottom-right-radius: 0;
border-top-right-radius: 0;
}
&:not(:first-child):not(:last-child) {
border-radius: 0;
margin-left: -$border-width;
}
&:last-child:not(:first-child) {
border-bottom-left-radius: 0;
border-top-left-radius: 0;
margin-left: -$border-width;
}
&:focus {
z-index: $zindex-0 + 1;
}
}
.form-select {
width: auto;
}
&.input-inline {
display: inline-flex;
}
}
// Form validation states
.form-input,
.form-select {
.has-success &,
&.is-success {
border-color: $success-color;
&:focus {
@include control-shadow($success-color);
}
}
.has-error &,
&.is-error {
border-color: $error-color;
&:focus {
@include control-shadow($error-color);
}
}
}
.form-checkbox,
.form-radio,
.form-switch {
.has-error &,
&.is-error {
.form-icon {
border-color: $error-color;
}
input {
&:checked + .form-icon {
background: $error-color;
border-color: $error-color;
}
&:focus + .form-icon {
@include control-shadow($error-color);
border-color: $error-color;
}
}
}
}
.form-checkbox {
.has-error &,
&.is-error {
input {
&:indeterminate + .form-icon {
background: $error-color;
border-color: $error-color;
}
}
}
}
// validation based on :placeholder-shown (Edge doesn't support it yet)
.form-input {
&:not(:placeholder-shown) {
&:invalid {
border-color: $error-color;
&:focus {
@include control-shadow($error-color);
}
& + .form-input-hint {
color: $error-color;
}
}
}
}
// Form disabled and readonly
.form-input,
.form-select {
&:disabled,
&.disabled {
background-color: $bg-color-dark;
cursor: not-allowed;
opacity: .5;
}
}
.form-input {
&[readonly] {
background-color: $bg-color;
}
}
input {
&:disabled,
&.disabled {
& + .form-icon {
background: $bg-color-dark;
cursor: not-allowed;
opacity: .5;
}
}
}
.form-switch {
input {
&:disabled,
&.disabled {
& + .form-icon::before {
background: $bg-color-light;
}
}
}
}
// Form horizontal
.form-horizontal {
padding: $layout-spacing 0;
.form-group {
display: flex;
flex-wrap: wrap;
}
}
// Form inline
.form-inline {
display: inline-block;
}
+5
View File
@@ -0,0 +1,5 @@
// CSS Icons
@import "icons/icons-core";
@import "icons/icons-navigation";
@import "icons/icons-action";
@import "icons/icons-object";
+34
View File
@@ -0,0 +1,34 @@
// Labels
.label {
@include label-base();
@include label-variant(lighten($body-font-color, 5%), $bg-color-dark);
display: inline-block;
// Label rounded
&.label-rounded {
border-radius: 5rem;
padding-left: .4rem;
padding-right: .4rem;
}
// Label colors
&.label-primary {
@include label-variant($light-color, $primary-color);
}
&.label-secondary {
@include label-variant($primary-color, $secondary-color);
}
&.label-success {
@include label-variant($light-color, $success-color);
}
&.label-warning {
@include label-variant($light-color, $warning-color);
}
&.label-error {
@include label-variant($light-color, $error-color);
}
}
+424
View File
@@ -0,0 +1,424 @@
// Layout
.container {
margin-left: auto;
margin-right: auto;
padding-left: $layout-spacing;
padding-right: $layout-spacing;
width: 100%;
@extend .clearfix;
$grid-spacing: ($layout-spacing / ($layout-spacing * 0 + 1)) * $html-font-size;
&.grid-xl {
max-width: $grid-spacing * 2 + $size-xl;
}
&.grid-lg {
max-width: $grid-spacing * 2 + $size-lg;
}
&.grid-md {
max-width: $grid-spacing * 2 + $size-md;
}
&.grid-sm {
max-width: $grid-spacing * 2 + $size-sm;
}
&.grid-xs {
max-width: $grid-spacing * 2 + $size-xs;
}
}
// Responsive breakpoint system
.show-xs,
.show-sm,
.show-md,
.show-lg,
.show-xl {
display: none !important;
}
// Responsive grid system
.columns {
display: flex;
flex-wrap: wrap;
margin-left: -$layout-spacing;
margin-right: -$layout-spacing;
&.col-gapless {
margin-left: 0;
margin-right: 0;
& > .column {
padding-left: 0;
padding-right: 0;
}
}
&.col-oneline {
flex-wrap: nowrap;
overflow-x: auto;
}
}
.column {
flex: 1;
max-width: 100%;
padding-left: $layout-spacing;
padding-right: $layout-spacing;
&.col-12,
&.col-11,
&.col-10,
&.col-9,
&.col-8,
&.col-7,
&.col-6,
&.col-5,
&.col-4,
&.col-3,
&.col-2,
&.col-1 {
flex: none;
}
}
.col-12 {
width: 100%;
}
.col-11 {
width: 91.66666667%;
}
.col-10 {
width: 83.33333333%;
}
.col-9 {
width: 75%;
}
.col-8 {
width: 66.66666667%;
}
.col-7 {
width: 58.33333333%;
}
.col-6 {
width: 50%;
}
.col-5 {
width: 41.66666667%;
}
.col-4 {
width: 33.33333333%;
}
.col-3 {
width: 25%;
}
.col-2 {
width: 16.66666667%;
}
.col-1 {
width: 8.33333333%;
}
.col-auto {
flex: 0 0 auto;
max-width: none;
width: auto;
}
.col-mx-auto {
margin-left: auto;
margin-right: auto;
}
.col-ml-auto {
margin-left: auto;
}
.col-mr-auto {
margin-right: auto;
}
@media (max-width: $size-xl) {
.col-xl-12,
.col-xl-11,
.col-xl-10,
.col-xl-9,
.col-xl-8,
.col-xl-7,
.col-xl-6,
.col-xl-5,
.col-xl-4,
.col-xl-3,
.col-xl-2,
.col-xl-1 {
flex: none;
}
.col-xl-12 {
width: 100%;
}
.col-xl-11 {
width: 91.66666667%;
}
.col-xl-10 {
width: 83.33333333%;
}
.col-xl-9 {
width: 75%;
}
.col-xl-8 {
width: 66.66666667%;
}
.col-xl-7 {
width: 58.33333333%;
}
.col-xl-6 {
width: 50%;
}
.col-xl-5 {
width: 41.66666667%;
}
.col-xl-4 {
width: 33.33333333%;
}
.col-xl-3 {
width: 25%;
}
.col-xl-2 {
width: 16.66666667%;
}
.col-xl-1 {
width: 8.33333333%;
}
.hide-xl {
display: none !important;
}
.show-xl {
display: block !important;
}
}
@media (max-width: $size-lg) {
.col-lg-12,
.col-lg-11,
.col-lg-10,
.col-lg-9,
.col-lg-8,
.col-lg-7,
.col-lg-6,
.col-lg-5,
.col-lg-4,
.col-lg-3,
.col-lg-2,
.col-lg-1 {
flex: none;
}
.col-lg-12 {
width: 100%;
}
.col-lg-11 {
width: 91.66666667%;
}
.col-lg-10 {
width: 83.33333333%;
}
.col-lg-9 {
width: 75%;
}
.col-lg-8 {
width: 66.66666667%;
}
.col-lg-7 {
width: 58.33333333%;
}
.col-lg-6 {
width: 50%;
}
.col-lg-5 {
width: 41.66666667%;
}
.col-lg-4 {
width: 33.33333333%;
}
.col-lg-3 {
width: 25%;
}
.col-lg-2 {
width: 16.66666667%;
}
.col-lg-1 {
width: 8.33333333%;
}
.hide-lg {
display: none !important;
}
.show-lg {
display: block !important;
}
}
@media (max-width: $size-md) {
.col-md-12,
.col-md-11,
.col-md-10,
.col-md-9,
.col-md-8,
.col-md-7,
.col-md-6,
.col-md-5,
.col-md-4,
.col-md-3,
.col-md-2,
.col-md-1 {
flex: none;
}
.col-md-12 {
width: 100%;
}
.col-md-11 {
width: 91.66666667%;
}
.col-md-10 {
width: 83.33333333%;
}
.col-md-9 {
width: 75%;
}
.col-md-8 {
width: 66.66666667%;
}
.col-md-7 {
width: 58.33333333%;
}
.col-md-6 {
width: 50%;
}
.col-md-5 {
width: 41.66666667%;
}
.col-md-4 {
width: 33.33333333%;
}
.col-md-3 {
width: 25%;
}
.col-md-2 {
width: 16.66666667%;
}
.col-md-1 {
width: 8.33333333%;
}
.hide-md {
display: none !important;
}
.show-md {
display: block !important;
}
}
@media (max-width: $size-sm) {
.col-sm-12,
.col-sm-11,
.col-sm-10,
.col-sm-9,
.col-sm-8,
.col-sm-7,
.col-sm-6,
.col-sm-5,
.col-sm-4,
.col-sm-3,
.col-sm-2,
.col-sm-1 {
flex: none;
}
.col-sm-12 {
width: 100%;
}
.col-sm-11 {
width: 91.66666667%;
}
.col-sm-10 {
width: 83.33333333%;
}
.col-sm-9 {
width: 75%;
}
.col-sm-8 {
width: 66.66666667%;
}
.col-sm-7 {
width: 58.33333333%;
}
.col-sm-6 {
width: 50%;
}
.col-sm-5 {
width: 41.66666667%;
}
.col-sm-4 {
width: 33.33333333%;
}
.col-sm-3 {
width: 25%;
}
.col-sm-2 {
width: 16.66666667%;
}
.col-sm-1 {
width: 8.33333333%;
}
.hide-sm {
display: none !important;
}
.show-sm {
display: block !important;
}
}
@media (max-width: $size-xs) {
.col-xs-12,
.col-xs-11,
.col-xs-10,
.col-xs-9,
.col-xs-8,
.col-xs-7,
.col-xs-6,
.col-xs-5,
.col-xs-4,
.col-xs-3,
.col-xs-2,
.col-xs-1 {
flex: none;
}
.col-xs-12 {
width: 100%;
}
.col-xs-11 {
width: 91.66666667%;
}
.col-xs-10 {
width: 83.33333333%;
}
.col-xs-9 {
width: 75%;
}
.col-xs-8 {
width: 66.66666667%;
}
.col-xs-7 {
width: 58.33333333%;
}
.col-xs-6 {
width: 50%;
}
.col-xs-5 {
width: 41.66666667%;
}
.col-xs-4 {
width: 33.33333333%;
}
.col-xs-3 {
width: 25%;
}
.col-xs-2 {
width: 16.66666667%;
}
.col-xs-1 {
width: 8.33333333%;
}
.hide-xs {
display: none !important;
}
.show-xs {
display: block !important;
}
}
+75
View File
@@ -0,0 +1,75 @@
// Media
// Image responsive
.img-responsive {
display: block;
height: auto;
max-width: 100%;
}
// object-fit support is coming to Microsoft Edge
// https://developer.microsoft.com/en-us/microsoft-edge/platform/status/objectfitandobjectposition/
.img-fit-cover {
object-fit: cover;
}
.img-fit-contain {
object-fit: contain;
}
// Video responsive
.video-responsive {
display: block;
overflow: hidden;
padding: 0;
position: relative;
width: 100%;
&::before {
content: "";
display: block;
padding-bottom: 56.25%; // Default ratio 16:9, you can calculate this value by dividing 9 by 16
}
iframe,
object,
embed {
border: 0;
bottom: 0;
height: 100%;
left: 0;
position: absolute;
right: 0;
top: 0;
width: 100%;
}
}
video.video-responsive {
height: auto;
max-width: 100%;
&::before {
content: none;
}
}
.video-responsive-4-3 {
&::before {
padding-bottom: 75%; // Ratio 4:3
}
}
.video-responsive-1-1 {
&::before {
padding-bottom: 100%; // Ratio 1:1
}
}
// Figure
.figure {
margin: 0 0 $layout-spacing 0;
.figure-caption {
color: $gray-color-dark;
margin-top: $layout-spacing;
}
}
+62
View File
@@ -0,0 +1,62 @@
// Menus
.menu {
@include shadow-variant(.05rem);
background: $bg-color-light;
border-radius: $border-radius;
list-style: none;
margin: 0;
min-width: $control-width-xs;
padding: $unit-2;
transform: translateY($layout-spacing-sm);
z-index: $zindex-3;
&.menu-nav {
background: transparent;
box-shadow: none;
}
.menu-item {
margin-top: 0;
padding: 0 $unit-2;
text-decoration: none;
user-select: none;
& > a {
border-radius: $border-radius;
color: inherit;
display: block;
margin: 0 (-$unit-2);
padding: $unit-1 $unit-2;
text-decoration: none;
&:focus,
&:hover {
background: $secondary-color;
color: $primary-color;
}
&:active,
&.active {
background: $secondary-color;
color: $primary-color;
}
}
.form-checkbox,
.form-radio,
.form-switch {
margin: $unit-h 0;
}
& + .menu-item {
margin-top: $unit-1;
}
}
.menu-badge {
float: right;
padding: $unit-1 0;
.btn {
margin-top: -$unit-h;
}
}
}
+57
View File
@@ -0,0 +1,57 @@
// Meters
// Credit: https://css-tricks.com/html5-meter-element/
.meter {
appearance: none;
background: $bg-color;
border: 0;
border-radius: $border-radius;
display: block;
width: 100%;
height: $unit-4;
&::-webkit-meter-inner-element {
display: block;
}
&::-webkit-meter-bar,
&::-webkit-meter-optimum-value,
&::-webkit-meter-suboptimum-value,
&::-webkit-meter-even-less-good-value {
border-radius: $border-radius;
}
&::-webkit-meter-bar {
background: $bg-color;
}
&::-webkit-meter-optimum-value {
background: $success-color;
}
&::-webkit-meter-suboptimum-value {
background: $warning-color;
}
&::-webkit-meter-even-less-good-value {
background: $error-color;
}
&::-moz-meter-bar,
&:-moz-meter-optimum,
&:-moz-meter-sub-optimum,
&:-moz-meter-sub-sub-optimum {
border-radius: $border-radius;
}
&:-moz-meter-optimum::-moz-meter-bar {
background: $success-color;
}
&:-moz-meter-sub-optimum::-moz-meter-bar {
background: $warning-color;
}
&:-moz-meter-sub-sub-optimum::-moz-meter-bar {
background: $error-color;
}
}
+11
View File
@@ -0,0 +1,11 @@
// Mixins
@import "mixins/avatar";
@import "mixins/button";
@import "mixins/clearfix";
@import "mixins/color";
@import "mixins/label";
@import "mixins/position";
@import "mixins/shadow";
@import "mixins/text";
@import "mixins/toast";
@import "mixins/transition";
+87
View File
@@ -0,0 +1,87 @@
// Modals
.modal {
align-items: center;
bottom: 0;
display: none;
justify-content: center;
left: 0;
opacity: 0;
overflow: hidden;
padding: $layout-spacing;
position: fixed;
right: 0;
top: 0;
&:target,
&.active {
display: flex;
opacity: 1;
z-index: $zindex-4;
.modal-overlay {
background: rgba($bg-color, .75);
bottom: 0;
cursor: default;
display: block;
left: 0;
position: absolute;
right: 0;
top: 0;
}
.modal-container {
animation: slide-down .2s ease 1;
z-index: $zindex-0;
}
}
&.modal-sm {
.modal-container {
max-width: $control-width-sm;
padding: 0 $unit-2;
}
}
&.modal-lg {
.modal-overlay {
background: $bg-color-light;
}
.modal-container {
box-shadow: none;
max-width: $control-width-lg;
}
}
}
.modal-container {
@include shadow-variant(.2rem);
background: $bg-color-light;
border-radius: $border-radius;
display: flex;
flex-direction: column;
max-height: 75vh;
max-width: $control-width-md;
padding: 0 $unit-4;
width: 100%;
&.modal-fullheight {
max-height: 100vh;
}
.modal-header {
color: $dark-color;
padding: $unit-4;
}
.modal-body {
overflow-y: auto;
padding: $unit-4;
position: relative;
}
.modal-footer {
padding: $unit-4;
text-align: right;
}
}
+29
View File
@@ -0,0 +1,29 @@
// Navbar
.navbar {
align-items: stretch;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.navbar-section {
align-items: center;
display: flex;
flex: 1 0 0;
&:not(:first-child):last-child {
justify-content: flex-end;
}
}
.navbar-center {
align-items: center;
display: flex;
flex: 0 0 auto;
}
.navbar-brand {
font-size: $font-size-lg;
font-weight: 500;
text-decoration: none;
}
}
+34
View File
@@ -0,0 +1,34 @@
// Navs
.nav {
display: flex;
flex-direction: column;
list-style: none;
margin: $unit-1 0;
.nav-item {
a {
color: $gray-color-dark;
padding: $unit-1 $unit-2;
text-decoration: none;
&:focus,
&:hover {
color: $primary-color;
}
}
&.active {
& > a {
color: darken($gray-color-dark, 10%);
font-weight: bold;
&:focus,
&:hover {
color: $primary-color;
}
}
}
}
& .nav {
margin-bottom: $unit-2;
margin-left: $unit-4;
}
}
+446
View File
@@ -0,0 +1,446 @@
/* Manually forked from Normalize.css */
/* normalize.css v5.0.0 | MIT License | github.com/necolas/normalize.css */
/**
* 1. Change the default font family in all browsers (opinionated).
* 2. Correct the line height in all browsers.
* 3. Prevent adjustments of font size after orientation changes in
* IE on Windows Phone and in iOS.
*/
/* Document
========================================================================== */
html {
font-family: sans-serif; /* 1 */
-ms-text-size-adjust: 100%; /* 3 */
-webkit-text-size-adjust: 100%; /* 3 */
}
/* Sections
========================================================================== */
/**
* Remove the margin in all browsers (opinionated).
*/
body {
margin: 0;
}
/**
* Add the correct display in IE 9-.
*/
article,
aside,
footer,
header,
nav,
section {
display: block;
}
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/* Grouping content
========================================================================== */
/**
* Add the correct display in IE 9-.
* 1. Add the correct display in IE.
*/
figcaption,
figure,
main { /* 1 */
display: block;
}
/**
* Add the correct margin in IE 8 (removed).
*/
/**
* 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box; /* 1 */
height: 0; /* 1 */
overflow: visible; /* 2 */
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers. (removed)
* 2. Correct the odd `em` font sizing in all browsers.
*/
/* Text-level semantics
========================================================================== */
/**
* 1. Remove the gray background on active links in IE 10.
* 2. Remove gaps in links underline in iOS 8+ and Safari 8+.
*/
a {
background-color: transparent; /* 1 */
-webkit-text-decoration-skip: objects; /* 2 */
}
/**
* Remove the outline on focused links when they are also active or hovered
* in all browsers (opinionated).
*/
a:active,
a:hover {
outline-width: 0;
}
/**
* Modify default styling of address.
*/
address {
font-style: normal;
}
/**
* 1. Remove the bottom border in Firefox 39-.
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. (removed)
*/
/**
* Prevent the duplicate application of `bolder` by the next rule in Safari 6.
*/
b,
strong {
font-weight: inherit;
}
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder;
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
pre,
samp {
font-family: $mono-font-family; /* 1 (changed) */
font-size: 1em; /* 2 */
}
/**
* Add the correct font style in Android 4.3-.
*/
dfn {
font-style: italic;
}
/**
* Add the correct background and color in IE 9-. (Removed)
*/
/**
* Add the correct font size in all browsers.
*/
small {
font-size: 80%;
font-weight: 400; /* (added) */
}
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
/**
* Add the correct display in IE 9-.
*/
audio,
video {
display: inline-block;
}
/**
* Add the correct display in iOS 4-7.
*/
audio:not([controls]) {
display: none;
height: 0;
}
/**
* Remove the border on images inside links in IE 10-.
*/
img {
border-style: none;
}
/**
* Hide the overflow in IE.
*/
svg:not(:root) {
overflow: hidden;
}
/* Forms
========================================================================== */
/**
* 1. Change the font styles in all browsers (opinionated).
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
font-family: inherit; /* 1 (changed) */
font-size: inherit; /* 1 (changed) */
line-height: inherit; /* 1 (changed) */
margin: 0; /* 2 */
}
/**
* Show the overflow in IE.
* 1. Show the overflow in Edge.
*/
button,
input { /* 1 */
overflow: visible;
}
/**
* Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Remove the inheritance of text transform in Firefox.
*/
button,
select { /* 1 */
text-transform: none;
}
/**
* 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
* controls in Android 4.
* 2. Correct the inability to style clickable types in iOS and Safari.
*/
button,
html [type="button"], /* 1 */
[type="reset"],
[type="submit"] {
-webkit-appearance: button; /* 2 */
}
/**
* Remove the inner border and padding in Firefox.
*/
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
/**
* Restore the focus styles unset by the previous rule (removed).
*/
/**
* Change the border, margin, and padding in all browsers (opinionated) (changed).
*/
fieldset {
border: 0;
margin: 0;
padding: 0;
}
/**
* 1. Correct the text wrapping in Edge and IE.
* 2. Correct the color inheritance from `fieldset` elements in IE.
* 3. Remove the padding so developers are not caught out when they zero out
* `fieldset` elements in all browsers.
*/
legend {
box-sizing: border-box; /* 1 */
color: inherit; /* 2 */
display: table; /* 1 */
max-width: 100%; /* 1 */
padding: 0; /* 3 */
white-space: normal; /* 1 */
}
/**
* 1. Add the correct display in IE 9-.
* 2. Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/
progress {
display: inline-block; /* 1 */
vertical-align: baseline; /* 2 */
}
/**
* Remove the default vertical scrollbar in IE.
*/
textarea {
overflow: auto;
}
/**
* 1. Add the correct box sizing in IE 10-.
* 2. Remove the padding in IE 10-.
*/
[type="checkbox"],
[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Correct the cursor style of increment and decrement buttons in Chrome.
*/
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Correct the odd appearance in Chrome and Safari.
* 2. Correct the outline style in Safari.
*/
[type="search"] {
-webkit-appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}
/**
* Remove the inner padding and cancel buttons in Chrome and Safari on macOS.
*/
[type="search"]::-webkit-search-cancel-button,
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
}
/* Interactive
========================================================================== */
/*
* Add the correct display in IE 9-.
* 1. Add the correct display in Edge, IE, and Firefox.
*/
details, /* 1 */
menu {
display: block;
}
/*
* Add the correct display in all browsers.
*/
summary {
display: list-item;
outline: none;
}
/* Scripting
========================================================================== */
/**
* Add the correct display in IE 9-.
*/
canvas {
display: inline-block;
}
/**
* Add the correct display in IE.
*/
template {
display: none;
}
/* Hidden
========================================================================== */
/**
* Add the correct display in IE 10-.
*/
[hidden] {
display: none;
}
@@ -0,0 +1,95 @@
// Off canvas menus
$off-canvas-breakpoint: $size-lg !default;
.off-canvas {
display: flex;
flex-flow: nowrap;
height: 100%;
position: relative;
width: 100%;
.off-canvas-toggle {
display: block;
position: absolute;
top: $layout-spacing;
transition: none;
z-index: $zindex-0;
@if $rtl == true {
right: $layout-spacing;
} @else {
left: $layout-spacing;
}
}
.off-canvas-sidebar {
background: $bg-color;
bottom: 0;
min-width: 10rem;
overflow-y: auto;
position: fixed;
top: 0;
transition: transform .25s ease;
z-index: $zindex-2;
@if $rtl == true {
right: 0;
transform: translateX(100%);
} @else {
left: 0;
transform: translateX(-100%);
}
}
.off-canvas-content {
flex: 1 1 auto;
height: 100%;
padding: $layout-spacing $layout-spacing $layout-spacing 4rem;
}
.off-canvas-overlay {
background: rgba($dark-color, .1);
border-color: transparent;
border-radius: 0;
bottom: 0;
display: none;
height: 100%;
left: 0;
position: fixed;
right: 0;
top: 0;
width: 100%;
}
.off-canvas-sidebar {
&:target,
&.active {
transform: translateX(0);
}
&:target ~ .off-canvas-overlay,
&.active ~ .off-canvas-overlay {
display: block;
z-index: $zindex-1;
}
}
}
// Responsive layout
@media (min-width: $off-canvas-breakpoint) {
.off-canvas {
&.off-canvas-sidebar-show {
.off-canvas-toggle {
display: none;
}
.off-canvas-sidebar {
flex: 0 0 auto;
position: relative;
transform: none;
}
.off-canvas-overlay {
display: none !important;
}
}
}
}
@@ -0,0 +1,61 @@
// Pagination
.pagination {
display: flex;
list-style: none;
margin: $unit-1 0;
padding: $unit-1 0;
.page-item {
margin: $unit-1 $unit-o;
span {
display: inline-block;
padding: $unit-1 $unit-1;
}
a {
border-radius: $border-radius;
color: $gray-color-dark;
display: inline-block;
padding: $unit-1 $unit-2;
text-decoration: none;
&:focus,
&:hover {
color: $primary-color;
}
}
&.disabled {
a {
cursor: default;
opacity: .5;
pointer-events: none;
}
}
&.active {
a {
background: $primary-color;
color: $light-color;
}
}
&.page-prev,
&.page-next {
flex: 1 0 50%;
}
&.page-next {
text-align: right;
}
.page-item-title {
margin: 0;
}
.page-item-subtitle {
margin: 0;
opacity: .5;
}
}
}
+23
View File
@@ -0,0 +1,23 @@
// Panels
.panel {
border: $border-width solid $border-color;
border-radius: $border-radius;
display: flex;
flex-direction: column;
.panel-header,
.panel-footer {
flex: 0 0 auto;
padding: $layout-spacing-lg;
}
.panel-nav {
flex: 0 0 auto;
}
.panel-body {
flex: 1 1 auto;
overflow-y: auto;
padding: 0 $layout-spacing-lg;
}
}
+135
View File
@@ -0,0 +1,135 @@
// Parallax
$parallax-deg: 3deg !default;
$parallax-offset: 4.5px !default;
$parallax-offset-z: 50px !default;
$parallax-perspective: 1000px !default;
$parallax-scale: .95 !default;
$parallax-fade-color: rgba(255, 255, 255, .35) !default;
// Mixin: Parallax direction
@mixin parallax-dir() {
height: 50%;
outline: none;
position: absolute;
width: 50%;
z-index: $zindex-1;
}
.parallax {
display: block;
height: auto;
position: relative;
width: auto;
.parallax-content {
@include shadow-variant(1rem);
height: auto;
transform: perspective($parallax-perspective);
transform-style: preserve-3d;
transition: all .4s ease;
width: 100%;
&::before {
content: "";
display: block;
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%;
}
}
.parallax-front {
align-items: center;
color: $light-color;
display: flex;
height: 100%;
justify-content: center;
left: 0;
position: absolute;
text-align: center;
text-shadow: 0 0 20px rgba($dark-color, .75);
top: 0;
transform: translateZ($parallax-offset-z) scale($parallax-scale);
transition: all .4s ease;
width: 100%;
z-index: $zindex-0;
}
.parallax-top-left {
@include parallax-dir();
left: 0;
top: 0;
&:focus ~ .parallax-content,
&:hover ~ .parallax-content {
transform: perspective($parallax-perspective) rotateX($parallax-deg) rotateY(-$parallax-deg);
&::before {
background: linear-gradient(135deg, $parallax-fade-color 0%, transparent 50%);
}
.parallax-front {
transform: translate3d($parallax-offset, $parallax-offset, $parallax-offset-z) scale($parallax-scale);
}
}
}
.parallax-top-right {
@include parallax-dir();
right: 0;
top: 0;
&:focus ~ .parallax-content,
&:hover ~ .parallax-content {
transform: perspective($parallax-perspective) rotateX($parallax-deg) rotateY($parallax-deg);
&::before {
background: linear-gradient(-135deg, $parallax-fade-color 0%, transparent 50%);
}
.parallax-front {
transform: translate3d(-$parallax-offset, $parallax-offset, $parallax-offset-z) scale($parallax-scale);
}
}
}
.parallax-bottom-left {
@include parallax-dir();
bottom: 0;
left: 0;
&:focus ~ .parallax-content,
&:hover ~ .parallax-content {
transform: perspective($parallax-perspective) rotateX(-$parallax-deg) rotateY(-$parallax-deg);
&::before {
background: linear-gradient(45deg, $parallax-fade-color 0%, transparent 50%);
}
.parallax-front {
transform: translate3d($parallax-offset, -$parallax-offset, $parallax-offset-z) scale($parallax-scale);
}
}
}
.parallax-bottom-right {
@include parallax-dir();
bottom: 0;
right: 0;
&:focus ~ .parallax-content,
&:hover ~ .parallax-content {
transform: perspective($parallax-perspective) rotateX(-$parallax-deg) rotateY($parallax-deg);
&::before {
background: linear-gradient(-45deg, $parallax-fade-color 0%, transparent 50%);
}
.parallax-front {
transform: translate3d(-$parallax-offset, -$parallax-offset, $parallax-offset-z) scale($parallax-scale);
}
}
}
}
+65
View File
@@ -0,0 +1,65 @@
// Popovers
.popover {
display: inline-block;
position: relative;
.popover-container {
left: 50%;
opacity: 0;
padding: $layout-spacing;
position: absolute;
top: 0;
transform: translate(-50%, -50%) scale(0);
transition: transform .2s ease;
width: $control-width-sm;
z-index: $zindex-3;
}
*:focus + .popover-container,
&:hover .popover-container {
display: block;
opacity: 1;
transform: translate(-50%, -100%);
}
&.popover-right {
.popover-container {
left: 100%;
top: 50%;
}
*:focus + .popover-container,
&:hover .popover-container {
transform: translate(0, -50%);
}
}
&.popover-bottom {
.popover-container {
left: 50%;
top: 100%;
}
*:focus + .popover-container,
&:hover .popover-container {
transform: translate(-50%, 0);
}
}
&.popover-left {
.popover-container {
left: 0;
top: 50%;
}
*:focus + .popover-container,
&:hover .popover-container {
transform: translate(-100%, -50%);
}
}
.card {
@include shadow-variant(.2rem);
border: 0;
}
}
+72
View File
@@ -0,0 +1,72 @@
body {
padding: 2rem 0;
}
img.logo {
width: 200px;
margin-bottom: 1rem;
}
h1, h2 {
font-weight: 700;
}
.footer {
color: $gray-color;
margin-top: 2rem;
img {
height: 18px;
vertical-align: middle;
margin: 0 0.2rem;
}
}
.toast {
.btn {
margin-left: 1rem;
text-decoration: none !important;
i {
margin-right: 0.3rem;
}
}
}
ul.problems {
margin: 1rem 0;
h5 {
margin: 0;
}
li.menu {
margin-bottom: 1rem;
.toast {
.btn {
float: right;
margin-top: -2px;
}
}
}
}
ul.details {
margin: 0.5rem;
list-style: none;
font-size: 90%;
.menu-item {
margin-top: .5rem !important;
border-top: 1px solid $border-color;
padding-top: 0.5rem;
&:first-child {
border: none;
}
}
.menu-badge {
padding: 0;
}
}
+45
View File
@@ -0,0 +1,45 @@
// Progress
// Credit: https://css-tricks.com/html5-progress-element/
.progress {
appearance: none;
background: $bg-color-dark;
border: 0;
border-radius: $border-radius;
color: $primary-color;
height: $unit-1;
position: relative;
width: 100%;
&::-webkit-progress-bar {
background: transparent;
border-radius: $border-radius;
}
&::-webkit-progress-value {
background: $primary-color;
border-radius: $border-radius;
}
&::-moz-progress-bar {
background: $primary-color;
border-radius: $border-radius;
}
&:indeterminate {
animation: progress-indeterminate 1.5s linear infinite;
background: $bg-color-dark linear-gradient(to right, $primary-color 30%, $bg-color-dark 30%) top left / 150% 150% no-repeat;
&::-moz-progress-bar {
background: transparent;
}
}
}
@keyframes progress-indeterminate {
0% {
background-position: 200% 0;
}
100% {
background-position: -200% 0;
}
}
+99
View File
@@ -0,0 +1,99 @@
// Sliders
// Credit: https://css-tricks.com/styling-cross-browser-compatible-range-inputs-css/
.slider {
appearance: none;
background: transparent;
display: block;
width: 100%;
height: $unit-6;
&:focus {
@include control-shadow();
outline: none;
}
&.tooltip:not([data-tooltip]) {
&::after {
content: attr(value);
}
}
// Slider Thumb
&::-webkit-slider-thumb {
-webkit-appearance: none;
background: $primary-color;
border: 0;
border-radius: 50%;
height: $unit-3;
margin-top: -($unit-3 - $unit-h) / 2;
transition: transform .2s ease;
width: $unit-3;
}
&::-moz-range-thumb {
background: $primary-color;
border: 0;
border-radius: 50%;
height: $unit-3;
transition: transform .2s ease;
width: $unit-3;
}
&::-ms-thumb {
background: $primary-color;
border: 0;
border-radius: 50%;
height: $unit-3;
transition: transform .2s ease;
width: $unit-3;
}
&:active {
&::-webkit-slider-thumb {
transform: scale(1.25);
}
&::-moz-range-thumb {
transform: scale(1.25);
}
&::-ms-thumb {
transform: scale(1.25);
}
}
&:disabled,
&.disabled {
&::-webkit-slider-thumb {
background: $gray-color-light;
transform: scale(1);
}
&::-moz-range-thumb {
background: $gray-color-light;
transform: scale(1);
}
&::-ms-thumb {
background: $gray-color-light;
transform: scale(1);
}
}
// Slider Track
&::-webkit-slider-runnable-track {
background: $bg-color-dark;
border-radius: $border-radius;
height: $unit-h;
width: 100%;
}
&::-moz-range-track {
background: $bg-color-dark;
border-radius: $border-radius;
height: $unit-h;
width: 100%;
}
&::-ms-track {
background: $bg-color-dark;
border-radius: $border-radius;
height: $unit-h;
width: 100%;
}
&::-ms-fill-lower {
background: $primary-color;
}
}
+70
View File
@@ -0,0 +1,70 @@
// Steps
.step {
display: flex;
flex-wrap: nowrap;
list-style: none;
margin: $unit-1 0;
width: 100%;
.step-item {
flex: 1 1 0;
margin-top: 0;
min-height: 1rem;
text-align: center;
position: relative;
&:not(:first-child)::before {
background: $primary-color;
content: "";
height: 2px;
left: -50%;
position: absolute;
top: 9px;
width: 100%;
}
a {
color: $gray-color;
display: inline-block;
padding: 20px 10px 0;
text-decoration: none;
&::before {
background: $primary-color;
border: $border-width-lg solid $light-color;
border-radius: 50%;
content: "";
display: block;
height: $unit-3;
left: 50%;
position: absolute;
top: $unit-1;
transform: translateX(-50%);
width: $unit-3;
z-index: $zindex-0;
}
}
&.active {
a {
&::before {
background: $light-color;
border: $border-width-lg solid $primary-color;
}
}
& ~ .step-item {
&::before {
background: $border-color;
}
a {
&::before {
background: $gray-color-light;
}
}
}
}
}
}
+57
View File
@@ -0,0 +1,57 @@
// Tables
.table {
border-collapse: collapse;
border-spacing: 0;
width: 100%;
@if $rtl == true {
text-align: right;
} @else {
text-align: left;
}
&.table-striped {
tbody {
tr:nth-of-type(odd) {
background: $bg-color;
}
}
}
&,
&.table-striped {
tbody {
tr {
&.active {
background: $bg-color-dark;
}
}
}
}
&.table-hover {
tbody {
tr {
&:hover {
background: $bg-color-dark;
}
}
}
}
// Tables with horizontal scrollbar
&.table-scroll {
display: block;
overflow-x: auto;
padding-bottom: .75rem;
white-space: nowrap;
}
td,
th {
border-bottom: $border-width solid $border-color;
padding: $unit-3 $unit-2;
}
th {
border-bottom-width: $border-width-lg;
}
}
+66
View File
@@ -0,0 +1,66 @@
// Tabs
.tab {
align-items: center;
border-bottom: $border-width solid $border-color;
display: flex;
flex-wrap: wrap;
list-style: none;
margin: $unit-1 0 ($unit-1 - $border-width) 0;
.tab-item {
margin-top: 0;
a {
border-bottom: $border-width-lg solid transparent;
color: inherit;
display: block;
margin: 0 $unit-2 0 0;
padding: $unit-2 $unit-1 $unit-2 - $border-width-lg $unit-1;
text-decoration: none;
&:focus,
&:hover {
color: $link-color;
}
}
&.active a,
a.active {
border-bottom-color: $primary-color;
color: $link-color;
}
&.tab-action {
flex: 1 0 auto;
text-align: right;
}
.btn-clear {
margin-top: -$unit-1;
}
}
&.tab-block {
.tab-item {
flex: 1 0 0;
text-align: center;
a {
margin: 0;
}
.badge {
&[data-badge]::after {
position: absolute;
right: $unit-h;
top: $unit-h;
transform: translate(0, 0);
}
}
}
}
&:not(.tab-block) {
.badge {
padding-right: 0;
}
}
}
+38
View File
@@ -0,0 +1,38 @@
// Tiles
.tile {
align-content: space-between;
align-items: flex-start;
display: flex;
.tile-icon,
.tile-action {
flex: 0 0 auto;
}
.tile-content {
flex: 1 1 auto;
&:not(:first-child) {
padding-left: $unit-2;
}
&:not(:last-child) {
padding-right: $unit-2;
}
}
.tile-title,
.tile-subtitle {
line-height: $line-height;
}
&.tile-centered {
align-items: center;
.tile-content {
overflow: hidden;
}
.tile-title,
.tile-subtitle {
@include text-ellipsis();
margin-bottom: 0;
}
}
}
@@ -0,0 +1,54 @@
// Timelines
.timeline {
.timeline-item {
display: flex;
margin-bottom: $unit-6;
position: relative;
&::before {
background: $border-color;
content: "";
height: 100%;
left: 11px;
position: absolute;
top: $unit-6;
width: 2px;
}
.timeline-left {
flex: 0 0 auto;
}
.timeline-content {
flex: 1 1 auto;
padding: 2px 0 2px $layout-spacing-lg;
}
.timeline-icon {
border-radius: 50%;
color: $light-color;
display: block;
height: $unit-6;
text-align: center;
width: $unit-6;
&::before {
border: $border-width-lg solid $primary-color;
border-radius: 50%;
content: "";
display: block;
height: $unit-2;
left: $unit-2;
position: absolute;
top: $unit-2;
width: $unit-2;
}
&.icon-lg {
background: $primary-color;
line-height: $line-height;
&::before {
content: none;
}
}
}
}
}
+42
View File
@@ -0,0 +1,42 @@
// Toasts
.toast {
@include toast-variant($dark-color);
border: $border-width solid $dark-color;
border-radius: $border-radius;
color: $light-color;
display: block;
padding: $layout-spacing;
width: 100%;
&.toast-primary {
@include toast-variant($primary-color);
}
&.toast-success {
@include toast-variant($success-color);
}
&.toast-warning {
@include toast-variant($warning-color);
}
&.toast-error {
@include toast-variant($error-color);
}
a {
color: $light-color;
text-decoration: underline;
&:focus,
&:hover,
&:active,
&.active {
opacity: .75;
}
}
.btn-clear {
margin: 4px -2px 4px 4px;
}
}
+79
View File
@@ -0,0 +1,79 @@
// Tooltips
.tooltip {
position: relative;
&::after {
background: rgba($dark-color, .9);
border-radius: $border-radius;
bottom: 100%;
color: $light-color;
content: attr(data-tooltip);
display: block;
font-size: $font-size-sm;
left: 50%;
max-width: $control-width-sm;
opacity: 0;
overflow: hidden;
padding: $unit-1 $unit-2;
pointer-events: none;
position: absolute;
text-overflow: ellipsis;
transform: translate(-50%, $unit-2);
transition: all .2s ease;
white-space: pre;
z-index: $zindex-3;
}
&:focus,
&:hover {
&::after {
opacity: 1;
transform: translate(-50%, -$unit-1);
}
}
&[disabled],
&.disabled {
pointer-events: auto;
}
&.tooltip-right {
&::after {
bottom: 50%;
left: 100%;
transform: translate(-$unit-1, 50%);
}
&:focus,
&:hover {
&::after {
transform: translate($unit-1, 50%);
}
}
}
&.tooltip-bottom {
&::after {
bottom: auto;
top: 100%;
transform: translate(-50%, -$unit-2);
}
&:focus,
&:hover {
&::after {
transform: translate(-50%, $unit-1);
}
}
}
&.tooltip-left {
&::after {
bottom: 50%;
left: auto;
right: 100%;
transform: translate($unit-2, 50%);
}
&:focus,
&:hover {
&::after {
transform: translate(-$unit-1, 50%);
}
}
}
}
+128
View File
@@ -0,0 +1,128 @@
// Typography
// Headings
h1,
h2,
h3,
h4,
h5,
h6 {
color: inherit;
font-weight: 500;
line-height: 1.2;
margin-bottom: .5em;
margin-top: 0;
}
.h1,
.h2,
.h3,
.h4,
.h5,
.h6 {
font-weight: 500;
}
h1,
.h1 {
font-size: 2rem;
}
h2,
.h2 {
font-size: 1.6rem;
}
h3,
.h3 {
font-size: 1.4rem;
}
h4,
.h4 {
font-size: 1.2rem;
}
h5,
.h5 {
font-size: 1rem;
}
h6,
.h6 {
font-size: .8rem;
}
// Paragraphs
p {
margin: 0 0 $line-height;
}
// Semantic text elements
a,
ins,
u {
text-decoration-skip: ink edges;
}
abbr[title] {
border-bottom: $border-width dotted;
cursor: help;
text-decoration: none;
}
kbd {
@include label-base();
@include label-variant($light-color, $dark-color);
font-size: $font-size-sm;
}
mark {
@include label-variant($body-font-color, $highlight-color);
border-radius: $border-radius;
padding: .05rem;
}
// Blockquote
blockquote {
border-left: $border-width-lg solid $border-color;
margin-left: 0;
padding: $unit-2 $unit-4;
p:last-child {
margin-bottom: 0;
}
}
// Lists
ul,
ol {
margin: $unit-4 0 $unit-4 $unit-4;
padding: 0;
ul,
ol {
margin: $unit-4 0 $unit-4 $unit-4;
}
li {
margin-top: $unit-2;
}
}
ul {
list-style: disc inside;
ul {
list-style-type: circle;
}
}
ol {
list-style: decimal inside;
ol {
list-style-type: lower-alpha;
}
}
dl {
dt {
font-weight: bold;
}
dd {
margin: $unit-2 0 $unit-4 0;
}
}
@@ -0,0 +1,8 @@
@import "utilities/colors";
@import "utilities/cursors";
@import "utilities/display";
@import "utilities/divider";
@import "utilities/loading";
@import "utilities/position";
@import "utilities/shapes";
@import "utilities/text";
+116
View File
@@ -0,0 +1,116 @@
// Core variables
$version: "0.5.3";
// Core features
$rtl: false !default;
// Core colors
$primary-color: #0074D9 !default;
$primary-color-dark: darken($primary-color, 3%) !default;
$primary-color-light: lighten($primary-color, 3%) !default;
$secondary-color: lighten($primary-color, 37.5%) !default;
$secondary-color-dark: darken($secondary-color, 3%) !default;
$secondary-color-light: lighten($secondary-color, 3%) !default;
// Gray colors
$dark-color: #454d5d !default;
$light-color: #fff !default;
$gray-color: lighten($dark-color, 40%) !default;
$gray-color-dark: darken($gray-color, 25%) !default;
$gray-color-light: lighten($gray-color, 20%) !default;
$border-color: lighten($dark-color, 60%) !default;
$border-color-dark: darken($border-color, 10%) !default;
$bg-color: lighten($dark-color, 66%) !default;
$bg-color-dark: darken($bg-color, 3%) !default;
$bg-color-light: $light-color !default;
// Control colors
$success-color: #2ECC40 !default;
$warning-color: #FF851B !default;
$error-color: #FF4136 !default;
// Other colors
$code-color: #288FED !default;
$highlight-color: #ffe9b3 !default;
$body-bg: $bg-color-light !default;
$body-font-color: lighten($dark-color, 5%) !default;
$link-color: $primary-color !default;
$link-color-dark: darken($link-color, 10%) !default;
$link-color-light: lighten($link-color, 10%) !default;
// Fonts
// Credit: https://www.smashingmagazine.com/2015/11/using-system-ui-fonts-practical-guide/
$base-font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto !default;
$mono-font-family: "SF Mono", "Segoe UI Mono", "Roboto Mono", Menlo, Courier, monospace !default;
$fallback-font-family: "Helvetica Neue", sans-serif !default;
$cjk-zh-hans-font-family: $base-font-family, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", $fallback-font-family !default;
$cjk-zh-hant-font-family: $base-font-family, "PingFang TC", "Hiragino Sans CNS", "Microsoft JhengHei", $fallback-font-family !default;
$cjk-jp-font-family: $base-font-family, "Hiragino Sans", "Hiragino Kaku Gothic Pro", "Yu Gothic", YuGothic, Meiryo, $fallback-font-family !default;
$cjk-ko-font-family: $base-font-family, "Malgun Gothic", $fallback-font-family !default;
$body-font-family: $base-font-family, $fallback-font-family !default;
// Unit sizes
$unit-o: .05rem !default;
$unit-h: .1rem !default;
$unit-1: .2rem !default;
$unit-2: .4rem !default;
$unit-3: .6rem !default;
$unit-4: .8rem !default;
$unit-5: 1rem !default;
$unit-6: 1.2rem !default;
$unit-7: 1.4rem !default;
$unit-8: 1.6rem !default;
$unit-9: 1.8rem !default;
$unit-10: 2rem !default;
$unit-12: 2.4rem !default;
$unit-16: 3.2rem !default;
// Font sizes
$html-font-size: 20px !default;
$html-line-height: 1.5 !default;
$font-size: .8rem !default;
$font-size-sm: .7rem !default;
$font-size-lg: .9rem !default;
$line-height: 1.2rem !default;
// Sizes
$layout-spacing: $unit-2 !default;
$layout-spacing-sm: $unit-1 !default;
$layout-spacing-lg: $unit-4 !default;
$border-radius: $unit-h !default;
$border-width: $unit-o !default;
$border-width-lg: $unit-h !default;
$control-size: $unit-9 !default;
$control-size-sm: $unit-7 !default;
$control-size-lg: $unit-10 !default;
$control-padding-x: $unit-2 !default;
$control-padding-x-sm: $unit-2 * .75 !default;
$control-padding-x-lg: $unit-2 * 1.5 !default;
$control-padding-y: ($control-size - $line-height) / 2 - $border-width !default;
$control-padding-y-sm: ($control-size-sm - $line-height) / 2 - $border-width !default;
$control-padding-y-lg: ($control-size-lg - $line-height) / 2 - $border-width !default;
$control-icon-size: .8rem !default;
$control-width-xs: 180px !default;
$control-width-sm: 320px !default;
$control-width-md: 640px !default;
$control-width-lg: 960px !default;
$control-width-xl: 1280px !default;
// Responsive breakpoints
$size-xs: 480px !default;
$size-sm: 600px !default;
$size-md: 840px !default;
$size-lg: 960px !default;
$size-xl: 1280px !default;
$size-2x: 1440px !default;
$responsive-breakpoint: $size-xs !default;
// Z-index
$zindex-0: 1 !default;
$zindex-1: 100 !default;
$zindex-2: 200 !default;
$zindex-3: 300 !default;
$zindex-4: 400 !default;
@@ -0,0 +1,316 @@
// Icon resize
.icon-resize-horiz,
.icon-resize-vert {
&::before,
&::after {
border: $icon-border-width solid currentColor;
border-bottom: 0;
border-right: 0;
content: "";
height: .45em;
width: .45em;
}
&::before {
transform: translate(-50%, -90%) rotate(45deg);
}
&::after {
transform: translate(-50%, -10%) rotate(225deg);
}
}
.icon-resize-horiz {
&::before {
transform: translate(-90%, -50%) rotate(-45deg);
}
&::after {
transform: translate(-10%, -50%) rotate(135deg);
}
}
// Icon more
.icon-more-horiz,
.icon-more-vert {
&::before {
background: currentColor;
box-shadow: -.4em 0, .4em 0;
border-radius: 50%;
content: "";
height: 3px;
width: 3px;
}
}
.icon-more-vert {
&::before {
box-shadow: 0 -.4em, 0 .4em;
}
}
// Icon plus, minus, cross
.icon-plus,
.icon-minus,
.icon-cross {
&::before {
background: currentColor;
content: "";
height: $icon-border-width;
width: 100%;
}
}
.icon-plus,
.icon-cross {
&::after {
background: currentColor;
content: "";
height: 100%;
width: $icon-border-width;
}
}
.icon-cross {
&::before {
width: 100%;
}
&::after {
height: 100%;
}
&::before,
&::after {
transform: translate(-50%, -50%) rotate(45deg);
}
}
// Icon check
.icon-check {
&::before {
border: $icon-border-width solid currentColor;
border-right: 0;
border-top: 0;
content: "";
height: .5em;
width: .9em;
transform: translate(-50%, -75%) rotate(-45deg);
}
}
// Icon stop
.icon-stop {
border: $icon-border-width solid currentColor;
border-radius: 50%;
&::before {
background: currentColor;
content: "";
height: $icon-border-width;
transform: translate(-50%, -50%) rotate(45deg);
width: 1em;
}
}
// Icon shutdown
.icon-shutdown {
border: $icon-border-width solid currentColor;
border-radius: 50%;
border-top-color: transparent;
&::before {
background: currentColor;
content: "";
height: .5em;
top: .1em;
width: $icon-border-width;
}
}
// Icon refresh
.icon-refresh {
&::before {
border: $icon-border-width solid currentColor;
border-radius: 50%;
border-right-color: transparent;
content: "";
height: 1em;
width: 1em;
}
&::after {
border: .2em solid currentColor;
border-top-color: transparent;
border-left-color: transparent;
content: "";
height: 0;
left: 80%;
top: 20%;
width: 0;
}
}
// Icon search
.icon-search {
&::before {
border: $icon-border-width solid currentColor;
border-radius: 50%;
content: "";
height: .75em;
left: 5%;
top: 5%;
transform: translate(0, 0) rotate(45deg);
width: .75em;
}
&::after {
background: currentColor;
content: "";
height: $icon-border-width;
left: 80%;
top: 80%;
transform: translate(-50%, -50%) rotate(45deg);
width: .4em;
}
}
// Icon edit
.icon-edit {
&::before {
border: $icon-border-width solid currentColor;
content: "";
height: .4em;
transform: translate(-40%, -60%) rotate(-45deg);
width: .85em;
}
&::after {
border: .15em solid currentColor;
border-top-color: transparent;
border-right-color: transparent;
content: "";
height: 0;
left: 5%;
top: 95%;
transform: translate(0, -100%);
width: 0;
}
}
// Icon delete
.icon-delete {
&::before {
border: $icon-border-width solid currentColor;
border-bottom-left-radius: $border-radius;
border-bottom-right-radius: $border-radius;
border-top: 0;
content: "";
height: .75em;
top: 60%;
width: .75em;
}
&::after {
background: currentColor;
box-shadow: -.25em .2em, .25em .2em;
content: "";
height: $icon-border-width;
top: $icon-border-width/2;
width: .5em;
}
}
// Icon share
.icon-share {
border: $icon-border-width solid currentColor;
border-radius: $border-radius;
border-right: 0;
border-top: 0;
&::before {
border: $icon-border-width solid currentColor;
border-left: 0;
border-top: 0;
content: "";
height: .4em;
left: 100%;
top: .25em;
transform: translate(-125%, -50%) rotate(-45deg);
width: .4em;
}
&::after {
border: $icon-border-width solid currentColor;
border-bottom: 0;
border-right: 0;
border-radius: 75% 0;
content: "";
height: .5em;
width: .6em;
}
}
// Icon flag
.icon-flag {
&::before {
background: currentColor;
content: "";
height: 1em;
left: 15%;
width: $icon-border-width;
}
&::after {
border: $icon-border-width solid currentColor;
border-bottom-right-radius: $border-radius;
border-left: 0;
border-top-right-radius: $border-radius;
content: "";
height: .65em;
top: 35%;
left: 60%;
width: .8em;
}
}
// Icon bookmark
.icon-bookmark {
&::before {
border: $icon-border-width solid currentColor;
border-bottom: 0;
border-top-left-radius: $border-radius;
border-top-right-radius: $border-radius;
content: "";
height: .9em;
width: .8em;
}
&::after {
border: $icon-border-width solid currentColor;
border-bottom: 0;
border-left: 0;
border-radius: $border-radius;
content: "";
height: .5em;
transform: translate(-50%, 35%) rotate(-45deg) skew(15deg, 15deg);
width: .5em;
}
}
// Icon download & upload
.icon-download,
.icon-upload {
border-bottom: $icon-border-width solid currentColor;
&::before {
border: $icon-border-width solid currentColor;
border-bottom: 0;
border-right: 0;
content: "";
height: .5em;
width: .5em;
transform: translate(-50%, -60%) rotate(-135deg);
}
&::after {
background: currentColor;
content: "";
height: .6em;
top: 40%;
width: $icon-border-width;
}
}
.icon-upload {
&::before {
transform: translate(-50%, -60%) rotate(45deg);
}
&::after {
top: 50%;
}
}
@@ -0,0 +1,53 @@
// Icon variables
$icon-border-width: $border-width-lg;
$icon-prefix: "icon";
// Icon base style
.#{$icon-prefix} {
box-sizing: border-box;
display: inline-block;
font-size: inherit;
font-style: normal;
height: 1em;
position: relative;
text-indent: -9999px;
vertical-align: middle;
width: 1em;
&::before,
&::after {
display: block;
left: 50%;
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
}
// Icon sizes
&.icon-2x {
font-size: 1.6rem;
}
&.icon-3x {
font-size: 2.4rem;
}
&.icon-4x {
font-size: 3.2rem;
}
}
// Component icon support
.accordion,
.btn,
.toast,
.menu {
.#{$icon-prefix} {
vertical-align: -10%;
}
}
.btn-lg {
.#{$icon-prefix} {
vertical-align: -15%;
}
}
@@ -0,0 +1,133 @@
// Icon arrows
.icon-arrow-down,
.icon-arrow-left,
.icon-arrow-right,
.icon-arrow-up,
.icon-downward,
.icon-back,
.icon-forward,
.icon-upward {
&::before {
border: $icon-border-width solid currentColor;
border-bottom: 0;
border-right: 0;
content: "";
height: .65em;
width: .65em;
}
}
.icon-arrow-down {
&::before {
transform: translate(-50%, -75%) rotate(225deg);
}
}
.icon-arrow-left {
&::before {
transform: translate(-25%, -50%) rotate(-45deg);
}
}
.icon-arrow-right {
&::before {
transform: translate(-75%, -50%) rotate(135deg);
}
}
.icon-arrow-up {
&::before {
transform: translate(-50%, -25%) rotate(45deg);
}
}
.icon-back,
.icon-forward {
&::after {
background: currentColor;
content: "";
height: $icon-border-width;
width: .8em;
}
}
.icon-downward,
.icon-upward {
&::after {
background: currentColor;
content: "";
height: .8em;
width: $icon-border-width;
}
}
.icon-back {
&::after {
left: 55%;
}
&::before {
transform: translate(-50%, -50%) rotate(-45deg);
}
}
.icon-downward {
&::after {
top: 45%;
}
&::before {
transform: translate(-50%, -50%) rotate(-135deg);
}
}
.icon-forward {
&::after {
left: 45%;
}
&::before {
transform: translate(-50%, -50%) rotate(135deg);
}
}
.icon-upward {
&::after {
top: 55%;
}
&::before {
transform: translate(-50%, -50%) rotate(45deg);
}
}
// Icon caret
.icon-caret {
&::before {
border-top: .3em solid currentColor;
border-right: .3em solid transparent;
border-left: .3em solid transparent;
content: "";
height: 0;
transform: translate(-50%, -25%);
width: 0;
}
}
// Icon menu
.icon-menu {
&::before {
background: currentColor;
box-shadow: 0 -.35em, 0 .35em;
content: "";
height: $icon-border-width;
width: 100%;
}
}
// Icon apps
.icon-apps {
&::before {
background: currentColor;
box-shadow: -.35em -.35em, -.35em 0, -.35em .35em, 0 -.35em, 0 .35em, .35em -.35em, .35em 0, .35em .35em;
content: "";
height: 3px;
width: 3px;
}
}
@@ -0,0 +1,176 @@
// Icon time
.icon-time {
border: $icon-border-width solid currentColor;
border-radius: 50%;
&::before {
background: currentColor;
content: "";
height: .4em;
transform: translate(-50%, -75%);
width: $icon-border-width;
}
&::after {
background: currentColor;
content: "";
height: .3em;
transform: translate(-50%, -75%) rotate(90deg);
transform-origin: 50% 90%;
width: $icon-border-width;
}
}
// Icon mail
.icon-mail {
&::before {
border: $icon-border-width solid currentColor;
border-radius: $border-radius;
content: "";
height: .8em;
width: 1em;
}
&::after {
border: $icon-border-width solid currentColor;
border-right: 0;
border-top: 0;
content: "";
height: .5em;
transform: translate(-50%, -90%) rotate(-45deg) skew(10deg, 10deg);
width: .5em;
}
}
// Icon people
.icon-people {
&::before {
border: $icon-border-width solid currentColor;
border-radius: 50%;
content: "";
height: .45em;
top: 25%;
width: .45em;
}
&::after {
border: $icon-border-width solid currentColor;
border-radius: 50% 50% 0 0;
content: "";
height: .4em;
top: 75%;
width: .9em;
}
}
// Icon message
.icon-message {
border: $icon-border-width solid currentColor;
border-bottom: 0;
border-radius: $border-radius;
border-right: 0;
&::before {
border: $icon-border-width solid currentColor;
border-bottom-right-radius: $border-radius;
border-left: 0;
border-top: 0;
content: "";
height: .8em;
left: 65%;
top: 40%;
width: .7em;
}
&::after {
background: currentColor;
border-radius: $border-radius;
content: "";
height: .3em;
left: 10%;
top: 100%;
transform: translate(0, -90%) rotate(45deg);
width: $icon-border-width;
}
}
// Icon photo
.icon-photo {
border: $icon-border-width solid currentColor;
border-radius: $border-radius;
&::before {
border: $icon-border-width solid currentColor;
border-radius: 50%;
content: "";
height: .25em;
left: 35%;
top: 35%;
width: .25em;
}
&::after {
border: $icon-border-width solid currentColor;
border-bottom: 0;
border-left: 0;
content: "";
height: .5em;
left: 60%;
transform: translate(-50%, 25%) rotate(-45deg);
width: .5em;
}
}
// Icon link
.icon-link {
&::before,
&::after {
border: $icon-border-width solid currentColor;
border-radius: 5em 0 0 5em;
border-right: 0;
content: "";
height: .5em;
width: .75em;
}
&::before {
transform: translate(-70%, -45%) rotate(-45deg);
}
&::after {
transform: translate(-30%, -55%) rotate(135deg);
}
}
// Icon location
.icon-location {
&::before {
border: $icon-border-width solid currentColor;
border-radius: 50% 50% 50% 0;
content: "";
height: .8em;
transform: translate(-50%, -60%) rotate(-45deg);
width: .8em;
}
&::after {
border: $icon-border-width solid currentColor;
border-radius: 50%;
content: "";
height: .2em;
transform: translate(-50%, -80%);
width: .2em;
}
}
// Icon emoji
.icon-emoji {
border: $icon-border-width solid currentColor;
border-radius: 50%;
&::before {
border-radius: 50%;
box-shadow: -.17em -.15em, .17em -.15em;
content: "";
height: .1em;
width: .1em;
}
&::after {
border: $icon-border-width solid currentColor;
border-bottom-color: transparent;
border-radius: 50%;
border-right-color: transparent;
content: "";
height: .5em;
transform: translate(-50%, -40%) rotate(-135deg);
width: .5em;
}
}
@@ -0,0 +1,6 @@
// Avatar mixin
@mixin avatar-base($size: $unit-8) {
font-size: $size / 2;
height: $size;
width: $size;
}
@@ -0,0 +1,54 @@
// Button variant mixin
@mixin button-variant($color: $primary-color) {
background: $color;
border-color: darken($color, 3%);
color: $light-color;
&:focus {
@include control-shadow($color);
}
&:focus,
&:hover {
background: darken($color, 2%);
border-color: darken($color, 5%);
color: $light-color;
}
&:active,
&.active {
background: darken($color, 7%);
border-color: darken($color, 10%);
color: $light-color;
}
&.loading {
&::after {
border-bottom-color: $light-color;
border-left-color: $light-color;
}
}
}
@mixin button-outline-variant($color: $primary-color) {
background: $light-color;
border-color: $color;
color: $color;
&:focus {
@include control-shadow($color);
}
&:focus,
&:hover {
background: lighten($color, 50%);
border-color: darken($color, 2%);
color: $color;
}
&:active,
&.active {
background: $color;
border-color: darken($color, 5%);
color: $light-color;
}
&.loading {
&::after {
border-bottom-color: $color;
border-left-color: $color;
}
}
}
@@ -0,0 +1,8 @@
// Clearfix mixin
@mixin clearfix() {
&::after {
clear: both;
content: "";
display: table;
}
}
@@ -0,0 +1,27 @@
// Background color utility mixin
@mixin bg-color-variant($name: ".bg-primary", $color: $primary-color) {
#{$name} {
background: $color;
@if (lightness($color) < 60) {
color: $light-color;
}
}
}
// Text color utility mixin
@mixin text-color-variant($name: ".text-primary", $color: $primary-color) {
#{$name} {
color: $color;
}
a#{$name} {
&:focus,
&:hover {
color: darken($color, 5%);
}
&:visited {
color: lighten($color, 5%);
}
}
}
@@ -0,0 +1,11 @@
// Label base style
@mixin label-base() {
border-radius: $border-radius;
line-height: 1.2;
padding: .1rem .2rem;
}
@mixin label-variant($color: $light-color, $bg-color: $primary-color) {
background: $bg-color;
color: $color;
}
@@ -0,0 +1,65 @@
// Margin utility mixin
@mixin margin-variant($id: 1, $size: $unit-1) {
.m-#{$id} {
margin: $size !important;
}
.mb-#{$id} {
margin-bottom: $size !important;
}
.ml-#{$id} {
margin-left: $size !important;
}
.mr-#{$id} {
margin-right: $size !important;
}
.mt-#{$id} {
margin-top: $size !important;
}
.mx-#{$id} {
margin-left: $size !important;
margin-right: $size !important;
}
.my-#{$id} {
margin-bottom: $size !important;
margin-top: $size !important;
}
}
// Padding utility mixin
@mixin padding-variant($id: 1, $size: $unit-1) {
.p-#{$id} {
padding: $size !important;
}
.pb-#{$id} {
padding-bottom: $size !important;
}
.pl-#{$id} {
padding-left: $size !important;
}
.pr-#{$id} {
padding-right: $size !important;
}
.pt-#{$id} {
padding-top: $size !important;
}
.px-#{$id} {
padding-left: $size !important;
padding-right: $size !important;
}
.py-#{$id} {
padding-bottom: $size !important;
padding-top: $size !important;
}
}
@@ -0,0 +1,9 @@
// Component focus shadow
@mixin control-shadow($color: $primary-color) {
box-shadow: 0 0 0 .1rem rgba($color, .2);
}
// Shadow mixin
@mixin shadow-variant($offset) {
box-shadow: 0 $offset ($offset + .05rem) * 2 rgba($dark-color, .3);
}
@@ -0,0 +1,6 @@
// Text Ellipsis
@mixin text-ellipsis() {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
@@ -0,0 +1,5 @@
// Toast variant mixin
@mixin toast-variant($color: $dark-color) {
background: rgba($color, .9);
border-color: $color;
}
@@ -0,0 +1,4 @@
// Component transition
@mixin control-transition() {
transition: all .2s ease;
}
@@ -0,0 +1,10 @@
// Variables and mixins
@import "variables";
@import "mixins";
/*! Spectre.css Icons v#{$version} | MIT License | github.com/picturepan2/spectre */
// Icons
@import "icons/icons-core";
@import "icons/icons-navigation";
@import "icons/icons-action";
@import "icons/icons-object";
+51
View File
@@ -0,0 +1,51 @@
// Variables and mixins
@import "variables";
@import "mixins";
/*! Spectre.css v#{$version} | MIT License | github.com/picturepan2/spectre */
// Reset and dependencies
@import "normalize";
@import "base";
// Elements
@import "typography";
@import "asian";
@import "tables";
@import "buttons";
@import "forms";
@import "labels";
@import "codes";
@import "media";
// Layout
@import "layout";
@import "navbar";
// Components
@import "accordions";
@import "avatars";
@import "badges";
@import "breadcrumbs";
@import "bars";
@import "cards";
@import "chips";
@import "dropdowns";
@import "empty";
@import "menus";
@import "modals";
@import "navs";
@import "pagination";
@import "panels";
@import "popovers";
@import "steps";
@import "tabs";
@import "tiles";
@import "toasts";
@import "tooltips";
// Custom
@import "problems";
// Utility classes
@import "animations";
@import "utilities";
@@ -0,0 +1,31 @@
// Text colors
@include text-color-variant(".text-primary", $primary-color);
@include text-color-variant(".text-secondary", $secondary-color-dark);
@include text-color-variant(".text-gray", $gray-color);
@include text-color-variant(".text-light", $light-color);
@include text-color-variant(".text-dark", $body-font-color);
@include text-color-variant(".text-success", $success-color);
@include text-color-variant(".text-warning", $warning-color);
@include text-color-variant(".text-error", $error-color);
// Background colors
@include bg-color-variant(".bg-primary", $primary-color);
@include bg-color-variant(".bg-secondary", $secondary-color);
@include bg-color-variant(".bg-dark", $dark-color);
@include bg-color-variant(".bg-gray", $bg-color);
@include bg-color-variant(".bg-success", $success-color);
@include bg-color-variant(".bg-warning", $warning-color);
@include bg-color-variant(".bg-error", $error-color);
@@ -0,0 +1,24 @@
// Cursors
.c-hand {
cursor: pointer;
}
.c-move {
cursor: move;
}
.c-zoom-in {
cursor: zoom-in;
}
.c-zoom-out {
cursor: zoom-out;
}
.c-not-allowed {
cursor: not-allowed;
}
.c-auto {
cursor: auto;
}
@@ -0,0 +1,44 @@
// Display
.d-block {
display: block;
}
.d-inline {
display: inline;
}
.d-inline-block {
display: inline-block;
}
.d-flex {
display: flex;
}
.d-inline-flex {
display: inline-flex;
}
.d-none,
.d-hide {
display: none !important;
}
.d-visible {
visibility: visible;
}
.d-invisible {
visibility: hidden;
}
.text-hide {
background: transparent;
border: 0;
color: transparent;
font-size: 0;
line-height: 0;
text-shadow: none;
}
.text-assistive {
border: 0;
clip: rect(0,0,0,0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
@@ -0,0 +1,50 @@
// Divider
.divider,
.divider-vert {
display: block;
position: relative;
&[data-content]::after {
background: $bg-color-light;
color: $gray-color;
content: attr(data-content);
display: inline-block;
font-size: $font-size-sm;
padding: 0 $unit-2;
transform: translateY(-$font-size-sm + $border-width);
}
}
.divider {
border-top: $border-width solid $border-color;
height: $border-width;
margin: $unit-2 0;
&[data-content] {
margin: $unit-4 0;
}
}
.divider-vert {
display: block;
padding: $unit-4;
&::before {
border-left: $border-width solid $border-color;
bottom: $unit-2;
content: "";
display: block;
left: 50%;
position: absolute;
top: $unit-2;
transform: translateX(-50%);
}
&[data-content]::after {
left: 50%;
padding: $unit-1 0;
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
}
}

Some files were not shown because too many files have changed in this diff Show More