mirror of
https://github.com/hunvreus/basecoat.git
synced 2026-11-11 04:38:18 +00:00
Adding Input Group, cleaning up other new components
This commit is contained in:
+411
-38
@@ -11,6 +11,7 @@
|
||||
--color-amber-100: oklch(96.2% 0.059 95.617);
|
||||
--color-amber-900: oklch(41.4% 0.112 45.904);
|
||||
--color-amber-950: oklch(27.9% 0.077 45.635);
|
||||
--color-yellow-500: oklch(79.5% 0.184 86.047);
|
||||
--color-green-50: oklch(98.2% 0.018 155.826);
|
||||
--color-green-500: oklch(72.3% 0.219 149.579);
|
||||
--color-green-600: oklch(62.7% 0.194 149.214);
|
||||
@@ -24,7 +25,6 @@
|
||||
--color-blue-800: oklch(42.4% 0.199 265.638);
|
||||
--color-blue-900: oklch(37.9% 0.146 265.522);
|
||||
--color-blue-950: oklch(28.2% 0.091 267.935);
|
||||
--color-purple-500: oklch(62.7% 0.265 303.9);
|
||||
--color-neutral-300: oklch(87% 0 0);
|
||||
--color-neutral-800: oklch(26.9% 0 0);
|
||||
--color-black: #000;
|
||||
@@ -304,6 +304,9 @@
|
||||
.right-1 {
|
||||
right: calc(var(--spacing) * 1);
|
||||
}
|
||||
.right-1\.5 {
|
||||
right: calc(var(--spacing) * 1.5);
|
||||
}
|
||||
.right-2 {
|
||||
right: calc(var(--spacing) * 2);
|
||||
}
|
||||
@@ -313,12 +316,18 @@
|
||||
.right-3 {
|
||||
right: calc(var(--spacing) * 3);
|
||||
}
|
||||
.bottom-0 {
|
||||
bottom: calc(var(--spacing) * 0);
|
||||
}
|
||||
.bottom-2 {
|
||||
bottom: calc(var(--spacing) * 2);
|
||||
}
|
||||
.bottom-3 {
|
||||
bottom: calc(var(--spacing) * 3);
|
||||
}
|
||||
.left-1\.5 {
|
||||
left: calc(var(--spacing) * 1.5);
|
||||
}
|
||||
.left-1\/2 {
|
||||
left: calc(1/2 * 100%);
|
||||
}
|
||||
@@ -355,6 +364,9 @@
|
||||
max-width: 96rem;
|
||||
}
|
||||
}
|
||||
.m-0 {
|
||||
margin: calc(var(--spacing) * 0);
|
||||
}
|
||||
.mx-auto {
|
||||
margin-inline: auto;
|
||||
}
|
||||
@@ -450,6 +462,10 @@
|
||||
width: calc(var(--spacing) * 2.5);
|
||||
height: calc(var(--spacing) * 2.5);
|
||||
}
|
||||
.size-3 {
|
||||
width: calc(var(--spacing) * 3);
|
||||
height: calc(var(--spacing) * 3);
|
||||
}
|
||||
.size-3\.5 {
|
||||
width: calc(var(--spacing) * 3.5);
|
||||
height: calc(var(--spacing) * 3.5);
|
||||
@@ -458,10 +474,6 @@
|
||||
width: calc(var(--spacing) * 4);
|
||||
height: calc(var(--spacing) * 4);
|
||||
}
|
||||
.size-5 {
|
||||
width: calc(var(--spacing) * 5);
|
||||
height: calc(var(--spacing) * 5);
|
||||
}
|
||||
.size-6 {
|
||||
width: calc(var(--spacing) * 6);
|
||||
height: calc(var(--spacing) * 6);
|
||||
@@ -486,10 +498,6 @@
|
||||
width: calc(var(--spacing) * 12);
|
||||
height: calc(var(--spacing) * 12);
|
||||
}
|
||||
.size-16 {
|
||||
width: calc(var(--spacing) * 16);
|
||||
height: calc(var(--spacing) * 16);
|
||||
}
|
||||
.h-4 {
|
||||
height: calc(var(--spacing) * 4);
|
||||
}
|
||||
@@ -508,8 +516,8 @@
|
||||
.h-14 {
|
||||
height: calc(var(--spacing) * 14);
|
||||
}
|
||||
.h-px {
|
||||
height: 1px;
|
||||
.h-auto {
|
||||
height: auto;
|
||||
}
|
||||
.max-h-64 {
|
||||
max-height: calc(var(--spacing) * 64);
|
||||
@@ -526,18 +534,42 @@
|
||||
.max-h-\[650px\] {
|
||||
max-height: 650px;
|
||||
}
|
||||
.min-h-21 {
|
||||
min-height: calc(var(--spacing) * 21);
|
||||
}
|
||||
.min-h-22 {
|
||||
min-height: calc(var(--spacing) * 22);
|
||||
}
|
||||
.min-h-24 {
|
||||
min-height: calc(var(--spacing) * 24);
|
||||
}
|
||||
.min-h-25 {
|
||||
min-height: calc(var(--spacing) * 25);
|
||||
}
|
||||
.min-h-26 {
|
||||
min-height: calc(var(--spacing) * 26);
|
||||
}
|
||||
.min-h-27 {
|
||||
min-height: calc(var(--spacing) * 27);
|
||||
}
|
||||
.min-h-28 {
|
||||
min-height: calc(var(--spacing) * 28);
|
||||
}
|
||||
.min-h-30 {
|
||||
min-height: calc(var(--spacing) * 30);
|
||||
}
|
||||
.min-h-32 {
|
||||
min-height: calc(var(--spacing) * 32);
|
||||
}
|
||||
.min-h-64 {
|
||||
min-height: calc(var(--spacing) * 64);
|
||||
.min-h-77 {
|
||||
min-height: calc(var(--spacing) * 77);
|
||||
}
|
||||
.min-h-\[350px\] {
|
||||
min-height: 350px;
|
||||
}
|
||||
.w-0 {
|
||||
width: calc(var(--spacing) * 0);
|
||||
}
|
||||
.w-1\/2 {
|
||||
width: calc(1/2 * 100%);
|
||||
}
|
||||
@@ -586,6 +618,15 @@
|
||||
.w-max {
|
||||
width: max-content;
|
||||
}
|
||||
.max-w-23 {
|
||||
max-width: calc(var(--spacing) * 23);
|
||||
}
|
||||
.max-w-24 {
|
||||
max-width: calc(var(--spacing) * 24);
|
||||
}
|
||||
.max-w-72 {
|
||||
max-width: calc(var(--spacing) * 72);
|
||||
}
|
||||
.max-w-\[75\%\] {
|
||||
max-width: 75%;
|
||||
}
|
||||
@@ -814,14 +855,14 @@
|
||||
.self-start {
|
||||
align-self: flex-start;
|
||||
}
|
||||
.self-stretch {
|
||||
align-self: stretch;
|
||||
}
|
||||
.truncate {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.overflow-hidden {
|
||||
overflow: hidden;
|
||||
}
|
||||
.overflow-x-auto {
|
||||
overflow-x: auto;
|
||||
}
|
||||
@@ -834,6 +875,9 @@
|
||||
.rounded-\[2px\] {
|
||||
border-radius: 2px;
|
||||
}
|
||||
.rounded-\[calc\(var\(--radius\)-5px\)\] {
|
||||
border-radius: calc(var(--radius) - 5px);
|
||||
}
|
||||
.rounded-full {
|
||||
border-radius: calc(infinity * 1px);
|
||||
}
|
||||
@@ -843,12 +887,23 @@
|
||||
.rounded-md {
|
||||
border-radius: var(--radius-md);
|
||||
}
|
||||
.rounded-none {
|
||||
border-radius: 0;
|
||||
}
|
||||
.rounded-sm {
|
||||
border-radius: var(--radius-sm);
|
||||
}
|
||||
.rounded-xl {
|
||||
border-radius: var(--radius-xl);
|
||||
}
|
||||
.rounded-l-md {
|
||||
border-top-left-radius: var(--radius-md);
|
||||
border-bottom-left-radius: var(--radius-md);
|
||||
}
|
||||
.rounded-r-md {
|
||||
border-top-right-radius: var(--radius-md);
|
||||
border-bottom-right-radius: var(--radius-md);
|
||||
}
|
||||
.border {
|
||||
border-style: var(--tw-border-style);
|
||||
border-width: 1px;
|
||||
@@ -861,10 +916,22 @@
|
||||
border-top-style: var(--tw-border-style);
|
||||
border-top-width: 1px;
|
||||
}
|
||||
.border-r {
|
||||
border-right-style: var(--tw-border-style);
|
||||
border-right-width: 1px;
|
||||
}
|
||||
.border-r-0 {
|
||||
border-right-style: var(--tw-border-style);
|
||||
border-right-width: 0px;
|
||||
}
|
||||
.border-b {
|
||||
border-bottom-style: var(--tw-border-style);
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
.border-l-0 {
|
||||
border-left-style: var(--tw-border-style);
|
||||
border-left-width: 0px;
|
||||
}
|
||||
.border-dashed {
|
||||
--tw-border-style: dashed;
|
||||
border-style: dashed;
|
||||
@@ -881,9 +948,18 @@
|
||||
border-color: color-mix(in oklab, var(--color-border) 50%, transparent);
|
||||
}
|
||||
}
|
||||
.border-input {
|
||||
border-color: var(--color-input);
|
||||
}
|
||||
.border-muted {
|
||||
border-color: var(--color-muted);
|
||||
}
|
||||
.border-muted-foreground\/20 {
|
||||
border-color: var(--color-muted-foreground);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
border-color: color-mix(in oklab, var(--color-muted-foreground) 20%, transparent);
|
||||
}
|
||||
}
|
||||
.border-transparent {
|
||||
border-color: transparent;
|
||||
}
|
||||
@@ -902,21 +978,18 @@
|
||||
.bg-background {
|
||||
background-color: var(--color-background);
|
||||
}
|
||||
.bg-blue-500 {
|
||||
background-color: var(--color-blue-500);
|
||||
}
|
||||
.bg-card {
|
||||
background-color: var(--color-card);
|
||||
}
|
||||
.bg-foreground {
|
||||
background-color: var(--color-foreground);
|
||||
}
|
||||
.bg-green-500 {
|
||||
background-color: var(--color-green-500);
|
||||
}
|
||||
.bg-muted {
|
||||
background-color: var(--color-muted);
|
||||
}
|
||||
.bg-muted-foreground {
|
||||
background-color: var(--color-muted-foreground);
|
||||
}
|
||||
.bg-muted\/50 {
|
||||
background-color: var(--color-muted);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
@@ -926,9 +999,6 @@
|
||||
.bg-primary {
|
||||
background-color: var(--color-primary);
|
||||
}
|
||||
.bg-purple-500 {
|
||||
background-color: var(--color-purple-500);
|
||||
}
|
||||
.bg-sidebar-primary {
|
||||
background-color: var(--color-sidebar-primary);
|
||||
}
|
||||
@@ -980,6 +1050,9 @@
|
||||
.px-4 {
|
||||
padding-inline: calc(var(--spacing) * 4);
|
||||
}
|
||||
.px-9 {
|
||||
padding-inline: calc(var(--spacing) * 9);
|
||||
}
|
||||
.px-\[0\.3rem\] {
|
||||
padding-inline: 0.3rem;
|
||||
}
|
||||
@@ -995,54 +1068,135 @@
|
||||
.py-4 {
|
||||
padding-block: calc(var(--spacing) * 4);
|
||||
}
|
||||
.py-15 {
|
||||
padding-block: calc(var(--spacing) * 15);
|
||||
}
|
||||
.py-\[0\.2rem\] {
|
||||
padding-block: 0.2rem;
|
||||
}
|
||||
.pt-1\.5 {
|
||||
padding-top: calc(var(--spacing) * 1.5);
|
||||
}
|
||||
.pt-2 {
|
||||
padding-top: calc(var(--spacing) * 2);
|
||||
}
|
||||
.pt-3 {
|
||||
padding-top: calc(var(--spacing) * 3);
|
||||
}
|
||||
.pt-10 {
|
||||
padding-top: calc(var(--spacing) * 10);
|
||||
}
|
||||
.pt-12 {
|
||||
padding-top: calc(var(--spacing) * 12);
|
||||
}
|
||||
.pt-14 {
|
||||
padding-top: calc(var(--spacing) * 14);
|
||||
}
|
||||
.pt-15 {
|
||||
padding-top: calc(var(--spacing) * 15);
|
||||
}
|
||||
.pr-2 {
|
||||
padding-right: calc(var(--spacing) * 2);
|
||||
}
|
||||
.pr-9 {
|
||||
padding-right: calc(var(--spacing) * 9);
|
||||
}
|
||||
.pr-10 {
|
||||
padding-right: calc(var(--spacing) * 10);
|
||||
}
|
||||
.pr-12 {
|
||||
padding-right: calc(var(--spacing) * 12);
|
||||
}
|
||||
.pr-16 {
|
||||
padding-right: calc(var(--spacing) * 16);
|
||||
}
|
||||
.pr-20 {
|
||||
padding-right: calc(var(--spacing) * 20);
|
||||
}
|
||||
.pr-22 {
|
||||
padding-right: calc(var(--spacing) * 22);
|
||||
}
|
||||
.pr-24 {
|
||||
padding-right: calc(var(--spacing) * 24);
|
||||
}
|
||||
.pr-26 {
|
||||
padding-right: calc(var(--spacing) * 26);
|
||||
}
|
||||
.pr-28 {
|
||||
padding-right: calc(var(--spacing) * 28);
|
||||
}
|
||||
.pr-30 {
|
||||
padding-right: calc(var(--spacing) * 30);
|
||||
}
|
||||
.pr-32 {
|
||||
padding-right: calc(var(--spacing) * 32);
|
||||
}
|
||||
.pr-129 {
|
||||
padding-right: calc(var(--spacing) * 129);
|
||||
}
|
||||
.pb-3 {
|
||||
padding-bottom: calc(var(--spacing) * 3);
|
||||
}
|
||||
.pb-4 {
|
||||
padding-bottom: calc(var(--spacing) * 4);
|
||||
}
|
||||
.pb-10 {
|
||||
padding-bottom: calc(var(--spacing) * 10);
|
||||
}
|
||||
.pb-10\.5 {
|
||||
padding-bottom: calc(var(--spacing) * 10.5);
|
||||
}
|
||||
.pb-11 {
|
||||
padding-bottom: calc(var(--spacing) * 11);
|
||||
}
|
||||
.pb-12 {
|
||||
padding-bottom: calc(var(--spacing) * 12);
|
||||
}
|
||||
.pb-14 {
|
||||
padding-bottom: calc(var(--spacing) * 14);
|
||||
}
|
||||
.pb-17 {
|
||||
padding-bottom: calc(var(--spacing) * 17);
|
||||
}
|
||||
.pl-6 {
|
||||
padding-left: calc(var(--spacing) * 6);
|
||||
}
|
||||
.pl-7 {
|
||||
padding-left: calc(var(--spacing) * 7);
|
||||
}
|
||||
.pl-8 {
|
||||
padding-left: calc(var(--spacing) * 8);
|
||||
}
|
||||
.pl-8\.5 {
|
||||
padding-left: calc(var(--spacing) * 8.5);
|
||||
}
|
||||
.pl-9 {
|
||||
padding-left: calc(var(--spacing) * 9);
|
||||
}
|
||||
.pl-10 {
|
||||
padding-left: calc(var(--spacing) * 10);
|
||||
}
|
||||
.pl-12 {
|
||||
padding-left: calc(var(--spacing) * 12);
|
||||
}
|
||||
.pl-14 {
|
||||
padding-left: calc(var(--spacing) * 14);
|
||||
}
|
||||
.pl-15 {
|
||||
padding-left: calc(var(--spacing) * 15);
|
||||
}
|
||||
.pl-16 {
|
||||
padding-left: calc(var(--spacing) * 16);
|
||||
}
|
||||
.pl-19 {
|
||||
padding-left: calc(var(--spacing) * 19);
|
||||
}
|
||||
.pl-20 {
|
||||
padding-left: calc(var(--spacing) * 20);
|
||||
}
|
||||
.pl-21 {
|
||||
padding-left: calc(var(--spacing) * 21);
|
||||
}
|
||||
.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
@@ -1162,9 +1316,6 @@
|
||||
.text-sidebar-primary-foreground {
|
||||
color: var(--color-sidebar-primary-foreground);
|
||||
}
|
||||
.text-white {
|
||||
color: var(--color-white);
|
||||
}
|
||||
.uppercase {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
@@ -1285,6 +1436,21 @@
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
.group-data-\[disabled\=true\]\:pointer-events-none {
|
||||
&:is(:where(.group)[data-disabled="true"] *) {
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
.group-data-\[disabled\=true\]\:opacity-50 {
|
||||
&:is(:where(.group)[data-disabled="true"] *) {
|
||||
opacity: 50%;
|
||||
}
|
||||
}
|
||||
.group-data-\[disabled\=true\]\/field\:opacity-50 {
|
||||
&:is(:where(.group\/field)[data-disabled="true"] *) {
|
||||
opacity: 50%;
|
||||
}
|
||||
}
|
||||
.group-\[\.copied\]\:block {
|
||||
&:is(:where(.group):is(.copied) *) {
|
||||
display: block;
|
||||
@@ -1300,6 +1466,16 @@
|
||||
border-color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
.peer-disabled\:cursor-not-allowed {
|
||||
&:is(:where(.peer):disabled ~ *) {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
.peer-disabled\:opacity-50 {
|
||||
&:is(:where(.peer):disabled ~ *) {
|
||||
opacity: 50%;
|
||||
}
|
||||
}
|
||||
.last\:border-b-0 {
|
||||
&:last-child {
|
||||
border-bottom-style: var(--tw-border-style);
|
||||
@@ -1385,6 +1561,13 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.hover\:bg-foreground {
|
||||
&:hover {
|
||||
@media (hover: hover) {
|
||||
background-color: var(--color-foreground);
|
||||
}
|
||||
}
|
||||
}
|
||||
.hover\:bg-muted {
|
||||
&:hover {
|
||||
@media (hover: hover) {
|
||||
@@ -1392,6 +1575,13 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.hover\:text-accent-foreground {
|
||||
&:hover {
|
||||
@media (hover: hover) {
|
||||
color: var(--color-accent-foreground);
|
||||
}
|
||||
}
|
||||
}
|
||||
.hover\:text-foreground {
|
||||
&:hover {
|
||||
@media (hover: hover) {
|
||||
@@ -1466,11 +1656,60 @@
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
.disabled\:border {
|
||||
&:disabled {
|
||||
border-style: var(--tw-border-style);
|
||||
border-width: 1px;
|
||||
}
|
||||
}
|
||||
.disabled\:opacity-50 {
|
||||
&:disabled {
|
||||
opacity: 50%;
|
||||
}
|
||||
}
|
||||
.has-data-\[state\=checked\]\:border-primary {
|
||||
&:has(*[data-state="checked"]) {
|
||||
border-color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
.has-data-\[state\=checked\]\:bg-primary\/5 {
|
||||
&:has(*[data-state="checked"]) {
|
||||
background-color: var(--color-primary);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
background-color: color-mix(in oklab, var(--color-primary) 5%, transparent);
|
||||
}
|
||||
}
|
||||
}
|
||||
.has-\[\:checkd\]\:border {
|
||||
&:has(*:is(:checkd)) {
|
||||
border-style: var(--tw-border-style);
|
||||
border-width: 1px;
|
||||
}
|
||||
}
|
||||
.has-\[\:checked\]\:border-primary {
|
||||
&:has(*:is(:checked)) {
|
||||
border-color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
.has-\[\:checked\]\:bg-muted {
|
||||
&:has(*:is(:checked)) {
|
||||
background-color: var(--color-muted);
|
||||
}
|
||||
}
|
||||
.has-\[\:checked\]\:bg-primary\/5 {
|
||||
&:has(*:is(:checked)) {
|
||||
background-color: var(--color-primary);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
background-color: color-mix(in oklab, var(--color-primary) 5%, transparent);
|
||||
}
|
||||
}
|
||||
}
|
||||
.has-\[input\:checkd\]\:border {
|
||||
&:has(*:is(input:checkd)) {
|
||||
border-style: var(--tw-border-style);
|
||||
border-width: 1px;
|
||||
}
|
||||
}
|
||||
.has-\[input\[type\=\'checkbox\'\]\:checked\]\:border-blue-600 {
|
||||
&:has(*:is(input[type='checkbox']:checked)) {
|
||||
border-color: var(--color-blue-600);
|
||||
@@ -1491,6 +1730,32 @@
|
||||
background-color: var(--color-green-50);
|
||||
}
|
||||
}
|
||||
.has-\[\>\[data-slot\=field\]\]\:w-full {
|
||||
&:has(>[data-slot=field]) {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.has-\[\>\[data-slot\=field\]\]\:flex-col {
|
||||
&:has(>[data-slot=field]) {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
.has-\[\>\[data-slot\=field\]\]\:rounded-md {
|
||||
&:has(>[data-slot=field]) {
|
||||
border-radius: var(--radius-md);
|
||||
}
|
||||
}
|
||||
.has-\[\>\[data-slot\=field\]\]\:border {
|
||||
&:has(>[data-slot=field]) {
|
||||
border-style: var(--tw-border-style);
|
||||
border-width: 1px;
|
||||
}
|
||||
}
|
||||
.has-\[\>svg\]\:px-2 {
|
||||
&:has(>svg) {
|
||||
padding-inline: calc(var(--spacing) * 2);
|
||||
}
|
||||
}
|
||||
.has-\[\>svg\]\:px-2\.5 {
|
||||
&:has(>svg) {
|
||||
padding-inline: calc(var(--spacing) * 2.5);
|
||||
@@ -1509,6 +1774,35 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.aria-pressed\:bg-transparent {
|
||||
&[aria-pressed="true"] {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
.aria-pressed\:text-blue-500 {
|
||||
&[aria-pressed="true"] {
|
||||
color: var(--color-blue-500);
|
||||
}
|
||||
}
|
||||
.aria-pressed\:text-blue-600 {
|
||||
&[aria-pressed="true"] {
|
||||
color: var(--color-blue-600);
|
||||
}
|
||||
}
|
||||
.aria-pressed\:text-yellow-500 {
|
||||
&[aria-pressed="true"] {
|
||||
color: var(--color-yellow-500);
|
||||
}
|
||||
}
|
||||
.aria-pressed\:hover\:bg-accent {
|
||||
&[aria-pressed="true"] {
|
||||
&:hover {
|
||||
@media (hover: hover) {
|
||||
background-color: var(--color-accent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.max-sm\:flex-col {
|
||||
@media (width < 40rem) {
|
||||
flex-direction: column;
|
||||
@@ -1691,6 +1985,18 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.dark\:hover\:bg-accent\/50 {
|
||||
&:is(.dark *) {
|
||||
&:hover {
|
||||
@media (hover: hover) {
|
||||
background-color: var(--color-accent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
background-color: color-mix(in oklab, var(--color-accent) 50%, transparent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.dark\:hover\:bg-destructive\/20 {
|
||||
&:is(.dark *) {
|
||||
&:hover {
|
||||
@@ -1713,6 +2019,26 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.dark\:has-data-\[state\=checked\]\:bg-primary\/10 {
|
||||
&:is(.dark *) {
|
||||
&:has(*[data-state="checked"]) {
|
||||
background-color: var(--color-primary);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
background-color: color-mix(in oklab, var(--color-primary) 10%, transparent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.dark\:has-\[\:checked\]\:bg-primary\/10 {
|
||||
&:is(.dark *) {
|
||||
&:has(*:is(:checked)) {
|
||||
background-color: var(--color-primary);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
background-color: color-mix(in oklab, var(--color-primary) 10%, transparent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.dark\:has-\[input\[type\=\'checkbox\'\]\:checked\]\:border-blue-900 {
|
||||
&:is(.dark *) {
|
||||
&:has(*:is(input[type='checkbox']:checked)) {
|
||||
@@ -1751,6 +2077,20 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.dark\:aria-pressed\:hover\:bg-accent\/50 {
|
||||
&:is(.dark *) {
|
||||
&[aria-pressed="true"] {
|
||||
&:hover {
|
||||
@media (hover: hover) {
|
||||
background-color: var(--color-accent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
background-color: color-mix(in oklab, var(--color-accent) 50%, transparent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.\[\&_\[data-new-link\]\:\:after\]\:ml-auto {
|
||||
& [data-new-link]::after {
|
||||
margin-left: auto;
|
||||
@@ -1962,11 +2302,6 @@
|
||||
padding-left: calc(var(--spacing) * 4);
|
||||
}
|
||||
}
|
||||
.\[\&\+\[data-slot\=item-content\]\]\:flex-none {
|
||||
&+[data-slot=item-content] {
|
||||
flex: none;
|
||||
}
|
||||
}
|
||||
.md\:\*\:\[\.card\]\:basis-1\/4 {
|
||||
@media (width >= 48rem) {
|
||||
:is(& > *) {
|
||||
@@ -1995,6 +2330,19 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.\[disabled\]\:border {
|
||||
&:is(disabled) {
|
||||
border-style: var(--tw-border-style);
|
||||
border-width: 1px;
|
||||
}
|
||||
}
|
||||
.\[\&\>\*\]\:data-\[slot\=field\]\:p-4 {
|
||||
&>* {
|
||||
&[data-slot="field"] {
|
||||
padding: calc(var(--spacing) * 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
.\[\&\>a\]\:underline {
|
||||
&>a {
|
||||
text-decoration-line: underline;
|
||||
@@ -2015,12 +2363,37 @@
|
||||
margin-bottom: calc(var(--spacing) * 3);
|
||||
}
|
||||
}
|
||||
.\[\&\>svg\]\:size-3 {
|
||||
&>svg {
|
||||
width: calc(var(--spacing) * 3);
|
||||
height: calc(var(--spacing) * 3);
|
||||
}
|
||||
}
|
||||
.\[\&\>svg\]\:size-4 {
|
||||
&>svg {
|
||||
width: calc(var(--spacing) * 4);
|
||||
height: calc(var(--spacing) * 4);
|
||||
}
|
||||
}
|
||||
.\[\&\>svg\]\:size-6 {
|
||||
&>svg {
|
||||
width: calc(var(--spacing) * 6);
|
||||
height: calc(var(--spacing) * 6);
|
||||
}
|
||||
}
|
||||
.aria-pressed\:\[\&\>svg\]\:fill-blue-600 {
|
||||
&[aria-pressed="true"] {
|
||||
&>svg {
|
||||
fill: var(--color-blue-600);
|
||||
}
|
||||
}
|
||||
}
|
||||
.\[\&\>svg\:not\(\[class\*\=\'size-\'\]\)\]\:size-3\.5 {
|
||||
&>svg:not([class*='size-']) {
|
||||
width: calc(var(--spacing) * 3.5);
|
||||
height: calc(var(--spacing) * 3.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
:root {
|
||||
--radius: 0.625rem;
|
||||
@@ -3387,11 +3760,11 @@
|
||||
line-height: var(--tw-leading, var(--text-base--line-height));
|
||||
--tw-font-weight: var(--font-weight-medium);
|
||||
font-weight: var(--font-weight-medium);
|
||||
}
|
||||
> .description {
|
||||
font-size: var(--text-sm);
|
||||
line-height: var(--tw-leading, var(--text-sm--line-height));
|
||||
color: var(--color-muted-foreground);
|
||||
& + p {
|
||||
font-size: var(--text-sm);
|
||||
line-height: var(--tw-leading, var(--text-sm--line-height));
|
||||
color: var(--color-muted-foreground);
|
||||
}
|
||||
}
|
||||
}
|
||||
.field {
|
||||
|
||||
+166
-97
@@ -29,9 +29,9 @@ toc:
|
||||
|
||||
{% set code_demo %}
|
||||
<form class="w-full max-w-md space-y-6">
|
||||
<fieldset class="fieldset" aria-describedby="payment-desc">
|
||||
<fieldset class="fieldset">
|
||||
<legend>Payment Method</legend>
|
||||
<p id="payment-desc" class="description">All transactions are secure and encrypted</p>
|
||||
<p>All transactions are secure and encrypted</p>
|
||||
|
||||
<div role="group" class="field">
|
||||
<label for="card-name">Name on Card</label>
|
||||
@@ -47,7 +47,7 @@ toc:
|
||||
<div class="grid grid-cols-3 gap-4">
|
||||
<div role="group" class="field">
|
||||
<label for="exp-month">Month</label>
|
||||
<select id="exp-month" class="select">
|
||||
<select id="exp-month" class="select w-full">
|
||||
<option value="">MM</option>
|
||||
<option value="01">01</option>
|
||||
<option value="02">02</option>
|
||||
@@ -65,7 +65,7 @@ toc:
|
||||
</div>
|
||||
<div role="group" class="field">
|
||||
<label for="exp-year">Year</label>
|
||||
<select id="exp-year" class="select">
|
||||
<select id="exp-year" class="select w-full">
|
||||
<option value="">YYYY</option>
|
||||
<option value="2024">2024</option>
|
||||
<option value="2025">2025</option>
|
||||
@@ -84,13 +84,15 @@ toc:
|
||||
|
||||
<hr role="separator" class="my-6 border-border">
|
||||
|
||||
<fieldset class="fieldset" aria-describedby="billing-desc">
|
||||
<fieldset class="fieldset">
|
||||
<legend>Billing Address</legend>
|
||||
<p id="billing-desc" class="description">The billing address associated with your payment method</p>
|
||||
<p>The billing address associated with your payment method</p>
|
||||
|
||||
<div class="flex items-center gap-3">
|
||||
<input type="checkbox" id="same-as-shipping" checked>
|
||||
<label for="same-as-shipping" class="font-normal">Same as shipping address</label>
|
||||
<div role="group" class="field">
|
||||
<label for="same-as-shipping" class="gap-3">
|
||||
<input type="checkbox" id="same-as-shipping" checked>
|
||||
Same as shipping address
|
||||
</label>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
@@ -101,7 +103,7 @@ toc:
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<div class="flex gap-2">
|
||||
<div class="flex gap-3">
|
||||
<button type="submit" class="btn">Submit</button>
|
||||
<button type="button" class="btn-outline">Cancel</button>
|
||||
</div>
|
||||
@@ -116,10 +118,10 @@ toc:
|
||||
<p>Field provides semantic HTML patterns for accessible forms:</p>
|
||||
<ul>
|
||||
<li><code><fieldset></code> and <code><legend></code> for grouping related fields</li>
|
||||
<li><code>role="group"</code> with <code>.field</code> class for individual fields</li>
|
||||
<li><code>.description</code> class for helper text</li>
|
||||
<li><code><p></code> after <code><legend></code> is automatically styled as description text</li>
|
||||
<li><code>role="group"</code> with <code>.field</code> class for individual field containers</li>
|
||||
<li><code>.description</code> class for field-level helper text (requires <code>aria-describedby</code>)</li>
|
||||
<li><code>.error</code> class with <code>role="alert"</code> for error messages</li>
|
||||
<li><code>aria-describedby</code> to associate descriptions and errors with inputs</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
@@ -130,53 +132,91 @@ toc:
|
||||
<h3 id="example-input"><a href="#example-input">Input</a></h3>
|
||||
|
||||
{% set code_input %}
|
||||
<div class="grid gap-6 w-full max-w-md">
|
||||
<div class="grid gap-6">
|
||||
<div role="group" class="field">
|
||||
<label for="username">Username</label>
|
||||
<input id="username" type="text" placeholder="evilrabbit" aria-describedby="username-desc">
|
||||
<p id="username-desc" class="description">Choose a unique username for your account</p>
|
||||
<p id="username-desc" class="description">Choose a unique username for your account.</p>
|
||||
</div>
|
||||
|
||||
<div role="group" class="field">
|
||||
<label for="password">Password</label>
|
||||
<input id="password" type="password" placeholder="••••••••" aria-invalid="true" aria-describedby="password-desc password-error">
|
||||
<p id="password-desc" class="description">Must be at least 8 characters</p>
|
||||
<p id="password-error" class="error" role="alert">Password is too short</p>
|
||||
<p id="password-desc" class="description">Must be at least 8 characters long.</p>
|
||||
<input id="password" type="password" placeholder="••••••••" aria-describedby="password-desc">
|
||||
</div>
|
||||
</div>
|
||||
{% endset %}
|
||||
|
||||
{{ code_preview("field-input", code_input) }}
|
||||
{{ code_preview("field-input", code_input, class="w-full max-w-md") }}
|
||||
|
||||
<h3 id="example-textarea"><a href="#example-textarea">Textarea</a></h3>
|
||||
|
||||
{% set code_textarea %}
|
||||
<div role="group" class="field w-full max-w-md">
|
||||
<label for="bio">Bio</label>
|
||||
<textarea id="bio" rows="4" placeholder="Tell us about yourself" aria-describedby="bio-desc"></textarea>
|
||||
<p id="bio-desc" class="description">Brief description for your profile (max 200 characters)</p>
|
||||
<div role="group" class="field">
|
||||
<label for="bio">Feedback</label>
|
||||
<textarea id="bio" rows="4" placeholder="Your feedback helps us improve..." aria-describedby="bio-desc"></textarea>
|
||||
<p id="bio-desc" class="description">Share your thoughts about our service.</p>
|
||||
</div>
|
||||
{% endset %}
|
||||
|
||||
{{ code_preview("field-textarea", code_textarea) }}
|
||||
{{ code_preview("field-textarea", code_textarea, class="w-full max-w-md") }}
|
||||
|
||||
<h3 id="example-select"><a href="#example-select">Select</a></h3>
|
||||
|
||||
{% set code_select %}
|
||||
<div role="group" class="field w-full max-w-md">
|
||||
<label for="country">Country</label>
|
||||
<select id="country" class="select" aria-describedby="country-desc">
|
||||
<option value="">Select a country</option>
|
||||
<option value="us">United States</option>
|
||||
<option value="uk">United Kingdom</option>
|
||||
<option value="ca">Canada</option>
|
||||
<option value="au">Australia</option>
|
||||
<div role="group" class="field">
|
||||
<label for="country">Department</label>
|
||||
<select id="country" class="select w-full" aria-describedby="country-desc">
|
||||
<option value="">Choose department</option>
|
||||
<option value="engineering">Engineering</option>
|
||||
<option value="design">Design</option>
|
||||
<option value="marketing">Marketing</option>
|
||||
<option value="sales">Sales</option>
|
||||
<option value="support">Customer Support</option>
|
||||
<option value="hr">Human Resources</option>
|
||||
<option value="finance">Finance</option>
|
||||
<option value="operations">Operations</option>
|
||||
</select>
|
||||
<p id="country-desc" class="description">Choose your country of residence</p>
|
||||
<p id="country-desc" class="description">Select your department or area of work.</p>
|
||||
</div>
|
||||
{% endset %}
|
||||
|
||||
{{ code_preview("field-select", code_select) }}
|
||||
{{ code_preview("field-select", code_select, class="w-full max-w-md") }}
|
||||
|
||||
<h3 id="example-slider"><a href="#example-slider">Slider</a></h3>
|
||||
|
||||
{% set code %}
|
||||
<div role="group" class="field">
|
||||
<label for="price-range">Price</label>
|
||||
<p id="price-range-desc" class="description">Set your budget: $<span id="price-range-value">150</span></p>
|
||||
<input id="price-range" type="range" min="0" max="500" value="150">
|
||||
</div>
|
||||
<script>
|
||||
(() => {
|
||||
const sliders = document.querySelectorAll('input[type="range"]');
|
||||
if (!sliders) return;
|
||||
|
||||
const updateSlider = (el) => {
|
||||
const min = parseFloat(el.min || 0);
|
||||
const max = parseFloat(el.max || 100);
|
||||
const value = parseFloat(el.value);
|
||||
const percent = (max === min) ? 0 : ((value - min) / (max - min)) * 100;
|
||||
el.style.setProperty('--slider-value', `${percent}%`);
|
||||
};
|
||||
|
||||
sliders.forEach(slider => {
|
||||
updateSlider(slider);
|
||||
slider.addEventListener('input', (event) => updateSlider(event.target));
|
||||
});
|
||||
|
||||
const priceSlider = document.getElementById('price-range');
|
||||
const priceValue = document.getElementById('price-range-value');
|
||||
|
||||
priceSlider.addEventListener('input', (event) => priceValue.innerHTML = event.target.value);
|
||||
})();
|
||||
</script>
|
||||
{% endset %}
|
||||
{{ code_preview("slider", code, "w-full max-w-sm") }}
|
||||
|
||||
<h3 id="example-fieldset"><a href="#example-fieldset">Fieldset</a></h3>
|
||||
|
||||
@@ -186,9 +226,9 @@ toc:
|
||||
|
||||
{% set code_fieldset %}
|
||||
<form class="w-full max-w-md">
|
||||
<fieldset class="fieldset" aria-describedby="profile-desc">
|
||||
<fieldset class="fieldset">
|
||||
<legend>Profile</legend>
|
||||
<p id="profile-desc" class="description">This information will be displayed on your profile</p>
|
||||
<p>This information will be displayed on your profile</p>
|
||||
|
||||
<div role="group" class="field">
|
||||
<label for="full-name">Full name</label>
|
||||
@@ -217,54 +257,84 @@ toc:
|
||||
<h3 id="example-checkbox"><a href="#example-checkbox">Checkbox</a></h3>
|
||||
|
||||
{% set code_checkbox %}
|
||||
<fieldset class="fieldset w-full max-w-md" aria-describedby="tasks-desc">
|
||||
<legend>Tasks</legend>
|
||||
<p id="tasks-desc" class="description">Select the tasks you want to receive updates for</p>
|
||||
<fieldset class="fieldset">
|
||||
<legend>Show these items on the desktop</legend>
|
||||
<p>Select the items you want to show on the desktop.</p>
|
||||
|
||||
<div class="flex flex-col gap-3">
|
||||
<div class="flex items-center gap-3">
|
||||
<input type="checkbox" id="push-notifications" checked>
|
||||
<label for="push-notifications" class="font-normal">Push notifications</label>
|
||||
<div class="field">
|
||||
<label class="gap-3">
|
||||
<input type="checkbox">
|
||||
Hard disks
|
||||
</label>
|
||||
</div>
|
||||
<div class="flex items-center gap-3">
|
||||
<input type="checkbox" id="email-notifications" checked>
|
||||
<label for="email-notifications" class="font-normal">Email notifications</label>
|
||||
<div class="field">
|
||||
<label class="gap-3">
|
||||
<input type="checkbox">
|
||||
External disks
|
||||
</label>
|
||||
</div>
|
||||
<div class="flex items-center gap-3">
|
||||
<input type="checkbox" id="sms-notifications">
|
||||
<label for="sms-notifications" class="font-normal">SMS notifications</label>
|
||||
<div class="field">
|
||||
<label class="gap-3">
|
||||
<input type="checkbox">
|
||||
CDs, DVDs and iPods
|
||||
</label>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="gap-3">
|
||||
<input type="checkbox">
|
||||
Connected servers
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr role="separator">
|
||||
|
||||
<div class="field">
|
||||
<div class="flex w-full gap-3 flex-row items-center">
|
||||
<input id="sync-desktop-documents" type="checkbox" checked class="input self-start">
|
||||
<div class="flex flex-1 flex-col gap-1.5 leading-snug">
|
||||
<label for="sync-desktop-documents">Sync Desktop & Documents folders</label>
|
||||
<p class="description">Your Desktop & Documents folders are being synced with iCloud Drive. You can access them from other devices.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
{% endset %}
|
||||
|
||||
{{ code_preview("field-checkbox", code_checkbox) }}
|
||||
{{ code_preview("field-checkbox", code_checkbox, class="w-full max-w-md") }}
|
||||
|
||||
<h3 id="example-radio"><a href="#example-radio">Radio Group</a></h3>
|
||||
|
||||
{% set code_radio %}
|
||||
<fieldset class="fieldset w-full max-w-md" aria-describedby="notify-desc">
|
||||
<legend>Notify me about</legend>
|
||||
<p id="notify-desc" class="description">Choose which notifications you want to receive</p>
|
||||
<fieldset class="fieldset">
|
||||
<legend>Subscription plan</legend>
|
||||
<p>Yearly and lifetime plans offer significant savings.</p>
|
||||
|
||||
<div class="flex flex-col gap-3">
|
||||
<div class="flex items-center gap-3">
|
||||
<input type="radio" id="notify-all" name="notifications" checked>
|
||||
<label for="notify-all" class="font-normal">All new messages</label>
|
||||
<div role="radiogroup" class="grid gap-3">
|
||||
<div class="field">
|
||||
<label class="gap-3">
|
||||
<input type="radio" name="subscription-plan" checked>
|
||||
Monthly ($9.99/month)
|
||||
</label>
|
||||
</div>
|
||||
<div class="flex items-center gap-3">
|
||||
<input type="radio" id="notify-direct" name="notifications">
|
||||
<label for="notify-direct" class="font-normal">Direct messages and mentions</label>
|
||||
<div class="field">
|
||||
<label class="gap-3">
|
||||
<input type="radio" name="subscription-plan">
|
||||
Yearly ($99.99/year)
|
||||
</label>
|
||||
</div>
|
||||
<div class="flex items-center gap-3">
|
||||
<input type="radio" id="notify-none" name="notifications">
|
||||
<label for="notify-none" class="font-normal">Nothing</label>
|
||||
<div class="field">
|
||||
<label class="gap-3">
|
||||
<input type="radio" name="subscription-plan">
|
||||
Lifetime ($299.99)
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
{% endset %}
|
||||
|
||||
{{ code_preview("field-radio", code_radio) }}
|
||||
{{ code_preview("field-radio", code_radio, class="w-full max-w-md") }}
|
||||
|
||||
<h3 id="example-switch"><a href="#example-switch">Switch</a></h3>
|
||||
|
||||
@@ -273,44 +343,43 @@ toc:
|
||||
</section>
|
||||
|
||||
{% set code_switch %}
|
||||
<fieldset class="fieldset w-full max-w-md">
|
||||
<legend>Notifications</legend>
|
||||
<p class="description">Configure how you receive notifications</p>
|
||||
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<label for="marketing" class="font-medium">Marketing emails</label>
|
||||
<p class="description text-sm">Receive emails about new products and features</p>
|
||||
</div>
|
||||
<input type="checkbox" id="marketing" class="toggle" checked>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<label for="security" class="font-medium">Security emails</label>
|
||||
<p class="description text-sm">Receive emails about account security</p>
|
||||
</div>
|
||||
<input type="checkbox" id="security" class="toggle" checked>
|
||||
</div>
|
||||
<div role="group" class="field flex-row">
|
||||
<div class="flex flex-1 flex-col gap-1.5 leading-snug">
|
||||
<label for="multi-factor-authentication">Multi-factor authentication</label>
|
||||
<p class="description">Enable multi-factor authentication. If you do not have a two-factor device, you can use a one-time code sent to your email.</p>
|
||||
</div>
|
||||
</fieldset>
|
||||
<input id="multi-factor-authentication" type="checkbox" role="switch">
|
||||
</div>
|
||||
{% endset %}
|
||||
|
||||
{{ code_preview("field-switch", code_switch) }}
|
||||
{{ code_preview("field-switch", code_switch, class="w-full max-w-md") }}
|
||||
|
||||
<h2 id="accessibility"><a href="#accessibility">Accessibility</a></h2>
|
||||
|
||||
<section class="prose">
|
||||
<ul>
|
||||
<li>Always use <code><label></code> elements with <code>for</code> attribute matching input <code>id</code></li>
|
||||
<li>Associate helper text and errors using <code>aria-describedby</code> on the input</li>
|
||||
<li>Use <code>aria-invalid="true"</code> on inputs with errors</li>
|
||||
<li>Use <code>role="alert"</code> on error messages for screen reader announcements</li>
|
||||
<li>Group related fields with <code><fieldset></code> and <code><legend></code></li>
|
||||
<li>Use <code>role="group"</code> for individual field wrappers</li>
|
||||
</ul>
|
||||
</section>
|
||||
<h3 id="example-choice-card"><a href="#example-choice-card">Choice Card</a></h3>
|
||||
|
||||
{% set code_choice_card %}
|
||||
<fieldset class="fieldset">
|
||||
<legend class="text-sm">Compute Environment</legend>
|
||||
<p>Select the compute environment for your cluster.</p>
|
||||
|
||||
<div role="group" class="field">
|
||||
<label class="flex gap-3 border border-transparent rounded-md p-4 has-[:checked]:border-primary has-[:checked]:bg-primary/5 dark:has-[:checked]:bg-primary/10">
|
||||
<div class="flex flex-1 flex-col gap-1.5 leading-snug">
|
||||
<h3>Kubernetes</h3>
|
||||
<p class="description text-">Run GPU workloads on a K8s configured cluster.</p>
|
||||
</div>
|
||||
<input id="choice-card" type="radio" name="choice-card" class="self-start" checked>
|
||||
</label>
|
||||
</div>
|
||||
<div role="group" class="field">
|
||||
<label class="flex gap-3 border border-transparent rounded-md p-4 has-[:checked]:border-primary has-[:checked]:bg-primary/5 dark:has-[:checked]:bg-primary/10">
|
||||
<div class="flex flex-1 flex-col gap-1.5 leading-snug">
|
||||
<h3>Virtual Machine</h3>
|
||||
<p class="description text-">Access a VM configured cluster to run GPU workloads.</p>
|
||||
</div>
|
||||
<input id="choice-card" type="radio" name="choice-card" class="self-start">
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
{% endset %}
|
||||
|
||||
{{ code_preview("field-choice-card", code_choice_card, class="w-full max-w-md") }}
|
||||
+259
-145
@@ -1,247 +1,361 @@
|
||||
---
|
||||
layout: layouts/page.njk
|
||||
title: Input Group
|
||||
description: Display additional information or actions alongside inputs using simple HTML patterns.
|
||||
description: Display additional information or actions to an input or textarea.
|
||||
toc:
|
||||
- label: Usage
|
||||
id: usage
|
||||
- label: Examples
|
||||
id: examples
|
||||
children:
|
||||
- label: Icon Prefix
|
||||
id: example-icon-prefix
|
||||
- label: Icon Suffix
|
||||
id: example-icon-suffix
|
||||
- label: Text Prefix/Suffix
|
||||
- label: Icon
|
||||
id: example-icon
|
||||
- label: Text
|
||||
id: example-text
|
||||
- label: Button Suffix
|
||||
- label: Button
|
||||
id: example-button
|
||||
- label: Multiple Elements
|
||||
id: example-multiple
|
||||
- label: Tooltip
|
||||
id: example-tooltip
|
||||
- label: Textarea
|
||||
id: example-textarea
|
||||
- label: Spinner
|
||||
id: example-spinner
|
||||
- label: Dropdown
|
||||
id: example-dropdown
|
||||
- label: Group
|
||||
id: example-group
|
||||
---
|
||||
|
||||
{% from "macros/code_preview.njk" import code_preview %}
|
||||
{% from "macros/code_block.njk" import code_block %}
|
||||
{% from "dropdown-menu.njk" import dropdown_menu %}
|
||||
{% from "popover.njk" import popover %}
|
||||
|
||||
<div class="alert mb-6">
|
||||
{% lucide "circle-alert" %}
|
||||
<h2>There is no dedicated Input Group component in Basecoat.</h2>
|
||||
</div>
|
||||
|
||||
{% set code_default %}
|
||||
<div class="relative">
|
||||
<input type="text" class="input pl-10" placeholder="Search...">
|
||||
<div class="absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none text-muted-foreground">
|
||||
{% lucide "search" %}
|
||||
<div class="grid gap-6">
|
||||
<div class="relative">
|
||||
<input type="text" class="input pl-9 pr-20" placeholder="Search...">
|
||||
<div class="absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none text-muted-foreground [&>svg]:size-4">
|
||||
{% lucide "search" %}
|
||||
</div>
|
||||
<div class="absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none text-muted-foreground text-sm">12 results</div>
|
||||
</div>
|
||||
|
||||
<div class="relative">
|
||||
<input type="text" class="input pl-15 pr-9" placeholder="example.com">
|
||||
<div class="absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none text-muted-foreground text-sm">https://</div>
|
||||
<div class="absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground [&>svg]:size-4" data-tooltip="This is content in a tooltip.">{% lucide "info" %}</div>
|
||||
</div>
|
||||
|
||||
<div class="relative">
|
||||
<textarea class="textarea pr-10 min-h-27 pb-12" placeholder="Ask, Search or Chat..."></textarea>
|
||||
<footer role="group" class="absolute bottom-0 px-3 pb-3 pt-1.5 flex items-center w-full gap-2">
|
||||
<button type="button" class="btn-icon-outline rounded-full size-6 text-muted-foreground hover:text-accent-foreground">
|
||||
{% lucide "plus" %}
|
||||
</button>
|
||||
{{ dropdown_menu(
|
||||
id="demo-dropdown-menu",
|
||||
trigger="Auto",
|
||||
trigger_attrs={"class": "btn-sm-ghost text-muted-foreground hover:text-accent-foreground h-6 p-2"},
|
||||
popover_attrs={"data-side": "top", "class": "min-w-32"},
|
||||
items=[
|
||||
{ type: "item", label: "Auto" },
|
||||
{ type: "item", label: "Agent" },
|
||||
{ type: "item", label: "Manual" }
|
||||
]
|
||||
) }}
|
||||
<div class="text-muted-foreground text-sm ml-auto">52% used</div>
|
||||
<hr class="w-0 h-4 border-r border-border shrink-0 m-0">
|
||||
<button type="button" class="btn-icon rounded-full size-6 bg-muted-foreground hover:bg-foreground" disabled>
|
||||
{% lucide "arrow-up" %}
|
||||
</button>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<div class="relative">
|
||||
<input type="text" class="input pr-9" placeholder="@shadcn">
|
||||
<div class="absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none bg-primary text-primary-foreground flex size-4 items-center justify-center rounded-full [&>svg]:size-3">{% lucide "check" %}</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endset %}
|
||||
|
||||
{{ code_preview("input-group-default", code_default) }}
|
||||
{{ code_preview("input-group-default", code_default, class="w-full max-w-sm") }}
|
||||
|
||||
<h2 id="usage"><a href="#usage">Usage</a></h2>
|
||||
|
||||
<section class="prose">
|
||||
<p>Input groups are achieved through composition using relative positioning and Tailwind utilities. No special component needed - just wrap your input with a positioned container and add your icons, text, or buttons.</p>
|
||||
<p><strong>Key patterns:</strong></p>
|
||||
<ul>
|
||||
<li>Use <code>relative</code> wrapper around input</li>
|
||||
<li>Position content with <code>absolute</code> + <code>top-1/2 -translate-y-1/2</code></li>
|
||||
<li>Add padding to input (<code>pl-*</code> or <code>pr-*</code>) to make room for content</li>
|
||||
<li>Use <code>pointer-events-none</code> for decorative icons</li>
|
||||
</ul>
|
||||
<p>Input groups are pure HTML composition using Tailwind utility classes. There is no dedicated component: use <code>relative</code> positioning on a wrapper, add your content with <code>absolute</code> positioning, and adjust input padding to make room.</p>
|
||||
<p>Browse the examples below and copy the pattern that fits your needs.</p>
|
||||
</section>
|
||||
|
||||
{{ code_block(code_default) }}
|
||||
|
||||
<h2 id="examples"><a href="#examples">Examples</a></h2>
|
||||
|
||||
<h3 id="example-icon-prefix"><a href="#example-icon-prefix">Icon Prefix</a></h3>
|
||||
<h3 id="example-icon"><a href="#example-icon">Icon</a></h3>
|
||||
|
||||
<section class="prose">
|
||||
<p>Add an icon at the start of the input field.</p>
|
||||
</section>
|
||||
|
||||
{% set code_icon_prefix %}
|
||||
<div class="flex flex-col gap-4 w-full max-w-sm">
|
||||
{% set code_icon %}
|
||||
<div class="grid gap-6">
|
||||
<div class="relative">
|
||||
<input type="text" class="input pl-10" placeholder="Search...">
|
||||
<div class="absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none text-muted-foreground">
|
||||
<input type="text" class="input pl-9" placeholder="Search...">
|
||||
<div class="absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none text-muted-foreground [&>svg]:size-4">
|
||||
{% lucide "search" %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="relative">
|
||||
<input type="email" class="input pl-10" placeholder="Email">
|
||||
<div class="absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none text-muted-foreground">
|
||||
<input type="email" class="input pl-9" placeholder="Enter your email">
|
||||
<div class="absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none text-muted-foreground [&>svg]:size-4">
|
||||
{% lucide "mail" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endset %}
|
||||
|
||||
{{ code_preview("input-group-icon-prefix", code_icon_prefix) }}
|
||||
|
||||
<h3 id="example-icon-suffix"><a href="#example-icon-suffix">Icon Suffix</a></h3>
|
||||
|
||||
<section class="prose">
|
||||
<p>Add an icon at the end of the input field.</p>
|
||||
</section>
|
||||
|
||||
{% set code_icon_suffix %}
|
||||
<div class="flex flex-col gap-4 w-full max-w-sm">
|
||||
<div class="relative">
|
||||
<input type="text" class="input pr-10" placeholder="Username">
|
||||
<div class="absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none text-green-500">
|
||||
<input type="text" class="input px-9" placeholder="Card number">
|
||||
<div class="absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none text-muted-foreground [&>svg]:size-4">
|
||||
{% lucide "credit-card" %}
|
||||
</div>
|
||||
<div class="absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none text-muted-foreground [&>svg]:size-4">
|
||||
{% lucide "check" %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="relative">
|
||||
<input type="text" class="input pr-16" placeholder="Card number">
|
||||
<div class="absolute right-3 top-1/2 -translate-y-1/2 flex items-center gap-1 pointer-events-none text-muted-foreground">
|
||||
{% lucide "credit-card" %}
|
||||
<div class="absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none text-muted-foreground [&>svg]:size-4 flex items-center gap-2">
|
||||
{% lucide "star" %}
|
||||
{% lucide "info" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endset %}
|
||||
|
||||
{{ code_preview("input-group-icon-suffix", code_icon_suffix) }}
|
||||
{{ code_preview("input-group-icon-prefix", code_icon, class="w-full max-w-sm") }}
|
||||
|
||||
<h3 id="example-text"><a href="#example-text">Text Prefix/Suffix</a></h3>
|
||||
|
||||
<section class="prose">
|
||||
<p>Display text before or after the input value.</p>
|
||||
</section>
|
||||
<h3 id="example-text"><a href="#example-text">Text</a></h3>
|
||||
|
||||
{% set code_text %}
|
||||
<div class="flex flex-col gap-4 w-full max-w-sm">
|
||||
<div class="grid gap-6">
|
||||
<div class="relative">
|
||||
<input type="text" class="input pl-12 pr-16" placeholder="0.00">
|
||||
<div class="absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none text-muted-foreground text-sm">
|
||||
$
|
||||
</div>
|
||||
<div class="absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none text-muted-foreground text-sm">
|
||||
USD
|
||||
</div>
|
||||
<input type="text" class="input pl-7 pr-12" placeholder="0.00">
|
||||
<div class="absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none text-muted-foreground text-sm">$</div>
|
||||
<div class="absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none text-muted-foreground text-sm">USD</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="relative">
|
||||
<input type="text" class="input pl-20" placeholder="example.com">
|
||||
<div class="absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none text-muted-foreground text-sm">
|
||||
https://
|
||||
</div>
|
||||
<input type="text" class="input pl-15 pr-12" placeholder="example.com">
|
||||
<div class="absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none text-muted-foreground text-sm">https://</div>
|
||||
<div class="absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none text-muted-foreground text-sm">.com</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="relative">
|
||||
<input type="text" class="input pr-32" placeholder="username">
|
||||
<div class="absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none text-muted-foreground text-sm">
|
||||
@company.com
|
||||
</div>
|
||||
<input type="text" class="input pr-30" placeholder="Enter your username">
|
||||
<div class="absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none text-muted-foreground text-sm">@company.com</div>
|
||||
</div>
|
||||
|
||||
<div class="relative">
|
||||
<textarea class="textarea pr-10 min-h-25 pb-12" placeholder="Enter your message"></textarea>
|
||||
<footer role="group" class="absolute bottom-0 px-3 pb-3 pt-1.5 flex items-center w-full gap-2">
|
||||
<div class="text-muted-foreground text-sm">120 characters left</div>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
{% endset %}
|
||||
|
||||
{{ code_preview("input-group-text", code_text) }}
|
||||
{{ code_preview("input-group-text", code_text, class="w-full max-w-sm") }}
|
||||
|
||||
<h3 id="example-button"><a href="#example-button">Button Suffix</a></h3>
|
||||
|
||||
<section class="prose">
|
||||
<p>Add interactive buttons inside the input.</p>
|
||||
</section>
|
||||
<h3 id="example-button"><a href="#example-button">Button</a></h3>
|
||||
|
||||
{% set code_button %}
|
||||
<div class="flex flex-col gap-4 w-full max-w-sm">
|
||||
<div class="grid gap-6">
|
||||
<div class="relative">
|
||||
<input type="text" class="input pr-10" placeholder="Search...">
|
||||
<button type="button" class="absolute right-1 top-1/2 -translate-y-1/2 btn-icon-sm-ghost">
|
||||
{% lucide "search" %}
|
||||
</button>
|
||||
<input type="text" readonly class="input pr-9" value="https://x.com/hunvreus">
|
||||
<button class="absolute right-1.5 top-1/2 -translate-y-1/2 btn-icon-ghost text-muted-foreground hover:text-accent-foreground size-6">{% lucide "copy" %}</button>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="relative">
|
||||
<input type="password" class="input pr-10" placeholder="Password">
|
||||
<button type="button" class="absolute right-1 top-1/2 -translate-y-1/2 btn-icon-sm-ghost">
|
||||
{% lucide "eye" %}
|
||||
</button>
|
||||
<input type="text" class="input pl-21 pr-9 rounded-full">
|
||||
<button
|
||||
aria-pressed="false"
|
||||
onclick="this.ariaPressed = this.ariaPressed === 'true' ? 'false' : 'true'"
|
||||
class="absolute right-1.5 top-1/2 -translate-y-1/2 btn-icon-ghost text-muted-foreground hover:text-accent-foreground size-6 rounded-full aria-pressed:bg-transparent aria-pressed:hover:bg-accent dark:aria-pressed:hover:bg-accent/50 aria-pressed:text-blue-600 aria-pressed:[&>svg]:fill-blue-600"
|
||||
>{% lucide "star" %}</button>
|
||||
<div class="absolute left-1.5 top-1/2 -translate-y-1/2 flex items-center gap-1 z-10">
|
||||
{% set trigger %}
|
||||
{% lucide "info" %}
|
||||
{% endset %}
|
||||
{% call popover(
|
||||
trigger=trigger,
|
||||
trigger_attrs={"class": "btn-sm-icon-ghost rounded-full size-6"},
|
||||
popover_attrs={"class": "max-w-72"}
|
||||
) %}
|
||||
<h3 class="font-medium mb-1">Your connection is not secure.</h3>
|
||||
<p>You should not enter any sensitive information on this site.</p>
|
||||
{% endcall %}
|
||||
<div class="text-muted-foreground text-sm pointer-events-none">https://</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="relative">
|
||||
<input type="text" class="input pr-10" value="https://example.com/page">
|
||||
<button type="button" class="absolute right-1 top-1/2 -translate-y-1/2 btn-icon-sm-ghost">
|
||||
{% lucide "copy" %}
|
||||
</button>
|
||||
<input type="text" readonly class="input pr-9" placeholder="Type to search...">
|
||||
<button type="button" class="absolute right-1.5 top-1/2 -translate-y-1/2 btn-secondary h-6 p-2 rounded">Search</button>
|
||||
</div>
|
||||
</div>
|
||||
{% endset %}
|
||||
|
||||
{{ code_preview("input-group-button", code_button) }}
|
||||
{{ code_preview("input-group-button", code_button, class="w-full max-w-sm") }}
|
||||
|
||||
<h3 id="example-multiple"><a href="#example-multiple">Multiple Elements</a></h3>
|
||||
<h3 id="example-tooltip"><a href="#example-tooltip">Tooltip</a></h3>
|
||||
|
||||
<section class="prose">
|
||||
<p>Combine multiple icons, text, and buttons.</p>
|
||||
</section>
|
||||
|
||||
{% set code_multiple %}
|
||||
<div class="flex flex-col gap-4 w-full max-w-sm">
|
||||
{% set code_tooltip %}
|
||||
<div class="grid gap-6">
|
||||
<div class="relative">
|
||||
<input type="text" class="input pl-10 pr-20" placeholder="Search...">
|
||||
<div class="absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none text-muted-foreground">
|
||||
{% lucide "search" %}
|
||||
</div>
|
||||
<div class="absolute right-3 top-1/2 -translate-y-1/2 flex items-center gap-1.5">
|
||||
<span class="text-xs text-muted-foreground pointer-events-none">⌘K</span>
|
||||
</div>
|
||||
<input type="password" class="input pr-9" placeholder="Enter password">
|
||||
<div class="absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground [&>svg]:size-4" data-tooltip="Password must be at least 8 characters long.">{% lucide "info" %}</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="relative">
|
||||
<input type="text" class="input pl-20 pr-10" placeholder="example.com">
|
||||
<div class="absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none text-muted-foreground text-sm">
|
||||
https://
|
||||
</div>
|
||||
<button type="button" class="absolute right-1 top-1/2 -translate-y-1/2 btn-icon-sm-ghost">
|
||||
{% lucide "info" %}
|
||||
</button>
|
||||
<input type="email" class="input pr-9" placeholder="Your email address">
|
||||
<div class="absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground [&>svg]:size-4" data-tooltip="We'll use this to send your notifications.">{% lucide "circle-help" %}</div>
|
||||
</div>
|
||||
|
||||
<div class="relative">
|
||||
<input type="email" class="input pl-9" placeholder="Your email address">
|
||||
<div class="absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground [&>svg]:size-4" data-tooltip="Click for help with API keys." data-side="left">{% lucide "circle-help" %}</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endset %}
|
||||
|
||||
{{ code_preview("input-group-multiple", code_multiple) }}
|
||||
{{ code_preview("input-group-tooltip", code_tooltip, class="w-full max-w-sm") }}
|
||||
|
||||
<h3 id="example-textarea"><a href="#example-textarea">Textarea</a></h3>
|
||||
|
||||
<section class="prose">
|
||||
<p>Add buttons to textareas for actions like submit.</p>
|
||||
</section>
|
||||
|
||||
{% set code_textarea %}
|
||||
<div class="flex flex-col gap-4 w-full max-w-sm">
|
||||
<div class="relative">
|
||||
<textarea class="textarea pr-10 min-h-24" placeholder="Enter your message..."></textarea>
|
||||
<button type="button" class="absolute right-2 bottom-2 btn-icon-sm">
|
||||
{% lucide "send" %}
|
||||
<div class="relative">
|
||||
<textarea class="textarea pt-15 pb-17 min-h-77" placeholder="console.log('Hello, world!')."></textarea>
|
||||
<header class="absolute top-0 flex items-center w-full gap-2 p-3 border-b">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-brand-javascript size-4 text-muted-foreground"><path d="M20 4l-2 14.5l-6 2l-6 -2l-2 -14.5z"></path><path d="M7.5 8h3v8l-2 -1"></path><path d="M16.5 8h-2.5a.5 .5 0 0 0 -.5 .5v3a.5 .5 0 0 0 .5 .5h1.423a.5 .5 0 0 1 .495 .57l-.418 2.93l-2 .5"></path></svg>
|
||||
<span class="font-mono text-sm text-muted-foreground mr-auto">script.js</span>
|
||||
<button class="btn-sm-icon-ghost text-muted-foreground hover:text-accent-foreground size-6">
|
||||
{% lucide "refresh-ccw" %}
|
||||
</button>
|
||||
<button class="btn-sm-icon-ghost text-muted-foreground hover:text-accent-foreground size-6">
|
||||
{% lucide "copy" %}
|
||||
</button>
|
||||
</header>
|
||||
<footer class="absolute bottom-0 flex items-center w-full gap-2 p-3 border-t">
|
||||
<span class="text-sm text-muted-foreground mr-auto">Line 1, Column 1</span>
|
||||
<button type="button" class="btn-sm">
|
||||
Run
|
||||
{% lucide "corner-down-left" %}
|
||||
</button>
|
||||
</footer>
|
||||
</div>
|
||||
{% endset %}
|
||||
|
||||
{{ code_preview("input-group-textarea", code_textarea, class="w-full max-w-md") }}
|
||||
|
||||
<h3 id="example-spinner"><a href="#example-spinner">Spinner</a></h3>
|
||||
|
||||
{% set code_spinner %}
|
||||
<div class="grid gap-6">
|
||||
<div class="relative">
|
||||
<input type="text" class="input pr-9" placeholder="Searching..." disabled>
|
||||
<div class="absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none text-muted-foreground [&>svg]:size-4 animate-spin opacity-50">
|
||||
{% lucide "loader-circle" %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="relative">
|
||||
<textarea class="textarea pb-10 min-h-32" placeholder="Type something..."></textarea>
|
||||
<div class="absolute bottom-3 left-3 right-3 flex items-center justify-between gap-2">
|
||||
<span class="text-xs text-muted-foreground">120 characters left</span>
|
||||
<button type="button" class="btn-sm">Submit</button>
|
||||
<input type="text" class="input pl-9" placeholder="Processing..." disabled>
|
||||
<div class="absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none text-muted-foreground [&>svg]:size-4 animate-spin opacity-50">
|
||||
{% lucide "loader-circle" %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="relative">
|
||||
<input type="text" class="input pr-24" placeholder="Saving changes..." disabled>
|
||||
<div class="absolute right-3 top-1/2 -translate-y-1/2 flex items-center gap-2 text-sm text-muted-foreground opacity-50">
|
||||
<div>Saving...</div>
|
||||
<div class="[&>svg]:size-4 animate-spin">
|
||||
{% lucide "loader-circle" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="relative">
|
||||
<input type="text" class="input pl-9 pr-26" placeholder="Refreshing data..." disabled>
|
||||
<div class="absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none text-muted-foreground [&>svg]:size-4 animate-spin opacity-50">
|
||||
{% lucide "loader" %}
|
||||
</div>
|
||||
<div class="absolute right-3 top-1/2 -translate-y-1/2 flex items-center gap-2 text-sm text-muted-foreground opacity-50">
|
||||
Please wait...
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endset %}
|
||||
|
||||
{{ code_preview("input-group-textarea", code_textarea) }}
|
||||
{{ code_preview("input-group-spinner", code_spinner, class="w-full max-w-md") }}
|
||||
|
||||
<h2 id="accessibility"><a href="#accessibility">Accessibility</a></h2>
|
||||
<h3 id="example-dropdown"><a href="#example-dropdown">Dropdown</a></h3>
|
||||
|
||||
<section class="prose">
|
||||
<ul>
|
||||
<li>Use <code>pointer-events-none</code> for decorative icons that shouldn't be interactive</li>
|
||||
<li>Ensure buttons have proper <code>aria-label</code> or visible text</li>
|
||||
<li>Maintain sufficient padding so text doesn't overlap with icons/buttons</li>
|
||||
<li>Use semantic button types (<code>type="button"</code> vs <code>type="submit"</code>)</li>
|
||||
</ul>
|
||||
</section>
|
||||
{% set code_dropdown %}
|
||||
<div class="grid gap-6">
|
||||
<div class="relative">
|
||||
<input type="text" class="input pr-9" placeholder="Enter file name">
|
||||
{% set trigger %}
|
||||
{% lucide "ellipsis" %}
|
||||
{% endset %}
|
||||
{{ dropdown_menu(
|
||||
main_attrs={"class": "absolute right-1.5 top-1/2 -translate-y-1/2"},
|
||||
trigger=trigger,
|
||||
trigger_attrs={"class": "btn-sm-icon-ghost text-muted-foreground hover:text-accent-foreground size-6"},
|
||||
popover_attrs={"data-align": "end", "class": "min-w-32"},
|
||||
items=[
|
||||
{ type: "item", label: "Settings" },
|
||||
{ type: "item", label: "Copy path" },
|
||||
{ type: "item", label: "Open location" }
|
||||
]
|
||||
) }}
|
||||
</div>
|
||||
|
||||
<div class="relative">
|
||||
<input type="text" class="input pr-30" placeholder="Enter search query">
|
||||
{% set trigger %}
|
||||
Search in...
|
||||
{% lucide "chevron-down", { "class": "size-3" } %}
|
||||
{% endset %}
|
||||
{{ dropdown_menu(
|
||||
main_attrs={"class": "absolute right-1.5 top-1/2 -translate-y-1/2"},
|
||||
trigger=trigger,
|
||||
trigger_attrs={"class": "btn-sm-ghost text-muted-foreground hover:text-accent-foreground p-2 h-6"},
|
||||
popover_attrs={"data-align": "end", "class": "min-w-32"},
|
||||
items=[
|
||||
{ type: "item", label: "Documentation" },
|
||||
{ type: "item", label: "Blog Posts" },
|
||||
{ type: "item", label: "Changelog" }
|
||||
]
|
||||
) }}
|
||||
</div>
|
||||
</div>
|
||||
{% endset %}
|
||||
|
||||
{{ code_preview("input-group-dropdown", code_dropdown, class="w-full max-w-sm") }}
|
||||
|
||||
<h3 id="example-group"><a href="#example-group">Group</a></h3>
|
||||
|
||||
{% set code_group %}
|
||||
<div class="flex w-fit items-stretch">
|
||||
<label for="url" class="text-sm flex items-center bg-muted border border-r-0 px-4 rounded-l-md">https://</label>
|
||||
<div class="relative">
|
||||
<input type="text" class="input pr-9 rounded-none">
|
||||
<div class="absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground [&>svg]:size-4">{% lucide "link-2" %}</div>
|
||||
</div>
|
||||
<div class="text-sm flex items-center bg-muted border border-l-0 px-4 rounded-r-md">.com</div>
|
||||
</div>
|
||||
{% endset %}
|
||||
|
||||
{{ code_preview("input-group-group", code_group, class="w-full max-w-sm") }}
|
||||
@@ -3,6 +3,8 @@ layout: layouts/page.njk
|
||||
title: Item
|
||||
description: A versatile component that you can use to display any content.
|
||||
toc:
|
||||
- label: Usage
|
||||
id: usage
|
||||
- label: Examples
|
||||
id: examples
|
||||
children:
|
||||
@@ -58,6 +60,13 @@ toc:
|
||||
|
||||
{{ code_preview("item-basic", code_basic | prettyHtml, class="w-full max-w-md") }}
|
||||
|
||||
<h2 id="usage"><a href="#usage">Usage</a></h2>
|
||||
|
||||
<section class="prose">
|
||||
<p>Items are pure HTML composition using Tailwind utility classes. Use semantic elements like <code><article></code> or <code><a></code>, apply flex layout, and compose with standard HTML elements like <code><h3></code>, <code><p></code>, <code><img></code>, or <code><button></code>.</p>
|
||||
<p>Browse the examples below and copy the pattern that fits your needs.</p>
|
||||
</section>
|
||||
|
||||
<h2 id="examples"><a href="#examples">Examples</a></h2>
|
||||
|
||||
<h3 id="example-variants"><a href="#example-variants">Variants</a></h3>
|
||||
|
||||
@@ -693,10 +693,10 @@
|
||||
|
||||
> legend {
|
||||
@apply text-base font-medium mb-3;
|
||||
}
|
||||
|
||||
> .description {
|
||||
@apply text-sm text-muted-foreground;
|
||||
& + p {
|
||||
@apply text-sm text-muted-foreground;
|
||||
}
|
||||
}
|
||||
}
|
||||
.field {
|
||||
|
||||
Reference in New Issue
Block a user