diff --git a/dist/basecoat.css b/dist/basecoat.css index e763d64..7f28e12 100644 --- a/dist/basecoat.css +++ b/dist/basecoat.css @@ -311,9 +311,6 @@ .mr-auto { margin-right: auto; } - .mb-1 { - margin-bottom: calc(var(--spacing) * 1); - } .ml-\(--sidebar-width\) { margin-left: var(--sidebar-width); } @@ -371,6 +368,9 @@ .h-4 { height: calc(var(--spacing) * 4); } + .h-6 { + height: calc(var(--spacing) * 6); + } .h-8 { height: calc(var(--spacing) * 8); } @@ -538,6 +538,9 @@ .gap-x-2 { column-gap: calc(var(--spacing) * 2); } + .gap-x-3 { + column-gap: calc(var(--spacing) * 3); + } .-space-x-2 { :where(& > :not(:last-child)) { --tw-space-x-reverse: 0; @@ -554,6 +557,9 @@ .gap-y-10 { row-gap: calc(var(--spacing) * 10); } + .self-start { + align-self: flex-start; + } .truncate { overflow: hidden; text-overflow: ellipsis; @@ -574,6 +580,9 @@ .rounded-md { border-radius: var(--radius-md); } + .rounded-sm { + border-radius: var(--radius-sm); + } .border { border-style: var(--tw-border-style); border-width: 1px; @@ -674,9 +683,6 @@ .px-4 { padding-inline: calc(var(--spacing) * 4); } - .py-0\.5 { - padding-block: calc(var(--spacing) * 0.5); - } .py-1\.5 { padding-block: calc(var(--spacing) * 1.5); } @@ -1366,12 +1372,12 @@ display: none !important; } .htmx-indicator { - transition-behavior: allow-discrete; visibility: hidden; opacity: 0%; transition-property: all; transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); transition-duration: var(--tw-duration, var(--default-transition-duration)); + transition-behavior: allow-discrete; } .htmx-indicator:not(.htmx-request) { display: none; @@ -1817,6 +1823,59 @@ } } } +@layer components { + .card { + display: flex; + flex-direction: column; + gap: calc(var(--spacing) * 6); + border-radius: var(--radius-xl); + border-style: var(--tw-border-style); + border-width: 1px; + background-color: var(--color-card); + padding-block: calc(var(--spacing) * 6); + color: var(--color-card-foreground); + --tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1)); + box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); + > header { + container-type: inline-size; + container-name: card-header; + display: grid; + grid-auto-rows: min-content; + grid-template-rows: auto auto; + align-items: flex-start; + gap: calc(var(--spacing) * 1.5); + padding-inline: calc(var(--spacing) * 6); + &:has(*[data-slot="card-action"]) { + grid-template-columns: 1fr auto; + } + &:is(.border-b) { + padding-bottom: calc(var(--spacing) * 6); + } + h2 { + --tw-leading: 1; + line-height: 1; + --tw-font-weight: var(--font-weight-semibold); + font-weight: var(--font-weight-semibold); + } + p { + font-size: var(--text-sm); + line-height: var(--tw-leading, var(--text-sm--line-height)); + color: var(--color-muted-foreground); + } + } + > section { + padding-inline: calc(var(--spacing) * 6); + } + > footer { + display: flex; + align-items: center; + padding-inline: calc(var(--spacing) * 6); + &:is(.border-t) { + padding-top: calc(var(--spacing) * 6); + } + } + } +} @layer components { .form input[type='checkbox']:not([role='switch']), .input[type='checkbox']:not([role='switch']) { width: calc(var(--spacing) * 4); @@ -2953,6 +3012,105 @@ } } } +@layer components { + .tabs { + [role='tablist'] { + display: inline-flex; + height: calc(var(--spacing) * 9); + width: fit-content; + align-items: center; + justify-content: center; + border-radius: var(--radius-lg); + background-color: var(--color-muted); + padding: 3px; + color: var(--color-muted-foreground); + [role='tab'] { + display: inline-flex; + height: calc(100% - 1px); + flex: 1; + align-items: center; + justify-content: center; + gap: calc(var(--spacing) * 1.5); + border-radius: var(--radius-md); + border-style: var(--tw-border-style); + border-width: 1px; + border-color: transparent; + padding-inline: calc(var(--spacing) * 2); + padding-block: calc(var(--spacing) * 1); + font-size: var(--text-sm); + line-height: var(--tw-leading, var(--text-sm--line-height)); + --tw-font-weight: var(--font-weight-medium); + font-weight: var(--font-weight-medium); + white-space: nowrap; + color: var(--color-foreground); + transition-property: color,box-shadow; + transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); + transition-duration: var(--tw-duration, var(--default-transition-duration)); + &:focus-visible { + border-color: var(--color-ring); + } + &:focus-visible { + --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor); + box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); + } + &:focus-visible { + --tw-ring-color: color-mix(in srgb, var(--ring) 50%, transparent); + @supports (color: color-mix(in lab, red, red)) { + --tw-ring-color: color-mix(in oklab, var(--color-ring) 50%, transparent); + } + } + &:focus-visible { + outline-style: var(--tw-outline-style); + outline-width: 1px; + } + &:focus-visible { + outline-color: var(--color-ring); + } + &:disabled { + pointer-events: none; + } + &:disabled { + opacity: 50%; + } + &:is(.dark *) { + color: var(--color-muted-foreground); + } + & svg { + pointer-events: none; + } + & svg { + flex-shrink: 0; + } + & svg:not([class*='size-']) { + width: calc(var(--spacing) * 4); + height: calc(var(--spacing) * 4); + } + &[aria-selected='true'] { + background-color: var(--color-background); + --tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1)); + box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); + &:is(.dark *) { + border-color: var(--color-input); + } + &:is(.dark *) { + background-color: color-mix(in srgb, var(--input) 30%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-input) 30%, transparent); + } + } + &:is(.dark *) { + color: var(--color-foreground); + } + } + } + } + [role='tabpanel'] { + flex: 1; + --tw-outline-style: none; + outline-style: none; + } + } +} @layer components { .form textarea, .textarea { display: flex; @@ -3026,6 +3184,67 @@ } } } +@layer components { + .toaster { + pointer-events: none; + position: fixed; + right: calc(var(--spacing) * 0); + bottom: calc(var(--spacing) * 0); + z-index: 50; + display: flex; + width: 100%; + flex-direction: column-reverse; + padding: calc(var(--spacing) * 4); + @media (width >= 40rem) { + max-width: calc(var(--spacing) * 90); + } + .toast { + pointer-events: auto; + margin-top: calc(var(--spacing) * 4); + display: grid; + width: 100%; + animation: toast-in 0.3s ease-in-out; + grid-template-rows: 1fr; + transition-property: grid-template-rows,opacity,margin; + transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); + transition-duration: var(--tw-duration, var(--default-transition-duration)); + --tw-duration: 300ms; + transition-duration: 300ms; + --tw-ease: var(--ease-in-out); + transition-timing-function: var(--ease-in-out); + .toast-content { + overflow: hidden; + border-radius: var(--radius-lg); + border-style: var(--tw-border-style); + border-width: 1px; + background-color: var(--color-popover); + font-size: 13px; + color: var(--color-popover-foreground); + --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1)); + box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); + } + &[aria-hidden='true'] { + margin: calc(var(--spacing) * 0); + grid-template-rows: 0fr; + overflow: hidden; + border-style: var(--tw-border-style); + border-width: 0px; + padding: calc(var(--spacing) * 0); + opacity: 0%; + .toast-content { + border-style: var(--tw-border-style); + border-width: 0px; + } + } + } + } +} +@keyframes toast-in { + from { + opacity: 0; + transform: translateY(100%); + } +} @layer components { [data-tooltip] { position: relative; @@ -3212,213 +3431,6 @@ } } } -@layer components { - .toasts { - pointer-events: none; - position: fixed; - right: calc(var(--spacing) * 0); - bottom: calc(var(--spacing) * 0); - z-index: 100; - max-width: var(--container-sm); - :where(& > :not(:last-child)) { - --tw-space-y-reverse: 0; - margin-block-start: calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse)); - margin-block-end: calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse))); - } - padding: calc(var(--spacing) * 6); - } - .toasts > [role='alert'], .toasts > [role='status'] { - transition-behavior: allow-discrete; - pointer-events: auto; - display: flex; - flex-direction: row-reverse; - align-items: flex-start; - justify-content: space-between; - column-gap: calc(var(--spacing) * 2); - border-radius: var(--radius-lg); - border-style: var(--tw-border-style); - border-width: 1px; - background-color: var(--color-background); - padding: calc(var(--spacing) * 4); - --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1)); - box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); - } - .toasts > [aria-hidden='true'] { - display: none; - --tw-scale-x: 75%; - --tw-scale-y: 75%; - --tw-scale-z: 75%; - scale: var(--tw-scale-x) var(--tw-scale-y); - opacity: 0%; - transition-property: all; - transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); - transition-duration: var(--tw-duration, var(--default-transition-duration)); - } - .toasts > [role='alert'] > button, .toasts > [role='status'] > button { - padding-block: calc(var(--spacing) * 0.5); - opacity: 50%; - transition-property: opacity; - transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); - transition-duration: var(--tw-duration, var(--default-transition-duration)); - &:hover { - @media (hover: hover) { - opacity: 100%; - } - } - } -} -@layer components { - .tabs { - [role='tablist'] { - display: inline-flex; - height: calc(var(--spacing) * 9); - width: fit-content; - align-items: center; - justify-content: center; - border-radius: var(--radius-lg); - background-color: var(--color-muted); - padding: 3px; - color: var(--color-muted-foreground); - [role='tab'] { - display: inline-flex; - height: calc(100% - 1px); - flex: 1; - align-items: center; - justify-content: center; - gap: calc(var(--spacing) * 1.5); - border-radius: var(--radius-md); - border-style: var(--tw-border-style); - border-width: 1px; - border-color: transparent; - padding-inline: calc(var(--spacing) * 2); - padding-block: calc(var(--spacing) * 1); - font-size: var(--text-sm); - line-height: var(--tw-leading, var(--text-sm--line-height)); - --tw-font-weight: var(--font-weight-medium); - font-weight: var(--font-weight-medium); - white-space: nowrap; - color: var(--color-foreground); - transition-property: color,box-shadow; - transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); - transition-duration: var(--tw-duration, var(--default-transition-duration)); - &:focus-visible { - border-color: var(--color-ring); - } - &:focus-visible { - --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor); - box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); - } - &:focus-visible { - --tw-ring-color: color-mix(in srgb, var(--ring) 50%, transparent); - @supports (color: color-mix(in lab, red, red)) { - --tw-ring-color: color-mix(in oklab, var(--color-ring) 50%, transparent); - } - } - &:focus-visible { - outline-style: var(--tw-outline-style); - outline-width: 1px; - } - &:focus-visible { - outline-color: var(--color-ring); - } - &:disabled { - pointer-events: none; - } - &:disabled { - opacity: 50%; - } - &:is(.dark *) { - color: var(--color-muted-foreground); - } - & svg { - pointer-events: none; - } - & svg { - flex-shrink: 0; - } - & svg:not([class*='size-']) { - width: calc(var(--spacing) * 4); - height: calc(var(--spacing) * 4); - } - &[aria-selected='true'] { - background-color: var(--color-background); - --tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1)); - box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); - &:is(.dark *) { - border-color: var(--color-input); - } - &:is(.dark *) { - background-color: color-mix(in srgb, var(--input) 30%, transparent); - @supports (color: color-mix(in lab, red, red)) { - background-color: color-mix(in oklab, var(--color-input) 30%, transparent); - } - } - &:is(.dark *) { - color: var(--color-foreground); - } - } - } - } - [role='tabpanel'] { - flex: 1; - --tw-outline-style: none; - outline-style: none; - } - } -} -@layer components { - .card { - display: flex; - flex-direction: column; - gap: calc(var(--spacing) * 6); - border-radius: var(--radius-xl); - border-style: var(--tw-border-style); - border-width: 1px; - background-color: var(--color-card); - padding-block: calc(var(--spacing) * 6); - color: var(--color-card-foreground); - --tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1)); - box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); - > header { - container-type: inline-size; - container-name: card-header; - display: grid; - grid-auto-rows: min-content; - grid-template-rows: auto auto; - align-items: flex-start; - gap: calc(var(--spacing) * 1.5); - padding-inline: calc(var(--spacing) * 6); - &:has(*[data-slot="card-action"]) { - grid-template-columns: 1fr auto; - } - &:is(.border-b) { - padding-bottom: calc(var(--spacing) * 6); - } - h2 { - --tw-leading: 1; - line-height: 1; - --tw-font-weight: var(--font-weight-semibold); - font-weight: var(--font-weight-semibold); - } - p { - font-size: var(--text-sm); - line-height: var(--tw-leading, var(--text-sm--line-height)); - color: var(--color-muted-foreground); - } - } - > section { - padding-inline: calc(var(--spacing) * 6); - } - > footer { - display: flex; - align-items: center; - padding-inline: calc(var(--spacing) * 6); - &:is(.border-t) { - padding-top: calc(var(--spacing) * 6); - } - } - } -} @property --tw-translate-x { syntax: "*"; inherits: false; diff --git a/dist/basecoat.tailwind.css b/dist/basecoat.tailwind.css index 0e55950..71ddc78 100644 --- a/dist/basecoat.tailwind.css +++ b/dist/basecoat.tailwind.css @@ -1,4 +1,5 @@ @import "tailwindcss"; +@import "tw-animate-css"; @custom-variant dark (&:is(.dark *)); @@ -161,8 +162,7 @@ } /* HTMX */ .htmx-indicator { - transition-behavior: allow-discrete; - @apply invisible opacity-0 transition-all; + @apply invisible opacity-0 transition-discrete transition-all; } .htmx-indicator:not(.htmx-request) { @apply hidden; @@ -359,6 +359,30 @@ } } +/* Card */ +@layer components { + .card { + @apply bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm; + + > 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; + + h2 { + @apply leading-none font-semibold; + } + p { + @apply text-muted-foreground text-sm; + } + } + > section { + @apply px-6; + } + > footer { + @apply flex items-center px-6 [.border-t]:pt-6; + } + } +} + /* Checkbox */ @layer components { .form input[type='checkbox']:not([role='switch']), @@ -377,8 +401,7 @@ details { &::details-content { block-size: 0; - @apply block opacity-0 transition-discrete - transition-all; + @apply block opacity-0 transition-discrete transition-all; } &[open]::details-content { block-size: auto; @@ -720,6 +743,26 @@ } } +/* Tabs */ +@layer components { + .tabs { + [role='tablist'] { + @apply bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]; + + [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; + } + } + } + [role='tabpanel'] { + @apply flex-1 outline-none; + } + } +} + /* Textarea */ @layer components { .form textarea, @@ -728,6 +771,34 @@ } } +/* Toasts */ +@layer components { + .toaster { + @apply fixed bottom-0 right-0 p-4 pointer-events-none z-50 w-full sm:max-w-90 flex flex-col-reverse; + + .toast { + @apply pointer-events-auto w-full mt-4 animate-[toast-in_0.3s_ease-in-out] grid grid-rows-[1fr] transition-[grid-template-rows,opacity,margin] duration-300 ease-in-out; + + .toast-content { + @apply text-popover-foreground text-[13px] bg-popover border shadow-lg rounded-lg overflow-hidden; + } + &[aria-hidden='true'] { + @apply grid-rows-[0fr] opacity-0 m-0 border-0 p-0 overflow-hidden; + + .toast-content { + @apply border-0; + } + } + } + } +} +@keyframes toast-in { + from { + opacity: 0; + transform: translateY(100%); + } +} + /* Tooltip */ @layer components { [data-tooltip] { @@ -780,71 +851,4 @@ } } } -} - -/* -------------------------------------------------------------------- */ - - -/* Notifications */ -@layer components { - .toasts { - @apply fixed bottom-0 right-0 p-6 space-y-2 pointer-events-none z-[100] max-w-sm; - } - .toasts > [role='alert'], - .toasts > [role='status'] { - transition-behavior: allow-discrete; - @apply bg-background border shadow-lg rounded-lg p-4 pointer-events-auto flex flex-row-reverse items-start justify-between gap-x-2; - } - .toasts > [aria-hidden='true'] { - @apply hidden opacity-0 scale-75 transition-all; - } - .toasts > [role='alert'] > button, - .toasts > [role='status'] > button { - @apply opacity-50 hover:opacity-100 transition-opacity py-0.5; - } -} - -/* Tabs */ -@layer components { - .tabs { - [role='tablist'] { - @apply bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]; - - [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; - } - } - } - [role='tabpanel'] { - @apply flex-1 outline-none; - } - } -} - -/* Card */ -@layer components { - .card { - @apply bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm; - - > 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; - - h2 { - @apply leading-none font-semibold; - } - p { - @apply text-muted-foreground text-sm; - } - } - > section { - @apply px-6; - } - > footer { - @apply flex items-center px-6 [.border-t]:pt-6; - } - } -} - +} \ No newline at end of file diff --git a/docs/_components/toast.njk b/docs/_components/toast.njk index bdb634f..dfcaed3 100644 --- a/docs/_components/toast.njk +++ b/docs/_components/toast.njk @@ -1,155 +1,133 @@ -{% macro toast( - id='toasts', - messages=None, - main_attrs=None +{% macro toaster( + id="toaster", + toasts=[], + main_attrs=None, + is_fragment=false ) %} -{% if registerComponent('toast') %} +{% if not is_fragment and registerComponent('toast') %} {% endif %} +{% set iconMapping = { + 'error': 'circle-x', + 'success': 'circle-check', + 'info': 'info', + 'warning': 'circle-alert' +} %} +