1
0
mirror of https://github.com/tabler/tabler.git synced 2025-12-21 17:34:25 +04:00

Dark mode improvements (#950)

Co-authored-by: Robert-Jan de Dreu <robertjandreu@gmail.com>
This commit is contained in:
Paweł Kuna
2021-12-07 20:36:35 +01:00
committed by GitHub
parent 1018977e7f
commit 45268ff596
48 changed files with 676 additions and 471 deletions

View File

@@ -75,39 +75,51 @@ defaults:
colors: colors:
blue: blue:
class: blue
hex: '#206bc4' hex: '#206bc4'
title: Blue title: Blue
azure: azure:
class: azure
hex: '#45aaf2' hex: '#45aaf2'
title: Azure title: Azure
indigo: indigo:
class: indigo
hex: '#6574cd' hex: '#6574cd'
title: Indigo title: Indigo
purple: purple:
class: purple
hex: '#a55eea' hex: '#a55eea'
title: Purple title: Purple
pink: pink:
class: pink
hex: '#f66d9b' hex: '#f66d9b'
title: Pink title: Pink
red: red:
class: red
hex: '#fa4654' hex: '#fa4654'
title: Red title: Red
orange: orange:
class: orange
hex: '#fd9644' hex: '#fd9644'
title: Orange title: Orange
yellow: yellow:
class: yellow
hex: '#f1c40f' hex: '#f1c40f'
title: Yellow title: Yellow
lime: lime:
class: lime
hex: '#7bd235' hex: '#7bd235'
title: Lime title: Lime
green: green:
class: green
hex: '#5eba00' hex: '#5eba00'
title: Green title: Green
teal: teal:
class: teal
hex: '#2bcbba' hex: '#2bcbba'
title: Teal title: Teal
cyan: cyan:
class: cyan
hex: '#17a2b8' hex: '#17a2b8'
title: Cyan title: Cyan

View File

@@ -12,7 +12,7 @@ const gulp = require('gulp'),
rollupStream = require('@rollup/stream'), rollupStream = require('@rollup/stream'),
rollupBabel = require('rollup-plugin-babel'), rollupBabel = require('rollup-plugin-babel'),
rollupCleanup = require('rollup-plugin-cleanup'), rollupCleanup = require('rollup-plugin-cleanup'),
{nodeResolve} = require('@rollup/plugin-node-resolve'), { nodeResolve } = require('@rollup/plugin-node-resolve'),
rollupCommonjs = require('@rollup/plugin-commonjs'), rollupCommonjs = require('@rollup/plugin-commonjs'),
rollupReplace = require('@rollup/plugin-replace'), rollupReplace = require('@rollup/plugin-replace'),
vinylSource = require('vinyl-source-stream'), vinylSource = require('vinyl-source-stream'),
@@ -28,24 +28,23 @@ const gulp = require('gulp'),
cp = require('child_process'), cp = require('child_process'),
pkg = require('./package.json'), pkg = require('./package.json'),
year = new Date().getFullYear(), year = new Date().getFullYear(),
argv = yargs(process.argv).argv; argv = yargs(process.argv).argv
let BUILD = false, let BUILD = false,
distDir = './.tmp', distDir = './.tmp',
demoDir = './.tmp', demoDir = './.tmp',
srcDir = './src'; srcDir = './src'
/** /**
* Enable BUILD mode and set directories * Enable BUILD mode and set directories
*/ */
gulp.task('build-on', (cb) => { gulp.task('build-on', (cb) => {
BUILD = true; BUILD = true
distDir = './dist'; distDir = './dist'
demoDir = './demo'; demoDir = './demo'
cb(); cb()
}); })
/** /**
* Return banner added to CSS and JS dist files * Return banner added to CSS and JS dist files
@@ -59,8 +58,8 @@ const getBanner = () => {
* Copyright 2018-${year} codecalm.net Paweł Kuna * Copyright 2018-${year} codecalm.net Paweł Kuna
* Licensed under MIT (https://github.com/tabler/tabler/blob/master/LICENSE) * Licensed under MIT (https://github.com/tabler/tabler/blob/master/LICENSE)
*/ */
`; `
}; }
/** /**
* Array.flat polyfill * Array.flat polyfill
@@ -69,10 +68,10 @@ if (!Array.prototype.flat) {
Object.defineProperty(Array.prototype, 'flat', { Object.defineProperty(Array.prototype, 'flat', {
value: function (depth = 1) { value: function (depth = 1) {
return this.reduce(function (flat, toFlatten) { return this.reduce(function (flat, toFlatten) {
return flat.concat((Array.isArray(toFlatten) && (depth > 1)) ? toFlatten.flat(depth - 1) : toFlatten); return flat.concat((Array.isArray(toFlatten) && (depth > 1)) ? toFlatten.flat(depth - 1) : toFlatten)
}, []); }, [])
} }
}); })
} }
/** /**
@@ -80,54 +79,54 @@ if (!Array.prototype.flat) {
*/ */
gulp.task('svg-icons', (cb) => { gulp.task('svg-icons', (cb) => {
const prepareSvgFile = (svg) => { const prepareSvgFile = (svg) => {
return svg.replace(/\n/g, '').replace(/>\s+</g, '><'); return svg.replace(/\n/g, '').replace(/>\s+</g, '><')
}; }
const generateIconsYml = (dir, filename) => { const generateIconsYml = (dir, filename) => {
const files = glob.sync(dir); const files = glob.sync(dir)
let svgList = {}; let svgList = {}
files.forEach((file) => { files.forEach((file) => {
const basename = path.basename(file, '.svg'); const basename = path.basename(file, '.svg')
svgList[basename] = prepareSvgFile(fs.readFileSync(file).toString()); svgList[basename] = prepareSvgFile(fs.readFileSync(file).toString())
}); })
fs.writeFileSync(filename, YAML.stringify(svgList)); fs.writeFileSync(filename, YAML.stringify(svgList))
}; }
generateIconsYml("./node_modules/@tabler/icons/icons/*.svg", `${srcDir}/pages/_data/icons.yml`); generateIconsYml("./node_modules/@tabler/icons/icons/*.svg", `${srcDir}/pages/_data/icons.yml`)
cb(); cb()
}); })
/** /**
* Check unused Jekyll partials * Check unused Jekyll partials
*/ */
gulp.task('unused-files', (cb) => { gulp.task('unused-files', (cb) => {
let foundFiles = []; let foundFiles = []
glob.sync(`${srcDir}/pages/**/*.{html,md}`).forEach((file) => { glob.sync(`${srcDir}/pages/**/*.{html,md}`).forEach((file) => {
let fileContent = fs.readFileSync(file); let fileContent = fs.readFileSync(file)
fileContent.toString().replace(/\{% include(_cached)? ([a-z0-9\/_-]+\.html)/g, (f, c, filename) => { fileContent.toString().replace(/\{% include(_cached)? ([a-z0-9\/_-]+\.html)/g, (f, c, filename) => {
filename = `${srcDir}/pages/_includes/${filename}`; filename = `${srcDir}/pages/_includes/${filename}`
if (!foundFiles.includes(filename)) { if (!foundFiles.includes(filename)) {
foundFiles.push(filename); foundFiles.push(filename)
} }
}); })
}); })
let includeFiles = glob.sync(`${srcDir}/pages/_includes/**/*.html`); let includeFiles = glob.sync(`${srcDir}/pages/_includes/**/*.html`)
includeFiles.forEach((file) => { includeFiles.forEach((file) => {
if (!foundFiles.includes(file)) { if (!foundFiles.includes(file)) {
console.log('file', file); console.log('file', file)
} }
}); })
cb(); cb()
}); })
/** /**
* Clean `dist` folder before build * Clean `dist` folder before build
@@ -135,13 +134,13 @@ gulp.task('unused-files', (cb) => {
gulp.task('clean-dirs', () => { gulp.task('clean-dirs', () => {
return gulp return gulp
.src(`{${distDir}/*,${demoDir}/*}`, { read: false }) .src(`{${distDir}/*,${demoDir}/*}`, { read: false })
.pipe(clean()); .pipe(clean())
}); })
gulp.task('clean-jekyll', (cb) => { gulp.task('clean-jekyll', (cb) => {
return spawn('bundle', ['exec', 'jekyll', 'clean'], { stdio: 'inherit' }) return spawn('bundle', ['exec', 'jekyll', 'clean'], { stdio: 'inherit' })
.on('close', cb); .on('close', cb)
}); })
/** /**
* Compile SASS to CSS and move it to dist directory * Compile SASS to CSS and move it to dist directory
@@ -155,10 +154,10 @@ gulp.task('sass', () => {
precision: 7, precision: 7,
importer: (url, prev, done) => { importer: (url, prev, done) => {
if (url[0] === '~') { if (url[0] === '~') {
url = path.resolve('node_modules', url.substr(1)); url = path.resolve('node_modules', url.substr(1))
} }
return { file: url }; return { file: url }
}, },
}).on('error', sass.logError)) }).on('error', sass.logError))
.pipe(postcss([ .pipe(postcss([
@@ -170,36 +169,41 @@ gulp.task('sass', () => {
})) }))
.pipe(rtlcss()) .pipe(rtlcss())
.pipe(rename((path) => { .pipe(rename((path) => {
path.basename += '.rtl'; path.basename += '.rtl'
})) }))
.pipe(gulp.dest(`${distDir}/css/`)); .pipe(gulp.dest(`${distDir}/css/`))
}); })
/** /**
* CSS minify * CSS minify
*/ */
gulp.task('css-minify', function(){ gulp.task('css-minify', function () {
return gulp.src(`${distDir}/css/!(*.min).css`) return gulp.src(`${distDir}/css/!(*.min).css`)
.pipe(debug()) .pipe(debug())
.pipe(cleanCSS()) .pipe(cleanCSS())
.pipe(rename((path) => { .pipe(rename((path) => {
path.basename += '.min'; path.basename += '.min'
})) }))
.pipe(gulp.dest(`${distDir}/css/`)); .pipe(gulp.dest(`${distDir}/css/`))
}); })
/** /**
* Compile JS files to dist directory * Compile JS files to dist directory
*/ */
let cache; let cache = {}
gulp.task('js', () => {
const compileJs = function (name, mjs = false) {
if (!cache[name]) {
cache[name] = null
}
const g = rollupStream({ const g = rollupStream({
input: `${srcDir}/js/tabler.js`, input: `${srcDir}/js/${name}.js`,
cache, cache: cache[name],
output: { output: {
name: 'tabler.js', name: `${name}.js`,
format: 'umd', format: mjs ? 'es' : 'umd',
...(mjs ? { exports: 'named' } : {})
}, },
plugins: [ plugins: [
rollupReplace({ rollupReplace({
@@ -215,17 +219,17 @@ gulp.task('js', () => {
] ]
}) })
.on('bundle', (bundle) => { .on('bundle', (bundle) => {
cache = bundle; cache[name] = bundle
}) })
.pipe(vinylSource('tabler.js')) .pipe(vinylSource(`${name}.js`))
.pipe(vinylBuffer()) .pipe(vinylBuffer())
.pipe(rename((path) => { .pipe(rename((path) => {
path.dirname = ''; path.dirname = ''
})) }))
.pipe(gulp.dest(`${distDir}/js/`)) .pipe(gulp.dest(`${distDir}/js/`))
.pipe(browserSync.reload({ .pipe(browserSync.reload({
stream: true, stream: true,
})); }))
if (BUILD) { if (BUILD) {
g.pipe(minifyJS({ g.pipe(minifyJS({
@@ -234,16 +238,31 @@ gulp.task('js', () => {
min: '.min.js' min: '.min.js'
}, },
})) }))
.pipe(gulp.dest(`${distDir}/js/`)); .pipe(gulp.dest(`${distDir}/js/`))
} }
return g; return g
}); }
/**
* Compile JS files to dist directory
*/
gulp.task('js', () => {
return compileJs('tabler')
})
gulp.task('js-demo', () => {
return compileJs('demo')
})
/** /**
* Compile JS module files to dist directory * Compile JS module files to dist directory
*/ */
let cacheEsm; gulp.task('mjs', () => {
return compileJs('tabler.esm', true)
})
let cacheEsm
gulp.task('mjs', () => { gulp.task('mjs', () => {
const g = rollupStream({ const g = rollupStream({
input: `${srcDir}/js/tabler.esm.js`, input: `${srcDir}/js/tabler.esm.js`,
@@ -267,17 +286,17 @@ gulp.task('mjs', () => {
] ]
}) })
.on('bundle', (bundle) => { .on('bundle', (bundle) => {
cacheEsm = bundle; cacheEsm = bundle
}) })
.pipe(vinylSource('tabler.esm.js')) .pipe(vinylSource('tabler.esm.js'))
.pipe(vinylBuffer()) .pipe(vinylBuffer())
.pipe(rename((path) => { .pipe(rename((path) => {
path.dirname = ''; path.dirname = ''
})) }))
.pipe(gulp.dest(`${distDir}/js/`)) .pipe(gulp.dest(`${distDir}/js/`))
.pipe(browserSync.reload({ .pipe(browserSync.reload({
stream: true, stream: true,
})); }))
if (BUILD) { if (BUILD) {
g.pipe(minifyJS({ g.pipe(minifyJS({
@@ -286,46 +305,48 @@ gulp.task('mjs', () => {
min: '.min.js' min: '.min.js'
}, },
})) }))
.pipe(gulp.dest(`${distDir}/js/`)); .pipe(gulp.dest(`${distDir}/js/`))
} }
return g; return g
}); })
/** /**
* Watch Jekyll files and build it to demo directory * Watch Jekyll files and build it to demo directory
*/ */
gulp.task('watch-jekyll', (cb) => { gulp.task('watch-jekyll', (cb) => {
browserSync.notify('Building Jekyll'); browserSync.notify('Building Jekyll')
return spawn('bundle', ['exec', 'jekyll', 'build', '--watch', '--destination', demoDir, '--trace'], { stdio: 'inherit' }) return spawn('bundle', ['exec', 'jekyll', 'build', '--watch', '--destination', demoDir, '--trace'], { stdio: 'inherit' })
.on('close', cb); .on('close', cb)
}); })
/** /**
* Build Jekyll files do demo directory * Build Jekyll files do demo directory
*/ */
gulp.task('build-jekyll', (cb) => { gulp.task('build-jekyll', (cb) => {
var env = Object.create(process.env); var env = Object.create(process.env)
if(argv.preview) { if (argv.preview) {
env.JEKYLL_ENV = 'preview'; env.JEKYLL_ENV = 'preview'
} } else {
else { env.JEKYLL_ENV = 'production'
env.JEKYLL_ENV = 'production';
} }
return spawn('bundle', ['exec', 'jekyll', 'build', '--destination', demoDir, '--trace'], { env: env, stdio: 'inherit' }) return spawn('bundle', ['exec', 'jekyll', 'build', '--destination', demoDir, '--trace'], {
.on('close', cb); env: env,
}); stdio: 'inherit'
})
.on('close', cb)
})
gulp.task('build-cleanup', () => { gulp.task('build-cleanup', () => {
return gulp return gulp
.src(`${demoDir}/redirects.json`, { read: false, allowEmpty: true }) .src(`${demoDir}/redirects.json`, { read: false, allowEmpty: true })
.pipe(clean()); .pipe(clean())
}); })
gulp.task('build-purgecss', (cb) => { gulp.task('build-purgecss', (cb) => {
if(argv.preview) { if (argv.preview) {
return gulp.src('demo/dist/{libs,css}/**/*.css') return gulp.src('demo/dist/{libs,css}/**/*.css')
.pipe(purgecss({ .pipe(purgecss({
content: ['demo/**/*.html'] content: ['demo/**/*.html']
@@ -333,11 +354,11 @@ gulp.task('build-purgecss', (cb) => {
.pipe(gulp.dest('demo/dist/css')) .pipe(gulp.dest('demo/dist/css'))
} }
cb(); cb()
}); })
gulp.task('build-critical', (cb) => { gulp.task('build-critical', (cb) => {
if(argv.preview) { if (argv.preview) {
return gulp return gulp
.src('demo/**/*.html') .src('demo/**/*.html')
.pipe( .pipe(
@@ -354,22 +375,22 @@ gulp.task('build-critical', (cb) => {
}) })
) )
.on('error', err => { .on('error', err => {
console.log(err.message); console.log(err.message)
}) })
.pipe(gulp.dest('demo')); .pipe(gulp.dest('demo'))
} }
cb(); cb()
}); })
/** /**
* Watch JS and SCSS files * Watch JS and SCSS files
*/ */
gulp.task('watch', (cb) => { gulp.task('watch', (cb) => {
gulp.watch('./src/scss/**/*.scss', gulp.series('sass')); gulp.watch('./src/scss/**/*.scss', gulp.series('sass'))
gulp.watch('./src/js/**/*.js', gulp.series('js', 'mjs')); gulp.watch('./src/js/**/*.js', gulp.parallel('js', 'mjs', 'js-demo'))
cb(); cb()
}); })
/** /**
* Create BrowserSync server * Create BrowserSync server
@@ -392,38 +413,38 @@ gulp.task('browser-sync', () => {
host: 'localhost', host: 'localhost',
notify: false, notify: false,
reloadOnRestart: true reloadOnRestart: true
}); })
}); })
/** /**
* Copy libs used in tabler from npm to dist directory * Copy libs used in tabler from npm to dist directory
*/ */
gulp.task('copy-libs', (cb) => { gulp.task('copy-libs', (cb) => {
const allLibs = require(`${srcDir}/pages/_data/libs`); const allLibs = require(`${srcDir}/pages/_data/libs`)
let files = []; let files = []
Object.keys(allLibs.js).forEach((lib) => { Object.keys(allLibs.js).forEach((lib) => {
files.push(Array.isArray(allLibs.js[lib]) ? allLibs.js[lib] : [allLibs.js[lib]]); files.push(Array.isArray(allLibs.js[lib]) ? allLibs.js[lib] : [allLibs.js[lib]])
}); })
Object.keys(allLibs.css).forEach((lib) => { Object.keys(allLibs.css).forEach((lib) => {
files.push(Array.isArray(allLibs.css[lib]) ? allLibs.css[lib] : [allLibs.css[lib]]); files.push(Array.isArray(allLibs.css[lib]) ? allLibs.css[lib] : [allLibs.css[lib]])
}); })
files = files.flat(); files = files.flat()
files.forEach((file) => { files.forEach((file) => {
if (!file.match(/^https?/)) { if (!file.match(/^https?/)) {
let dirname = path.dirname(file).replace('@', ''); let dirname = path.dirname(file).replace('@', '')
let cmd = `mkdir -p "dist/libs/${dirname}" && cp -r node_modules/${file} ${distDir}/libs/${file.replace('@', '')}`; let cmd = `mkdir -p "dist/libs/${dirname}" && cp -r node_modules/${file} ${distDir}/libs/${file.replace('@', '')}`
cp.exec(cmd) cp.exec(cmd)
} }
}); })
cb(); cb()
}); })
/** /**
* Copy static files (flags, payments images, etc) to dist directory * Copy static files (flags, payments images, etc) to dist directory
@@ -431,8 +452,8 @@ gulp.task('copy-libs', (cb) => {
gulp.task('copy-images', () => { gulp.task('copy-images', () => {
return gulp return gulp
.src(`${srcDir}/img/**/*`) .src(`${srcDir}/img/**/*`)
.pipe(gulp.dest(`${distDir}/img`)); .pipe(gulp.dest(`${distDir}/img`))
}); })
/** /**
* Copy static files (demo images, etc) to demo directory * Copy static files (demo images, etc) to demo directory
@@ -440,8 +461,8 @@ gulp.task('copy-images', () => {
gulp.task('copy-static', () => { gulp.task('copy-static', () => {
return gulp return gulp
.src(`${srcDir}/static/**/*`) .src(`${srcDir}/static/**/*`)
.pipe(gulp.dest(`${demoDir}/static`)); .pipe(gulp.dest(`${demoDir}/static`))
}); })
/** /**
* Copy Tabler dist files to demo directory * Copy Tabler dist files to demo directory
@@ -449,8 +470,8 @@ gulp.task('copy-static', () => {
gulp.task('copy-dist', () => { gulp.task('copy-dist', () => {
return gulp return gulp
.src(`${distDir}/**/*`) .src(`${distDir}/**/*`)
.pipe(gulp.dest(`${demoDir}/dist/`)); .pipe(gulp.dest(`${demoDir}/dist/`))
}); })
/** /**
* Add banner to build JS and CSS files * Add banner to build JS and CSS files
@@ -459,12 +480,12 @@ gulp.task('add-banner', () => {
return gulp.src(`${distDir}/{css,js}/**/*.{js,css}`) return gulp.src(`${distDir}/{css,js}/**/*.{js,css}`)
.pipe(header(getBanner())) .pipe(header(getBanner()))
.pipe(gulp.dest(`${distDir}`)) .pipe(gulp.dest(`${distDir}`))
}); })
gulp.task('clean', gulp.series('clean-dirs', 'clean-jekyll')); gulp.task('clean', gulp.series('clean-dirs', 'clean-jekyll'))
gulp.task('start', gulp.series('clean', 'sass', 'js', 'mjs', 'build-jekyll', gulp.parallel('watch-jekyll', 'watch', 'browser-sync'))); gulp.task('start', gulp.series('clean', 'sass', 'js', 'js-demo', 'mjs', 'build-jekyll', gulp.parallel('watch-jekyll', 'watch', 'browser-sync')))
gulp.task('build-core', gulp.series('build-on', 'clean', 'sass', 'css-minify', 'js', 'mjs', 'copy-images', 'copy-libs', 'add-banner')); gulp.task('build-core', gulp.series('build-on', 'clean', 'sass', 'css-minify', 'js', 'js-demo', 'mjs', 'copy-images', 'copy-libs', 'add-banner'))
gulp.task('build-demo', gulp.series('build-on', 'build-jekyll', 'copy-static', 'copy-dist', 'build-cleanup', 'build-purgecss'/*, 'build-critical'*/)); gulp.task('build-demo', gulp.series('build-on', 'build-jekyll', 'copy-static', 'copy-dist', 'build-cleanup', 'build-purgecss'/*, 'build-critical'*/))
gulp.task('build', gulp.series('build-core', 'build-demo')); gulp.task('build', gulp.series('build-core', 'build-demo'))

98
src/js/demo.js Normal file
View File

@@ -0,0 +1,98 @@
// Setting items
const items = {
'theme': { localStorage: 'tablerTheme', default: 'light' },
'menu-position': { localStorage: 'tablerMenuPosition', default: 'top' },
'menu-behavior': { localStorage: 'tablerMenuBehavior', default: 'sticky' },
'container-layout': { localStorage: 'tablerContainerLayout', default: 'boxed' },
}
// Theme config
const config = {}
for (const [key, params] of Object.entries(items)) {
config[key] = localStorage.getItem(params.localStorage) ? localStorage.getItem(params.localStorage) : params.default
}
// Parse url params
const parseUrl = () => {
const search = window.location.search.substring(1)
const params = search.split('&')
for (let i = 0; i < params.length; i++) {
const arr = params[i].split('=')
const key = arr[0]
const value = arr[1]
if (!!items[key]) {
// Save to localStorage
localStorage.setItem(items[key].localStorage, value)
// Update local variables
config[key] = value
}
}
}
// Toggle form controls
const toggleFormControls = (form) => {
for (const [key, params] of Object.entries(items)) {
const elem = form.querySelector(`[name="settings-${key}"][value="${config[key]}"]`)
if (elem) {
elem.checked = true
}
}
}
// Update body classes
const updateBodyClasses = () => {
document.body.classList.remove('theme-dark');
document.body.classList.remove('theme-light');
document.body.classList.add(`theme-${config.theme}`);
// for (const [key, params] of Object.entries(items)) {
// document.body.setAttribute(`data-${key}`, config[key]);
// }
}
// Submit form
const submitForm = (form) => {
// Save data to localStorage
for (const [key, params] of Object.entries(items)) {
// Save to localStorage
const value = form.querySelector(`[name="settings-${key}"]:checked`).value
localStorage.setItem(params.localStorage, value)
// Update local variables
config[key] = value
}
// Update body classes
updateBodyClasses();
window.dispatchEvent(new Event('resize'));
(new bootstrap.Offcanvas(form)).hide()
}
// Parse url
parseUrl()
// Update body classes
updateBodyClasses();
// Elements
const form = document.querySelector('#offcanvasSettings')
// Toggle form controls
if (form) {
form.addEventListener('submit', function (e) {
e.preventDefault()
submitForm(form)
})
toggleFormControls(form)
}

View File

@@ -176,9 +176,6 @@ layout:
condensed: condensed:
url: layout-condensed.html url: layout-condensed.html
title: Condensed title: Condensed
condensed-dark:
url: layout-condensed-dark.html
title: Condensed dark
combo: combo:
url: layout-combo.html url: layout-combo.html
title: Combined title: Combined
@@ -191,9 +188,6 @@ layout:
navbar-overlap: navbar-overlap:
url: layout-navbar-overlap.html url: layout-navbar-overlap.html
title: Navbar overlap title: Navbar overlap
dark-mode:
url: layout-dark.html
title: Dark mode
rtl-mode: rtl-mode:
url: layout-rtl.html url: layout-rtl.html
title: RTL mode title: RTL mode

View File

@@ -116,7 +116,7 @@ Add the `.btn-pill` class to your button to make it rounded and give it a modern
Replace the default modifier class with the `.btn-outline-*` class, if you want to remove the color and the background of your button and give it a more subtle look. Outline buttons are perfect to use as secondary buttons, as they don't distract users from the main action. Replace the default modifier class with the `.btn-outline-*` class, if you want to remove the color and the background of your button and give it a more subtle look. Outline buttons are perfect to use as secondary buttons, as they don't distract users from the main action.
{% capture code %} {% capture code %}
{% for button in site.button-variants %} {% for button in site.theme-colors %}
{% assign btn-color = button[1].class %} {% assign btn-color = button[1].class %}
{% assign btn-title = button[1].title %} {% assign btn-title = button[1].title %}
{% include ui/button.html text=btn-title color=btn-color outline=true %} {% include ui/button.html text=btn-title color=btn-color outline=true %}

View File

@@ -3,7 +3,7 @@
<div class="card-title">Development activity</div> <div class="card-title">Development activity</div>
</div> </div>
<div class="position-relative"> <div class="position-relative">
<div class="position-absolute top-0 left-0 px-3 mt-1 w-50"> <div class="position-absolute top-0 left-0 px-3 mt-1 w-75">
<div class="row g-2"> <div class="row g-2">
<div class="col-auto">{% include ui/chart-sparkline.html id="activity" percentage=35 type="donut" %}</div> <div class="col-auto">{% include ui/chart-sparkline.html id="activity" percentage=35 type="donut" %}</div>
<div class="col"> <div class="col">

View File

@@ -1,5 +1,5 @@
<footer class="footer footer-transparent d-print-none"> <footer class="footer footer-transparent d-print-none">
<div class="container"> <div class="container{% if page.layout-fluid %}-fluid{% else %}-xl{% endif %}">
<div class="row text-center align-items-center flex-row-reverse"> <div class="row text-center align-items-center flex-row-reverse">
<div class="col-lg-auto ms-lg-auto"> <div class="col-lg-auto ms-lg-auto">
<ul class="list-inline list-inline-dots mb-0"> <ul class="list-inline list-inline-dots mb-0">

View File

@@ -17,6 +17,7 @@
<!-- Tabler Core --> <!-- Tabler Core -->
<script src="{{ site.base }}/dist/js/tabler{% if jekyll.environment != 'development' %}.min{% endif %}.js{% if jekyll.environment == 'preview' %}?{{ site.time | date: '%s' }}{% endif %}"></script> <script src="{{ site.base }}/dist/js/tabler{% if jekyll.environment != 'development' %}.min{% endif %}.js{% if jekyll.environment == 'preview' %}?{{ site.time | date: '%s' }}{% endif %}"></script>
<script src="{{ site.base }}/dist/js/demo{% if jekyll.environment != 'development' %}.min{% endif %}.js{% if jekyll.environment == 'preview' %}?{{ site.time | date: '%s' }}{% endif %}"></script>
{% removeemptylines %} {% removeemptylines %}

View File

@@ -11,6 +11,14 @@
</div> </div>
{% endunless %} {% endunless %}
<a href="?theme=dark" class="nav-link px-0 hide-theme-dark" title="Enable dark mode" data-bs-toggle="tooltip" data-bs-placement="bottom">
{% include ui/icon.html icon="moon" %}
</a>
<a href="?theme=light" class="nav-link px-0 hide-theme-light" title="Enable light mode" data-bs-toggle="tooltip" data-bs-placement="bottom">
{% include ui/icon.html icon="sun" %}
</a>
<div class="nav-item dropdown d-none d-md-flex me-3"> <div class="nav-item dropdown d-none d-md-flex me-3">
<a href="#" class="nav-link px-0" data-bs-toggle="dropdown" tabindex="-1" aria-label="Show notifications"> <a href="#" class="nav-link px-0" data-bs-toggle="dropdown" tabindex="-1" aria-label="Show notifications">
{% include ui/icon.html icon="bell" %} {% include ui/icon.html icon="bell" %}

View File

@@ -1,203 +0,0 @@
{% include ui/modal/header.html title="Customize Tabler" %}
<div class="modal-body">
<p class="text-muted">Set preferences that will be saved for your live preview.</p>
<div class="mb-3">
<label class="form-label">Color scheme</label>
<div class="form-hint">Light or dark presentation.</div>
<div class="btn-group w-100">
<button class="btn" data-theme-toggle="theme:light">{% include ui/icon.html icon="sun" %} Light</button>
<button class="btn" data-theme-toggle="theme:dark">{% include ui/icon.html icon="moon" %} Dark</button>
</div>
</div>
<div class="mb-4 text-muted">
You can use the <code>.theme-dark-auto</code> class to automatically adjust the color version to the system settings.
</div>
<div class="mb-3">
<label class="form-label">Navigation position</label>
<div class="form-hint">Choose where the main navigation in your project should be located.</div>
<div class="btn-group w-100">
<button class="btn" data-theme-toggle="navbar-position:horizontal">Topnav</button>
<button class="btn" data-theme-toggle="navbar-position:vertical">Sidenav</button>
<button class="btn" data-theme-toggle="navbar-position:both">Both</button>
</div>
</div>
<div class="mb-3">
<label class="form-label">Sidebar size</label>
<div class="form-hint">Standard sidebar width or narrow version with icons only.</div>
<div class="btn-group w-100">
<button class="btn" data-theme-toggle="navbar-size:wide">Wide</button>
<button class="btn" data-theme-toggle="navbar-size:narrow">Narrow</button>
</div>
</div>
<div class="mb-3">
<label class="form-label">Sidebar position</label>
<div class="form-hint">Choose whether the sidebar should appear on the left or on the right.</div>
<div class="btn-group w-100">
<button class="btn" data-theme-toggle="navbar-side:left">Left</button>
<button class="btn" data-theme-toggle="navbar-side:right">Right</button>
</div>
</div>
<div>
<label class="form-label">Navigation color</label>
<div class="form-hint">Light or dark version of the sidebar </div>
<div class="btn-group w-100">
<button class="btn" data-theme-toggle="navbar-color:light">Light</button>
<button class="btn" data-theme-toggle="navbar-color:dark">Dark</button>
</div>
</div>
</div>
{% capture_global scripts %}
<script>
(function() {
var navbarPrimary = document.getElementById('navbar-primary'),
navbarSecondary = document.getElementById('navbar-secondary');
var defaults = {
theme: 'light',
'navbar-position': 'horizontal',
'navbar-size': 'wide',
'navbar-side': 'left',
'navbar-color': 'light',
};
var eventsClean = {
'theme': function () {
document.body.classList.remove('theme-dark');
},
'navbar-position': function () {
navbarPrimary.classList.remove('navbar-vertical');
navbarSecondary.classList.remove('d-none');
},
'navbar-size': function () {
navbarPrimary.classList.remove('navbar-vertical-narrow');
},
'navbar-side': function () {
navbarPrimary.classList.remove('navbar-right');
},
'navbar-color': function () {
navbarPrimary.classList.remove('navbar-dark');
navbarPrimary.classList.add('navbar-light');
},
};
var events = {
'theme:light': function () {
},
'theme:dark': function () {
document.body.classList.add('theme-dark');
},
'navbar-position:vertical': function () {
navbarPrimary.classList.add('navbar-vertical');
navbarSecondary.classList.add('d-none');
},
'navbar-position:horizontal': function () {
},
'navbar-position:both': function () {
navbarPrimary.classList.add('navbar-vertical');
},
'navbar-size:wide': function () {
},
'navbar-size:narrow': function () {
navbarPrimary.classList.add('navbar-vertical-narrow');
},
'navbar-side:left': function () {
},
'navbar-side:right': function () {
navbarPrimary.classList.add('navbar-right');
},
'navbar-color:light': function () {
},
'navbar-color:dark': function () {
navbarPrimary.classList.add('navbar-dark');
navbarPrimary.classList.remove('navbar-light');
},
};
var updateThemeConfig = function (name) {
var key, value;
if (name) {
[key, value] = name.split(':');
setConfig(key, value);
}
applyConfig();
};
var disableTransitions = function () {
document.body.classList.add('no-transitions');
setTimeout(function () {
document.body.classList.remove('no-transitions');
}, 300);
};
var getConfig = function () {
var config = {};
for (var key in defaults) {
config[key] = localStorage.getItem('tabler-' + key) || defaults[key];
}
return config;
};
var setConfig = function (key, value) {
localStorage.setItem('tabler-' + key, value);
};
var applyConfig = function () {
disableTransitions();
var config = getConfig();
for (var key in config) {
var value = config[key];
eventsClean[key] && eventsClean[key].call();
events[key + ':' + value] && events[key + ':' + value].call();
([].slice.call(document.querySelectorAll('[data-theme-toggle^="' + key + '"]'))).map(function (activeTrigger) {
activeTrigger.classList.remove('active')
});
document.querySelector('[data-theme-toggle="' + key + ':' + value + '"]').classList.add('active');
}
};
applyConfig();
for (var name in events) {
var event = events[name];
(function (event, name) {
document.querySelector('[data-theme-toggle="' + name + '"]').addEventListener("click", function (e) {
updateThemeConfig(name);
event.call();
e.preventDefault();
return false;
});
})(event, name);
}
})();
</script>
{% endcapture_global %}

View File

@@ -0,0 +1,88 @@
<div class="settings">
<a href="#" class="btn btn-icon btn-lg settings-btn" data-bs-toggle="offcanvas" data-bs-target="#offcanvasSettings">
{% include ui/icon.html icon="settings" %}
</a>
<form class="offcanvas offcanvas-end offcanvas-narrow" tabindex="-1" id="offcanvasSettings">
<div class="offcanvas-header">
<h2 class="offcanvas-title">Theme Builder</h2>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<div class="mb-4">
<label class="form-label">Color scheme</label>
<p class="form-hint">The perfect color mode for your app.</p>
<div class="row g-2">
{% assign schemes = 'light,mixed,colored,dark,transparent' | split: ',' %}
{% for scheme in schemes %}
<div class="col-6">
<label class="form-selectgroup-item">
<input type="radio" name="settings-theme" value="{{ scheme }}" class="form-selectgroup-input" />
<div class="form-selectgroup-label text-center">
<span class="form-selectgroup-check form-selectgroup-check-floated"></span>
<div class="settings-scheme settings-scheme-{{ scheme }}"></div>
<div>{{ scheme | capitalize }}</div>
</div>
</label>
</div>
{% endfor %}
</div>
</div>
<div class="mb-4">
<div class="form-label">Menu position</div>
<p class="form-hint">Toggle the position of the menu.</p>
<div>
{% assign positions = 'top,top-condensed,top-overlap,combo,left,right' | split: ',' %}
{% for position in positions %}
<label class="form-check">
<input class="form-check-input" name="settings-menu-position" value="{{ position }}" type="radio" />
<span class="form-check-label">{{ position | capitalize }}</span>
</label>
{% endfor %}
</div>
</div>
<div class="mb-4">
<div class="form-label">Menu behavior</div>
<p class="form-hint">Change the behavior of the menu.</p>
<div>
{% assign behaviors = 'sticky,fixed,compact' | split: ',' %}
{% for behavior in behaviors %}
<label class="form-check">
<input class="form-check-input" name="settings-menu-behavior" value="{{ behavior }}" type="radio" />
<span class="form-check-label">{{ behavior | capitalize }}</span>
</label>
{% endfor %}
</div>
</div>
<div class="mb-4">
<div class="form-label">Layout</div>
<p class="form-hint">Toggle container layout system.</p>
<div>
{% assign systems = 'boxed,fluid' | split: ',' %}
{% for system in systems %}
<label class="form-check">
<input class="form-check-input" name="settings-container-layout" value="{{ system }}" type="radio" />
<span class="form-check-label">{{ system | capitalize }}</span>
</label>
{% endfor %}
</div>
</div>
</div>
<div class="offcanvas-footer">
<button type="submit" class="btn btn-primary w-100">
{% include ui/icon.html icon="settings" %}
Save settings
</button>
</div>
</form>
</div>

View File

@@ -1,7 +1,7 @@
{% removeemptylines %} {% removeemptylines %}
{% assign spinner-class = false %} {% assign spinner-class = false %}
{% assign color = include.color | default: 'white' %} {% assign color = include.color %}
{% if include.color == false %} {% if include.color == false %}
{% assign color = null %} {% assign color = null %}
{% endif %} {% endif %}

View File

@@ -39,7 +39,7 @@
</head> </head>
{% assign layout-dark = page.layout-dark | default: site.layout-dark %} {% assign layout-dark = page.layout-dark | default: site.layout-dark %}
<body class="{% if layout-dark %} theme-dark{% endif %}{% if layout.body-class %} {{ layout.body-class }}{% endif %}{% if page.body-class %} {{ page.body-class }}{% endif %}"> <body {% if layout.body-class or page.body-class %} class="{% if layout.body-class %} {{ layout.body-class }}{% endif %}{% if page.body-class %} {{ page.body-class }}{% endif %}"{% endif %}>
{{ content }} {{ content }}

View File

@@ -39,3 +39,5 @@ layout: base
{% include layout/footer.html %} {% include layout/footer.html %}
</div> </div>
</div> </div>
{% comment %}{% include settings.html %}{% endcomment %}

View File

@@ -6,7 +6,7 @@ body-class: border-top-wide border-primary d-flex flex-column
<div class="page page-center"> <div class="page page-center">
<div class="container-{{ page.container-size | default: 'tight' }} py-4"> <div class="container-{{ page.container-size | default: 'tight' }} py-4">
<div class="text-center mb-4"> <div class="text-center mb-4">
<a href="{{ site.base }}"><img src="{{ site.base }}/static/logo.svg" height="36" alt=""></a> <a href="{{ site.base }}" class="navbar-brand navbar-brand-autodark"><img src="{{ site.base }}/static/logo.svg" height="36" alt=""></a>
</div> </div>
{{ content }} {{ content }}

View File

@@ -1,7 +0,0 @@
---
page-header: Condensed dark layout
menu: layout.condensed-dark
layout-navbar-condensed: true
layout-navbar-dark: true
layout: homepage
---

View File

@@ -1,6 +0,0 @@
---
page-header: Dark mode
menu: layout.dark-mode
layout-dark: true
layout: homepage
---

View File

@@ -0,0 +1,81 @@
---
title: Dark mode playground
page-header: Dark mode playground
---
{% assign colors = '' | split: ',' %}
{% for color in site.theme-colors %}
{% assign colors = colors | push: color[0] %}
{% endfor %}
{% for color in site.colors %}
{% assign colors = colors | push: color[0] %}
{% endfor %}
{% capture html %}
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Alias magni minus omnis provident qui repudiandae saepe sunt vel, veniam voluptatibus? Cum eius est harum molestias necessitatibus quasi repellat velit voluptatum.</p>
<div class="card">
<div class="card-body">
<div class="space-y">
<div>
<div class="btn-list">
{% include ui/button.html text="Default" icon="check" %}
{% for color in colors %}
{% assign title = color | capitalize %}
{% include ui/button.html color=color text=title icon="check" %}
{% endfor %}
</div>
</div>
<div>
<div class="btn-list">
{% include ui/button.html text="Default" disabled=true %}
{% for color in colors %}
{% assign title = color | capitalize %}
{% include ui/button.html color=color text=title icon="check" disabled=true %}
{% endfor %}
</div>
</div>
<div>
<div class="btn-list">
{% for color in colors %}
{% assign title = color | capitalize %}
{% include ui/button.html color=color text=title icon="check" ghost=true %}
{% endfor %}
</div>
</div>
<div>
<div class="btn-list">
{% for color in colors %}
{% assign title = color | capitalize %}
{% include ui/button.html color=color text=title icon="check" ghost=true disabled=true %}
{% endfor %}
</div>
</div>
<div>
<div class="btn-list">
{% for color in colors %}
{% assign title = color | capitalize %}
{% include ui/button.html color=color text=title icon="check" outline=true %}
{% endfor %}
</div>
</div>
<div>
<div class="btn-list">
{% for color in colors %}
{% assign title = color | capitalize %}
{% include ui/button.html color=color text=title icon="check" outline=true disabled=true %}
{% endfor %}
</div>
</div>
</div>
</div>
</div>
{% endcapture %}
<div class="row g-5">
<div class="col-lg py-3">{{ html }}</div>
<div class="col-lg py-3 theme-dark">
{{ html }}
</div>
</div>

View File

@@ -4,7 +4,7 @@ page-header-description: About 2,410 result (0.19 seconds)
menu: extra.search-results menu: extra.search-results
--- ---
<div class="row"> <div class="row g-3">
<div class="col-3"> <div class="col-3">
{% include parts/nav/nav-aside.html %} {% include parts/nav/nav-aside.html %}
</div> </div>

View File

@@ -7,6 +7,7 @@
@import "layout/navbar"; @import "layout/navbar";
@import "layout/page"; @import "layout/page";
@import "layout/footer"; @import "layout/footer";
@import "layout/dark";
@import "ui/accordion"; @import "ui/accordion";
@import "ui/alerts"; @import "ui/alerts";
@@ -60,5 +61,4 @@
@import "utils/shadow"; @import "utils/shadow";
@import "utils/text"; @import "utils/text";
@import "dark";
@import "debug"; @import "debug";

View File

@@ -78,7 +78,9 @@ $text-muted-light-opacity: .4 !default;
$text-muted-dark-opacity: .8 !default; $text-muted-dark-opacity: .8 !default;
$border-opacity: .16 !default; $border-opacity: .16 !default;
$border-light-opacity: .08 !default;
$border-dark-opacity: .24 !default; $border-dark-opacity: .24 !default;
$border-active-opacity: .48 !default;
$gray-50: #f8fafc !default; $gray-50: #f8fafc !default;
$gray-100: #f1f5f9 !default; $gray-100: #f1f5f9 !default;
@@ -122,9 +124,15 @@ $text-muted-dark: mix($body-color, #ffffff, percentage($text-muted-dark-opacity)
$border-color: mix($text-muted, #ffffff, percentage($border-opacity)) !default; $border-color: mix($text-muted, #ffffff, percentage($border-opacity)) !default;
$border-color-transparent: rgba($text-muted, $border-opacity) !default; $border-color-transparent: rgba($text-muted, $border-opacity) !default;
$border-color-light: mix($text-muted, #ffffff, percentage($border-light-opacity)) !default;
$border-color-light-transparent: rgba($text-muted, $border-light-opacity) !default;
$border-color-dark: mix($text-muted, #ffffff, percentage($border-dark-opacity)) !default; $border-color-dark: mix($text-muted, #ffffff, percentage($border-dark-opacity)) !default;
$border-color-dark-transparent: rgba($text-muted, $border-dark-opacity) !default; $border-color-dark-transparent: rgba($text-muted, $border-dark-opacity) !default;
$border-color-active: mix($text-muted, #ffffff, percentage($border-active-opacity)) !default;
$border-color-active-transparent: rgba($text-muted, $border-active-opacity) !default;
$active-bg: rgba($blue, .06) !default; $active-bg: rgba($blue, .06) !default;
$hover-bg: rgba($text-muted, .06) !default; $hover-bg: rgba($text-muted, .06) !default;
@@ -183,7 +191,8 @@ $social-colors: (
// Dark mode // Dark mode
$dark-mode-darken: darken($dark, 2%) !default; $dark-mode-darken: darken($dark, 2%) !default;
$dark-mode-lighten: lighten($dark, 2%) !default; $dark-mode-lighten: lighten($dark, 2%) !default;
$dark-mode-lighten-10: lighten($dark, 10%) !default; $dark-mode-border-color: lighten($dark, 8%) !default;
$dark-mode-border-color-light: lighten($dark, 4%) !default;
$dark-mode-text: $light; $dark-mode-text: $light;
// Borders // Borders
@@ -275,6 +284,9 @@ $aspect-ratios: (
"9x21": calc(21 / 9 * 100%), "9x21": calc(21 / 9 * 100%),
) !default; ) !default;
// Shadows
$shadow: rgba($dark, .04) 0 2px 4px 0 !default;
// Transitions // Transitions
$transition-time: .3s !default; $transition-time: .3s !default;
@@ -282,12 +294,13 @@ $transition-time: .3s !default;
$overlay-gradient: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, .6) 100%) !default; $overlay-gradient: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, .6) 100%) !default;
//accordion //accordion
$accordion-bg: transparent !default;
$accordion-border-color: $border-color-transparent !default; $accordion-border-color: $border-color-transparent !default;
$accordion-icon-width: 1rem !default; $accordion-icon-width: 1rem !default;
$accordion-button-bg: transparent !default;
$accordion-button-active-bg: transparent !default; $accordion-button-active-bg: transparent !default;
$accordion-button-active-color: inherit !default; $accordion-button-active-color: inherit !default;
$accordion-button-focus-border-color: $accordion-border-color !default; $accordion-button-focus-border-color: $accordion-border-color !default;
//alerts //alerts
@@ -358,7 +371,7 @@ $card-spacer-x: 1rem !default;
$card-status-size: $border-width-wide !default; $card-status-size: $border-width-wide !default;
$card-group-margin: 1.5rem !default; $card-group-margin: 1.5rem !default;
$card-shadow: rgba($dark, .04) 0 2px 4px 0 !default; $card-shadow: $shadow !default;
$card-shadow-hover: rgba($dark, .16) 0 2px 16px 0 !default; $card-shadow-hover: rgba($dark, .16) 0 2px 16px 0 !default;
$cards-grid-gap: 1rem !default; $cards-grid-gap: 1rem !default;
@@ -522,9 +535,9 @@ $table-border-color: $border-color-transparent !default;
$table-head-border-color: $border-color-transparent !default; $table-head-border-color: $border-color-transparent !default;
$table-head-padding-y: .5rem !default; $table-head-padding-y: .5rem !default;
$table-head-color: $text-muted !default; $table-head-color: $text-muted !default;
$table-head-bg: $light !default; $table-head-bg: var(--#{$variable-prefix}border-color-light) !default;
$table-striped-order: even !default; $table-striped-order: even !default;
$table-striped-bg: $light !default; $table-striped-bg: var(--#{$variable-prefix}border-color-light) !default;
$table-group-separator-color: $border-color-transparent !default; $table-group-separator-color: $border-color-transparent !default;
//toasts //toasts
@@ -583,8 +596,8 @@ $form-switch-bg-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/200
$form-switch-bg-size: auto !default; $form-switch-bg-size: auto !default;
$form-range-track-height: .25rem !default; $form-range-track-height: .25rem !default;
$form-range-track-bg: $gray-200 !default; $form-range-track-bg: var(--#{$variable-prefix}border-color-light) !default;
$form-range-thumb-border: 2px solid $white !default; $form-range-thumb-border: 2px solid $form-range-track-bg !default;
$form-range-thumb-height: 1rem !default; $form-range-thumb-height: 1rem !default;
$form-range-thumb-focus-box-shadow-width: .125rem !default; $form-range-thumb-focus-box-shadow-width: .125rem !default;
@@ -602,3 +615,5 @@ $flag-sizes: $avatar-sizes !default;
//Payments //Payments
$payment-sizes: $avatar-sizes !default; $payment-sizes: $avatar-sizes !default;
// Offcanvas
$offcanvas-border-color: $border-color-transparent !default;

View File

@@ -85,8 +85,8 @@ $demo-icon-size: 7rem;
height: $demo-icon-size; height: $demo-icon-size;
text-align: center; text-align: center;
padding: .5rem; padding: .5rem;
border-right: 1px solid $border-color; border-right: 1px solid var(--#{$variable-prefix}border-color);
border-bottom: 1px solid $border-color; border-bottom: 1px solid var(--#{$variable-prefix}border-color);
color: inherit; color: inherit;
cursor: pointer; cursor: pointer;
@@ -101,3 +101,32 @@ $demo-icon-size: 7rem;
} }
} }
//
// Settings
//
.settings-btn {
position: fixed;
right: -1px;
top: 10rem;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
box-shadow: $shadow;
}
.settings-scheme {
display: inline-block;
border-radius: 50%;
height: 3rem;
width: 3rem;
position: relative;
border: 1px solid var(--#{$variable-prefix}border-color);
box-shadow: $shadow;
&-light { background: linear-gradient(135deg, $white 50%, $light 50%); }
&-mixed { background-image: linear-gradient(135deg, $dark 50%, #fff 50%); }
&-transparent { background: $light; }
&-dark { background: $dark; }
&-colored { background-image: linear-gradient(135deg, var(--#{$variable-prefix}primary) 50%, $light 50%); }
}

View File

@@ -81,7 +81,7 @@
@include dark-mode { @include dark-mode {
.example { .example {
background-color: $dark-mode-darken; background-color: $dark-mode-darken;
border-color: $dark-mode-lighten-10; border-color: $dark-mode-border-color;
} }
.example-content { .example-content {
@@ -89,7 +89,7 @@
} }
.example-code { .example-code {
border-color: $dark-mode-lighten-10; border-color: $dark-mode-border-color;
border-top: none; border-top: none;
} }
} }

View File

@@ -1,8 +1,16 @@
// stylelint-disable property-no-vendor-prefix // stylelint-disable property-no-vendor-prefix
html { :root {
font-size: 16px; font-size: 16px;
scroll-behavior: smooth;
height: 100%; height: 100%;
--#{$variable-prefix}card-bg: #{$card-bg};
--#{$variable-prefix}card-bg-rgb: #{to-rgb($card-bg)};
--#{$variable-prefix}border-color: #{$border-color};
--#{$variable-prefix}border-color-rgb: #{to-rgb($border-color)};
--#{$variable-prefix}border-color-light: #{$border-color-light};
--#{$variable-prefix}border-color-light-rgb: #{to-rgb($border-color-light)};
} }
body { body {
@@ -17,12 +25,19 @@ body {
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
* {
@include scrollbar;
}
@media print { @media print {
background: transparent; background: transparent;
} }
} }
@include scrollbar;
//
// Fluid container
//
[data-container-layout="fluid"] {
[class^="container-"],
[class*=" container-"] {
max-width: 100%;
}
}

View File

@@ -1,14 +1,35 @@
/*!
* Tabler (v0.9.0): _dark.scss
* Copyright 2018-2021 The Tabler Authors
* Copyright 2018-2021 codecalm
* Licensed under MIT (https://github.com/tabler/tabler/blob/master/LICENSE)
*/
// stylelint-disable declaration-no-important // stylelint-disable declaration-no-important
body:not(.theme-dark) .hide-theme-light {
display: none !important;
}
@include dark-mode { @include dark-mode {
& { & {
--#{$variable-prefix}body-color: #{$dark-mode-text};
--#{$variable-prefix}body-color-rgb: #{to-rgb($dark-mode-text)};
--#{$variable-prefix}body-bg: #{$dark-mode-darken};
--#{$variable-prefix}body-bg-rgb: #{to-rgb($dark-mode-darken)};
--#{$variable-prefix}card-bg: #{$dark};
--#{$variable-prefix}card-bg-rgb: #{to-rgb($dark)};
--#{$variable-prefix}border-color: #{$dark-mode-border-color};
--#{$variable-prefix}border-color-light: #{$dark-mode-border-color-light};
color: $dark-mode-text; color: $dark-mode-text;
background-color: $dark-mode-darken; background-color: $dark-mode-darken;
} }
pre { .hide-theme-dark {
background-color: $dark-mode-darken; display: none !important;
border-color: $dark-mode-lighten-10;
} }
.text-body { .text-body {
@@ -36,6 +57,11 @@
color: inherit; color: inherit;
} }
pre {
background-color: $dark-mode-darken;
border-color: $dark-mode-border-color;
}
.card-tabs .nav-tabs .nav-link.active { .card-tabs .nav-tabs .nav-link.active {
background-color: $dark; background-color: $dark;
color: inherit; color: inherit;
@@ -56,7 +82,7 @@
.form-imagecheck-figure:before { .form-imagecheck-figure:before {
background-color: $dark-mode-darken; background-color: $dark-mode-darken;
color: $dark-mode-text; color: $dark-mode-text;
border-color: $dark-mode-lighten-10; border-color: $dark-mode-border-color;
} }
.form-control-plaintext { .form-control-plaintext {
@@ -67,12 +93,16 @@
background-color: $dark-mode-darken; background-color: $dark-mode-darken;
} }
.input-group-text {
border-color: $dark-mode-border-color;
}
.highlight { .highlight {
background-color: $dark-mode-darken; background-color: $dark-mode-darken;
} }
.avatar { .avatar {
--tblr-avatar-bg: #{$dark-mode-lighten}; --#{$variable-prefix}avatar-bg: #{$dark-mode-lighten};
} }
.avatar-list-stacked .avatar { .avatar-list-stacked .avatar {
@@ -81,19 +111,38 @@
.markdown, .markdown,
.markdown>*, .markdown>*,
.btn-close,
.accordion-button { .accordion-button {
color: inherit; color: inherit;
} }
.btn-close,
.accordion-button:after {
filter: $btn-close-white-filter;
}
.apexcharts-text { .apexcharts-text {
fill: $dark-mode-text; fill: $dark-mode-text;
} }
.apexcharts-gridline {
stroke: var(--#{$variable-prefix}border-color);
}
.apexcharts-legend-text { .apexcharts-legend-text {
color: inherit !important; color: inherit !important;
} }
.apexcharts-tooltip {
background: $dark !important;
border: 1px solid $dark-mode-border-color !important;
box-shadow: 2px 2px 6px -4px $dark-mode-darken !important;
.apexcharts-tooltip-title {
background: $dark !important;
border-bottom: 1px solid $dark-mode-border-color !important;
}
}
.navbar-brand-autodark { .navbar-brand-autodark {
@include autodark-image; @include autodark-image;
} }
@@ -108,13 +157,12 @@
border-color: $border-color-transparent; border-color: $border-color-transparent;
} }
.form-fieldset {
border-color: $input-border-color;
}
.list-group-header { .list-group-header {
background: $dark-mode-darken; background: $dark-mode-darken;
border-color: $input-border-color; }
.apexcharts-radialbar-area {
stroke: $dark-mode-border-color;
} }
} }

View File

@@ -58,7 +58,7 @@
@mixin navbar-dark { @mixin navbar-dark {
@include navbar-color($dark, $navbar-dark-color, $navbar-dark-brand-color, $navbar-dark-active-color, $navbar-dark-disabled-color); @include navbar-color($dark, $navbar-dark-color, $navbar-dark-brand-color, $navbar-dark-active-color, $navbar-dark-disabled-color);
@include scrollbar(true); @include scrollbar;
.input-icon-addon { .input-icon-addon {
color: rgba($dark-mode-text, .64); color: rgba($dark-mode-text, .64);

View File

@@ -1,7 +1,3 @@
@function hex-to-rgb($hex) {
@return red($hex), green($hex), blue($hex);
}
@function theme-color-lighter($color, $transparent: false) { @function theme-color-lighter($color, $transparent: false) {
@if ($transparent) { @if ($transparent) {
@return rgba($color, .1); @return rgba($color, .1);

View File

@@ -13,7 +13,7 @@
} }
} }
@mixin scrollbar($is-dark: false) { @mixin scrollbar {
&::-webkit-scrollbar { &::-webkit-scrollbar {
width: 6px; width: 6px;
height: 6px; height: 6px;
@@ -22,33 +22,20 @@
&::-webkit-scrollbar-thumb { &::-webkit-scrollbar-thumb {
border-radius: 5px; border-radius: 5px;
background: rgba(var(--#{$variable-prefix}body-color-rgb), .16);
@if ($is-dark) {
background: transparent;
} @else {
background: $gray-600;
}
} }
&::-webkit-scrollbar-track { &::-webkit-scrollbar-track {
@if ($is-dark) { background: rgba(var(--#{$variable-prefix}body-color-rgb), .06);
background: transparent; }
} @else {
background: $gray-300; &:hover::-webkit-scrollbar-thumb {
} background: rgba(var(--#{$variable-prefix}body-color-rgb), .32);
} }
&::-webkit-scrollbar-corner { &::-webkit-scrollbar-corner {
background: transparent; background: transparent;
} }
&:hover::-webkit-scrollbar-thumb {
@if ($is-dark) {
background: mix($white, $dark, 20%);
} @else {
background: $gray-600;
}
}
} }

View File

@@ -3,3 +3,4 @@
@import "vendor/nouislider"; @import "vendor/nouislider";
@import "vendor/litepicker"; @import "vendor/litepicker";
@import "vendor/tom-select"; @import "vendor/tom-select";
@import "vendor/apexcharts";

View File

@@ -11,6 +11,7 @@
&:not(.collapsed) { &:not(.collapsed) {
font-weight: $font-weight-bold; font-weight: $font-weight-bold;
border-bottom-color: transparent; border-bottom-color: transparent;
box-shadow: none;
&:after { &:after {
opacity: 1; opacity: 1;

View File

@@ -50,5 +50,5 @@
line-height: $h4-line-height; line-height: $h4-line-height;
font-weight: $font-weight-bold; font-weight: $font-weight-bold;
margin-bottom: .25rem; margin-bottom: .25rem;
color: var(--tblr-alert-color); color: var(--#{$variable-prefix}alert-color);
} }

View File

@@ -1,6 +1,6 @@
.avatar { .avatar {
--#{$variable-prefix}avatar-size: #{$avatar-size}; --#{$variable-prefix}avatar-size: #{$avatar-size};
--#{$variable-prefix}avatar-bg: #{$gray-200}; --#{$variable-prefix}avatar-bg: var(--#{$variable-prefix}border-color-light);
position: relative; position: relative;
width: var(--#{$variable-prefix}avatar-size); width: var(--#{$variable-prefix}avatar-size);
height: var(--#{$variable-prefix}avatar-size); height: var(--#{$variable-prefix}avatar-size);
@@ -18,8 +18,8 @@
border-radius: $avatar-border-radius; border-radius: $avatar-border-radius;
svg { svg {
width: calc(var(--tblr-avatar-size) / #{divide(40, 24)}); width: calc(var(--#{$variable-prefix}avatar-size) / #{divide(40, 24)});
height: calc(var(--tblr-avatar-size) / #{divide(40, 24)}); height: calc(var(--#{$variable-prefix}avatar-size) / #{divide(40, 24)});
} }
.badge { .badge {
@@ -112,7 +112,7 @@
.page-avatar { .page-avatar {
.page-cover ~ * & { .page-cover ~ * & {
margin-top: calc(calc(-1 * calc(var(--tblr-avatar-size) * .5)) - #{$content-padding-y}); margin-top: calc(calc(-1 * calc(var(--#{$variable-prefix}avatar-size) * .5)) - #{$content-padding-y});
box-shadow: 0 0 0 .25rem $body-bg; box-shadow: 0 0 0 .25rem $body-bg;
} }
} }

View File

@@ -1,21 +1,22 @@
.btn { .btn {
--#{$variable-prefix}btn-color-text-rgb: var(--#{$variable-prefix}body-color-rgb);
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
color: $body-color; border-color: var(--#{$variable-prefix}border-color);
background-color: $white;
border-color: $border-color-dark-transparent;
white-space: nowrap; white-space: nowrap;
background-color: var(--#{$variable-prefix}btn-color, var(--#{$variable-prefix}card-bg));
color: var(--#{$variable-prefix}btn-color-text);
&:hover { &:hover {
color: $body-color; color: var(--#{$variable-prefix}btn-color-text);
border-color: $text-muted-light; border-color: rgba(var(--#{$variable-prefix}btn-color-text-rgb), #{$border-active-opacity});
background-color: $light;
} }
&:focus { &:focus:not([disabled]):not(.disabled) {
border-color: rgba(var(--#{$variable-prefix}btn-color, hex-to-rgb($primary)), .5); border-color: var(--#{$variable-prefix}btn-color, #{$primary});
box-shadow: 0 0 0 $input-btn-focus-width rgba(var(--#{$variable-prefix}btn-color, hex-to-rgb($primary)), $input-btn-focus-color-opacity)
} }
&:disabled, &:disabled,
@@ -29,7 +30,7 @@
min-width: $icon-size; min-width: $icon-size;
margin: 0 .5rem 0 -.25rem; margin: 0 .5rem 0 -.25rem;
vertical-align: bottom; vertical-align: bottom;
color: $text-muted; color: inherit;
} }
.avatar { .avatar {
@@ -49,45 +50,36 @@
} }
%btn-color { %btn-color {
background-color: rgba(var(--#{$variable-prefix}btn-color), 1); border-color: $border-color-dark-transparent;
color: var(--#{$variable-prefix}btn-color-text);
.icon {
color: inherit;
}
&:hover { &:hover {
color: var(--#{$variable-prefix}btn-color-text); color: var(--#{$variable-prefix}btn-color-text);
background: rgba(var(--#{$variable-prefix}btn-color-darker), 1); background: var(--#{$variable-prefix}btn-color-interactive);
border-color: transparent; border-color: var(--#{$variable-prefix}btn-color);
} }
} }
%btn-outline { %btn-outline {
background-color: transparent; background-color: transparent;
color: rgba(var(--#{$variable-prefix}btn-color), 1); color: var(--#{$variable-prefix}btn-color);
border-color: $border-color-transparent; border-color: var(--#{$variable-prefix}btn-color);
.icon {
color: inherit;
}
&:hover { &:hover {
background-color: rgba(var(--#{$variable-prefix}btn-color), 1); background-color: var(--#{$variable-prefix}btn-color);
color: var(--#{$variable-prefix}btn-color-text); color: var(--#{$variable-prefix}btn-color-text);
border-color: rgba(var(--#{$variable-prefix}btn-color), 1); border-color: var(--#{$variable-prefix}btn-color);
} }
} }
%btn-ghost { %btn-ghost {
background: transparent; background: transparent;
color: rgba(var(--#{$variable-prefix}btn-color), 1); color: var(--#{$variable-prefix}btn-color);
border-color: transparent; border-color: transparent;
&:hover { &:hover {
background-color: rgba(var(--#{$variable-prefix}btn-color), 1); background-color: var(--#{$variable-prefix}btn-color);
color: var(--#{$variable-prefix}btn-color-text); color: var(--#{$variable-prefix}btn-color-text);
border-color: rgba(var(--#{$variable-prefix}btn-color), 1); border-color: var(--#{$variable-prefix}btn-color);
} }
} }
@@ -180,7 +172,9 @@
} }
} }
//
// Button color variations
//
$btn-colors: $theme-colors; $btn-colors: $theme-colors;
@if $enable-extra-colors { @if $enable-extra-colors {
@@ -195,8 +189,8 @@ $btn-colors: $theme-colors;
.btn-#{$name}, .btn-#{$name},
.btn-outline-#{$name}, .btn-outline-#{$name},
.btn-ghost-#{$name} { .btn-ghost-#{$name} {
--#{$variable-prefix}btn-color: #{hex-to-rgb($color)}; --#{$variable-prefix}btn-color: #{$color};
--#{$variable-prefix}btn-color-darker: #{hex-to-rgb(theme-color-darker($color))}; --#{$variable-prefix}btn-color-interactive: #{theme-color-darker($color)};
--#{$variable-prefix}btn-color-text: #{color-contrast($color)}; --#{$variable-prefix}btn-color-text: #{color-contrast($color)};
} }

View File

@@ -1,5 +1,4 @@
.border-0 { .border-0 {
.card, .nav-link { .card, .nav-link {
border: 0 !important; border: 0 !important;
} }
@@ -7,12 +6,12 @@
.card-stacked::after { .card-stacked::after {
border: 1px solid rgba($text-muted, 0.07) !important; border: 1px solid rgba($text-muted, 0.07) !important;
} }
} }
.card { .card {
box-shadow: $card-shadow; box-shadow: $card-shadow;
border: $card-border-width solid $card-border-color; border: $card-border-width solid $card-border-color;
background: var(--#{$variable-prefix}card-bg, #{$card-bg});
@media print { @media print {
border: none; border: none;
@@ -95,7 +94,7 @@
padding: $card-spacer-y $card-spacer-x; padding: $card-spacer-y $card-spacer-x;
text-align: center; text-align: center;
@include transition(background $transition-time); @include transition(background $transition-time);
border-top: 1px solid $border-color; border-top: 1px solid var(--#{$variable-prefix}border-color);
flex: 1; flex: 1;
color: inherit; color: inherit;
font-weight: $font-weight-medium; font-weight: $font-weight-medium;
@@ -105,8 +104,8 @@
background: $active-bg; background: $active-bg;
} }
&:not(:first-child) { & + & {
border-left: 1px solid $border-color; border-left: 1px solid var(--#{$variable-prefix}border-color);
} }
} }

View File

@@ -24,7 +24,7 @@ $countries: (
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: center; background-position: center;
background-size: cover; background-size: cover;
border: 1px solid $border-color; border: 1px solid var(--#{$variable-prefix}border-color);
border-radius: 3px; border-radius: 3px;
} }

View File

@@ -9,6 +9,7 @@ Form label
*/ */
.form-label { .form-label {
display: block; display: block;
font-weight: $font-weight-medium;
&.required { &.required {
&:after { &:after {
@@ -30,11 +31,8 @@ Form hint
*/ */
.form-hint { .form-hint {
display: block; display: block;
font-size: $h5-font-size;
line-height: $h5-line-height;
color: $text-muted; color: $text-muted;
&:last-child { &:last-child {
margin-bottom: 0; margin-bottom: 0;
} }
@@ -44,7 +42,7 @@ Form hint
} }
.form-label + & { .form-label + & {
margin-top: -.5rem; margin-top: -.25rem;
} }
.input-group + &, .input-group + &,
@@ -59,7 +57,8 @@ Form control
*/ */
.form-control { .form-control {
&:-webkit-autofill { &:-webkit-autofill {
box-shadow: 0 0 0 1000px $white inset; box-shadow: 0 0 0 1000px var(--#{$variable-prefix}body-bg) inset;
color: var(--#{$variable-prefix}body-color);
} }
&:disabled, &:disabled,
@@ -130,8 +129,8 @@ Form control
.form-fieldset { .form-fieldset {
padding: 1rem; padding: 1rem;
margin-bottom: 1rem; margin-bottom: 1rem;
background: $gray-50; background: var(--#{$variable-prefix}border-color-light);
border: 1px solid $border-color; border: 1px solid var(--#{$variable-prefix}border-color);
border-radius: $border-radius; border-radius: $border-radius;
} }

View File

@@ -1,6 +1,6 @@
.legend { .legend {
display: inline-block; display: inline-block;
background: $border-color; background: var(--#{$variable-prefix}border-color-light);
width: .75em; width: .75em;
height: .75em; height: .75em;
border-radius: $border-radius; border-radius: $border-radius;

View File

@@ -11,7 +11,7 @@
line-height: 1; line-height: 1;
text-transform: uppercase; text-transform: uppercase;
color: $text-muted; color: $text-muted;
border-bottom: 1px solid $list-group-border-color; border-bottom: 1px solid var(--#{$variable-prefix}border-color);
.list-group-flush > & { .list-group-flush > & {
&:last-child { &:last-child {

View File

@@ -19,7 +19,7 @@
} }
& + & { & + & {
border-top: 1px solid $border-color; border-top: 1px solid var(--#{$variable-prefix}border-color);
} }
} }

View File

@@ -11,7 +11,7 @@
.nav { .nav {
margin-left: 1.25rem; margin-left: 1.25rem;
border-left: 1px solid $border-color; border-left: 1px solid var(--#{$variable-prefix}border-color);
padding-left: .5rem; padding-left: .5rem;
} }

View File

@@ -1,3 +1,21 @@
.offcanvas-blur { .offcanvas {
backdrop-filter: blur($modal-backdrop-blur); background: var(--#{$variable-prefix}card-bg);
}
.offcanvas-header {
border-bottom: 1px solid $border-color-transparent;
}
.offcanvas-footer {
padding: $offcanvas-padding-y $offcanvas-padding-x;
}
.offcanvas-title {
font-size: $h3-font-size;
font-weight: $font-weight-medium;
line-height: 1.5rem;
}
.offcanvas-narrow {
width: 20rem;
} }

View File

@@ -16,6 +16,7 @@
width: 100%; width: 100%;
line-height: $progress-height; line-height: $progress-height;
appearance: none; appearance: none;
background: var(--#{$variable-prefix}border-color-light);
&::-webkit-progress-bar { &::-webkit-progress-bar {
background: $gray-100; background: $gray-100;
@@ -62,6 +63,6 @@
.progress-separated { .progress-separated {
.progress-bar { .progress-bar {
border-right: 2px solid $white; border-right: 2px solid var(--#{$variable-prefix}card-bg, #{$card-bg});
} }
} }

View File

@@ -18,7 +18,7 @@ Image check
display: block; display: block;
margin: 0; margin: 0;
user-select: none; user-select: none;
border: 1px solid $border-color; border: 1px solid var(--#{$variable-prefix}border-color);
border-radius: 3px; border-radius: 3px;
.form-imagecheck-input:focus ~ & { .form-imagecheck-input:focus ~ & {
@@ -27,7 +27,7 @@ Image check
} }
.form-imagecheck-input:checked ~ & { .form-imagecheck-input:checked ~ & {
border-color: $border-color; border-color: $primary;
} }
&:before { &:before {

View File

@@ -86,17 +86,23 @@ Select group
} }
} }
.form-selectgroup-check-floated {
position: absolute;
top: $input-btn-padding-y;
right: $input-btn-padding-y;
}
.form-selectgroup-input:checked + .form-selectgroup-label { .form-selectgroup-input:checked + .form-selectgroup-label {
z-index: 1; z-index: 1;
color: $primary; color: $primary;
background: rgba($primary, .04); background: rgba($primary, .04);
border-color: $input-focus-border-color; border-color: $primary;
} }
.form-selectgroup-input:focus + .form-selectgroup-label { .form-selectgroup-input:focus + .form-selectgroup-label {
z-index: 2; z-index: 2;
color: $primary; color: $primary;
border-color: $input-focus-border-color; border-color: $primary;
box-shadow: $input-btn-focus-box-shadow; box-shadow: $input-btn-focus-box-shadow;
} }

View File

@@ -1,5 +1,5 @@
%validation-lite { %validation-lite {
border-color: $input-border-color; border-color: var(--#{$variable-prefix}border-color);
} }
@each $state, $data in $form-validation-states { @each $state, $data in $form-validation-states {

2
src/scss/vendor/_apexcharts.scss vendored Normal file
View File

@@ -0,0 +1,2 @@
.apexcharts-tooltip {
}

View File

@@ -4,9 +4,12 @@
--litepicker-button-next-month-color: #{$text-muted}; --litepicker-button-next-month-color: #{$text-muted};
--litepicker-button-prev-month-color-hover: #{$primary}; --litepicker-button-prev-month-color-hover: #{$primary};
--litepicker-button-next-month-color-hover: #{$primary}; --litepicker-button-next-month-color-hover: #{$primary};
--litepicker-day-color: var(--#{$variable-prefix}body-color);
--litepicker-day-color-hover: #{$primary}; --litepicker-day-color-hover: #{$primary};
--litepicker-is-end-color-bg: #{$primary}; --litepicker-is-end-color-bg: #{$primary};
--litepicker-is-today-color: #{$primary}; --litepicker-is-today-color: #{$primary};
--litepicker-month-header-color: var(--#{$variable-prefix}body-color);
--litepicker-container-months-color-bg: var(--#{$variable-prefix}card-bg);
font: inherit; font: inherit;
user-select: none; user-select: none;
@@ -15,7 +18,7 @@
} }
.container__months { .container__months {
border: 1px solid $border-color-transparent; border: 1px solid var(--#{$variable-prefix}border-color);
border-radius: $border-radius; border-radius: $border-radius;
box-shadow: $dropdown-box-shadow; box-shadow: $dropdown-box-shadow;

View File

@@ -1,10 +1,12 @@
@import "~tom-select/src/scss/tom-select.bootstrap5.scss"; @import "~tom-select/src/scss/tom-select.bootstrap5.scss";
.ts-input {
color: inherit;
}
.ts-control{ .ts-control{
.dropdown-menu { .dropdown-menu {
width: 100%; width: 100%;
height: auto; height: auto;
} }
} }