mirror of
https://github.com/shoelace-style/webawesome.git
synced 2026-01-19 15:34:15 +00:00
Compare commits
22 Commits
lm/checkbo
...
dropdown-i
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2c60e74e3d | ||
|
|
5fb6faf527 | ||
|
|
fa558eeda0 | ||
|
|
ed3cb6d782 | ||
|
|
09c8f02f79 | ||
|
|
d6fe9f7819 | ||
|
|
200b02f023 | ||
|
|
1429095eed | ||
|
|
9706964511 | ||
|
|
bb0a961784 | ||
|
|
e2f2a8a0d3 | ||
|
|
86293cc3e1 | ||
|
|
8fb521d9ef | ||
|
|
2491ca45ac | ||
|
|
411d385d65 | ||
|
|
634828d89a | ||
|
|
17fd3d238c | ||
|
|
ab0f2a1411 | ||
|
|
4069360242 | ||
|
|
8c51c5b933 | ||
|
|
5a6ce1c4d3 | ||
|
|
e695b54dcd |
19
package-lock.json
generated
19
package-lock.json
generated
@@ -14029,7 +14029,8 @@
|
||||
"devDependencies": {
|
||||
"@wc-toolkit/jsx-types": "^1.3.0",
|
||||
"eleventy-plugin-git-commit-date": "^0.1.3",
|
||||
"esbuild": "^0.25.11"
|
||||
"esbuild": "^0.25.11",
|
||||
"npm-check-updates": "^19.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17.0"
|
||||
@@ -14037,7 +14038,7 @@
|
||||
},
|
||||
"packages/webawesome-pro": {
|
||||
"name": "@shoelace-style/webawesome-pro",
|
||||
"version": "3.0.0-beta.6",
|
||||
"version": "3.0.0",
|
||||
"dependencies": {
|
||||
"@ctrl/tinycolor": "4.1.0",
|
||||
"@floating-ui/dom": "^1.6.13",
|
||||
@@ -14966,6 +14967,20 @@
|
||||
"engines": {
|
||||
"node": "^18 || >=20"
|
||||
}
|
||||
},
|
||||
"packages/webawesome/node_modules/npm-check-updates": {
|
||||
"version": "19.1.2",
|
||||
"resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-19.1.2.tgz",
|
||||
"integrity": "sha512-FNeFCVgPOj0fz89hOpGtxP2rnnRHR7hD2E8qNU8SMWfkyDZXA/xpgjsL3UMLSo3F/K13QvJDnbxPngulNDDo/g==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"ncu": "build/cli.js",
|
||||
"npm-check-updates": "build/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0",
|
||||
"npm": ">=8.12.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { nanoid } from 'nanoid';
|
||||
import { parse as HTMLParse } from 'node-html-parser';
|
||||
import { execFileSync } from 'node:child_process';
|
||||
import * as fs from 'node:fs';
|
||||
import * as path from 'node:path';
|
||||
import { anchorHeadingsTransformer } from './_transformers/anchor-headings.js';
|
||||
@@ -21,7 +20,6 @@ import { replaceTextPlugin } from './_plugins/replace-text.js';
|
||||
import { searchPlugin } from './_plugins/search.js';
|
||||
const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
|
||||
const isDev = process.argv.includes('--develop');
|
||||
const ignoreGit = process.env.ELEVENTY_IGNORE_GIT === 'true';
|
||||
const passThroughExtensions = ['js', 'css', 'png', 'svg', 'jpg', 'mp4'];
|
||||
|
||||
async function getPackageData() {
|
||||
@@ -60,15 +58,6 @@ export default async function (eleventyConfig) {
|
||||
if (updateComponentData) {
|
||||
allComponents = getComponents();
|
||||
}
|
||||
|
||||
// Invalidate last-modified cache for changed content files during watch
|
||||
if (Array.isArray(changedFiles)) {
|
||||
for (const file of changedFiles) {
|
||||
if (/\.(md|njk|html)$/i.test(file)) {
|
||||
lastModCache.delete(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -135,78 +124,8 @@ export default async function (eleventyConfig) {
|
||||
eleventyConfig.addFilter('stripExtension', string => path.parse(string + '').name);
|
||||
eleventyConfig.addFilter('stripPrefix', content => content.replace(/^wa-/, ''));
|
||||
eleventyConfig.addFilter('uniqueId', (_value, length = 8) => nanoid(length));
|
||||
// Returns last modified date as ISO 8601 (UTC, Z-suffixed)
|
||||
// Fallback order: front matter override -> Git last commit date -> filesystem mtime -> now
|
||||
// Caching: in-memory per inputPath during one build/dev session
|
||||
// Override: pass a Date or string: {{ page.inputPath | gitLastModifiedISO(lastUpdated) }}
|
||||
const lastModCache = new Map();
|
||||
let repoRoot = null; // lazily resolved; null => not resolved, undefined => failed
|
||||
|
||||
function getLastModifiedISO(inputPath, overrideDate) {
|
||||
if (overrideDate instanceof Date) {
|
||||
return overrideDate.toISOString();
|
||||
}
|
||||
if (typeof overrideDate === 'string' && overrideDate) {
|
||||
const parsed = new Date(overrideDate);
|
||||
if (!isNaN(parsed.getTime())) return parsed.toISOString();
|
||||
}
|
||||
if (!inputPath) return new Date().toISOString();
|
||||
if (lastModCache.has(inputPath)) return lastModCache.get(inputPath);
|
||||
|
||||
// Try Git (ISO via %cI). Use a repo-root-relative path for portability.
|
||||
if (!ignoreGit) {
|
||||
try {
|
||||
if (repoRoot === null) {
|
||||
try {
|
||||
repoRoot = execFileSync('git', ['rev-parse', '--show-toplevel'], {
|
||||
stdio: ['ignore', 'pipe', 'ignore'],
|
||||
cwd: __dirname,
|
||||
})
|
||||
.toString()
|
||||
.trim();
|
||||
} catch (_) {
|
||||
repoRoot = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
const gitPath = repoRoot ? path.relative(repoRoot, inputPath) : inputPath;
|
||||
const args = ['log', '-1', '--format=%cI', '--follow', '--', gitPath];
|
||||
const result = execFileSync('git', args, {
|
||||
stdio: ['ignore', 'pipe', 'ignore'],
|
||||
cwd: repoRoot || path.dirname(inputPath),
|
||||
})
|
||||
.toString()
|
||||
.trim();
|
||||
if (result) {
|
||||
const iso = new Date(result).toISOString();
|
||||
lastModCache.set(inputPath, iso);
|
||||
return iso;
|
||||
}
|
||||
} catch (_) {
|
||||
// continue to fs fallback
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to filesystem mtime
|
||||
try {
|
||||
const stats = fs.statSync(inputPath);
|
||||
const iso = new Date(stats.mtime).toISOString();
|
||||
lastModCache.set(inputPath, iso);
|
||||
return iso;
|
||||
} catch (_) {
|
||||
const now = new Date().toISOString();
|
||||
lastModCache.set(inputPath, now);
|
||||
return now;
|
||||
}
|
||||
}
|
||||
|
||||
eleventyConfig.addFilter('gitLastModifiedISO', function (inputPath, overrideDate) {
|
||||
return getLastModifiedISO(inputPath, overrideDate);
|
||||
});
|
||||
|
||||
// Attach lastUpdatedISO to page data so templates can use {{ lastUpdatedISO }} directly
|
||||
eleventyConfig.addGlobalData('eleventyComputed', {
|
||||
lastUpdatedISO: data => getLastModifiedISO(data.page?.inputPath, data.lastUpdated),
|
||||
// Page title with smart + default site name formatting
|
||||
pageTitle: data => composePageTitle(data.title),
|
||||
// Open Graph title with smart + default site name formatting
|
||||
@@ -220,6 +139,7 @@ export default async function (eleventyConfig) {
|
||||
},
|
||||
ogType: data => data.ogType || 'website',
|
||||
});
|
||||
|
||||
// Trims whitespace and pipes from the start and end of a string. Useful for CEM types, which can be pipe-delimited.
|
||||
// With Prettier 3, this means a leading pipe will exist be present when the line wraps.
|
||||
eleventyConfig.addFilter('trimPipes', content => {
|
||||
@@ -393,18 +313,19 @@ export default async function (eleventyConfig) {
|
||||
|
||||
// This needs to happen in "eleventy.after" otherwise incremental builds never update.
|
||||
eleventyConfig.on('eleventy.after', function () {
|
||||
let assetsDir = path.join(process.env.BASE_DIR || 'docs', 'assets');
|
||||
const baseDir = process.env.BASE_DIR || 'docs';
|
||||
let assetsDir = path.join(baseDir, 'assets');
|
||||
const siteAssetsDir = path.join(eleventyConfig.directories.output, 'assets');
|
||||
fs.cpSync(assetsDir, siteAssetsDir, { recursive: true });
|
||||
|
||||
// Passthrough copy for manifest.json (PWA manifest file)
|
||||
fs.cpSync(path.join(baseDir, 'manifest.json'), path.join(eleventyConfig.directories.output, 'manifest.json'));
|
||||
});
|
||||
|
||||
for (let glob of passThrough) {
|
||||
eleventyConfig.addPassthroughCopy(glob);
|
||||
}
|
||||
|
||||
// Passthrough copy for manifest.json (PWA manifest file)
|
||||
eleventyConfig.addPassthroughCopy('manifest.json');
|
||||
|
||||
// // SSR plugin
|
||||
// if (!isDev) {
|
||||
// //
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% raw %}
|
||||
{%- if not currentUser.hasPro -%}
|
||||
{%- if req.stripe.discount.active and not currentUser.hasPro -%}
|
||||
<div slot="banner" class="banner-wa-launch wa-dark">
|
||||
<div class="banner-content wa-split">
|
||||
<div class="wa-cluster wa-gap-s">
|
||||
|
||||
@@ -1,97 +1,95 @@
|
||||
<wa-dialog id="dialog-site" light-dismiss without-header>
|
||||
{% raw %}
|
||||
{%- if req.stripe.discount.active and not currentUser.hasPro -%}
|
||||
<wa-dialog id="dialog-site" light-dismiss without-header>
|
||||
|
||||
<div class="background-wa-pattern" style="justify-content: center; margin-inline: calc(var(--spacing) * -1); margin-block-start: calc(var(--spacing) * -1); margin-block-end: var(--spacing); background: linear-gradient(to bottom, var(--wa-color-brand), var(--wa-color-brand-50)); color: var(--wa-color-brand-on-loud); padding: var(--wa-space-3xl) var(--spacing); --background-pattern-opacity: 0.2; --background-pattern-image: url('/assets/images/bg-wa-pattern.svg');">
|
||||
<div class="background-wa-pattern" style="justify-content: center; margin-inline: calc(var(--spacing) * -1); margin-block-start: calc(var(--spacing) * -1); margin-block-end: var(--spacing); background: linear-gradient(to bottom, var(--wa-color-brand), var(--wa-color-brand-50)); color: var(--wa-color-brand-on-loud); padding: var(--wa-space-3xl) var(--spacing); --background-pattern-opacity: 0.2; --background-pattern-image: url('/assets/images/bg-wa-pattern.svg');">
|
||||
|
||||
<div class="wa-stack wa-align-items-center" style="text-align: center;">
|
||||
<wa-icon name="party-horn" family="duotone" variant="solid" style="font-size: var(--wa-font-size-3xl); --secondary-color: var(--wa-color-brand-40); --secondary-opacity: 1.0;"></wa-icon>
|
||||
<h2 class="wa-heading-2xl brand-font">Get a lifetime discount on Web Awesome Pro!</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="wa-stack wa-align-items-center" style="text-align: center;">
|
||||
<wa-icon name="party-horn" family="duotone" variant="solid" style="font-size: var(--wa-font-size-3xl); --secondary-color: var(--wa-color-brand-40); --secondary-opacity: 1.0;"></wa-icon>
|
||||
<h2 class="wa-heading-2xl brand-font">Get a lifetime discount on Web Awesome Pro!</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="wa-stack wa-gap-l">
|
||||
<p>Celebrate our official launch with a 20% discount on a Web Awesome Pro plan…<span class="appearance-underlined variant-drawn" style="--underline-color: var(--wa-color-brand);">for life</span>! But hurry, this lifetime discount is only available for a limited time.</p>
|
||||
<div class="wa-stack wa-gap-l">
|
||||
<p>Celebrate our official launch with a 20% discount on a Web Awesome Pro plan…<span class="appearance-underlined variant-drawn" style="--underline-color: var(--wa-color-brand);">for life</span>! But hurry, this lifetime discount is only available for a limited time.</p>
|
||||
|
||||
<div class="wa-split">
|
||||
<wa-button type="button" appearance="plain" data-dialog="close" class="plausible-event-name=launch_dialog:close_button_click">Maybe Later</wa-button>
|
||||
<wa-button variant="neutral" appearance="accent" href="/purchase" class="brand-font plausible-event-name=launch_dialog:pro_purchase_button_click">
|
||||
<wa-icon slot="start" variant="regular" name="rocket-launch"></wa-icon>
|
||||
Get Pro + Save 20%
|
||||
</wa-button>
|
||||
</div>
|
||||
</div>
|
||||
</wa-dialog>
|
||||
<div class="wa-split">
|
||||
<wa-button type="button" appearance="plain" data-dialog="close" class="plausible-event-name=launch_dialog:close_button_click">Maybe Later</wa-button>
|
||||
<wa-button variant="neutral" appearance="accent" href="/purchase" class="brand-font plausible-event-name=launch_dialog:pro_purchase_button_click">
|
||||
<wa-icon slot="start" variant="regular" name="rocket-launch"></wa-icon>
|
||||
Get Pro + Save 20%
|
||||
</wa-button>
|
||||
</div>
|
||||
</div>
|
||||
</wa-dialog>
|
||||
|
||||
<script type="module">
|
||||
(function() {
|
||||
const SITE_DIALOG_DISMISSED_KEY = 'dialog-wa-launch-sale-dismissed';
|
||||
<script type="module">
|
||||
(function() {
|
||||
const SITE_DIALOG_DISMISSED_KEY = 'dialog-wa-launch-sale-dismissed';
|
||||
|
||||
// Early exit if user has dismissed the dialog
|
||||
try {
|
||||
if (localStorage.getItem(SITE_DIALOG_DISMISSED_KEY) === 'true') {
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
// localStorage may be disabled or unavailable
|
||||
return;
|
||||
}
|
||||
|
||||
// Wait for DOM and dialog element
|
||||
const dialog = document.getElementById('dialog-site');
|
||||
if (!dialog) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Helper function to safely track Plausible events
|
||||
const trackEvent = (eventName) => {
|
||||
if (typeof plausible !== 'undefined') {
|
||||
plausible(eventName);
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize dialog functionality
|
||||
let initCalled = false;
|
||||
const initDialog = () => {
|
||||
// Prevent double initialization
|
||||
if (initCalled) {
|
||||
return;
|
||||
}
|
||||
initCalled = true;
|
||||
|
||||
// Track when dialog is shown
|
||||
dialog.addEventListener('wa-show', () => {
|
||||
trackEvent('launch_dialog:view');
|
||||
}, { once: true });
|
||||
|
||||
// Track when dialog is dismissed
|
||||
dialog.addEventListener('wa-hide', (event) => {
|
||||
// Track overlay click or Escape key dismissal
|
||||
// Button clicks are tracked via CSS classes, so we only track non-button dismissals
|
||||
if (event.detail?.source === dialog) {
|
||||
trackEvent('launch_dialog:overlay_click');
|
||||
}
|
||||
|
||||
// Save dismissal state to localStorage
|
||||
// Early exit if user has dismissed the dialog
|
||||
try {
|
||||
localStorage.setItem(SITE_DIALOG_DISMISSED_KEY, 'true');
|
||||
if (localStorage.getItem(SITE_DIALOG_DISMISSED_KEY) === 'true') {
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
// localStorage may be disabled or unavailable
|
||||
return;
|
||||
}
|
||||
}, { once: true });
|
||||
|
||||
// Show dialog after a short delay to ensure page is loaded
|
||||
setTimeout(() => {
|
||||
dialog.open = true;
|
||||
}, 500);
|
||||
};
|
||||
// Wait for DOM and dialog element
|
||||
const dialog = document.getElementById('dialog-site');
|
||||
if (!dialog) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize when ready
|
||||
if (customElements.get('wa-dialog')) {
|
||||
initDialog();
|
||||
} else {
|
||||
document.addEventListener('wa-discovery-complete', initDialog, { once: true });
|
||||
// Fallback timeout in case wa-discovery-complete doesn't fire
|
||||
setTimeout(initDialog, 100);
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
// Helper function to safely track Plausible events
|
||||
const trackEvent = (eventName) => {
|
||||
if (typeof plausible !== 'undefined') {
|
||||
plausible(eventName);
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize dialog functionality
|
||||
let initCalled = false;
|
||||
const initDialog = () => {
|
||||
// Prevent double initialization
|
||||
if (initCalled) {
|
||||
return;
|
||||
}
|
||||
initCalled = true;
|
||||
|
||||
// Track when dialog is shown
|
||||
dialog.addEventListener('wa-show', () => {
|
||||
trackEvent('launch_dialog:view');
|
||||
}, { once: true });
|
||||
|
||||
// Track when dialog is dismissed
|
||||
dialog.addEventListener('wa-hide', (event) => {
|
||||
// Track overlay click or Escape key dismissal
|
||||
// Button clicks are tracked via CSS classes, so we only track non-button dismissals
|
||||
if (event.detail?.source === dialog) {
|
||||
trackEvent('launch_dialog:overlay_click');
|
||||
}
|
||||
|
||||
// Save dismissal state to localStorage
|
||||
try {
|
||||
localStorage.setItem(SITE_DIALOG_DISMISSED_KEY, 'true');
|
||||
} catch (e) {
|
||||
// localStorage may be disabled or unavailable
|
||||
}
|
||||
}, { once: true });
|
||||
|
||||
// Show dialog after a short delay to ensure page is loaded
|
||||
setTimeout(() => {
|
||||
dialog.open = true;
|
||||
}, 500);
|
||||
};
|
||||
|
||||
customElements.whenDefined("wa-dialog").then(() => {
|
||||
initDialog()
|
||||
})
|
||||
})();
|
||||
</script>
|
||||
{%- endif -%}
|
||||
{% endraw %}
|
||||
|
||||
@@ -139,11 +139,7 @@
|
||||
|
||||
{#- Site-Wide Dialog -#}
|
||||
{% if hasSiteDialog %}
|
||||
{% raw %}
|
||||
{%- if not currentUser.hasPro -%}
|
||||
{% include "_dialog-wa-launch.njk" ignore missing %}
|
||||
{%- endif -%}
|
||||
{% endraw %}
|
||||
{% include "_dialog-wa-launch.njk" ignore missing %}
|
||||
{% endif %}
|
||||
|
||||
{# Footer #}
|
||||
|
||||
@@ -78,10 +78,10 @@
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><span class="is-planned wa-split">Charts <a href="https://github.com/shoelace-style/webawesome/issues/1073" target="_blank">{{ plannedBadge("A Web Awesome Kickstarter stretch goal!") }}</a></span></li>
|
||||
<li><span class="is-planned wa-split">Charts <span><a href="https://github.com/shoelace-style/webawesome/issues/1073" target="_blank">{{ plannedBadge("A Web Awesome Kickstarter stretch goal!") }}</a>{{ proBadge({ description: "This will require access to Web Awesome Pro" }) }}</span></span></li>
|
||||
<li><a href="/docs/components/checkbox/">Checkbox</a></li>
|
||||
<li><a href="/docs/components/color-picker/">Color Picker</a></li>
|
||||
<li><span class="is-planned wa-split">Combobox <a href="https://github.com/shoelace-style/webawesome/issues/1074" target="_blank">{{ plannedBadge("A Web Awesome Kickstarter stretch goal!") }}</a></span></li>
|
||||
<li><span class="is-planned wa-split">Combobox <span><a href="https://github.com/shoelace-style/webawesome/issues/1074" target="_blank">{{ plannedBadge("A Web Awesome Kickstarter stretch goal!") }}</a>{{ proBadge({ description: "This will require access to Web Awesome Pro" }) }}</span></span></li>
|
||||
<li><a href="/docs/components/comparison/">Comparison</a></li>
|
||||
<li>
|
||||
<a class="wa-cluster wa-gap-xs" href="/docs/components/copy-button/">
|
||||
@@ -89,8 +89,8 @@
|
||||
<wa-icon name="flask" aria-hidden="true" class="icon-shrink"></wa-icon>
|
||||
</a>
|
||||
</li>
|
||||
<li><span class="is-planned wa-split">Data Grid <a href="https://github.com/shoelace-style/webawesome/issues/1072" target="_blank">{{ plannedBadge("A Web Awesome Kickstarter stretch goal!") }}</a></span></li>
|
||||
<li><span class="is-planned wa-split">Datepicker <a href="https://github.com/shoelace-style/webawesome/issues/1075" target="_blank">{{ plannedBadge("A Web Awesome Kickstarter stretch goal!") }}</a></span></li>
|
||||
<li><span class="is-planned wa-split">Data Grid <span><a href="https://github.com/shoelace-style/webawesome/issues/1072" target="_blank">{{ plannedBadge("A Web Awesome Kickstarter stretch goal!") }}</a>{{ proBadge({ description: "This will require access to Web Awesome Pro" }) }}</span></span></li>
|
||||
<li><span class="is-planned wa-split">Datepicker <span><a href="https://github.com/shoelace-style/webawesome/issues/1075" target="_blank">{{ plannedBadge("A Web Awesome Kickstarter stretch goal!") }}</a>{{ proBadge({ description: "This will require access to Web Awesome Pro" }) }}</span></span></li>
|
||||
<li><a href="/docs/components/details/">Details</a></li>
|
||||
<li><a href="/docs/components/dialog/">Dialog</a></li>
|
||||
<li><a href="/docs/components/divider/">Divider</a></li>
|
||||
@@ -101,7 +101,7 @@
|
||||
<li><a href="/docs/components/dropdown-item">Dropdown Item</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><span class="is-planned wa-split">File Input <a href="https://github.com/shoelace-style/webawesome/issues/1240" target="_blank">{{ plannedBadge("A Web Awesome Kickstarter stretch goal!") }}</a></span></li>
|
||||
<li><span class="is-planned wa-split">File Input <span><a href="https://github.com/shoelace-style/webawesome/issues/1240" target="_blank">{{ plannedBadge("A Web Awesome Kickstarter stretch goal!") }}</a>{{ proBadge({ description: "This will require access to Web Awesome Pro" }) }}</span></span></li>
|
||||
<li><a href="/docs/components/format-bytes/">Format Bytes</a></li>
|
||||
<li><a href="/docs/components/format-date/">Format Date</a></li>
|
||||
<li><a href="/docs/components/format-number/">Format Number</a></li>
|
||||
@@ -146,7 +146,7 @@
|
||||
</li>
|
||||
<li><a href="/docs/components/tag/">Tag</a></li>
|
||||
<li><a href="/docs/components/textarea/">Textarea</a></li>
|
||||
<li><span class="is-planned wa-split">Toast <a href="https://github.com/shoelace-style/webawesome/issues/105" target="_blank">{{ plannedBadge("A Web Awesome Kickstarter stretch goal!") }}</a></span></li>
|
||||
<li><span class="is-planned wa-split">Toast <span><a href="https://github.com/shoelace-style/webawesome/issues/105" target="_blank">{{ plannedBadge("A Web Awesome Kickstarter stretch goal!") }}</a>{{ proBadge( { description: "This will require access to Web Awesome Pro" }) }}</span></span></li>
|
||||
<li><a href="/docs/components/tooltip/">Tooltip</a></li>
|
||||
<li>
|
||||
<a href="/docs/components/tree/">Tree</a>
|
||||
@@ -154,7 +154,7 @@
|
||||
<li><a href="/docs/components/tree-item/">Tree Item</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><span class="is-planned wa-split">Video <a href="https://github.com/shoelace-style/webawesome/issues/985" target="_blank">{{ plannedBadge("A Web Awesome Kickstarter stretch goal!") }}</a></span></li>
|
||||
<li><span class="is-planned wa-split">Video <span><a href="https://github.com/shoelace-style/webawesome/issues/985" target="_blank">{{ plannedBadge("A Web Awesome Kickstarter stretch goal!") }}</a>{{ proBadge( { description: "This will require access to Web Awesome Pro" }) }}</span></span></li>
|
||||
<li><a href="/docs/components/zoomable-frame">Zoomable Frame</a></li>
|
||||
{# PLOP_NEW_COMPONENT_PLACEHOLDER #}
|
||||
</ul>
|
||||
|
||||
@@ -1,10 +1,20 @@
|
||||
import * as path from 'node:path';
|
||||
import nunjucks from 'nunjucks';
|
||||
|
||||
const baseDir = process.env.BASE_DIR || 'docs';
|
||||
|
||||
const views = [path.join(baseDir), path.join(baseDir, '_layouts'), path.join(baseDir, '_includes')];
|
||||
|
||||
const nunjucksEnv = new nunjucks.Environment(new nunjucks.FileSystemLoader(views), {
|
||||
autoescape: true,
|
||||
noCache: process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test',
|
||||
});
|
||||
|
||||
/**
|
||||
* This function simulates what a server would do running "on top" of eleventy.
|
||||
*/
|
||||
export function SimulateWebAwesomeApp(str) {
|
||||
return nunjucks.renderString(str, {
|
||||
return nunjucksEnv.renderString(str, {
|
||||
// Stub the server EJS shortcodes.
|
||||
currentUser: {
|
||||
hasPro: false,
|
||||
|
||||
@@ -38,7 +38,7 @@ wa-page > [slot='banner'] {
|
||||
}
|
||||
|
||||
&.banner-wa-launch {
|
||||
/* custom brand colors carrried over from theme-site for the banner */
|
||||
/* custom brand colors carried over from theme-site for the banner */
|
||||
--wa-color-brand-95: #fef0ec;
|
||||
--wa-color-brand-90: #fce0d8;
|
||||
--wa-color-brand-80: #f8bcac;
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
border-radius: var(--wa-border-radius-l);
|
||||
padding: 0;
|
||||
margin: 0 auto;
|
||||
overflow: hidden;
|
||||
|
||||
&::part(dialog) {
|
||||
margin-block-start: 10vh;
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
---
|
||||
title: Changelog
|
||||
dateLastUpdated: 2025-11-07
|
||||
description: Changes to each version of the project are documented here.
|
||||
layout: page-outline
|
||||
---
|
||||
|
||||
<p class="wa-caption-s">Last updated: <wa-format-date month="long" day="numeric" year="numeric" date="{{ lastUpdatedISO }}"></wa-format-date></p>
|
||||
<p class="wa-caption-s">Last updated: <wa-format-date month="long" day="numeric" year="numeric" date="{{ dateLastUpdated }}"></wa-format-date></p>
|
||||
|
||||
Web Awesome follows [Semantic Versioning](https://semver.org/). Breaking changes in components with the <wa-badge variant="brand">Stable</wa-badge> badge will not be accepted until the next major version. As such, all contributions must consider the project's roadmap and take this into consideration. Features that are deemed no longer necessary will be deprecated but not removed.
|
||||
|
||||
@@ -12,14 +13,23 @@ Components with the <wa-badge variant="warning">Experimental</wa-badge> badge sh
|
||||
|
||||
## Next
|
||||
|
||||
- Added `layers.css` to define cascade layer order and updated palettes, themes, native styles, and utilities to import the new rule for more fail-safe modularity [pr:1793]
|
||||
- Fixed a bug in `<wa-slider>` that caused some touch devices to end up with the incorrect value [issue:1703]
|
||||
- Fixed a bug in `<wa-card>` that prevented some slots from being detected correctly [discuss:1450]
|
||||
- Fixed a z-index bug in `<wa-scroller>` styles [issue:1724]
|
||||
- Fixed a bug in `<wa-icon>` that caused some icon libraries to render with the incorrect SVG fill [issue:1733]
|
||||
- Fixed a bug in `<wa-tree-item>` that caused the spinner to not show when lazy loading [issue:1678]
|
||||
- Fixed a bug in `<wa-dropdown>` that caused the browser to hang when cancelling the `wa-hide` event [issue:1483]
|
||||
- Fixed a bug in `<wa-dropdown-item>` that prevented the icon dependency from being imported [issue:1825]
|
||||
- Improved performance of `<wa-icon>` so initial rendering occurs faster, especially with multiple icons on the page [issue:1729]
|
||||
- Modified the default `transition` styles of `<wa-dropdown-item>` to use design tokens [pr:1693]
|
||||
|
||||
## 3.0.0
|
||||
|
||||
- 🚨 BREAKING: Changed `appearance="filled outlined"` to `appearance="filled-outlined"` in the following elements [issue:1127]
|
||||
- `<wa-badge>`
|
||||
- `<wa-button>`
|
||||
- `<wa-callout>`
|
||||
- `<wa-card>`
|
||||
- `<wa-details>`
|
||||
- `<wa-input>`
|
||||
- `<wa-select>`
|
||||
|
||||
@@ -22,7 +22,7 @@ As soon as all elements are registered _or_ after two seconds have elapsed, the
|
||||
|
||||
:::details Are you using Turbo in your app?
|
||||
|
||||
If you're using [Turbo](https://turbo.hotwired.dev/) to serve a multi-page application (MPA) as a single page application (SPA), you might notice FOUCE when navigating from page to page. This is because Turbo renders the new page's content before the autoloader has a change to register new components.
|
||||
If you're using [Turbo](https://turbo.hotwired.dev/) to serve a multi-page application (MPA) as a single page application (SPA), you might notice FOUCE when navigating from page to page. This is because Turbo renders the new page's content before the autoloader has a chance to register new components.
|
||||
|
||||
The following function acts as a middleware to ensure components are registered _before_ the page shows, eliminating FOUCE for page-to-page navigation with Turbo.
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
"spellcheck": "cspell \"**/*.{js,ts,json,html,css,md}\" --no-progress --config=\"../../cspell.json\"",
|
||||
"verify": "npm run prettier && npm run build && npm run test",
|
||||
"prepublishOnly": "npm run verify",
|
||||
"check-updates": "npx npm-check-updates --interactive --format group",
|
||||
"check-updates": "npm-check-updates --cooldown 7 --interactive --format group",
|
||||
"print-version": "echo $npm_package_version",
|
||||
"tag-version": "git tag -a \"v$(npm run print-version | tail -n1)\" -m \"tag v$(npm run print-version | tail -n1)\"",
|
||||
"postversion": "npm run tag-version"
|
||||
@@ -91,6 +91,7 @@
|
||||
"devDependencies": {
|
||||
"@wc-toolkit/jsx-types": "^1.3.0",
|
||||
"eleventy-plugin-git-commit-date": "^0.1.3",
|
||||
"esbuild": "^0.25.11"
|
||||
"esbuild": "^0.25.11",
|
||||
"npm-check-updates": "^19.1.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,27 +16,28 @@
|
||||
}
|
||||
|
||||
/* Appearance modifiers */
|
||||
:host([appearance~='plain']) {
|
||||
:host([appearance='plain']) {
|
||||
background-color: transparent;
|
||||
border-color: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
:host([appearance~='outlined']) {
|
||||
:host([appearance='outlined']) {
|
||||
background-color: var(--wa-color-surface-default);
|
||||
border-color: var(--wa-color-surface-border);
|
||||
}
|
||||
|
||||
:host([appearance~='filled']) {
|
||||
:host([appearance='filled']) {
|
||||
background-color: var(--wa-color-neutral-fill-quiet);
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
:host([appearance~='filled'][appearance~='outlined']) {
|
||||
border-color: var(--wa-color-neutral-border-quiet);
|
||||
:host([appearance='filled-outlined']) {
|
||||
background-color: var(--wa-color-neutral-fill-quiet);
|
||||
border-color: var(--wa-color-surface-border);
|
||||
}
|
||||
|
||||
:host([appearance~='accent']) {
|
||||
:host([appearance='accent']) {
|
||||
color: var(--wa-color-neutral-on-loud);
|
||||
background-color: var(--wa-color-neutral-fill-loud);
|
||||
border-color: transparent;
|
||||
|
||||
@@ -30,11 +30,19 @@ import styles from './card.css';
|
||||
export default class WaCard extends WebAwesomeElement {
|
||||
static css = [sizeStyles, styles];
|
||||
|
||||
private readonly hasSlotController = new HasSlotController(this, 'footer', 'header', 'media');
|
||||
private readonly hasSlotController = new HasSlotController(
|
||||
this,
|
||||
'footer',
|
||||
'header',
|
||||
'media',
|
||||
'header-actions',
|
||||
'footer-actions',
|
||||
'actions',
|
||||
);
|
||||
|
||||
/** The card's visual appearance. */
|
||||
@property({ reflect: true })
|
||||
appearance: 'accent' | 'filled' | 'outlined' | 'plain' = 'outlined';
|
||||
appearance: 'accent' | 'filled' | 'outlined' | 'filled-outlined' | 'plain' = 'outlined';
|
||||
|
||||
/** Renders the card with a header. Only needed for SSR, otherwise is automatically added. */
|
||||
@property({ attribute: 'with-header', type: Boolean, reflect: true }) withHeader = false;
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
line-height: var(--wa-line-height-condensed);
|
||||
cursor: pointer;
|
||||
transition:
|
||||
100ms background-color ease,
|
||||
100ms color ease;
|
||||
var(--wa-transition-fast) background-color var(--wa-transition-easing),
|
||||
var(--wa-transition-fast) color var(--wa-transition-easing);
|
||||
}
|
||||
|
||||
@media (hover: hover) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import { customElement, property, query, state } from 'lit/decorators.js';
|
||||
import { animateWithClass } from '../../internal/animate.js';
|
||||
import { HasSlotController } from '../../internal/slot.js';
|
||||
import WebAwesomeElement from '../../internal/webawesome-element.js';
|
||||
import '../icon/icon.js';
|
||||
import styles from './dropdown-item.css';
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { expect, fixture, html } from '@open-wc/testing';
|
||||
import { aTimeout, expect, fixture, html, waitUntil } from '@open-wc/testing';
|
||||
import sinon from 'sinon';
|
||||
import type WaDropdown from './dropdown.js';
|
||||
|
||||
describe('<wa-dropdown>', () => {
|
||||
it('should render a component', async () => {
|
||||
@@ -6,4 +8,112 @@ describe('<wa-dropdown>', () => {
|
||||
|
||||
expect(el).to.exist;
|
||||
});
|
||||
|
||||
it('should respect the open attribute when included', async () => {
|
||||
const el = await fixture<WaDropdown>(html`
|
||||
<wa-dropdown open>
|
||||
<wa-button slot="trigger">Dropdown</wa-button>
|
||||
<wa-dropdown-item>One</wa-dropdown-item>
|
||||
</wa-dropdown>
|
||||
`);
|
||||
|
||||
await el.updateComplete;
|
||||
await aTimeout(200);
|
||||
|
||||
expect(el.open).to.be.true;
|
||||
});
|
||||
|
||||
it('should fire a single show/after-show and hide/after-hide in normal open/close flow', async () => {
|
||||
const el = await fixture<WaDropdown>(html`
|
||||
<wa-dropdown>
|
||||
<wa-button slot="trigger">Dropdown</wa-button>
|
||||
<wa-dropdown-item>One</wa-dropdown-item>
|
||||
<wa-dropdown-item>Two</wa-dropdown-item>
|
||||
</wa-dropdown>
|
||||
`);
|
||||
|
||||
// setup spies to track how often we see different show/hide events
|
||||
const showSpy = sinon.spy();
|
||||
const afterShowSpy = sinon.spy();
|
||||
const hideSpy = sinon.spy();
|
||||
const afterHideSpy = sinon.spy();
|
||||
|
||||
el.addEventListener('wa-show', showSpy);
|
||||
el.addEventListener('wa-after-show', afterShowSpy);
|
||||
el.addEventListener('wa-hide', hideSpy);
|
||||
el.addEventListener('wa-after-hide', afterHideSpy);
|
||||
|
||||
// open the dropdown by triggering a click on the trigger
|
||||
const trigger = el.querySelector<HTMLElement>('[slot="trigger"]')!;
|
||||
trigger.click();
|
||||
|
||||
await waitUntil(() => showSpy.calledOnce);
|
||||
await waitUntil(() => afterShowSpy.calledOnce);
|
||||
|
||||
expect(showSpy.callCount).to.equal(1);
|
||||
expect(afterShowSpy.callCount).to.equal(1);
|
||||
|
||||
expect(el.open).to.be.true;
|
||||
|
||||
// close the dropdown by clicking the trigger again
|
||||
trigger.click();
|
||||
|
||||
await waitUntil(() => hideSpy.calledOnce);
|
||||
await waitUntil(() => afterHideSpy.calledOnce);
|
||||
|
||||
expect(hideSpy.callCount).to.equal(1);
|
||||
expect(afterHideSpy.callCount).to.equal(1);
|
||||
|
||||
expect(el.open).to.be.false;
|
||||
});
|
||||
|
||||
it('should fire a single show/after-show and hide/after-hide when wa-hide event is cancelled', async () => {
|
||||
const el = await fixture<WaDropdown>(html`
|
||||
<wa-dropdown>
|
||||
<wa-button slot="trigger">Dropdown</wa-button>
|
||||
<wa-dropdown-item>One</wa-dropdown-item>
|
||||
<wa-dropdown-item>Two</wa-dropdown-item>
|
||||
</wa-dropdown>
|
||||
`);
|
||||
|
||||
// setup spies to track how often we see different show/hide events
|
||||
const showSpy = sinon.spy();
|
||||
const afterShowSpy = sinon.spy();
|
||||
const hideSpy = sinon.spy();
|
||||
const afterHideSpy = sinon.spy();
|
||||
|
||||
el.addEventListener('wa-show', showSpy);
|
||||
el.addEventListener('wa-after-show', afterShowSpy);
|
||||
|
||||
// Intercept wa-hide and prevent it
|
||||
el.addEventListener('wa-hide', event => {
|
||||
event.preventDefault();
|
||||
hideSpy(event);
|
||||
});
|
||||
|
||||
el.addEventListener('wa-after-hide', afterHideSpy);
|
||||
|
||||
// open the dropdown by triggering a click on the trigger
|
||||
const trigger = el.querySelector<HTMLElement>('[slot="trigger"]')!;
|
||||
trigger.click();
|
||||
|
||||
await waitUntil(() => showSpy.calledOnce);
|
||||
await waitUntil(() => afterShowSpy.calledOnce);
|
||||
|
||||
expect(showSpy.callCount).to.equal(1);
|
||||
expect(afterShowSpy.callCount).to.equal(1);
|
||||
|
||||
expect(el.open).to.be.true;
|
||||
|
||||
// click on the trigger (which should do nothing to the open state)
|
||||
trigger.click();
|
||||
|
||||
await waitUntil(() => hideSpy.calledOnce);
|
||||
|
||||
expect(hideSpy.callCount).to.equal(1);
|
||||
// after-hide should not have been called if hide is cancelled
|
||||
expect(afterHideSpy.callCount).to.equal(0);
|
||||
|
||||
expect(el.open).to.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -109,6 +109,18 @@ export default class WaDropdown extends WebAwesomeElement {
|
||||
|
||||
async updated(changedProperties: PropertyValues) {
|
||||
if (changedProperties.has('open')) {
|
||||
const previousOpen = changedProperties.get('open');
|
||||
// check if the previous value is the same
|
||||
// (if they are, do not trigger menu showing / hiding)
|
||||
if (previousOpen === this.open) {
|
||||
return;
|
||||
}
|
||||
// check if we are changing from undefined to false
|
||||
// (if we are, we can skip menu hiding)
|
||||
if (previousOpen === undefined && this.open === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.customStates.set('open', this.open);
|
||||
|
||||
if (this.open) {
|
||||
@@ -227,6 +239,12 @@ export default class WaDropdown extends WebAwesomeElement {
|
||||
return;
|
||||
}
|
||||
|
||||
// if this dropdown is already open, do nothing
|
||||
// (this can happen when wa-hide was cancelled)
|
||||
if (this.popup.active) {
|
||||
return;
|
||||
}
|
||||
|
||||
openDropdowns.forEach(dropdown => (dropdown.open = false));
|
||||
|
||||
this.popup.active = true; // Use wa-popup's active property instead of showPopover
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
svg {
|
||||
height: 1em;
|
||||
fill: currentColor;
|
||||
overflow: visible;
|
||||
|
||||
/* Duotone colors with path-specific opacity fallback */
|
||||
|
||||
@@ -187,7 +187,7 @@ export default class WaIcon extends WebAwesomeElement {
|
||||
}
|
||||
}
|
||||
|
||||
@watch(['family', 'name', 'library', 'variant', 'src', 'autoWidth', 'swapOpacity'])
|
||||
@watch(['family', 'name', 'library', 'variant', 'src', 'autoWidth', 'swapOpacity'], { waitUntilFirstUpdate: true })
|
||||
async setIcon() {
|
||||
const { url, fromLibrary } = this.getIconSource();
|
||||
const library = fromLibrary ? getIconLibrary(this.library) : undefined;
|
||||
@@ -249,7 +249,7 @@ export default class WaIcon extends WebAwesomeElement {
|
||||
return this.svg;
|
||||
}
|
||||
|
||||
return html`<svg part="svg" fill="currentColor" width="16" height="16"></svg>`;
|
||||
return html`<svg part="svg" width="16" height="16"></svg>`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,6 +53,19 @@
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#start-shadow,
|
||||
#end-shadow {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#start-shadow {
|
||||
opacity: var(--start-shadow-opacity);
|
||||
}
|
||||
|
||||
#end-shadow {
|
||||
opacity: var(--end-shadow-opacity);
|
||||
}
|
||||
|
||||
/* Horizontal shadows */
|
||||
:host([orientation='horizontal']) {
|
||||
#start-shadow,
|
||||
@@ -64,14 +77,6 @@
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#start-shadow {
|
||||
opacity: var(--start-shadow-opacity);
|
||||
}
|
||||
|
||||
#end-shadow {
|
||||
opacity: var(--end-shadow-opacity);
|
||||
}
|
||||
|
||||
#start-shadow {
|
||||
&:dir(ltr) {
|
||||
left: 0;
|
||||
@@ -102,21 +107,12 @@
|
||||
#start-shadow,
|
||||
#end-shadow {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
right: 0;
|
||||
left: 0;
|
||||
height: var(--shadow-size);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#start-shadow {
|
||||
opacity: var(--start-shadow-opacity);
|
||||
}
|
||||
|
||||
#end-shadow {
|
||||
opacity: var(--end-shadow-opacity);
|
||||
}
|
||||
|
||||
#start-shadow {
|
||||
top: 0;
|
||||
background: linear-gradient(to bottom, var(--shadow-color), transparent 100%);
|
||||
|
||||
@@ -74,7 +74,6 @@
|
||||
padding: 0 var(--wa-form-control-padding-inline);
|
||||
position: relative;
|
||||
vertical-align: middle;
|
||||
width: 100%;
|
||||
transition:
|
||||
background-color var(--wa-transition-normal),
|
||||
border var(--wa-transition-normal),
|
||||
|
||||
@@ -119,7 +119,7 @@ export default class WaSelect extends WebAwesomeFormAssociatedElement {
|
||||
@state() optionValues: Set<string | null> | undefined;
|
||||
|
||||
/** The name of the select, submitted as a name/value pair with form data. */
|
||||
@property() name = '';
|
||||
@property({ reflect: true }) name = '';
|
||||
|
||||
private _defaultValue: null | string | string[] = null;
|
||||
|
||||
|
||||
@@ -73,12 +73,16 @@ slot:not([name])::slotted(wa-icon) {
|
||||
rotate: -90deg;
|
||||
}
|
||||
|
||||
.tree-item-expanded slot[name='expand-icon'],
|
||||
.tree-item-expanded:not(.tree-item-loading) slot[name='expand-icon'],
|
||||
.tree-item:not(.tree-item-expanded) slot[name='collapse-icon'] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tree-item:not(.tree-item-has-expand-button) .expand-icon-slot {
|
||||
.tree-item:not(.tree-item-has-expand-button):not(.tree-item-loading) .expand-icon-slot {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tree-item-loading .expand-icon-slot wa-icon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
@@ -254,6 +254,7 @@ export default class WaTreeItem extends WebAwesomeElement {
|
||||
'tree-item-expanded': this.expanded,
|
||||
'tree-item-selected': this.selected,
|
||||
'tree-item-leaf': this.isLeaf,
|
||||
'tree-item-loading': this.loading,
|
||||
'tree-item-has-expand-button': showExpandButton,
|
||||
})}"
|
||||
>
|
||||
@@ -272,8 +273,10 @@ export default class WaTreeItem extends WebAwesomeElement {
|
||||
${when(
|
||||
this.loading,
|
||||
() => html` <wa-spinner part="spinner" exportparts="base:spinner__base"></wa-spinner> `,
|
||||
() => html`
|
||||
<wa-icon name=${isRtl ? 'chevron-left' : 'chevron-right'} library="system" variant="solid"></wa-icon>
|
||||
`,
|
||||
)}
|
||||
<wa-icon name=${isRtl ? 'chevron-left' : 'chevron-right'} library="system" variant="solid"></wa-icon>
|
||||
</slot>
|
||||
<slot class="expand-icon-slot" name="collapse-icon">
|
||||
<wa-icon name=${isRtl ? 'chevron-left' : 'chevron-right'} library="system" variant="solid"></wa-icon>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/* Rules shared by all palettes */
|
||||
@import url('../../layers.css');
|
||||
@import url('../variants.css');
|
||||
|
||||
/* Generates --wa-color-{hue}-on tokens for pairing with any palette's key colors */
|
||||
:where(:root),
|
||||
:host {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@import url('base.css');
|
||||
@import url('../variants.css');
|
||||
|
||||
@layer wa-color-palette {
|
||||
.wa-palette-bright {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@import url('base.css');
|
||||
@import url('../variants.css');
|
||||
|
||||
@layer wa-color-palette {
|
||||
:where(:root),
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@import url('base.css');
|
||||
@import url('../variants.css');
|
||||
|
||||
@layer wa-color-palette {
|
||||
.wa-palette-shoelace,
|
||||
|
||||
2
packages/webawesome/src/styles/layers.css
Normal file
2
packages/webawesome/src/styles/layers.css
Normal file
@@ -0,0 +1,2 @@
|
||||
/* Order of precedence for all cascade layers in Web Awesome */
|
||||
@layer wa-native, wa-utilities, wa-color-palette, wa-color-variant, wa-theme, wa-theme-dimension, wa-theme-overrides;
|
||||
@@ -1,3 +1,6 @@
|
||||
@import url('layers.css');
|
||||
|
||||
/* Required utilities */
|
||||
@import url('utilities/size.css');
|
||||
@import url('utilities/variants.css');
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
@import url('../layers.css');
|
||||
@import url('../color/palettes/bright.css'); /* To use this palette, add class="wa-palette-bright" to the <html> element */
|
||||
@import url('https://fonts.bunny.net/css2?family=Crimson+Pro:ital,wght@0,200..900;1,200..900&family=Quicksand:wght@300..700&display=swap');
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
@import url('../layers.css');
|
||||
@import url('../color/palettes/default.css');
|
||||
|
||||
@layer wa-theme {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
@import url('../layers.css');
|
||||
@import url('../color/palettes/shoelace.css'); /* To use this palette, add class="wa-palette-shoelace" to the <html> element */
|
||||
|
||||
@layer wa-theme {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
@import url('layers.css');
|
||||
|
||||
@import url('utilities/fouce.css');
|
||||
@import url('utilities/visually-hidden.css');
|
||||
@import url('utilities/scroll-lock.css');
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
@layer wa-native, wa-utilities, wa-color-palette, wa-color-variant, wa-theme, wa-theme-dimension, wa-theme-overrides;
|
||||
/* Cascade layers */
|
||||
@import url('layers.css');
|
||||
|
||||
/* Native Styles */
|
||||
/* Native styles */
|
||||
@import url('native.css');
|
||||
|
||||
/* CSS Utilities */
|
||||
/* CSS utilities */
|
||||
@import url('utilities.css');
|
||||
|
||||
/* Theme */
|
||||
|
||||
Reference in New Issue
Block a user