diff --git a/docs/src/assets/styles.css b/docs/src/assets/styles.css index d8a18c6..a68b102 100644 --- a/docs/src/assets/styles.css +++ b/docs/src/assets/styles.css @@ -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 { diff --git a/docs/src/components/field.njk b/docs/src/components/field.njk index 6bf8bd4..3589847 100644 --- a/docs/src/components/field.njk +++ b/docs/src/components/field.njk @@ -29,9 +29,9 @@ toc: {% set code_demo %}
-
+
Payment Method -

All transactions are secure and encrypted

+

All transactions are secure and encrypted

@@ -47,7 +47,7 @@ toc:
- @@ -65,7 +65,7 @@ toc:
- @@ -84,13 +84,15 @@ toc: -
+
Billing Address -

The billing address associated with your payment method

+

The billing address associated with your payment method

-
- - +
+
@@ -101,7 +103,7 @@ toc:
-
+
@@ -116,10 +118,10 @@ toc:

Field provides semantic HTML patterns for accessible forms:

  • <fieldset> and <legend> for grouping related fields
  • -
  • role="group" with .field class for individual fields
  • -
  • .description class for helper text
  • +
  • <p> after <legend> is automatically styled as description text
  • +
  • role="group" with .field class for individual field containers
  • +
  • .description class for field-level helper text (requires aria-describedby)
  • .error class with role="alert" for error messages
  • -
  • aria-describedby to associate descriptions and errors with inputs
@@ -130,53 +132,91 @@ toc:

Input

{% set code_input %} -
+
-

Choose a unique username for your account

+

Choose a unique username for your account.

- -

Must be at least 8 characters

- +

Must be at least 8 characters long.

+
{% endset %} -{{ code_preview("field-input", code_input) }} +{{ code_preview("field-input", code_input, class="w-full max-w-md") }}

Textarea

{% set code_textarea %} -
- - -

Brief description for your profile (max 200 characters)

+
+ + +

Share your thoughts about our service.

{% endset %} -{{ code_preview("field-textarea", code_textarea) }} +{{ code_preview("field-textarea", code_textarea, class="w-full max-w-md") }}

Select

{% set code_select %} -
- - + + + + + + + + + -

Choose your country of residence

+

Select your department or area of work.

{% endset %} -{{ code_preview("field-select", code_select) }} +{{ code_preview("field-select", code_select, class="w-full max-w-md") }} + +

Slider

+ +{% set code %} +
+ +

Set your budget: $150

+ +
+ +{% endset %} +{{ code_preview("slider", code, "w-full max-w-sm") }}

Fieldset

@@ -186,9 +226,9 @@ toc: {% set code_fieldset %} -
+
Profile -

This information will be displayed on your profile

+

This information will be displayed on your profile

@@ -217,54 +257,84 @@ toc:

Checkbox

{% set code_checkbox %} -
- Tasks -

Select the tasks you want to receive updates for

+
+ Show these items on the desktop +

Select the items you want to show on the desktop.

-
- - +
+
-
- - +
+
-
- - +
+ +
+
+ +
+
+ +
+ +
+
+ +
+ +

Your Desktop & Documents folders are being synced with iCloud Drive. You can access them from other devices.

+
{% endset %} -{{ code_preview("field-checkbox", code_checkbox) }} +{{ code_preview("field-checkbox", code_checkbox, class="w-full max-w-md") }}

Radio Group

{% set code_radio %} -
- Notify me about -

Choose which notifications you want to receive

+
+ Subscription plan +

Yearly and lifetime plans offer significant savings.

-
-
- - +
+
+
-
- - +
+
-
- - +
+
{% endset %} -{{ code_preview("field-radio", code_radio) }} +{{ code_preview("field-radio", code_radio, class="w-full max-w-md") }}

Switch

@@ -273,44 +343,43 @@ toc: {% set code_switch %} -
- Notifications -

Configure how you receive notifications

- -
-
-
- -

Receive emails about new products and features

-
- -
- -
-
- -

Receive emails about account security

-
- -
+
+
+ +

Enable multi-factor authentication. If you do not have a two-factor device, you can use a one-time code sent to your email.

-
+ +
{% endset %} -{{ code_preview("field-switch", code_switch) }} +{{ code_preview("field-switch", code_switch, class="w-full max-w-md") }} -

Accessibility

- -
-
    -
  • Always use <label> elements with for attribute matching input id
  • -
  • Associate helper text and errors using aria-describedby on the input
  • -
  • Use aria-invalid="true" on inputs with errors
  • -
  • Use role="alert" on error messages for screen reader announcements
  • -
  • Group related fields with <fieldset> and <legend>
  • -
  • Use role="group" for individual field wrappers
  • -
-
+

Choice Card

+{% set code_choice_card %} +
+ Compute Environment +

Select the compute environment for your cluster.

+
+ +
+
+ +
+
+{% endset %} +{{ code_preview("field-choice-card", code_choice_card, class="w-full max-w-md") }} \ No newline at end of file diff --git a/docs/src/components/input-group.njk b/docs/src/components/input-group.njk index c5a89da..5f9bfcb 100644 --- a/docs/src/components/input-group.njk +++ b/docs/src/components/input-group.njk @@ -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 %} + +
+ {% lucide "circle-alert" %} +

There is no dedicated Input Group component in Basecoat.

