Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/src/_includes/partials/kitchen-sink/form.njk
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
<section id="form" class="w-full rounded-lg border scroll-mt-16">
<header class="border-b px-4 py-3">
<h2 class="text-sm font-medium">Form</h2>
<a href="/components/form" class="text-muted-foreground hover:text-foreground" data-tooltip="See documentation" data-side="left">
{% lucide "book-open", { "class": "size-4" } %}
</a>
</header>
<div class="p-4">
<form class="form grid w-full max-w-sm gap-6">
Expand Down
23 changes: 23 additions & 0 deletions scripts/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ async function build() {
await ensureDir(cssDistDir); // Ensure dist dir exists for css package
await fs.copyFile(path.join(srcCssDir, 'basecoat.css'), path.join(cssDistDir, 'basecoat.css'));
console.log(`Copied basecoat.css to ${cssDistDir}`);
await fs.copyFile(path.join(srcCssDir, 'basecoat.shared.css'), path.join(cssDistDir, 'basecoat.shared.css'));
console.log(`Copied basecoat.shared.css to ${cssDistDir}`);

// Create Tailwind CSS builds for the CSS package
const cdnCssSrc = path.join(srcCssDir, 'basecoat.cdn.css');
Expand All @@ -161,6 +163,27 @@ async function build() {
await execPromise(`npx tailwindcss -i "${cdnCssSrc}" -o "${cssDistCdnMinPath}" --minify`);
console.log(`Generated minified CSS: ${cssDistCdnMinPath}`);

// Now for the Quasar build
const quasarCssSrc = path.join(srcCssDir, 'basecoat.quasar.css');
const cssDistQuasarPath = path.join(cssDistDir, 'basecoat.quasar.css');
const cssDistQuasarMinPath = path.join(cssDistDir, 'basecoat.quasar.min.css');

await execPromise(`npx tailwindcss -i "${quasarCssSrc}" -o "${cssDistQuasarPath}"`);
console.log(`Generated non-minified Quasar CSS: ${cssDistQuasarPath}`);
await execPromise(`npx tailwindcss -i "${quasarCssSrc}" -o "${cssDistQuasarMinPath}" --minify`);
console.log(`Generated minified Quasar CSS: ${cssDistQuasarMinPath}`);

console.log('HACK: Modifying Quasar CSS for :root, :host to body...');
let quasarCssContent = await fs.readFile(cssDistQuasarPath, 'utf-8');
quasarCssContent = quasarCssContent.replace(/:root, :host/g, 'body');
await fs.writeFile(cssDistQuasarPath, quasarCssContent);
console.log(`Modified ${cssDistQuasarPath} to replace :root with body`);

let quasarMinCssContent = await fs.readFile(cssDistQuasarMinPath, 'utf-8');
quasarMinCssContent = quasarMinCssContent.replace(/:root,:host/g, 'body');
await fs.writeFile(cssDistQuasarMinPath, quasarMinCssContent);
console.log(`Modified ${cssDistQuasarMinPath} to replace :root with body`);

console.log('Build process finished successfully!');
}

Expand Down
171 changes: 17 additions & 154 deletions src/css/basecoat.css
Original file line number Diff line number Diff line change
@@ -1,136 +1,7 @@
@custom-variant dark (&:is(.dark *));

:root {
--radius: 0.625rem;
--background: oklch(1 0 0);
--foreground: oklch(0.145 0 0);
--card: oklch(1 0 0);
--card-foreground: oklch(0.145 0 0);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.145 0 0);
--primary: oklch(0.205 0 0);
--primary-foreground: oklch(0.985 0 0);
--secondary: oklch(0.97 0 0);
--secondary-foreground: oklch(0.205 0 0);
--muted: oklch(0.97 0 0);
--muted-foreground: oklch(0.556 0 0);
--accent: oklch(0.97 0 0);
--accent-foreground: oklch(0.205 0 0);
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.922 0 0);
--input: oklch(0.922 0 0);
--ring: oklch(0.708 0 0);
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
--sidebar: oklch(0.985 0 0);
--sidebar-foreground: oklch(0.145 0 0);
--sidebar-primary: oklch(0.205 0 0);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.97 0 0);
--sidebar-accent-foreground: oklch(0.205 0 0);
--sidebar-border: oklch(0.922 0 0);
--sidebar-ring: oklch(0.708 0 0);
--sidebar-width: 16rem;
--sidebar-mobile-width: 18rem;
--scrollbar-track: transparent;
--scrollbar-thumb: rgba(0, 0, 0, 0.3);
--scrollbar-width: 6px;
--scrollbar-radius: 6px;
--chevron-down-icon: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="oklch(0.556 0 0)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-down-icon lucide-chevron-down"><path d="m6 9 6 6 6-6"/></svg>'); /* --muted-foreground */
--chevron-down-icon-50: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="oklch(0.556 0 0 / 0.5)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-down-icon lucide-chevron-down"><path d="m6 9 6 6 6-6"/></svg>'); /* --muted-foreground + 50% opacity */
--check-icon: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="oklch(0.556 0 0)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-check-icon lucide-check"><path d="M20 6 9 17l-5-5"/></svg>'); /* --muted-foreground */
}

