mirror of
https://github.com/hunvreus/basecoat.git
synced 2026-11-13 13:48:28 +00:00
Prepare 1.0 docs and style migration
This commit is contained in:
@@ -1,14 +0,0 @@
|
||||
---
|
||||
const { site } = Astro.props;
|
||||
const logo = site.logo?.svg || '';
|
||||
---
|
||||
|
||||
<a href="/" class="btn-ghost h-12 w-full justify-start p-2">
|
||||
<div class="bg-sidebar-primary text-sidebar-primary-foreground flex aspect-square size-8 items-center justify-center rounded-lg">
|
||||
{logo && <Fragment set:html={logo} />}
|
||||
</div>
|
||||
<div class="grid flex-1 text-left text-sm leading-tight">
|
||||
<span class="truncate font-semibold">{site.title}</span>
|
||||
{site.subtitle && <span class="truncate text-xs text-muted-foreground">{site.subtitle}</span>}
|
||||
</div>
|
||||
</a>
|
||||
+32
-6
@@ -36,9 +36,10 @@
|
||||
--sidebar-width: 16rem;
|
||||
--sidebar-mobile-width: 18rem;
|
||||
--scrollbar-track: transparent;
|
||||
--scrollbar-thumb: rgba(0, 0, 0, 0.3);
|
||||
--scrollbar-width: 6px;
|
||||
--scrollbar-radius: 6px;
|
||||
--scrollbar-thumb: var(--border);
|
||||
--scrollbar-width: 0.625rem;
|
||||
--scrollbar-thin-width: 0.375rem;
|
||||
--scrollbar-radius: 9999px;
|
||||
--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 */
|
||||
@@ -76,7 +77,6 @@
|
||||
--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 */
|
||||
@@ -132,11 +132,12 @@
|
||||
@apply bg-background text-foreground overscroll-none antialiased;
|
||||
}
|
||||
.scrollbar {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-width: auto;
|
||||
scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: var(--scrollbar-width);
|
||||
height: var(--scrollbar-width);
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
background: var(--scrollbar-track);
|
||||
@@ -144,7 +145,32 @@
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: var(--scrollbar-thumb);
|
||||
border-radius: var(--scrollbar-radius);
|
||||
border: 1px solid transparent;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
&::-webkit-scrollbar-corner {
|
||||
background: var(--scrollbar-track);
|
||||
}
|
||||
}
|
||||
.scrollbar-thin {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: var(--scrollbar-thin-width);
|
||||
height: var(--scrollbar-thin-width);
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
background: var(--scrollbar-track);
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: var(--scrollbar-thumb);
|
||||
border-radius: var(--scrollbar-radius);
|
||||
border: 1px solid transparent;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
&::-webkit-scrollbar-corner {
|
||||
background: var(--scrollbar-track);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
/* Components */
|
||||
@import "./components/alert.css";
|
||||
@import "./components/avatar.css";
|
||||
@import "./components/badge.css";
|
||||
@import "./components/button.css";
|
||||
@import "./components/button-group.css";
|
||||
@import "./components/card.css";
|
||||
@import "./components/chart.css";
|
||||
@import "./components/collapsible.css";
|
||||
@import "./components/command.css";
|
||||
@import "./components/combobox.css";
|
||||
|
||||
@@ -5,6 +5,11 @@
|
||||
@apply relative w-full;
|
||||
}
|
||||
|
||||
.alert:has(> footer),
|
||||
.alert-destructive:has(> footer) {
|
||||
@apply pe-18;
|
||||
}
|
||||
|
||||
.alert > :is(h2, h3, h4, h5, h6, strong, [data-title]),
|
||||
.alert-destructive > :is(h2, h3, h4, h5, h6, strong, [data-title]) {
|
||||
@apply min-h-4;
|
||||
@@ -18,4 +23,9 @@
|
||||
@apply list-inside list-disc;
|
||||
}
|
||||
}
|
||||
|
||||
.alert > footer,
|
||||
.alert-destructive > footer {
|
||||
@apply absolute;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/* Avatar */
|
||||
@layer components {
|
||||
.avatar,
|
||||
.avatar-sm,
|
||||
.avatar-lg {
|
||||
@apply relative inline-flex shrink-0 select-none appearance-none border-0 bg-transparent p-0 align-middle outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 after:absolute after:inset-0 after:rounded-[inherit] after:border after:border-border after:mix-blend-darken dark:after:mix-blend-lighten;
|
||||
}
|
||||
|
||||
.avatar > img,
|
||||
.avatar-sm > img,
|
||||
.avatar-lg > img {
|
||||
@apply absolute inset-0 aspect-square size-full rounded-[inherit] object-cover;
|
||||
}
|
||||
|
||||
.avatar > span:not([data-badge]),
|
||||
.avatar-sm > span:not([data-badge]),
|
||||
.avatar-lg > span:not([data-badge]) {
|
||||
@apply flex size-full items-center justify-center rounded-[inherit] text-sm;
|
||||
}
|
||||
|
||||
.avatar-sm > span:not([data-badge]) {
|
||||
@apply text-xs;
|
||||
}
|
||||
|
||||
.avatar > [data-badge],
|
||||
.avatar-sm > [data-badge],
|
||||
.avatar-lg > [data-badge] {
|
||||
@apply absolute end-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full bg-blend-color ring-2 select-none;
|
||||
}
|
||||
|
||||
.avatar-sm > [data-badge] {
|
||||
@apply size-2 [&>svg]:hidden;
|
||||
}
|
||||
|
||||
.avatar > [data-badge] {
|
||||
@apply size-2.5 [&>svg]:size-2;
|
||||
}
|
||||
|
||||
.avatar-lg > [data-badge] {
|
||||
@apply size-3 [&>svg]:size-2;
|
||||
}
|
||||
|
||||
.avatar-group {
|
||||
@apply flex -space-x-2;
|
||||
}
|
||||
|
||||
.avatar-group > :is(.avatar, .avatar-sm, .avatar-lg),
|
||||
.avatar-group > [data-count] {
|
||||
@apply ring-2 ring-background;
|
||||
}
|
||||
|
||||
.avatar-group > [data-count] {
|
||||
@apply relative flex shrink-0 items-center justify-center;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,10 @@
|
||||
@layer components {
|
||||
.button-group {
|
||||
@apply isolate inline-flex w-fit items-stretch;
|
||||
|
||||
&:has(> :is(.dropdown-menu, .popover, .select) > [data-popover][aria-hidden='false']) {
|
||||
@apply relative z-50;
|
||||
}
|
||||
|
||||
> .input {
|
||||
@apply flex-1;
|
||||
@@ -44,7 +48,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.button-group-text {
|
||||
.button-group > :is(span, label, output) {
|
||||
@apply flex items-center [&_svg]:pointer-events-none;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* Card */
|
||||
@layer components {
|
||||
.card {
|
||||
.card,
|
||||
.card-sm {
|
||||
@apply flex flex-col;
|
||||
|
||||
> header {
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/* Chart */
|
||||
@layer components {
|
||||
.chart {
|
||||
@apply relative flex aspect-video w-full justify-center text-xs;
|
||||
}
|
||||
|
||||
.chart > canvas {
|
||||
@apply block size-full;
|
||||
}
|
||||
|
||||
.chart-tooltip {
|
||||
@apply pointer-events-none fixed z-50 grid min-w-32 -translate-x-1/2 translate-y-2 items-start transition-[left,top,opacity] duration-150 ease-out;
|
||||
}
|
||||
|
||||
.chart-tooltip[hidden] {
|
||||
@apply opacity-0;
|
||||
}
|
||||
|
||||
.chart-tooltip-items {
|
||||
@apply grid gap-1.5;
|
||||
}
|
||||
|
||||
.chart-tooltip-item {
|
||||
@apply flex w-full flex-wrap items-center gap-2;
|
||||
}
|
||||
|
||||
.chart-tooltip-indicator {
|
||||
@apply size-2.5 shrink-0 rounded-[2px];
|
||||
background-color: var(--chart-indicator-color);
|
||||
}
|
||||
|
||||
.chart-legend-indicator {
|
||||
@apply size-2 shrink-0 rounded-[2px];
|
||||
background-color: var(--chart-indicator-color);
|
||||
}
|
||||
|
||||
.chart-tooltip-label {
|
||||
@apply text-muted-foreground leading-none;
|
||||
}
|
||||
|
||||
.chart-tooltip-value {
|
||||
@apply ms-auto font-mono font-medium leading-none tabular-nums;
|
||||
}
|
||||
|
||||
.chart-legend {
|
||||
@apply flex flex-wrap items-center justify-center gap-4 pt-3;
|
||||
}
|
||||
|
||||
.chart-legend-item {
|
||||
@apply flex items-center gap-1.5 text-xs;
|
||||
}
|
||||
|
||||
.chart-legend-item[aria-pressed='false'] {
|
||||
@apply opacity-70;
|
||||
}
|
||||
}
|
||||
+105
-14
@@ -272,7 +272,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.button-group-text {
|
||||
.button-group > :is(span, label, output) {
|
||||
@apply bg-muted gap-2 rounded-4xl border px-2.5 text-sm font-medium [&_svg:not([class*='size-'])]:size-4;
|
||||
}
|
||||
|
||||
@@ -391,7 +391,7 @@
|
||||
/* Alert */
|
||||
.alert,
|
||||
.alert-destructive {
|
||||
@apply grid gap-0.5 rounded-2xl border px-4 py-3 text-start text-sm has-[>[data-action]]:relative has-[>[data-action]]:pe-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2.5 [&>svg]:row-span-2 [&>svg]:translate-y-0.5 [&>svg]:text-current [&>svg:not([class*='size-'])]:size-4;
|
||||
@apply grid gap-0.5 rounded-2xl border px-4 py-3 text-start text-sm has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2.5 [&>svg]:row-span-2 [&>svg]:translate-y-0.5 [&>svg]:text-current [&>svg:not([class*='size-'])]:size-4;
|
||||
}
|
||||
|
||||
.alert {
|
||||
@@ -419,9 +419,57 @@
|
||||
@apply text-destructive/90 text-sm text-balance md:text-pretty [&_p:not(:last-child)]:mb-4;
|
||||
}
|
||||
|
||||
.alert > [data-action],
|
||||
.alert-destructive > [data-action] {
|
||||
@apply absolute top-2.5 end-3;
|
||||
.alert > footer,
|
||||
.alert-destructive > footer {
|
||||
@apply top-2.5 end-3;
|
||||
}
|
||||
/* Avatar */
|
||||
.avatar,
|
||||
.avatar-sm,
|
||||
.avatar-lg {
|
||||
@apply rounded-full after:rounded-[inherit];
|
||||
}
|
||||
|
||||
.avatar {
|
||||
@apply size-8;
|
||||
}
|
||||
|
||||
.avatar-sm {
|
||||
@apply size-6;
|
||||
}
|
||||
|
||||
.avatar-lg {
|
||||
@apply size-10;
|
||||
}
|
||||
|
||||
.avatar > span:not([data-badge]),
|
||||
.avatar-sm > span:not([data-badge]),
|
||||
.avatar-lg > span:not([data-badge]) {
|
||||
@apply bg-muted text-muted-foreground rounded-[inherit];
|
||||
}
|
||||
|
||||
.avatar > img,
|
||||
.avatar-sm > img,
|
||||
.avatar-lg > img {
|
||||
@apply rounded-[inherit];
|
||||
}
|
||||
|
||||
.avatar > [data-badge],
|
||||
.avatar-sm > [data-badge],
|
||||
.avatar-lg > [data-badge] {
|
||||
@apply bg-primary text-primary-foreground ring-background;
|
||||
}
|
||||
|
||||
.avatar-group > [data-count] {
|
||||
@apply bg-muted text-muted-foreground size-8 rounded-full text-sm [&>svg]:size-4;
|
||||
}
|
||||
|
||||
.avatar-group:has(> .avatar-sm) > [data-count] {
|
||||
@apply size-6 [&>svg]:size-3;
|
||||
}
|
||||
|
||||
.avatar-group:has(> .avatar-lg) > [data-count] {
|
||||
@apply size-10 [&>svg]:size-5;
|
||||
}
|
||||
|
||||
/* Badge */
|
||||
@@ -732,28 +780,71 @@
|
||||
}
|
||||
|
||||
/* Card */
|
||||
.card,
|
||||
.card-sm {
|
||||
@apply bg-card text-card-foreground ring-foreground/5 dark:ring-foreground/10 overflow-hidden rounded-4xl text-sm shadow-md ring-1 has-[>img:first-child]:pt-0 [&>img:first-child]:rounded-t-4xl [&>img:last-child]:rounded-b-4xl;
|
||||
}
|
||||
|
||||
.card {
|
||||
@apply bg-card text-card-foreground ring-foreground/5 dark:ring-foreground/10 gap-6 overflow-hidden rounded-4xl py-6 text-sm shadow-md ring-1 has-[>img:first-child]:pt-0 data-[size=sm]:gap-4 data-[size=sm]:py-4 [&>img:first-child]:rounded-t-4xl [&>img:last-child]:rounded-b-4xl;
|
||||
@apply gap-6 py-6;
|
||||
}
|
||||
|
||||
.card > header {
|
||||
@apply gap-1.5 rounded-t-4xl px-6 in-data-[size=sm]:px-4 [.border-b]:pb-6 in-data-[size=sm]:[.border-b]:pb-4;
|
||||
.card-sm {
|
||||
@apply gap-4 py-4;
|
||||
}
|
||||
|
||||
.card > header > :is(h2, h3, [data-title], .card-title) {
|
||||
.card > header,
|
||||
.card-sm > header {
|
||||
@apply gap-1.5 rounded-t-4xl px-6 [.border-b]:pb-6;
|
||||
}
|
||||
|
||||
.card-sm > header {
|
||||
@apply px-4 [.border-b]:pb-4;
|
||||
}
|
||||
|
||||
.card > header > :is(h2, h3, [data-title], .card-title),
|
||||
.card-sm > header > :is(h2, h3, [data-title], .card-title) {
|
||||
@apply text-base font-medium;
|
||||
}
|
||||
|
||||
.card > header > :is(p, [data-description], .card-description) {
|
||||
.card > header > :is(p, [data-description], .card-description),
|
||||
.card-sm > header > :is(p, [data-description], .card-description) {
|
||||
@apply text-muted-foreground text-sm;
|
||||
}
|
||||
|
||||
.card > section {
|
||||
@apply px-6 in-data-[size=sm]:px-4;
|
||||
.card > section,
|
||||
.card-sm > section {
|
||||
@apply px-6;
|
||||
}
|
||||
|
||||
.card > footer {
|
||||
@apply rounded-b-4xl px-6 in-data-[size=sm]:px-4 [.border-t]:pt-6 in-data-[size=sm]:[.border-t]:pt-4;
|
||||
.card-sm > section {
|
||||
@apply px-4;
|
||||
}
|
||||
|
||||
.card > footer,
|
||||
.card-sm > footer {
|
||||
@apply rounded-b-4xl px-6 [.border-t]:pt-6;
|
||||
}
|
||||
|
||||
.card-sm > footer {
|
||||
@apply px-4 [.border-t]:pt-4;
|
||||
}
|
||||
|
||||
/* Chart */
|
||||
.chart-tooltip {
|
||||
@apply border-border/50 bg-background text-foreground gap-1.5 rounded-2xl border px-2.5 py-1.5 text-xs shadow-xl;
|
||||
}
|
||||
|
||||
.chart-tooltip-title {
|
||||
@apply font-medium;
|
||||
}
|
||||
|
||||
.chart-legend-item {
|
||||
@apply text-foreground;
|
||||
}
|
||||
|
||||
.chart-legend-item[aria-pressed='false'] {
|
||||
@apply text-muted-foreground;
|
||||
}
|
||||
|
||||
/* Checkbox */
|
||||
|
||||
+110
-15
@@ -264,7 +264,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.button-group-text {
|
||||
.button-group > :is(span, label, output) {
|
||||
@apply bg-muted gap-2 rounded-none border px-2.5 text-xs font-medium [&_svg:not([class*='size-'])]:size-4;
|
||||
}
|
||||
|
||||
@@ -383,7 +383,7 @@
|
||||
/* Alert */
|
||||
.alert,
|
||||
.alert-destructive {
|
||||
@apply grid gap-0.5 rounded-none border px-2.5 py-2 text-start text-xs has-[>[data-action]]:relative has-[>[data-action]]:pe-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2 [&>svg]:row-span-2 [&>svg]:translate-y-0 [&>svg]:text-current [&>svg:not([class*='size-'])]:size-4;
|
||||
@apply grid gap-0.5 rounded-none border px-2.5 py-2 text-start text-xs has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2 [&>svg]:row-span-2 [&>svg]:translate-y-0 [&>svg]:text-current [&>svg:not([class*='size-'])]:size-4;
|
||||
}
|
||||
|
||||
.alert {
|
||||
@@ -411,9 +411,57 @@
|
||||
@apply text-destructive/90 text-xs/relaxed text-balance md:text-pretty [&_p:not(:last-child)]:mb-2;
|
||||
}
|
||||
|
||||
.alert > [data-action],
|
||||
.alert-destructive > [data-action] {
|
||||
@apply absolute top-[calc(--spacing(1.25))] end-[calc(--spacing(1.25))];
|
||||
.alert > footer,
|
||||
.alert-destructive > footer {
|
||||
@apply top-[calc(--spacing(1.25))] end-[calc(--spacing(1.25))];
|
||||
}
|
||||
/* Avatar */
|
||||
.avatar,
|
||||
.avatar-sm,
|
||||
.avatar-lg {
|
||||
@apply rounded-full after:rounded-[inherit];
|
||||
}
|
||||
|
||||
.avatar {
|
||||
@apply size-8;
|
||||
}
|
||||
|
||||
.avatar-sm {
|
||||
@apply size-6;
|
||||
}
|
||||
|
||||
.avatar-lg {
|
||||
@apply size-10;
|
||||
}
|
||||
|
||||
.avatar > span:not([data-badge]),
|
||||
.avatar-sm > span:not([data-badge]),
|
||||
.avatar-lg > span:not([data-badge]) {
|
||||
@apply bg-muted text-muted-foreground rounded-[inherit];
|
||||
}
|
||||
|
||||
.avatar > img,
|
||||
.avatar-sm > img,
|
||||
.avatar-lg > img {
|
||||
@apply rounded-[inherit];
|
||||
}
|
||||
|
||||
.avatar > [data-badge],
|
||||
.avatar-sm > [data-badge],
|
||||
.avatar-lg > [data-badge] {
|
||||
@apply bg-primary text-primary-foreground ring-background;
|
||||
}
|
||||
|
||||
.avatar-group > [data-count] {
|
||||
@apply bg-muted text-muted-foreground size-8 rounded-full text-xs [&>svg]:size-4;
|
||||
}
|
||||
|
||||
.avatar-group:has(> .avatar-sm) > [data-count] {
|
||||
@apply size-6 [&>svg]:size-3;
|
||||
}
|
||||
|
||||
.avatar-group:has(> .avatar-lg) > [data-count] {
|
||||
@apply size-10 [&>svg]:size-5;
|
||||
}
|
||||
|
||||
/* Badge */
|
||||
@@ -716,28 +764,75 @@
|
||||
}
|
||||
|
||||
/* Card */
|
||||
.card,
|
||||
.card-sm {
|
||||
@apply ring-foreground/10 bg-card text-card-foreground overflow-hidden rounded-none text-xs/relaxed ring-1 has-[>footer]:pb-0 has-[>img:first-child]:pt-0 [&>img:first-child]:rounded-none [&>img:last-child]:rounded-none;
|
||||
}
|
||||
|
||||
.card {
|
||||
@apply ring-foreground/10 bg-card text-card-foreground gap-4 overflow-hidden rounded-none py-4 text-xs/relaxed ring-1 has-[>footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-2 data-[size=sm]:py-3 data-[size=sm]:has-[>footer]:pb-0 [&>img:first-child]:rounded-none [&>img:last-child]:rounded-none;
|
||||
@apply gap-4 py-4;
|
||||
}
|
||||
|
||||
.card > header {
|
||||
@apply gap-1 rounded-none px-4 in-data-[size=sm]:px-3 [.border-b]:pb-4 in-data-[size=sm]:[.border-b]:pb-3;
|
||||
.card-sm {
|
||||
@apply gap-2 py-3;
|
||||
}
|
||||
|
||||
.card > header > :is(h2, h3, [data-title], .card-title) {
|
||||
@apply text-sm font-medium in-data-[size=sm]:text-sm;
|
||||
.card > header,
|
||||
.card-sm > header {
|
||||
@apply gap-1 rounded-none px-4 [.border-b]:pb-4;
|
||||
}
|
||||
|
||||
.card > header > :is(p, [data-description], .card-description) {
|
||||
.card-sm > header {
|
||||
@apply px-3 [.border-b]:pb-3;
|
||||
}
|
||||
|
||||
.card > header > :is(h2, h3, [data-title], .card-title),
|
||||
.card-sm > header > :is(h2, h3, [data-title], .card-title) {
|
||||
@apply text-sm font-medium;
|
||||
}
|
||||
|
||||
.card-sm > header > :is(h2, h3, [data-title], .card-title) {
|
||||
@apply text-sm;
|
||||
}
|
||||
|
||||
.card > header > :is(p, [data-description], .card-description),
|
||||
.card-sm > header > :is(p, [data-description], .card-description) {
|
||||
@apply text-muted-foreground text-xs/relaxed;
|
||||
}
|
||||
|
||||
.card > section {
|
||||
@apply px-4 in-data-[size=sm]:px-3;
|
||||
.card > section,
|
||||
.card-sm > section {
|
||||
@apply px-4;
|
||||
}
|
||||
|
||||
.card > footer {
|
||||
@apply rounded-none border-t p-4 in-data-[size=sm]:p-3;
|
||||
.card-sm > section {
|
||||
@apply px-3;
|
||||
}
|
||||
|
||||
.card > footer,
|
||||
.card-sm > footer {
|
||||
@apply rounded-none border-t p-4;
|
||||
}
|
||||
|
||||
.card-sm > footer {
|
||||
@apply p-3;
|
||||
}
|
||||
|
||||
/* Chart */
|
||||
.chart-tooltip {
|
||||
@apply border-border/50 bg-background text-foreground gap-1.5 rounded-none border px-2.5 py-1.5 text-xs shadow-xl;
|
||||
}
|
||||
|
||||
.chart-tooltip-title {
|
||||
@apply font-medium;
|
||||
}
|
||||
|
||||
.chart-legend-item {
|
||||
@apply text-foreground;
|
||||
}
|
||||
|
||||
.chart-legend-item[aria-pressed='false'] {
|
||||
@apply text-muted-foreground;
|
||||
}
|
||||
|
||||
/* Checkbox */
|
||||
|
||||
+105
-14
@@ -264,7 +264,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.button-group-text {
|
||||
.button-group > :is(span, label, output) {
|
||||
@apply bg-muted gap-2 rounded-4xl border px-2.5 text-sm font-medium [&_svg:not([class*='size-'])]:size-4;
|
||||
}
|
||||
|
||||
@@ -383,7 +383,7 @@
|
||||
/* Alert */
|
||||
.alert,
|
||||
.alert-destructive {
|
||||
@apply grid gap-0.5 rounded-lg border px-4 py-3 text-start text-sm has-[>[data-action]]:relative has-[>[data-action]]:pe-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2.5 [&>svg]:row-span-2 [&>svg]:translate-y-0.5 [&>svg]:text-current [&>svg:not([class*='size-'])]:size-4;
|
||||
@apply grid gap-0.5 rounded-lg border px-4 py-3 text-start text-sm has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2.5 [&>svg]:row-span-2 [&>svg]:translate-y-0.5 [&>svg]:text-current [&>svg:not([class*='size-'])]:size-4;
|
||||
}
|
||||
|
||||
.alert {
|
||||
@@ -411,9 +411,57 @@
|
||||
@apply text-destructive/90 text-sm text-balance md:text-pretty [&_p:not(:last-child)]:mb-4;
|
||||
}
|
||||
|
||||
.alert > [data-action],
|
||||
.alert-destructive > [data-action] {
|
||||
@apply absolute top-2.5 end-3;
|
||||
.alert > footer,
|
||||
.alert-destructive > footer {
|
||||
@apply top-2.5 end-3;
|
||||
}
|
||||
/* Avatar */
|
||||
.avatar,
|
||||
.avatar-sm,
|
||||
.avatar-lg {
|
||||
@apply rounded-full after:rounded-[inherit];
|
||||
}
|
||||
|
||||
.avatar {
|
||||
@apply size-8;
|
||||
}
|
||||
|
||||
.avatar-sm {
|
||||
@apply size-6;
|
||||
}
|
||||
|
||||
.avatar-lg {
|
||||
@apply size-10;
|
||||
}
|
||||
|
||||
.avatar > span:not([data-badge]),
|
||||
.avatar-sm > span:not([data-badge]),
|
||||
.avatar-lg > span:not([data-badge]) {
|
||||
@apply bg-muted text-muted-foreground rounded-[inherit];
|
||||
}
|
||||
|
||||
.avatar > img,
|
||||
.avatar-sm > img,
|
||||
.avatar-lg > img {
|
||||
@apply rounded-[inherit];
|
||||
}
|
||||
|
||||
.avatar > [data-badge],
|
||||
.avatar-sm > [data-badge],
|
||||
.avatar-lg > [data-badge] {
|
||||
@apply bg-primary text-primary-foreground ring-background;
|
||||
}
|
||||
|
||||
.avatar-group > [data-count] {
|
||||
@apply bg-muted text-muted-foreground size-8 rounded-full text-sm [&>svg]:size-4;
|
||||
}
|
||||
|
||||
.avatar-group:has(> .avatar-sm) > [data-count] {
|
||||
@apply size-6 [&>svg]:size-3;
|
||||
}
|
||||
|
||||
.avatar-group:has(> .avatar-lg) > [data-count] {
|
||||
@apply size-10 [&>svg]:size-5;
|
||||
}
|
||||
|
||||
/* Badge */
|
||||
@@ -720,28 +768,71 @@
|
||||
}
|
||||
|
||||
/* Card */
|
||||
.card,
|
||||
.card-sm {
|
||||
@apply ring-foreground/10 bg-card text-card-foreground overflow-hidden rounded-2xl text-sm ring-1 has-[>img:first-child]:pt-0 [&>img:first-child]:rounded-t-xl [&>img:last-child]:rounded-b-xl;
|
||||
}
|
||||
|
||||
.card {
|
||||
@apply ring-foreground/10 bg-card text-card-foreground gap-6 overflow-hidden rounded-2xl py-6 text-sm ring-1 has-[>img:first-child]:pt-0 data-[size=sm]:gap-4 data-[size=sm]:py-4 [&>img:first-child]:rounded-t-xl [&>img:last-child]:rounded-b-xl;
|
||||
@apply gap-6 py-6;
|
||||
}
|
||||
|
||||
.card > header {
|
||||
@apply gap-2 rounded-t-xl px-6 in-data-[size=sm]:px-4 [.border-b]:pb-6 in-data-[size=sm]:[.border-b]:pb-4;
|
||||
.card-sm {
|
||||
@apply gap-4 py-4;
|
||||
}
|
||||
|
||||
.card > header > :is(h2, h3, [data-title], .card-title) {
|
||||
.card > header,
|
||||
.card-sm > header {
|
||||
@apply gap-2 rounded-t-xl px-6 [.border-b]:pb-6;
|
||||
}
|
||||
|
||||
.card-sm > header {
|
||||
@apply px-4 [.border-b]:pb-4;
|
||||
}
|
||||
|
||||
.card > header > :is(h2, h3, [data-title], .card-title),
|
||||
.card-sm > header > :is(h2, h3, [data-title], .card-title) {
|
||||
@apply text-base font-medium;
|
||||
}
|
||||
|
||||
.card > header > :is(p, [data-description], .card-description) {
|
||||
.card > header > :is(p, [data-description], .card-description),
|
||||
.card-sm > header > :is(p, [data-description], .card-description) {
|
||||
@apply text-muted-foreground text-sm;
|
||||
}
|
||||
|
||||
.card > section {
|
||||
@apply px-6 in-data-[size=sm]:px-4;
|
||||
.card > section,
|
||||
.card-sm > section {
|
||||
@apply px-6;
|
||||
}
|
||||
|
||||
.card > footer {
|
||||
@apply rounded-b-xl px-6 in-data-[size=sm]:px-4 [.border-t]:pt-6 in-data-[size=sm]:[.border-t]:pt-4;
|
||||
.card-sm > section {
|
||||
@apply px-4;
|
||||
}
|
||||
|
||||
.card > footer,
|
||||
.card-sm > footer {
|
||||
@apply rounded-b-xl px-6 [.border-t]:pt-6;
|
||||
}
|
||||
|
||||
.card-sm > footer {
|
||||
@apply px-4 [.border-t]:pt-4;
|
||||
}
|
||||
|
||||
/* Chart */
|
||||
.chart-tooltip {
|
||||
@apply border-border/50 bg-background text-foreground gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs shadow-xl;
|
||||
}
|
||||
|
||||
.chart-tooltip-title {
|
||||
@apply font-medium;
|
||||
}
|
||||
|
||||
.chart-legend-item {
|
||||
@apply text-foreground;
|
||||
}
|
||||
|
||||
.chart-legend-item[aria-pressed='false'] {
|
||||
@apply text-muted-foreground;
|
||||
}
|
||||
|
||||
/* Checkbox */
|
||||
|
||||
+105
-14
@@ -264,7 +264,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.button-group-text {
|
||||
.button-group > :is(span, label, output) {
|
||||
@apply bg-muted gap-2 rounded-md border px-2.5 text-xs/relaxed font-medium [&_svg:not([class*='size-'])]:size-4;
|
||||
}
|
||||
|
||||
@@ -383,7 +383,7 @@
|
||||
/* Alert */
|
||||
.alert,
|
||||
.alert-destructive {
|
||||
@apply grid gap-0.5 rounded-lg border px-2 py-1.5 text-start text-xs/relaxed has-[>[data-action]]:relative has-[>[data-action]]:pe-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-1.5 [&>svg]:row-span-2 [&>svg]:translate-y-0.5 [&>svg]:text-current [&>svg:not([class*='size-'])]:size-3.5;
|
||||
@apply grid gap-0.5 rounded-lg border px-2 py-1.5 text-start text-xs/relaxed has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-1.5 [&>svg]:row-span-2 [&>svg]:translate-y-0.5 [&>svg]:text-current [&>svg:not([class*='size-'])]:size-3.5;
|
||||
}
|
||||
|
||||
.alert {
|
||||
@@ -411,9 +411,57 @@
|
||||
@apply text-destructive/90 text-xs/relaxed text-balance md:text-pretty [&_p:not(:last-child)]:mb-4;
|
||||
}
|
||||
|
||||
.alert > [data-action],
|
||||
.alert-destructive > [data-action] {
|
||||
@apply absolute top-1.5 end-2;
|
||||
.alert > footer,
|
||||
.alert-destructive > footer {
|
||||
@apply top-1.5 end-2;
|
||||
}
|
||||
/* Avatar */
|
||||
.avatar,
|
||||
.avatar-sm,
|
||||
.avatar-lg {
|
||||
@apply rounded-full after:rounded-[inherit];
|
||||
}
|
||||
|
||||
.avatar {
|
||||
@apply size-8;
|
||||
}
|
||||
|
||||
.avatar-sm {
|
||||
@apply size-6;
|
||||
}
|
||||
|
||||
.avatar-lg {
|
||||
@apply size-10;
|
||||
}
|
||||
|
||||
.avatar > span:not([data-badge]),
|
||||
.avatar-sm > span:not([data-badge]),
|
||||
.avatar-lg > span:not([data-badge]) {
|
||||
@apply bg-muted text-muted-foreground rounded-[inherit];
|
||||
}
|
||||
|
||||
.avatar > img,
|
||||
.avatar-sm > img,
|
||||
.avatar-lg > img {
|
||||
@apply rounded-[inherit];
|
||||
}
|
||||
|
||||
.avatar > [data-badge],
|
||||
.avatar-sm > [data-badge],
|
||||
.avatar-lg > [data-badge] {
|
||||
@apply bg-primary text-primary-foreground ring-background;
|
||||
}
|
||||
|
||||
.avatar-group > [data-count] {
|
||||
@apply bg-muted text-muted-foreground size-8 rounded-full text-xs/relaxed [&>svg]:size-4;
|
||||
}
|
||||
|
||||
.avatar-group:has(> .avatar-sm) > [data-count] {
|
||||
@apply size-6 [&>svg]:size-3;
|
||||
}
|
||||
|
||||
.avatar-group:has(> .avatar-lg) > [data-count] {
|
||||
@apply size-10 [&>svg]:size-5;
|
||||
}
|
||||
|
||||
/* Badge */
|
||||
@@ -724,28 +772,71 @@
|
||||
}
|
||||
|
||||
/* Card */
|
||||
.card,
|
||||
.card-sm {
|
||||
@apply ring-foreground/10 bg-card text-card-foreground overflow-hidden rounded-lg text-xs/relaxed ring-1 has-[>img:first-child]:pt-0 [&>img:first-child]:rounded-t-lg [&>img:last-child]:rounded-b-lg;
|
||||
}
|
||||
|
||||
.card {
|
||||
@apply ring-foreground/10 bg-card text-card-foreground gap-4 overflow-hidden rounded-lg py-4 text-xs/relaxed ring-1 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 [&>img:first-child]:rounded-t-lg [&>img:last-child]:rounded-b-lg;
|
||||
@apply gap-4 py-4;
|
||||
}
|
||||
|
||||
.card > header {
|
||||
@apply gap-1 rounded-t-lg px-4 in-data-[size=sm]:px-3 [.border-b]:pb-4 in-data-[size=sm]:[.border-b]:pb-3;
|
||||
.card-sm {
|
||||
@apply gap-3 py-3;
|
||||
}
|
||||
|
||||
.card > header > :is(h2, h3, [data-title], .card-title) {
|
||||
.card > header,
|
||||
.card-sm > header {
|
||||
@apply gap-1 rounded-t-lg px-4 [.border-b]:pb-4;
|
||||
}
|
||||
|
||||
.card-sm > header {
|
||||
@apply px-3 [.border-b]:pb-3;
|
||||
}
|
||||
|
||||
.card > header > :is(h2, h3, [data-title], .card-title),
|
||||
.card-sm > header > :is(h2, h3, [data-title], .card-title) {
|
||||
@apply text-sm font-medium;
|
||||
}
|
||||
|
||||
.card > header > :is(p, [data-description], .card-description) {
|
||||
.card > header > :is(p, [data-description], .card-description),
|
||||
.card-sm > header > :is(p, [data-description], .card-description) {
|
||||
@apply text-muted-foreground text-xs/relaxed;
|
||||
}
|
||||
|
||||
.card > section {
|
||||
@apply px-4 in-data-[size=sm]:px-3;
|
||||
.card > section,
|
||||
.card-sm > section {
|
||||
@apply px-4;
|
||||
}
|
||||
|
||||
.card > footer {
|
||||
@apply rounded-b-lg px-4 in-data-[size=sm]:px-3 [.border-t]:pt-4 in-data-[size=sm]:[.border-t]:pt-3;
|
||||
.card-sm > section {
|
||||
@apply px-3;
|
||||
}
|
||||
|
||||
.card > footer,
|
||||
.card-sm > footer {
|
||||
@apply rounded-b-lg px-4 [.border-t]:pt-4;
|
||||
}
|
||||
|
||||
.card-sm > footer {
|
||||
@apply px-3 [.border-t]:pt-3;
|
||||
}
|
||||
|
||||
/* Chart */
|
||||
.chart-tooltip {
|
||||
@apply border-border/50 bg-background text-foreground gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs shadow-xl;
|
||||
}
|
||||
|
||||
.chart-tooltip-title {
|
||||
@apply font-medium;
|
||||
}
|
||||
|
||||
.chart-legend-item {
|
||||
@apply text-foreground;
|
||||
}
|
||||
|
||||
.chart-legend-item[aria-pressed='false'] {
|
||||
@apply text-muted-foreground;
|
||||
}
|
||||
|
||||
/* Checkbox */
|
||||
|
||||
+110
-15
@@ -264,7 +264,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.button-group-text {
|
||||
.button-group > :is(span, label, output) {
|
||||
@apply bg-muted gap-2 rounded-lg border px-2.5 text-sm font-medium [&_svg:not([class*='size-'])]:size-4;
|
||||
}
|
||||
|
||||
@@ -383,7 +383,7 @@
|
||||
/* Alert */
|
||||
.alert,
|
||||
.alert-destructive {
|
||||
@apply grid gap-0.5 rounded-lg border px-2.5 py-2 text-start text-sm has-[>[data-action]]:relative has-[>[data-action]]:pe-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2 [&>svg]:row-span-2 [&>svg]:translate-y-0.5 [&>svg]:text-current [&>svg:not([class*='size-'])]:size-4;
|
||||
@apply grid gap-0.5 rounded-lg border px-2.5 py-2 text-start text-sm has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2 [&>svg]:row-span-2 [&>svg]:translate-y-0.5 [&>svg]:text-current [&>svg:not([class*='size-'])]:size-4;
|
||||
}
|
||||
|
||||
.alert {
|
||||
@@ -411,9 +411,57 @@
|
||||
@apply text-destructive/90 text-sm text-balance md:text-pretty [&_p:not(:last-child)]:mb-4;
|
||||
}
|
||||
|
||||
.alert > [data-action],
|
||||
.alert-destructive > [data-action] {
|
||||
@apply absolute top-2 end-2;
|
||||
.alert > footer,
|
||||
.alert-destructive > footer {
|
||||
@apply top-2 end-2;
|
||||
}
|
||||
/* Avatar */
|
||||
.avatar,
|
||||
.avatar-sm,
|
||||
.avatar-lg {
|
||||
@apply rounded-full after:rounded-[inherit];
|
||||
}
|
||||
|
||||
.avatar {
|
||||
@apply size-8;
|
||||
}
|
||||
|
||||
.avatar-sm {
|
||||
@apply size-6;
|
||||
}
|
||||
|
||||
.avatar-lg {
|
||||
@apply size-10;
|
||||
}
|
||||
|
||||
.avatar > span:not([data-badge]),
|
||||
.avatar-sm > span:not([data-badge]),
|
||||
.avatar-lg > span:not([data-badge]) {
|
||||
@apply bg-muted text-muted-foreground rounded-[inherit];
|
||||
}
|
||||
|
||||
.avatar > img,
|
||||
.avatar-sm > img,
|
||||
.avatar-lg > img {
|
||||
@apply rounded-[inherit];
|
||||
}
|
||||
|
||||
.avatar > [data-badge],
|
||||
.avatar-sm > [data-badge],
|
||||
.avatar-lg > [data-badge] {
|
||||
@apply bg-primary text-primary-foreground ring-background;
|
||||
}
|
||||
|
||||
.avatar-group > [data-count] {
|
||||
@apply bg-muted text-muted-foreground size-8 rounded-full text-sm [&>svg]:size-4;
|
||||
}
|
||||
|
||||
.avatar-group:has(> .avatar-sm) > [data-count] {
|
||||
@apply size-6 [&>svg]:size-3;
|
||||
}
|
||||
|
||||
.avatar-group:has(> .avatar-lg) > [data-count] {
|
||||
@apply size-10 [&>svg]:size-5;
|
||||
}
|
||||
|
||||
/* Badge */
|
||||
@@ -720,28 +768,75 @@
|
||||
}
|
||||
|
||||
/* Card */
|
||||
.card,
|
||||
.card-sm {
|
||||
@apply ring-foreground/10 bg-card text-card-foreground overflow-hidden rounded-xl text-sm ring-1 has-[>footer]:pb-0 has-[>img:first-child]:pt-0 [&>img:first-child]:rounded-t-xl [&>img:last-child]:rounded-b-xl;
|
||||
}
|
||||
|
||||
.card {
|
||||
@apply ring-foreground/10 bg-card text-card-foreground gap-4 overflow-hidden rounded-xl py-4 text-sm ring-1 has-[>footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-[>footer]:pb-0 [&>img:first-child]:rounded-t-xl [&>img:last-child]:rounded-b-xl;
|
||||
@apply gap-4 py-4;
|
||||
}
|
||||
|
||||
.card > header {
|
||||
@apply gap-1 rounded-t-xl px-4 in-data-[size=sm]:px-3 [.border-b]:pb-4 in-data-[size=sm]:[.border-b]:pb-3;
|
||||
.card-sm {
|
||||
@apply gap-3 py-3;
|
||||
}
|
||||
|
||||
.card > header > :is(h2, h3, [data-title], .card-title) {
|
||||
@apply text-base leading-snug font-medium in-data-[size=sm]:text-sm;
|
||||
.card > header,
|
||||
.card-sm > header {
|
||||
@apply gap-1 rounded-t-xl px-4 [.border-b]:pb-4;
|
||||
}
|
||||
|
||||
.card > header > :is(p, [data-description], .card-description) {
|
||||
.card-sm > header {
|
||||
@apply px-3 [.border-b]:pb-3;
|
||||
}
|
||||
|
||||
.card > header > :is(h2, h3, [data-title], .card-title),
|
||||
.card-sm > header > :is(h2, h3, [data-title], .card-title) {
|
||||
@apply text-base leading-snug font-medium;
|
||||
}
|
||||
|
||||
.card-sm > header > :is(h2, h3, [data-title], .card-title) {
|
||||
@apply text-sm;
|
||||
}
|
||||
|
||||
.card > header > :is(p, [data-description], .card-description),
|
||||
.card-sm > header > :is(p, [data-description], .card-description) {
|
||||
@apply text-muted-foreground text-sm;
|
||||
}
|
||||
|
||||
.card > section {
|
||||
@apply px-4 in-data-[size=sm]:px-3;
|
||||
.card > section,
|
||||
.card-sm > section {
|
||||
@apply px-4;
|
||||
}
|
||||
|
||||
.card > footer {
|
||||
@apply bg-muted/50 rounded-b-xl border-t p-4 in-data-[size=sm]:p-3;
|
||||
.card-sm > section {
|
||||
@apply px-3;
|
||||
}
|
||||
|
||||
.card > footer,
|
||||
.card-sm > footer {
|
||||
@apply bg-muted/50 rounded-b-xl border-t p-4;
|
||||
}
|
||||
|
||||
.card-sm > footer {
|
||||
@apply p-3;
|
||||
}
|
||||
|
||||
/* Chart */
|
||||
.chart-tooltip {
|
||||
@apply border-border/50 bg-background text-foreground gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs shadow-xl;
|
||||
}
|
||||
|
||||
.chart-tooltip-title {
|
||||
@apply font-medium;
|
||||
}
|
||||
|
||||
.chart-legend-item {
|
||||
@apply text-foreground;
|
||||
}
|
||||
|
||||
.chart-legend-item[aria-pressed='false'] {
|
||||
@apply text-muted-foreground;
|
||||
}
|
||||
|
||||
/* Checkbox */
|
||||
|
||||
+105
-14
@@ -272,7 +272,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.button-group-text {
|
||||
.button-group > :is(span, label, output) {
|
||||
@apply bg-muted gap-2 rounded-2xl border px-2.5 text-sm font-medium [&_svg:not([class*='size-'])]:size-4;
|
||||
}
|
||||
|
||||
@@ -391,7 +391,7 @@
|
||||
/* Alert */
|
||||
.alert,
|
||||
.alert-destructive {
|
||||
@apply grid gap-0.5 rounded-2xl border px-4 py-3 text-start text-sm has-[>[data-action]]:relative has-[>[data-action]]:pe-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2.5 [&>svg]:row-span-2 [&>svg]:translate-y-0.5 [&>svg]:text-current [&>svg:not([class*='size-'])]:size-4;
|
||||
@apply grid gap-0.5 rounded-2xl border px-4 py-3 text-start text-sm has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2.5 [&>svg]:row-span-2 [&>svg]:translate-y-0.5 [&>svg]:text-current [&>svg:not([class*='size-'])]:size-4;
|
||||
}
|
||||
|
||||
.alert {
|
||||
@@ -419,9 +419,57 @@
|
||||
@apply text-destructive/90 text-sm text-balance md:text-pretty [&_p:not(:last-child)]:mb-4;
|
||||
}
|
||||
|
||||
.alert > [data-action],
|
||||
.alert-destructive > [data-action] {
|
||||
@apply absolute top-2.5 end-3;
|
||||
.alert > footer,
|
||||
.alert-destructive > footer {
|
||||
@apply top-2.5 end-3;
|
||||
}
|
||||
/* Avatar */
|
||||
.avatar,
|
||||
.avatar-sm,
|
||||
.avatar-lg {
|
||||
@apply rounded-full after:rounded-[inherit];
|
||||
}
|
||||
|
||||
.avatar {
|
||||
@apply size-8;
|
||||
}
|
||||
|
||||
.avatar-sm {
|
||||
@apply size-6;
|
||||
}
|
||||
|
||||
.avatar-lg {
|
||||
@apply size-10;
|
||||
}
|
||||
|
||||
.avatar > span:not([data-badge]),
|
||||
.avatar-sm > span:not([data-badge]),
|
||||
.avatar-lg > span:not([data-badge]) {
|
||||
@apply bg-muted text-muted-foreground rounded-[inherit];
|
||||
}
|
||||
|
||||
.avatar > img,
|
||||
.avatar-sm > img,
|
||||
.avatar-lg > img {
|
||||
@apply rounded-[inherit];
|
||||
}
|
||||
|
||||
.avatar > [data-badge],
|
||||
.avatar-sm > [data-badge],
|
||||
.avatar-lg > [data-badge] {
|
||||
@apply bg-primary text-primary-foreground ring-background;
|
||||
}
|
||||
|
||||
.avatar-group > [data-count] {
|
||||
@apply bg-muted text-muted-foreground size-8 rounded-full text-sm [&>svg]:size-4;
|
||||
}
|
||||
|
||||
.avatar-group:has(> .avatar-sm) > [data-count] {
|
||||
@apply size-6 [&>svg]:size-3;
|
||||
}
|
||||
|
||||
.avatar-group:has(> .avatar-lg) > [data-count] {
|
||||
@apply size-10 [&>svg]:size-5;
|
||||
}
|
||||
|
||||
/* Badge */
|
||||
@@ -732,28 +780,71 @@
|
||||
}
|
||||
|
||||
/* Card */
|
||||
.card,
|
||||
.card-sm {
|
||||
@apply bg-card text-card-foreground ring-foreground/5 dark:ring-foreground/10 overflow-hidden rounded-[min(var(--radius-4xl),24px)] text-sm shadow-sm ring-1 has-[>img:first-child]:pt-0 [&>img:first-child]:rounded-t-[min(var(--radius-4xl),24px)] [&>img:last-child]:rounded-b-[min(var(--radius-4xl),24px)];
|
||||
}
|
||||
|
||||
.card {
|
||||
@apply bg-card text-card-foreground ring-foreground/5 dark:ring-foreground/10 gap-5 overflow-hidden rounded-[min(var(--radius-4xl),24px)] py-5 text-sm shadow-sm ring-1 has-[>img:first-child]:pt-0 data-[size=sm]:gap-4 data-[size=sm]:py-4 [&>img:first-child]:rounded-t-[min(var(--radius-4xl),24px)] [&>img:last-child]:rounded-b-[min(var(--radius-4xl),24px)];
|
||||
@apply gap-5 py-5;
|
||||
}
|
||||
|
||||
.card > header {
|
||||
@apply gap-1.5 rounded-t-[min(var(--radius-4xl),24px)] px-5 in-data-[size=sm]:px-4 [.border-b]:pb-5 in-data-[size=sm]:[.border-b]:pb-4;
|
||||
.card-sm {
|
||||
@apply gap-4 py-4;
|
||||
}
|
||||
|
||||
.card > header > :is(h2, h3, [data-title], .card-title) {
|
||||
.card > header,
|
||||
.card-sm > header {
|
||||
@apply gap-1.5 rounded-t-[min(var(--radius-4xl),24px)] px-5 [.border-b]:pb-5;
|
||||
}
|
||||
|
||||
.card-sm > header {
|
||||
@apply px-4 [.border-b]:pb-4;
|
||||
}
|
||||
|
||||
.card > header > :is(h2, h3, [data-title], .card-title),
|
||||
.card-sm > header > :is(h2, h3, [data-title], .card-title) {
|
||||
@apply text-base font-medium;
|
||||
}
|
||||
|
||||
.card > header > :is(p, [data-description], .card-description) {
|
||||
.card > header > :is(p, [data-description], .card-description),
|
||||
.card-sm > header > :is(p, [data-description], .card-description) {
|
||||
@apply text-muted-foreground text-sm;
|
||||
}
|
||||
|
||||
.card > section {
|
||||
@apply px-5 in-data-[size=sm]:px-4;
|
||||
.card > section,
|
||||
.card-sm > section {
|
||||
@apply px-5;
|
||||
}
|
||||
|
||||
.card > footer {
|
||||
@apply rounded-b-[min(var(--radius-4xl),24px)] px-5 in-data-[size=sm]:px-4 [.border-t]:pt-5 in-data-[size=sm]:[.border-t]:pt-4;
|
||||
.card-sm > section {
|
||||
@apply px-4;
|
||||
}
|
||||
|
||||
.card > footer,
|
||||
.card-sm > footer {
|
||||
@apply rounded-b-[min(var(--radius-4xl),24px)] px-5 [.border-t]:pt-5;
|
||||
}
|
||||
|
||||
.card-sm > footer {
|
||||
@apply px-4 [.border-t]:pt-4;
|
||||
}
|
||||
|
||||
/* Chart */
|
||||
.chart-tooltip {
|
||||
@apply border-border/50 bg-background text-foreground gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs shadow-xl;
|
||||
}
|
||||
|
||||
.chart-tooltip-title {
|
||||
@apply font-medium;
|
||||
}
|
||||
|
||||
.chart-legend-item {
|
||||
@apply text-foreground;
|
||||
}
|
||||
|
||||
.chart-legend-item[aria-pressed='false'] {
|
||||
@apply text-muted-foreground;
|
||||
}
|
||||
|
||||
/* Checkbox */
|
||||
|
||||
+106
-15
@@ -261,7 +261,7 @@
|
||||
@apply border-border focus-visible:border-ring;
|
||||
}
|
||||
|
||||
> .button-group-text {
|
||||
> :is(span, label, output) {
|
||||
@apply border-border;
|
||||
}
|
||||
}
|
||||
@@ -280,7 +280,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.button-group-text {
|
||||
.button-group > :is(span, label, output) {
|
||||
@apply gap-2 border border-transparent border-b-input bg-transparent px-2.5 text-xs font-semibold uppercase [&_svg:not([class*='size-'])]:size-3.5;
|
||||
}
|
||||
|
||||
@@ -399,7 +399,7 @@
|
||||
/* Alert */
|
||||
.alert,
|
||||
.alert-destructive {
|
||||
@apply grid gap-1 bg-background border px-4 py-3 text-start text-sm has-[>[data-action]]:relative has-[>[data-action]]:pe-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2.5 [&>svg]:row-span-2 [&>svg]:translate-y-0.5 [&>svg]:text-current [&>svg:not([class*='size-'])]:size-4 relative after:-inset-y-px after:-start-px after:w-0.5 after:absolute;
|
||||
@apply grid gap-1 bg-background border px-4 py-3 text-start text-sm has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2.5 [&>svg]:row-span-2 [&>svg]:translate-y-0.5 [&>svg]:text-current [&>svg:not([class*='size-'])]:size-4 relative after:-inset-y-px after:-start-px after:w-0.5 after:absolute;
|
||||
}
|
||||
|
||||
.alert {
|
||||
@@ -427,9 +427,57 @@
|
||||
@apply text-destructive/90 text-sm text-balance md:text-pretty [&_p:not(:last-child)]:mb-4;
|
||||
}
|
||||
|
||||
.alert > [data-action],
|
||||
.alert-destructive > [data-action] {
|
||||
@apply absolute top-2.5 end-3;
|
||||
.alert > footer,
|
||||
.alert-destructive > footer {
|
||||
@apply top-2.5 end-3;
|
||||
}
|
||||
/* Avatar */
|
||||
.avatar,
|
||||
.avatar-sm,
|
||||
.avatar-lg {
|
||||
@apply rounded-full after:rounded-[inherit];
|
||||
}
|
||||
|
||||
.avatar {
|
||||
@apply size-8;
|
||||
}
|
||||
|
||||
.avatar-sm {
|
||||
@apply size-6;
|
||||
}
|
||||
|
||||
.avatar-lg {
|
||||
@apply size-10;
|
||||
}
|
||||
|
||||
.avatar > span:not([data-badge]),
|
||||
.avatar-sm > span:not([data-badge]),
|
||||
.avatar-lg > span:not([data-badge]) {
|
||||
@apply bg-muted text-muted-foreground rounded-[inherit];
|
||||
}
|
||||
|
||||
.avatar > img,
|
||||
.avatar-sm > img,
|
||||
.avatar-lg > img {
|
||||
@apply rounded-[inherit];
|
||||
}
|
||||
|
||||
.avatar > [data-badge],
|
||||
.avatar-sm > [data-badge],
|
||||
.avatar-lg > [data-badge] {
|
||||
@apply bg-primary text-primary-foreground ring-background;
|
||||
}
|
||||
|
||||
.avatar-group > [data-count] {
|
||||
@apply bg-muted text-muted-foreground size-8 rounded-full text-sm [&>svg]:size-4;
|
||||
}
|
||||
|
||||
.avatar-group:has(> .avatar-sm) > [data-count] {
|
||||
@apply size-6 [&>svg]:size-3;
|
||||
}
|
||||
|
||||
.avatar-group:has(> .avatar-lg) > [data-count] {
|
||||
@apply size-10 [&>svg]:size-5;
|
||||
}
|
||||
|
||||
/* Badge */
|
||||
@@ -740,28 +788,71 @@
|
||||
}
|
||||
|
||||
/* Card */
|
||||
.card,
|
||||
.card-sm {
|
||||
@apply bg-card text-card-foreground ring-foreground/5 overflow-hidden text-sm shadow-sm ring-1 has-[>img:first-child]:pt-0 [&>img:first-child]:rounded-none [&>img:last-child]:rounded-none;
|
||||
}
|
||||
|
||||
.card {
|
||||
@apply bg-card text-card-foreground ring-foreground/5 gap-8 overflow-hidden py-8 text-sm shadow-sm ring-1 has-[>img:first-child]:pt-0 data-[size=sm]:gap-5 data-[size=sm]:py-5 [&>img:first-child]:rounded-none [&>img:last-child]:rounded-none;
|
||||
@apply gap-8 py-8;
|
||||
}
|
||||
|
||||
.card > header {
|
||||
@apply gap-1.5 rounded-none px-8 in-data-[size=sm]:px-5 [.border-b]:pb-8 in-data-[size=sm]:[.border-b]:pb-5;
|
||||
.card-sm {
|
||||
@apply gap-5 py-5;
|
||||
}
|
||||
|
||||
.card > header > :is(h2, h3, [data-title], .card-title) {
|
||||
.card > header,
|
||||
.card-sm > header {
|
||||
@apply gap-1.5 rounded-none px-8 [.border-b]:pb-8;
|
||||
}
|
||||
|
||||
.card-sm > header {
|
||||
@apply px-5 [.border-b]:pb-5;
|
||||
}
|
||||
|
||||
.card > header > :is(h2, h3, [data-title], .card-title),
|
||||
.card-sm > header > :is(h2, h3, [data-title], .card-title) {
|
||||
@apply text-lg font-semibold tracking-wider uppercase;
|
||||
}
|
||||
|
||||
.card > header > :is(p, [data-description], .card-description) {
|
||||
.card > header > :is(p, [data-description], .card-description),
|
||||
.card-sm > header > :is(p, [data-description], .card-description) {
|
||||
@apply text-muted-foreground text-sm leading-relaxed;
|
||||
}
|
||||
|
||||
.card > section {
|
||||
@apply px-8 in-data-[size=sm]:px-5;
|
||||
.card > section,
|
||||
.card-sm > section {
|
||||
@apply px-8;
|
||||
}
|
||||
|
||||
.card > footer {
|
||||
@apply px-8 in-data-[size=sm]:px-5 [.border-t]:pt-8 in-data-[size=sm]:[.border-t]:pt-5;
|
||||
.card-sm > section {
|
||||
@apply px-5;
|
||||
}
|
||||
|
||||
.card > footer,
|
||||
.card-sm > footer {
|
||||
@apply px-8 [.border-t]:pt-8;
|
||||
}
|
||||
|
||||
.card-sm > footer {
|
||||
@apply px-5 [.border-t]:pt-5;
|
||||
}
|
||||
|
||||
/* Chart */
|
||||
.chart-tooltip {
|
||||
@apply border-border/50 bg-background text-foreground gap-1.5 rounded-none border px-2.5 py-1.5 text-xs shadow-xl;
|
||||
}
|
||||
|
||||
.chart-tooltip-title {
|
||||
@apply font-medium;
|
||||
}
|
||||
|
||||
.chart-legend-item {
|
||||
@apply text-foreground;
|
||||
}
|
||||
|
||||
.chart-legend-item[aria-pressed='false'] {
|
||||
@apply text-muted-foreground;
|
||||
}
|
||||
|
||||
/* Checkbox */
|
||||
|
||||
+110
-15
@@ -264,7 +264,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.button-group-text {
|
||||
.button-group > :is(span, label, output) {
|
||||
@apply bg-muted gap-2 rounded-md border px-2.5 text-sm font-medium shadow-xs [&_svg:not([class*='size-'])]:size-4;
|
||||
}
|
||||
|
||||
@@ -383,7 +383,7 @@
|
||||
/* Alert */
|
||||
.alert,
|
||||
.alert-destructive {
|
||||
@apply grid gap-0.5 rounded-lg border px-4 py-3 text-start text-sm has-[>[data-action]]:relative has-[>[data-action]]:pe-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2.5 [&>svg]:row-span-2 [&>svg]:translate-y-0.5 [&>svg]:text-current [&>svg:not([class*='size-'])]:size-4;
|
||||
@apply grid gap-0.5 rounded-lg border px-4 py-3 text-start text-sm has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2.5 [&>svg]:row-span-2 [&>svg]:translate-y-0.5 [&>svg]:text-current [&>svg:not([class*='size-'])]:size-4;
|
||||
}
|
||||
|
||||
.alert {
|
||||
@@ -411,9 +411,57 @@
|
||||
@apply text-destructive/90 text-sm text-balance md:text-pretty [&_p:not(:last-child)]:mb-4;
|
||||
}
|
||||
|
||||
.alert > [data-action],
|
||||
.alert-destructive > [data-action] {
|
||||
@apply absolute top-2.5 end-3;
|
||||
.alert > footer,
|
||||
.alert-destructive > footer {
|
||||
@apply top-2.5 end-3;
|
||||
}
|
||||
/* Avatar */
|
||||
.avatar,
|
||||
.avatar-sm,
|
||||
.avatar-lg {
|
||||
@apply rounded-full after:rounded-[inherit];
|
||||
}
|
||||
|
||||
.avatar {
|
||||
@apply size-8;
|
||||
}
|
||||
|
||||
.avatar-sm {
|
||||
@apply size-6;
|
||||
}
|
||||
|
||||
.avatar-lg {
|
||||
@apply size-10;
|
||||
}
|
||||
|
||||
.avatar > span:not([data-badge]),
|
||||
.avatar-sm > span:not([data-badge]),
|
||||
.avatar-lg > span:not([data-badge]) {
|
||||
@apply bg-muted text-muted-foreground rounded-[inherit];
|
||||
}
|
||||
|
||||
.avatar > img,
|
||||
.avatar-sm > img,
|
||||
.avatar-lg > img {
|
||||
@apply rounded-[inherit];
|
||||
}
|
||||
|
||||
.avatar > [data-badge],
|
||||
.avatar-sm > [data-badge],
|
||||
.avatar-lg > [data-badge] {
|
||||
@apply bg-primary text-primary-foreground ring-background;
|
||||
}
|
||||
|
||||
.avatar-group > [data-count] {
|
||||
@apply bg-muted text-muted-foreground size-8 rounded-full text-sm [&>svg]:size-4;
|
||||
}
|
||||
|
||||
.avatar-group:has(> .avatar-sm) > [data-count] {
|
||||
@apply size-6 [&>svg]:size-3;
|
||||
}
|
||||
|
||||
.avatar-group:has(> .avatar-lg) > [data-count] {
|
||||
@apply size-10 [&>svg]:size-5;
|
||||
}
|
||||
|
||||
/* Badge */
|
||||
@@ -720,28 +768,75 @@
|
||||
}
|
||||
|
||||
/* Card */
|
||||
.card,
|
||||
.card-sm {
|
||||
@apply ring-foreground/10 bg-card text-card-foreground overflow-hidden rounded-xl text-sm shadow-xs ring-1 has-[>img:first-child]:pt-0 [&>img:first-child]:rounded-t-xl [&>img:last-child]:rounded-b-xl;
|
||||
}
|
||||
|
||||
.card {
|
||||
@apply ring-foreground/10 bg-card text-card-foreground gap-6 overflow-hidden rounded-xl py-6 text-sm shadow-xs ring-1 has-[>img:first-child]:pt-0 data-[size=sm]:gap-4 data-[size=sm]:py-4 [&>img:first-child]:rounded-t-xl [&>img:last-child]:rounded-b-xl;
|
||||
@apply gap-6 py-6;
|
||||
}
|
||||
|
||||
.card > header {
|
||||
@apply gap-1 rounded-t-xl px-6 in-data-[size=sm]:px-4 [.border-b]:pb-6 in-data-[size=sm]:[.border-b]:pb-4;
|
||||
.card-sm {
|
||||
@apply gap-4 py-4;
|
||||
}
|
||||
|
||||
.card > header > :is(h2, h3, [data-title], .card-title) {
|
||||
@apply text-base leading-normal font-medium in-data-[size=sm]:text-sm;
|
||||
.card > header,
|
||||
.card-sm > header {
|
||||
@apply gap-1 rounded-t-xl px-6 [.border-b]:pb-6;
|
||||
}
|
||||
|
||||
.card > header > :is(p, [data-description], .card-description) {
|
||||
.card-sm > header {
|
||||
@apply px-4 [.border-b]:pb-4;
|
||||
}
|
||||
|
||||
.card > header > :is(h2, h3, [data-title], .card-title),
|
||||
.card-sm > header > :is(h2, h3, [data-title], .card-title) {
|
||||
@apply text-base leading-normal font-medium;
|
||||
}
|
||||
|
||||
.card-sm > header > :is(h2, h3, [data-title], .card-title) {
|
||||
@apply text-sm;
|
||||
}
|
||||
|
||||
.card > header > :is(p, [data-description], .card-description),
|
||||
.card-sm > header > :is(p, [data-description], .card-description) {
|
||||
@apply text-muted-foreground text-sm;
|
||||
}
|
||||
|
||||
.card > section {
|
||||
@apply px-6 in-data-[size=sm]:px-4;
|
||||
.card > section,
|
||||
.card-sm > section {
|
||||
@apply px-6;
|
||||
}
|
||||
|
||||
.card > footer {
|
||||
@apply rounded-b-xl px-6 in-data-[size=sm]:px-4 [.border-t]:pt-6 in-data-[size=sm]:[.border-t]:pt-4;
|
||||
.card-sm > section {
|
||||
@apply px-4;
|
||||
}
|
||||
|
||||
.card > footer,
|
||||
.card-sm > footer {
|
||||
@apply rounded-b-xl px-6 [.border-t]:pt-6;
|
||||
}
|
||||
|
||||
.card-sm > footer {
|
||||
@apply px-4 [.border-t]:pt-4;
|
||||
}
|
||||
|
||||
/* Chart */
|
||||
.chart-tooltip {
|
||||
@apply border-border/50 bg-background text-foreground gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs shadow-xl;
|
||||
}
|
||||
|
||||
.chart-tooltip-title {
|
||||
@apply font-medium;
|
||||
}
|
||||
|
||||
.chart-legend-item {
|
||||
@apply text-foreground;
|
||||
}
|
||||
|
||||
.chart-legend-item[aria-pressed='false'] {
|
||||
@apply text-muted-foreground;
|
||||
}
|
||||
|
||||
/* Checkbox */
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
@import "../docs/css/fonts.css";
|
||||
@import "../docs/css/themes/claude.css";
|
||||
@import "../docs/css/themes/doom-64.css";
|
||||
@import "../docs/css/themes/supabase.css";
|
||||
|
||||
:root {
|
||||
--font-sans: "Geist Sans", ui-sans-serif, system-ui, sans-serif;
|
||||
--font-heading: "Geist Sans", ui-sans-serif, system-ui, sans-serif;
|
||||
--font-mono: "Geist Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
||||
}
|
||||
|
||||
.preview {
|
||||
@apply flex min-h-[350px] w-full items-center justify-center p-10;
|
||||
}
|
||||
|
||||
.prose {
|
||||
> .relative.my-6 {
|
||||
@apply my-6;
|
||||
}
|
||||
|
||||
pre.scrollbar {
|
||||
@apply grid max-h-[650px] overflow-y-auto rounded-lg bg-muted/40 text-sm;
|
||||
}
|
||||
|
||||
pre.scrollbar > code {
|
||||
@apply block rounded-[inherit] bg-transparent p-3.5 font-mono;
|
||||
}
|
||||
}
|
||||
|
||||
.htmx-indicator {
|
||||
@apply invisible opacity-0 transition-discrete transition-all;
|
||||
}
|
||||
.htmx-indicator:not(.htmx-request) {
|
||||
@apply hidden;
|
||||
}
|
||||
.htmx-request,
|
||||
.htmx-request.htmx-indicator {
|
||||
@apply visible opacity-100;
|
||||
}
|
||||
@@ -50,7 +50,7 @@
|
||||
id="{{ id }}-menu"
|
||||
aria-orientation="vertical"
|
||||
data-empty="{{ empty_text }}"
|
||||
class="scrollbar {{ menu_attrs.class }}"
|
||||
class="scrollbar-thin {{ menu_attrs.class }}"
|
||||
{% for key, value in menu_attrs.items() %}
|
||||
{% if key != 'class' %}{{ key }}="{{ value }}"{% endif %}
|
||||
{% endfor %}
|
||||
@@ -121,7 +121,7 @@
|
||||
id="{{ id }}-menu"
|
||||
aria-orientation="vertical"
|
||||
data-empty="{{ empty_text }}"
|
||||
class="scrollbar {{ menu_attrs.class }}"
|
||||
class="scrollbar-thin {{ menu_attrs.class }}"
|
||||
{% for key, value in menu_attrs.items() %}
|
||||
{% if key != 'class' %}{{ key }}="{{ value }}"{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
+351
@@ -0,0 +1,351 @@
|
||||
(() => {
|
||||
const instances = new WeakMap();
|
||||
const defaultColors = ['var(--chart-1)', 'var(--chart-2)', 'var(--chart-3)', 'var(--chart-4)', 'var(--chart-5)'];
|
||||
|
||||
const isChartJsData = (data) => {
|
||||
return data && typeof data === 'object' && Array.isArray(data.datasets);
|
||||
};
|
||||
|
||||
const resolveTarget = (target) => {
|
||||
if (typeof target === 'string') {
|
||||
const elements = Array.from(document.querySelectorAll(target));
|
||||
if (elements.length === 0) {
|
||||
throw new Error(`Chart target not found: ${target}`);
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
if (target instanceof HTMLCanvasElement) return [target];
|
||||
if (target instanceof Element) {
|
||||
const canvas = target.matches('canvas') ? target : target.querySelector('canvas');
|
||||
if (canvas) return [canvas];
|
||||
}
|
||||
|
||||
if (target instanceof NodeList || Array.isArray(target)) {
|
||||
return Array.from(target).flatMap(resolveTarget);
|
||||
}
|
||||
|
||||
throw new Error('Chart target must be a selector, canvas, element, NodeList, or array.');
|
||||
};
|
||||
|
||||
const readOption = (canvas, config, key, dataName) => {
|
||||
if (config[key] !== undefined) return config[key];
|
||||
return canvas.dataset[dataName];
|
||||
};
|
||||
|
||||
const readBoolean = (canvas, config, key, dataName, defaultValue) => {
|
||||
const value = readOption(canvas, config, key, dataName);
|
||||
if (value === undefined) return defaultValue;
|
||||
if (typeof value === 'boolean') return value;
|
||||
return value !== 'false';
|
||||
};
|
||||
|
||||
const readJsonAttribute = (canvas, name) => {
|
||||
const value = canvas.getAttribute(name);
|
||||
if (!value) return undefined;
|
||||
|
||||
try {
|
||||
return JSON.parse(value);
|
||||
} catch (error) {
|
||||
console.error(`Invalid JSON in ${name}:`, error);
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
const colorForIndex = (index) => defaultColors[index % defaultColors.length];
|
||||
|
||||
const resolveColor = (color, element) => {
|
||||
if (Array.isArray(color)) return color.map(item => resolveColor(item, element));
|
||||
if (typeof color !== 'string') return color;
|
||||
|
||||
const probe = document.createElement('span');
|
||||
probe.style.color = color;
|
||||
probe.style.display = 'none';
|
||||
(element.parentElement || document.body).appendChild(probe);
|
||||
const resolved = getComputedStyle(probe).color;
|
||||
probe.remove();
|
||||
|
||||
return resolved || color;
|
||||
};
|
||||
|
||||
const resolveDatasetColors = (chartData, element) => {
|
||||
chartData.datasets?.forEach((dataset) => {
|
||||
dataset.borderColor = resolveColor(dataset.borderColor, element);
|
||||
dataset.backgroundColor = resolveColor(dataset.backgroundColor, element);
|
||||
dataset.hoverBorderColor = resolveColor(dataset.hoverBorderColor, element);
|
||||
dataset.hoverBackgroundColor = resolveColor(dataset.hoverBackgroundColor, element);
|
||||
});
|
||||
return chartData;
|
||||
};
|
||||
|
||||
const chartColor = (element, token) => resolveColor(`var(${token})`, element);
|
||||
|
||||
const colorMix = (color, opacity) => `color-mix(in oklab, ${color} ${opacity * 100}%, transparent)`;
|
||||
|
||||
const ensureContainer = (canvas) => {
|
||||
if (canvas.parentElement?.classList.contains('chart')) {
|
||||
canvas.parentElement.dataset.basecoatChartContainer = 'true';
|
||||
return canvas.parentElement;
|
||||
}
|
||||
|
||||
const container = document.createElement('div');
|
||||
container.className = 'chart';
|
||||
container.dataset.basecoatChartContainer = 'true';
|
||||
canvas.insertAdjacentElement('beforebegin', container);
|
||||
container.append(canvas);
|
||||
return container;
|
||||
};
|
||||
|
||||
const seriesEntries = (series) => Object.entries(series || {});
|
||||
|
||||
const valueFor = (row, key) => {
|
||||
if (row && typeof row === 'object') return row[key];
|
||||
return undefined;
|
||||
};
|
||||
|
||||
const toChartData = ({ type, labelKey, data, series }) => {
|
||||
if (isChartJsData(data)) return data;
|
||||
|
||||
const rows = Array.isArray(data) ? data : [];
|
||||
const entries = seriesEntries(series);
|
||||
const labels = rows.map((row) => valueFor(row, labelKey));
|
||||
|
||||
if (type === 'pie' || type === 'doughnut' || type === 'polarArea') {
|
||||
const [firstKey, firstSeries = {}] = entries[0] || [];
|
||||
return {
|
||||
labels,
|
||||
datasets: [{
|
||||
label: firstSeries.label || firstKey || 'Value',
|
||||
data: rows.map((row) => valueFor(row, firstKey)),
|
||||
backgroundColor: rows.map((row, index) => row?.color || row?.fill || colorForIndex(index)),
|
||||
borderColor: rows.map((row, index) => row?.color || row?.fill || colorForIndex(index)),
|
||||
...(firstSeries.dataset || {}),
|
||||
}],
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
labels,
|
||||
datasets: entries.map(([key, item], index) => {
|
||||
const color = item.color || colorForIndex(index);
|
||||
return {
|
||||
label: item.label || key,
|
||||
data: rows.map((row) => valueFor(row, key)),
|
||||
borderColor: color,
|
||||
backgroundColor: item.backgroundColor || color,
|
||||
fill: type === 'line' ? false : undefined,
|
||||
type: item.type,
|
||||
yAxisID: item.axis,
|
||||
hidden: item.hidden,
|
||||
...(item.dataset || {}),
|
||||
};
|
||||
}),
|
||||
};
|
||||
};
|
||||
|
||||
const formatValue = (value) => {
|
||||
return typeof value === 'number' ? value.toLocaleString() : String(value);
|
||||
};
|
||||
|
||||
const ensureTooltip = (canvas) => {
|
||||
let tooltip = canvas._basecoatChartTooltip;
|
||||
if (tooltip) return tooltip;
|
||||
|
||||
tooltip = document.createElement('div');
|
||||
tooltip.className = 'chart-tooltip';
|
||||
tooltip.hidden = true;
|
||||
tooltip.setAttribute('role', 'status');
|
||||
tooltip.setAttribute('aria-live', 'polite');
|
||||
document.body.appendChild(tooltip);
|
||||
canvas._basecoatChartTooltip = tooltip;
|
||||
return tooltip;
|
||||
};
|
||||
|
||||
const renderTooltip = (context) => {
|
||||
const { chart, tooltip } = context;
|
||||
const element = ensureTooltip(chart.canvas);
|
||||
|
||||
if (tooltip.opacity === 0) {
|
||||
element.hidden = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const children = [];
|
||||
|
||||
if (tooltip.title?.length) {
|
||||
const title = document.createElement('div');
|
||||
title.className = 'chart-tooltip-title';
|
||||
title.textContent = tooltip.title.join(', ');
|
||||
children.push(title);
|
||||
}
|
||||
|
||||
const items = document.createElement('div');
|
||||
items.className = 'chart-tooltip-items';
|
||||
tooltip.dataPoints.forEach((item) => {
|
||||
const color = item.dataset.borderColor || item.dataset.backgroundColor || colorForIndex(item.datasetIndex);
|
||||
const value = item.formattedValue || formatValue(item.raw);
|
||||
|
||||
const row = document.createElement('div');
|
||||
row.className = 'chart-tooltip-item';
|
||||
|
||||
const indicator = document.createElement('span');
|
||||
indicator.className = 'chart-tooltip-indicator';
|
||||
indicator.style.setProperty('--chart-indicator-color', color);
|
||||
|
||||
const label = document.createElement('span');
|
||||
label.className = 'chart-tooltip-label';
|
||||
label.textContent = item.dataset.label || item.label;
|
||||
|
||||
const tooltipValue = document.createElement('span');
|
||||
tooltipValue.className = 'chart-tooltip-value';
|
||||
tooltipValue.textContent = value;
|
||||
|
||||
row.append(indicator, label, tooltipValue);
|
||||
items.append(row);
|
||||
});
|
||||
children.push(items);
|
||||
|
||||
const rect = chart.canvas.getBoundingClientRect();
|
||||
element.replaceChildren(...children);
|
||||
element.hidden = false;
|
||||
element.style.left = `${rect.left + window.scrollX + tooltip.caretX}px`;
|
||||
element.style.top = `${rect.top + window.scrollY + tooltip.caretY}px`;
|
||||
};
|
||||
|
||||
const createLegendPlugin = (canvas, enabled) => ({
|
||||
id: `basecoatLegend-${Math.random().toString(36).slice(2)}`,
|
||||
afterUpdate(chart) {
|
||||
if (!enabled) return;
|
||||
|
||||
let legend = canvas._basecoatChartLegend;
|
||||
if (!legend) {
|
||||
legend = document.createElement('ul');
|
||||
legend.className = 'chart-legend';
|
||||
canvas._basecoatChartContainer.insertAdjacentElement('afterend', legend);
|
||||
canvas._basecoatChartLegend = legend;
|
||||
}
|
||||
|
||||
const items = chart.options.plugins.legend.labels.generateLabels(chart);
|
||||
legend.replaceChildren(...items.map((item) => {
|
||||
const content = document.createElement('span');
|
||||
content.className = 'chart-legend-item';
|
||||
|
||||
const indicator = document.createElement('span');
|
||||
indicator.className = 'chart-legend-indicator';
|
||||
indicator.style.setProperty('--chart-indicator-color', item.fillStyle || item.strokeStyle || colorForIndex(item.datasetIndex || item.index || 0));
|
||||
|
||||
const label = document.createElement('span');
|
||||
label.textContent = item.text;
|
||||
|
||||
content.append(indicator, label);
|
||||
|
||||
const listItem = document.createElement('li');
|
||||
listItem.append(content);
|
||||
return listItem;
|
||||
}));
|
||||
},
|
||||
});
|
||||
|
||||
const removeGeneratedElements = (canvas) => {
|
||||
canvas._basecoatChartTooltip?.remove();
|
||||
canvas._basecoatChartLegend?.remove();
|
||||
delete canvas._basecoatChartTooltip;
|
||||
delete canvas._basecoatChartLegend;
|
||||
};
|
||||
|
||||
const initChart = (canvas, config = {}) => {
|
||||
const Chart = config.Chart || window.Chart;
|
||||
if (!Chart) {
|
||||
throw new Error('Chart.js is required before calling basecoat.chart().');
|
||||
}
|
||||
|
||||
const previous = instances.get(canvas);
|
||||
if (previous) previous.destroy();
|
||||
removeGeneratedElements(canvas);
|
||||
|
||||
const type = readOption(canvas, config, 'type', 'chartType') || 'bar';
|
||||
const labelKey = readOption(canvas, config, 'labelKey', 'chartLabelKey') || 'label';
|
||||
const legend = readBoolean(canvas, config, 'legend', 'chartLegend', false);
|
||||
const tooltip = readBoolean(canvas, config, 'tooltip', 'chartTooltip', true);
|
||||
const data = config.data || readJsonAttribute(canvas, 'data-chart-data') || [];
|
||||
const series = config.series || readJsonAttribute(canvas, 'data-chart-series') || {};
|
||||
const chartData = config.chartData || toChartData({ type, labelKey, data, series });
|
||||
const userOptions = config.options || {};
|
||||
const legendPlugin = createLegendPlugin(canvas, legend);
|
||||
const container = ensureContainer(canvas);
|
||||
const borderColor = chartColor(canvas, '--border');
|
||||
const gridColor = resolveColor(colorMix('var(--border)', 0.5), canvas);
|
||||
const mutedColor = chartColor(canvas, '--muted-foreground');
|
||||
|
||||
canvas.classList.remove('chart');
|
||||
canvas._basecoatChartContainer = container;
|
||||
canvas.dataset.chartLegend = String(legend);
|
||||
|
||||
const chart = new Chart(canvas, {
|
||||
type,
|
||||
data: resolveDatasetColors(chartData, canvas),
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
interaction: {
|
||||
mode: 'index',
|
||||
intersect: false,
|
||||
},
|
||||
...userOptions,
|
||||
scales: {
|
||||
x: {
|
||||
border: { display: false, color: borderColor },
|
||||
grid: { display: false, color: gridColor },
|
||||
ticks: { color: mutedColor, padding: 8 },
|
||||
...(userOptions.scales?.x || {}),
|
||||
},
|
||||
y: {
|
||||
border: { display: false, color: borderColor },
|
||||
grid: { color: gridColor },
|
||||
ticks: { display: false, color: mutedColor },
|
||||
...(userOptions.scales?.y || {}),
|
||||
},
|
||||
...(Object.fromEntries(Object.entries(userOptions.scales || {}).filter(([key]) => key !== 'x' && key !== 'y'))),
|
||||
},
|
||||
plugins: {
|
||||
...userOptions.plugins,
|
||||
legend: {
|
||||
display: false,
|
||||
...(userOptions.plugins?.legend || {}),
|
||||
},
|
||||
tooltip: {
|
||||
enabled: false,
|
||||
external: tooltip ? renderTooltip : undefined,
|
||||
...(userOptions.plugins?.tooltip || {}),
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [legendPlugin, ...(config.plugins || [])],
|
||||
});
|
||||
|
||||
instances.set(canvas, chart);
|
||||
canvas.dataset.chartInitialized = 'true';
|
||||
canvas.chart = chart;
|
||||
canvas._destroy = () => {
|
||||
chart.destroy();
|
||||
removeGeneratedElements(canvas);
|
||||
instances.delete(canvas);
|
||||
canvas.removeAttribute('data-chart-initialized');
|
||||
delete canvas._basecoatChartContainer;
|
||||
delete canvas.chart;
|
||||
delete canvas._destroy;
|
||||
};
|
||||
|
||||
return chart;
|
||||
};
|
||||
|
||||
const chart = (target, config = {}) => {
|
||||
const canvases = resolveTarget(target);
|
||||
const charts = canvases.map((canvas) => initChart(canvas, config));
|
||||
return charts.length === 1 ? charts[0] : charts;
|
||||
};
|
||||
|
||||
if (window.basecoat) {
|
||||
window.basecoat.chart = chart;
|
||||
}
|
||||
})();
|
||||
+5
-1
@@ -115,7 +115,11 @@
|
||||
} else {
|
||||
const option = optionOrOptions;
|
||||
if (!option) return;
|
||||
state.selectedLabel.innerHTML = option.innerHTML;
|
||||
if (option.dataset.label) {
|
||||
state.selectedLabel.textContent = option.dataset.label;
|
||||
} else {
|
||||
state.selectedLabel.innerHTML = option.innerHTML;
|
||||
}
|
||||
selectedDetail = toSelected(option);
|
||||
value = selectedDetail.value;
|
||||
state.input.value = serializeSelection(state, [selectedDetail]);
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
id="{{ id }}-menu"
|
||||
aria-orientation="vertical"
|
||||
data-empty="{{ empty_text }}"
|
||||
class="scrollbar {{ menu_attrs.class }}"
|
||||
class="scrollbar-thin {{ menu_attrs.class }}"
|
||||
{% for key, value in menu_attrs %}
|
||||
{% if key != 'class' %}{{ key }}="{{ value }}"{% endif %}
|
||||
{% endfor %}
|
||||
@@ -121,7 +121,7 @@
|
||||
id="{{ id }}-menu"
|
||||
aria-orientation="vertical"
|
||||
data-empty="{{ empty_text }}"
|
||||
class="scrollbar {{ menu_attrs.class }}"
|
||||
class="scrollbar-thin {{ menu_attrs.class }}"
|
||||
{% for key, value in menu_attrs %}
|
||||
{% if key != 'class' %}{{ key }}="{{ value }}"{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import Nunjucks from 'nunjucks';
|
||||
|
||||
const types = ['success', 'error', 'info', 'warning'];
|
||||
const env = new Nunjucks.Environment(
|
||||
new Nunjucks.FileSystemLoader([
|
||||
path.resolve('src/nunjucks'),
|
||||
path.resolve('docs/src/fragments/toast'),
|
||||
]),
|
||||
{ autoescape: true },
|
||||
);
|
||||
|
||||
export function getStaticPaths() {
|
||||
return types.map((type) => ({ params: { type } }));
|
||||
@@ -10,6 +18,7 @@ export function getStaticPaths() {
|
||||
export function GET({ params }) {
|
||||
const type = String(params.type || '');
|
||||
if (!types.includes(type)) return new Response('Not found', { status: 404 });
|
||||
const html = fs.readFileSync(path.resolve('docs/generated/fragments/toast', `${type}.html`), 'utf8');
|
||||
const source = fs.readFileSync(path.resolve('docs/src/fragments/toast', `${type}.njk`), 'utf8');
|
||||
const html = env.renderString(source).trim();
|
||||
return new Response(html, { headers: { 'content-type': 'text/html; charset=utf-8' } });
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ function flatten(menu) {
|
||||
|
||||
export function GET({ site }) {
|
||||
const origin = site?.toString().replace(/\/$/, '') || 'https://basecoatui.com';
|
||||
const manifest = JSON.parse(fs.readFileSync(path.resolve('docs/generated/docs.json'), 'utf8'));
|
||||
const manifest = JSON.parse(fs.readFileSync(path.resolve('docs/src/docs.json'), 'utf8'));
|
||||
const urls = flatten(manifest.menu).map((slug) => ` <url><loc>${origin}${routePath(slug)}</loc></url>`).join('\n');
|
||||
return new Response(`<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n${urls}\n</urlset>\n`, {
|
||||
headers: { 'content-type': 'application/xml; charset=utf-8' },
|
||||
|
||||
Reference in New Issue
Block a user