+
{% set code_default %} -
- -
- {% lucide "search" %} +
+
+ +
+ {% lucide "search" %} +
+
12 results
+
+ +
+ +
https://
+
{% lucide "info" %}
+
+ +
+ +
+ + {{ 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" } + ] + ) }} +
52% used
+
+ +
+
+ +
+ +
{% lucide "check" %}
{% endset %} -{{ code_preview("input-group-default", code_default) }} +{{ code_preview("input-group-default", code_default, class="w-full max-w-sm") }}

Usage

-

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.

-

Key patterns:

-
    -
  • Use relative wrapper around input
  • -
  • Position content with absolute + top-1/2 -translate-y-1/2
  • -
  • Add padding to input (pl-* or pr-*) to make room for content
  • -
  • Use pointer-events-none for decorative icons
  • -
+

Input groups are pure HTML composition using Tailwind utility classes. There is no dedicated component: use relative positioning on a wrapper, add your content with absolute positioning, and adjust input padding to make room.

+

Browse the examples below and copy the pattern that fits your needs.

-{{ code_block(code_default) }} -

Examples

-

Icon Prefix

+

Icon

-
-

Add an icon at the start of the input field.

-
- -{% set code_icon_prefix %} -
+{% set code_icon %} +
- -
+ +
{% lucide "search" %}
- +
- -
+ +
{% lucide "mail" %}
-
-{% endset %} -{{ code_preview("input-group-icon-prefix", code_icon_prefix) }} - -

Icon Suffix

- -
-

Add an icon at the end of the input field.

-
- -{% set code_icon_suffix %} -
- -
+ +
+ {% lucide "credit-card" %} +
+
{% lucide "check" %}
- +
-
- {% lucide "credit-card" %} +
+ {% lucide "star" %} {% lucide "info" %}
{% endset %} -{{ code_preview("input-group-icon-suffix", code_icon_suffix) }} +{{ code_preview("input-group-icon-prefix", code_icon, class="w-full max-w-sm") }} -

Text Prefix/Suffix

- -
-

Display text before or after the input value.

-
+

Text

{% set code_text %} -
+
- -
- $ -
-
- USD -
+ +
$
+
USD
- +
- -
- https:// -
+ +
https://
+
.com
- +
- -
- @company.com -
+ +
@company.com
+
+ +
+ +
+
120 characters left
+
{% endset %} -{{ code_preview("input-group-text", code_text) }} +{{ code_preview("input-group-text", code_text, class="w-full max-w-sm") }} -

Button Suffix

- -
-

Add interactive buttons inside the input.

-
+

Button

{% set code_button %} -
+
- - + +
- +
- - + + +
+ {% 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"} + ) %} +

Your connection is not secure.

+

You should not enter any sensitive information on this site.

+ {% endcall %} +
https://
+
- +
- - + +
{% endset %} -{{ code_preview("input-group-button", code_button) }} +{{ code_preview("input-group-button", code_button, class="w-full max-w-sm") }} -

Multiple Elements

+

Tooltip

-
-

Combine multiple icons, text, and buttons.

-
- -{% set code_multiple %} -
+{% set code_tooltip %} +
- -
- {% lucide "search" %} -
-
- ⌘K -
+ +
{% lucide "info" %}
- +
- -
- https:// -
- + +
{% lucide "circle-help" %}
+
+ +
+ +
{% lucide "circle-help" %}
{% endset %} -{{ code_preview("input-group-multiple", code_multiple) }} +{{ code_preview("input-group-tooltip", code_tooltip, class="w-full max-w-sm") }}

Textarea

-
-

Add buttons to textareas for actions like submit.

-
- {% set code_textarea %} -
-
- - + + +
+ Line 1, Column 1 + +
+
+{% endset %} + +{{ code_preview("input-group-textarea", code_textarea, class="w-full max-w-md") }} + +

Spinner

+ +{% set code_spinner %} +
+
+ +
+ {% lucide "loader-circle" %} +
- -
- 120 characters left - + +
+ {% lucide "loader-circle" %} +
+
+ +
+ +
+
Saving...
+
+ {% lucide "loader-circle" %} +
+
+
+ +
+ +
+ {% lucide "loader" %} +
+
+ Please wait...
{% endset %} -{{ code_preview("input-group-textarea", code_textarea) }} +{{ code_preview("input-group-spinner", code_spinner, class="w-full max-w-md") }} -

Accessibility

+

Dropdown

-
-
    -
  • Use pointer-events-none for decorative icons that shouldn't be interactive
  • -
  • Ensure buttons have proper aria-label or visible text
  • -
  • Maintain sufficient padding so text doesn't overlap with icons/buttons
  • -
  • Use semantic button types (type="button" vs type="submit")
  • -
-
+{% set code_dropdown %} +
+
+ + {% 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" } + ] + ) }} +
+
+ + {% 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" } + ] + ) }} +
+
+{% endset %} + +{{ code_preview("input-group-dropdown", code_dropdown, class="w-full max-w-sm") }} + +

Group

+ +{% set code_group %} +
+ +
+ +
{% lucide "link-2" %}
+
+
.com
+
+{% endset %} + +{{ code_preview("input-group-group", code_group, class="w-full max-w-sm") }} \ No newline at end of file diff --git a/docs/src/components/item.njk b/docs/src/components/item.njk index 54afdda..6af2b36 100644 --- a/docs/src/components/item.njk +++ b/docs/src/components/item.njk @@ -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") }} +

Usage

+ +
+

Items are pure HTML composition using Tailwind utility classes. Use semantic elements like <article> or <a>, apply flex layout, and compose with standard HTML elements like <h3>, <p>, <img>, or <button>.

+

Browse the examples below and copy the pattern that fits your needs.

+
+

Examples

Variants

diff --git a/src/css/basecoat.css b/src/css/basecoat.css index 5d15493..3f5da68 100644 --- a/src/css/basecoat.css +++ b/src/css/basecoat.css @@ -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 {