.dark {
--background: oklch(0.145 0 0);
--foreground: oklch(0.985 0 0);
--card: oklch(0.205 0 0);
--card-foreground: oklch(0.985 0 0);
--popover: oklch(0.269 0 0);
--popover-foreground: oklch(0.985 0 0);
--primary: oklch(0.922 0 0);
--primary-foreground: oklch(0.205 0 0);
--secondary: oklch(0.269 0 0);
--secondary-foreground: oklch(0.985 0 0);
--muted: oklch(0.269 0 0);
--muted-foreground: oklch(0.708 0 0);
--accent: oklch(0.371 0 0);
--accent-foreground: oklch(0.985 0 0);
--destructive: oklch(0.704 0.191 22.216);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 15%);
--ring: oklch(0.556 0 0);
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
--sidebar: oklch(0.205 0 0);
--sidebar-foreground: oklch(0.985 0 0);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.269 0 0);
--sidebar-accent-foreground: oklch(0.985 0 0);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.439 0 0);
--scrollbar-thumb: rgba(255, 255, 255, 0.3);
--chevron-down-icon: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="oklch(0.708 0 0)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-down-icon lucide-chevron-down"><path d="m6 9 6 6 6-6"/></svg>'); /* --muted-foreground */
--chevron-down-icon-50: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="oklch(0.708 0 0 / 0.5)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-down-icon lucide-chevron-down"><path d="m6 9 6 6 6-6"/></svg>'); /* --muted-foreground + 50% opacity */
--check-icon: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="oklch(0.708 0 0)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-check-icon lucide-check"><path d="M20 6 9 17l-5-5"/></svg>');/* --muted-foreground */
color-scheme: dark;
}

@theme {
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
--color-chart-1: var(--chart-1);
--color-chart-2: var(--chart-2);
--color-chart-3: var(--chart-3);
--color-chart-4: var(--chart-4);
--color-chart-5: var(--chart-5);
--color-sidebar: var(--sidebar);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-ring: var(--sidebar-ring);
}
@import "./basecoat.shared.css";

