diff --git a/dist/basecoat.css b/dist/basecoat.css index 5915cc4..274c121 100644 --- a/dist/basecoat.css +++ b/dist/basecoat.css @@ -69,8 +69,6 @@ --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); --shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); --shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25); - --ease-in: cubic-bezier(0.4, 0, 1, 1); - --ease-out: cubic-bezier(0, 0, 0.2, 1); --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1); --animate-spin: spin 1s linear infinite; --animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; @@ -255,6 +253,9 @@ .pointer-events-none { pointer-events: none; } + .invisible { + visibility: hidden; + } .sr-only { position: absolute; width: 1px; @@ -383,6 +384,10 @@ .aspect-video { aspect-ratio: var(--aspect-video); } + .size-2 { + width: calc(var(--spacing) * 2); + height: calc(var(--spacing) * 2); + } .size-3\.5 { width: calc(var(--spacing) * 3.5); height: calc(var(--spacing) * 3.5); @@ -533,21 +538,10 @@ --tw-translate-y: calc(calc(1/2 * 100%) * -1); translate: var(--tw-translate-x) var(--tw-translate-y); } - .translate-y-0 { - --tw-translate-y: calc(var(--spacing) * 0); - translate: var(--tw-translate-x) var(--tw-translate-y); - } .translate-y-0\.5 { --tw-translate-y: calc(var(--spacing) * 0.5); translate: var(--tw-translate-x) var(--tw-translate-y); } - .translate-y-2 { - --tw-translate-y: calc(var(--spacing) * 2); - translate: var(--tw-translate-x) var(--tw-translate-y); - } - .transform { - transform: var(--tw-rotate-x) var(--tw-rotate-y) var(--tw-rotate-z) var(--tw-skew-x) var(--tw-skew-y); - } .animate-pulse { animation: var(--animate-pulse); } @@ -720,6 +714,9 @@ .bg-background { background-color: var(--color-background); } + .bg-foreground { + background-color: var(--color-foreground); + } .bg-muted { background-color: var(--color-muted); } @@ -890,9 +887,6 @@ .text-sidebar-primary-foreground { color: var(--color-sidebar-primary-foreground); } - .text-transparent { - color: transparent; - } .text-zinc-50 { color: var(--color-zinc-50); } @@ -906,18 +900,12 @@ .underline-offset-4 { text-underline-offset: 4px; } - .opacity-0 { - opacity: 0%; - } .opacity-50 { opacity: 50%; } .opacity-60 { opacity: 60%; } - .opacity-100 { - opacity: 100%; - } .shadow-none { --tw-shadow: 0 0 #0000; box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); @@ -947,11 +935,6 @@ .filter { filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,); } - .transition { - transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter; - transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); - transition-duration: var(--tw-duration, var(--default-transition-duration)); - } .transition-\[margin-left\] { transition-property: margin-left; transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); @@ -981,22 +964,10 @@ --tw-duration: 200ms; transition-duration: 200ms; } - .duration-300 { - --tw-duration: 300ms; - transition-duration: 300ms; - } - .ease-in { - --tw-ease: var(--ease-in); - transition-timing-function: var(--ease-in); - } .ease-in-out { --tw-ease: var(--ease-in-out); transition-timing-function: var(--ease-in-out); } - .ease-out { - --tw-ease: var(--ease-out); - transition-timing-function: var(--ease-out); - } .outline-none { --tw-outline-style: none; outline-style: none; @@ -1010,6 +981,11 @@ rotate: 180deg; } } + .group-aria-checked\:visible { + &:is(:where(.group)[aria-checked="true"] *) { + visibility: visible; + } + } .peer-aria-hidden\:ml-0 { &:is(:where(.peer)[aria-hidden="true"] ~ *) { margin-left: calc(var(--spacing) * 0); @@ -1564,16 +1540,6 @@ height: calc(var(--spacing) * 4); } } - .\[\&\>\[role\=img\]\>svg\]\:w-full { - &>[role=img]>svg { - width: 100%; - } - } - .\[\&\>\[role\=img\]\>svg\]\:shrink-0 { - &>[role=img]>svg { - flex-shrink: 0; - } - } .\[\&\>h2\]\:mt-16 { &>h2 { margin-top: calc(var(--spacing) * 16); @@ -2780,7 +2746,7 @@ translate: var(--tw-translate-x) var(--tw-translate-y); } } - [role='menuitem'], [role='option'] { + [role='menuitem'], [role='menuitemcheckbox'], [role='menuitemradio'], [role='option'] { position: relative; display: flex; width: 100%; @@ -2829,7 +2795,7 @@ color: var(--color-muted-foreground); } } - [role='menuitem'] { + [role='menuitem'], [role='menuitemcheckbox'], [role='menuitemradio'] { &:hover { @media (hover: hover) { background-color: var(--color-accent); @@ -3676,6 +3642,7 @@ [data-tooltip] { position: relative; &:before { + pointer-events: none; visibility: hidden; position: absolute; z-index: 50; @@ -3710,6 +3677,9 @@ scale: var(--tw-scale-x) var(--tw-scale-y); opacity: 100%; } + &:focus-visible:not(:hover):before { + display: none; + } &:not([data-side]), &[data-side='top'] { &::before { content: var(--tw-content); @@ -3930,6 +3900,9 @@ li { margin-bottom: calc(var(--spacing) * 2); } + ul, ol { + margin-block: calc(var(--spacing) * 2); + } } .prose > *:first-child { margin-top: calc(var(--spacing) * 0) !important; @@ -3983,31 +3956,6 @@ inherits: false; initial-value: 0; } -@property --tw-rotate-x { - syntax: "*"; - inherits: false; - initial-value: rotateX(0); -} -@property --tw-rotate-y { - syntax: "*"; - inherits: false; - initial-value: rotateY(0); -} -@property --tw-rotate-z { - syntax: "*"; - inherits: false; - initial-value: rotateZ(0); -} -@property --tw-skew-x { - syntax: "*"; - inherits: false; - initial-value: skewX(0); -} -@property --tw-skew-y { - syntax: "*"; - inherits: false; - initial-value: skewY(0); -} @property --tw-space-y-reverse { syntax: "*"; inherits: false; @@ -4222,11 +4170,6 @@ --tw-translate-x: 0; --tw-translate-y: 0; --tw-translate-z: 0; - --tw-rotate-x: rotateX(0); - --tw-rotate-y: rotateY(0); - --tw-rotate-z: rotateZ(0); - --tw-skew-x: skewX(0); - --tw-skew-y: skewY(0); --tw-space-y-reverse: 0; --tw-space-x-reverse: 0; --tw-border-style: solid; diff --git a/dist/basecoat.tailwind.css b/dist/basecoat.tailwind.css index f79a2db..9420de0 100644 --- a/dist/basecoat.tailwind.css +++ b/dist/basecoat.tailwind.css @@ -627,10 +627,14 @@ } } [role='menuitem'], + [role='menuitemcheckbox'], + [role='menuitemradio'], [role='option'] { @apply aria-hidden:hidden [&_svg]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none [&_svg]:shrink-0 [&_svg]:size-4 aria-disabled:opacity-50 aria-disabled:pointer-events-none disabled:opacity-50 disabled:pointer-events-none w-full truncate; } - [role='menuitem'] { + [role='menuitem'], + [role='menuitemcheckbox'], + [role='menuitemradio'] { @apply focus-visible:bg-accent focus-visible:text-accent-foreground hover:bg-accent hover:text-accent-foreground; } [role='option'] { @@ -860,11 +864,14 @@ @apply relative; &:before { - @apply absolute content-[attr(data-tooltip)] bg-primary text-primary-foreground z-50 truncate max-w-xs w-fit rounded-md px-3 py-1.5 text-xs invisible opacity-0 scale-95 transition-all; + @apply absolute content-[attr(data-tooltip)] bg-primary text-primary-foreground z-50 truncate max-w-xs w-fit rounded-md px-3 py-1.5 text-xs invisible opacity-0 scale-95 transition-all pointer-events-none; } &:hover:before { @apply visible opacity-100 scale-100; } + &:focus-visible:not(:hover):before { + @apply hidden; + } &:not([data-side]), &[data-side='top'] { @apply before:bottom-full before:mb-1.5 before:translate-y-2 hover:before:translate-y-0 ; @@ -979,6 +986,10 @@ li { @apply mb-2; } + ul, + ol { + @apply my-2; + } } .prose > *:first-child { @apply !mt-0; diff --git a/docs/_includes/components/dropdown-menu-script.njk b/docs/_includes/components/dropdown-menu-script.njk index eb6c707..3bc772c 100644 --- a/docs/_includes/components/dropdown-menu-script.njk +++ b/docs/_includes/components/dropdown-menu-script.njk @@ -10,7 +10,7 @@ init() { this.$nextTick(() => { - this.menuItems = Array.from(this.$el.querySelectorAll('[role=menuitem]:not([disabled])')); + this.menuItems = Array.from(this.$el.querySelectorAll('[role=menuitem]:not([disabled]),[role=menuitemcheckbox]:not([disabled]),[role=menuitemradio]:not([disabled])')); }); }, focusMenuitem() { @@ -44,7 +44,7 @@ } }, handleMenuitemClick(event) { - const menuitem = event.target.closest('[role=menuitem]'); + const menuitem = event.target.closest('[role=menuitem],[role=menuitemcheckbox],[role=menuitemradio]'); if (menuitem && menuitem.getAttribute('aria-disabled') !== 'true' && !menuitem.disabled) { this.$nextTick(() => { this.$refs.trigger.focus(); @@ -53,7 +53,7 @@ } }, handleMenuitemMousemove(event) { - const menuitem = event.target.closest('[role=menuitem]'); + const menuitem = event.target.closest('[role=menuitem],[role=menuitemcheckbox],[role=menuitemradio]'); if (menuitem && menuitem.getAttribute('aria-disabled') !== 'true' && !menuitem.disabled) { this.focusedIndex = this.menuItems.indexOf(menuitem); this.focusMenuitem(); diff --git a/docs/_includes/components/tabs.njk b/docs/_includes/components/tabs.njk index 8a0d43f..7135365 100644 --- a/docs/_includes/components/tabs.njk +++ b/docs/_includes/components/tabs.njk @@ -20,7 +20,7 @@ {% if key != 'class' %}{{ key }}="{{ value }}"{% endif %} {% endfor %} > -
@@ -69,28 +160,79 @@
Notifications
You will need to include the Javascript (Alpine.js) code provided below before the HTML code for this component. As with all interactive components, you will need to add some Alpine.js properties to certain elements (e.g. x-bind, x-data, @click).
The Alert Dialog component uses the same Alpine.js code as the Dialog component with one small difference: we set initialCloseOnOverlayClick to false to prevent the dialog from closing when the overlay is clicked.
The example above uses some simple Tailwind CSS along with the Dropdown Menu.
-You will need to include the Javascript (Alpine.js) code provided below before the HTML code for this component. As with all interactive components, you will need to add some Alpine.js properties to certain elements (e.g. x-bind, x-data, @click).
Combobox uses the same Alpine.js code and markup as the Select component, the only difference being the search box at the top of the listbox.
You can set up a few additional options on the <div data-popover> element:
You will need to include the Javascript (Alpine.js) code provided below before the HTML code for this component. As with all interactive components, you will need to add some Alpine.js properties to certain elements (e.g. x-bind, x-data, @click).
If you use Jinja (or Nunjucks), you can use the dialog() macro directly, making sure to set close_on_overlay_click to False (or false for Nunjucks).
The component is structured as such:
<div class="dialog"> which wraps around the entire component and holds it state (e.g. open/close).<button> that acts as the trigger to open or close the popover.<div role="dialog"> that holds the dialog itself. It also acts as the backdrop for the dialog.<header> that contains the title (<h2>) and description (<p>) of the dialog.<section> for the content.<footer> that usually contains actions.<button>.If you use Jinja (or Nunjucks), you can use the dialog() macro directly. Read more about using Basecoat with Jinja and Nunjucks.
You will need to include the Javascript (Alpine.js) code provided below before the HTML code for this component. As with all interactive components, you will need to add some Alpine.js properties to certain elements (e.g. x-bind, x-data, @click).
The component is structured as such:
+<div class="popover"> which wraps around the entire component and holds it state (e.g. open/close).<button> that acts as the trigger to open or close the popover.<div data-popover> that holds the content of the popover.<div data-popover> is a <nav role="menu"> that contains a combination of:
+ <button role="menuitem"> for menu items.<button role="menuitemcheckbox"> for menu items with checkboxes.<button role="menuitemradio"> for menu items with radio buttons.<hr role="separator"> to display a horizontal separator.<div role="group"> to group options.<span role="heading"> for group headings.As with the Popover component, you can set up a few additional options on the <div data-popover> element:
data-side can be set to top, bottom, left, or right to change the side of the popover.data-align can be set to start, center, or end to change the alignment of the popover.If you use Jinja (or Nunjucks), you can use the dropdown_menu() macro directly. Read more about using Basecoat with Jinja and Nunjucks.
You can use one of the btn classes to style any element as a button:
btn or btn-primary for primary
- buttons, then btn-secondary, btn-destructive, btn-outline,
- btn-ghost, btn-link. You can also use btn-icon to
- style an icon as a button, along with all of its variants (e.g. btn-icon-destructive).
- btn-sm for small and btn-lg for large.
- You can combine this with other attributes, for example btn-lg-destructive
- or btn-icon-sm-secondary.
- Adding the form class to the parent of any form element (<label>, <input>, <textarea>, <select>) will automatically apply the style you would get from adding label, input, textarea, or select classes. Read more about Label, Input, Textarea, and Select.
Simply add the label class to your <label> element or have a parent with the form class (read more about form). Labels will be styled accordingly if a peer or child element is disabled.
Simply add the label class to your <label> element or have a parent with the form class (read more about form). Labels' style may be affected by the presence of a disabled peer or child element.
If you use a <select> element, just add the select class to it or have a parent with the form class (read more about form).
You will need to include the Javascript (Alpine.js) code provided below before the HTML code for this component. As with all interactive components, you will need to add some Alpine.js properties to certain elements (e.g. x-bind, x-data, @click).
If you need to do more than what <select> allows (e.g. HTML options), you can use the code below which uses the Popover component. Make sure to include the hidden input with the name you want to use for that field.
If you need to do more than what <select> allows (e.g. HTML options), you can use this component. It is structured as such:
<div class="popover"> which wraps around the entire component and holds it state (e.g. open/close).<button> that acts as the trigger to open or close the popover.<div data-popover> that holds the content of the popover.<div data-popover> is a <nav role="listbox"> that contains a combination of:
+ <div role="option"> for the options with a data-value attribute.<hr role="separator"> to display a horizontal separator.<div role="group"> to group options.<span role="heading"> for group headings.<input type="hidden"> to hold the value of the field (if needed).As with the Popover component, you can set up a few additional options on the <div data-popover> element:
data-side can be set to top, bottom, left, or right to change the side of the popover.data-align can be set to start, center, or end to change the alignment of the popover.If you use Jinja (or Nunjucks), you can use the select() macro directly.
If you use Jinja (or Nunjucks), you can use the dropdown_menu() macro directly. Read more about using Basecoat with Jinja and Nunjucks.
You will need to include the Javascript (Alpine.js) code provided below before the HTML code for this component. As with all interactive components, you will need to add some Alpine.js properties to certain elements (e.g. x-bind, x-data, @click).
You can style an <input type="range"> element by either adding the input class or having a parent with the form class (read more about form). However, the range input also requries some Javacript code to be able to paint the left side of the slider.
The component is structured as such:
+<div class="tabs"> which wraps around the entire component and holds it state (e.g. open/close).<nav role="tablist"> that holds the tab buttons (<button role="tab">).<div role="tabpanel"> that holds the tab panels corresponding to each tab button.If you use Jinja (or Nunjucks), you can use the tabs() macro directly. Read more about using Basecoat with Jinja and Nunjucks.
Make changes to your account here. Click save when you're done.
+Change your password here. After saving, you'll be logged out.
+