@layer base {
* {
@apply border-border outline-ring/50;
}
html {
@apply scroll-smooth;
}
body {
@apply bg-background text-foreground overscroll-none antialiased;
}
.scrollbar {
scrollbar-width: thin;
scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
Expand Down Expand Up @@ -185,7 +56,7 @@
.badge-secondary,
.badge-destructive,
.badge-outline {
@apply inline-flex items-center justify-center rounded-full border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden;
@apply basecoat-badge px-2 py-0.5;
}
.badge,
.badge-primary {
Expand Down Expand Up @@ -424,7 +295,7 @@
/* Card */
@layer components {
.card {
@apply bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm;
@apply basecoat-card gap-6 py-6;

> header {
@apply @container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6;
Expand All @@ -450,11 +321,10 @@
@layer components {
:is(.form, .field) input[type='checkbox']:not([role='switch']),
.input[type='checkbox']:not([role='switch']) {
@apply appearance-none border-input dark:bg-input/30 checked:bg-primary dark:checked:bg-primary checked:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50;
@apply basecoat-checkbox;

&:checked:after {
@apply content-[''] block size-3.5 bg-primary-foreground;
@apply mask-[image:var(--check-icon)] mask-size-[0.875rem] mask-no-repeat mask-center;
&:checked {
@apply basecoat-checkbox-checked;
}
}
}
Expand Down Expand Up @@ -761,9 +631,7 @@
.input[type='month'],
.input[type='week'],
.input[type='time'] {
@apply appearance-none file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm;
@apply focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px];
@apply aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive;
@apply basecoat-input-text w-full;
}
}

Expand Down Expand Up @@ -863,10 +731,10 @@
@layer components {
:is(.form, .field) input[type='radio'],
.input[type='radio'] {
@apply appearance-none border-input text-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 aspect-square size-4 shrink-0 rounded-full border shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 relative;
@apply basecoat-radio;

&:checked:before {
@apply absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 content-[''] rounded-full size-2 bg-primary;
&:checked {
@apply basecoat-radio-checked;
}
}
}
Expand Down Expand Up @@ -1111,11 +979,10 @@
@layer components {
:is(.form, .field) input[type='checkbox'][role='switch'],
.input[type='checkbox'][role='switch'] {
@apply appearance-none focus-visible:border-ring focus-visible:ring-ring/50 inline-flex h-[1.15rem] w-8 shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50;
@apply bg-input dark:bg-input/80 checked:bg-primary dark:checked:bg-primary;
@apply before:content-[''] before:pointer-events-none before:block before:size-4 before:rounded-full before:ring-0 before:transition-all;
@apply before:bg-background dark:before:bg-foreground;
@apply dark:checked:before:bg-primary-foreground checked:before:ms-3.5;
@apply basecoat-switch;
&:checked {
@apply basecoat-switch-checked;
}
}
}

Expand Down Expand Up @@ -1153,14 +1020,10 @@
@apply flex flex-col gap-2;

[role='tablist'] {
@apply bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px];
@apply basecoat-tabs h-9;

[role='tab'] {
@apply focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring text-foreground dark:text-muted-foreground inline-flex h-[calc(100%_-_1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4;

&[aria-selected='true'] {
@apply bg-background dark:text-foreground dark:border-input dark:bg-input/30 shadow-sm;
}
@apply basecoat-tab h-[calc(100%_-_1px)];
}
}
[role='tabpanel'] {
Expand All @@ -1173,7 +1036,7 @@
@layer components {
:is(.form, .field) textarea,
.textarea {
@apply border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm;
@apply basecoat-textarea;
}
}

Expand Down
78 changes: 78 additions & 0 deletions src/css/basecoat.quasar.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
@custom-variant dark (&:is(.body--dark *));
@layer theme, base, components, utilities;
@import "tailwindcss/theme.css" layer(theme);
@import "tailwindcss/utilities.css" layer(utilities) source(none);
@import "./basecoat.shared.css";

@layer components {
.q-toggle__inner>.q-toggle__native {
@apply basecoat-switch;
}

.q-toggle__inner--truthy>.q-toggle__native {
@apply basecoat-switch-checked;
}

.q-checkbox__inner>.q-checkbox__native {
@apply basecoat-checkbox;
}

.q-checkbox__inner--truthy>.q-checkbox__native {
@apply basecoat-checkbox-checked;
}

.q-radio__inner>.q-radio__native {
@apply basecoat-radio;
}

.q-radio__inner--truthy>.q-radio__native {
@apply basecoat-radio-checked;
}

.textarea {
@apply basecoat-textarea;
}

.input-text {
@apply basecoat-input-text;
}

.q-card {
@apply basecoat-card border-input;
}

.q-badge {
@apply basecoat-badge border-transparent px-1.5 py-0;
}

.q-tabs {
@apply basecoat-tabs pb-[0px];
}

.q-tab {
@apply mb-[3px] basecoat-tab;
}

.q-toggle__inner>.q-toggle__native,
.q-checkbox__inner>.q-checkbox__native,
.q-radio__inner>.q-radio__native {
display: block !important;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}

.q-radio__bg,
.q-checkbox__bg,
.q-toggle__track,
.q-toggle__thumb,
.q-field__label,
.q-tab__indicator {
display: none !important;
}

.q-btn, .q-btn-group, .q-toggle, .q-menu, .q-uploader, .q-time, .q-date, .q-table__container, .q-stepper {
@apply rounded-md;
}
}
Loading