# October 2025 - New Components · JGuang UI

> Spinner, Kbd, Button Group, Input Group, Field, Item, and Empty components.

- Page: https://jiguang132.com/systems/jguang-ui/docs/changelog/2025-10-new-components
- Based on: shadcn/ui documentation (MIT) @ bc0705384b51252af26dcc65425b216bf5eb063c

For this round of components, I looked at what we build every day, the boring stuff we rebuild over and over, and made reusable abstractions you can actually use.

**These components work with every component library, Radix, Base UI, React Aria, you name it. Copy and paste to your projects.**

- [Spinner](#spinner): An indicator to show a loading state.
- [Kbd](#kbd): Display a keyboard key or group of keys.
- [Button Group](#button-group): A group of buttons for actions and split buttons.
- [Input Group](#input-group): Input with icons, buttons, labels and more.
- [Field](#field): One component. All your forms.
- [Item](#item): Display lists of items, cards, and more.
- [Empty](#empty): Use this one for empty states.

### Spinner

Okay let's start with the easiest ones: **Spinner** and **Kbd**. Pretty basic. We all know what they do.

Here's how you render a spinner:

```tsx
import { Spinner } from "@/components/ui/spinner"
```

```tsx
<Spinner />
```

Here's what it looks like:


> **Component preview · Base UI**  
> `spinner-basic`


Here's what it looks like in a button:


> **Component preview · Base UI**  
> `spinner-button`


You can edit the code and replace it with your own spinner.


> **Component preview · Base UI**  
> `spinner-custom`


### Kbd

Kbd is a component that renders a keyboard key.

```tsx
import { Kbd, KbdGroup } from "@/components/ui/kbd"
```

```tsx
<Kbd>Ctrl</Kbd>
```

Use `KbdGroup` to group keyboard keys together.

```tsx showLineNumbers
<KbdGroup>
  <Kbd>Ctrl</Kbd>
  <Kbd>B</Kbd>
</KbdGroup>
```


> **Component preview · Base UI**  
> `kbd-demo`


You can add it to buttons, tooltips, input groups, and more.

### Button Group

I got a lot of requests for this one: Button Group. It's a container that groups related buttons together with consistent styling. Great for action groups, split buttons, and more.


> **Component preview · Base UI**  
> `button-group-demo`


Here's the code:

```tsx
import { ButtonGroup } from "@/components/ui/button-group"
```

```tsx showLineNumbers
<ButtonGroup>
  <Button>Button 1</Button>
  <Button>Button 2</Button>
</ButtonGroup>
```

You can nest button groups to create more complex layouts with spacing.

```tsx showLineNumbers
<ButtonGroup>
  <ButtonGroup>
    <Button>Button 1</Button>
    <Button>Button 2</Button>
  </ButtonGroup>
  <ButtonGroup>
    <Button>Button 3</Button>
    <Button>Button 4</Button>
  </ButtonGroup>
</ButtonGroup>
```

Use `ButtonGroupSeparator` to create split buttons. Classic dropdown pattern.


> **Component preview · Base UI**  
> `button-group-dropdown`


You can also use it to add prefix or suffix buttons and text to inputs.


> **Component preview · Base UI**  
> `button-group-select`


```tsx showLineNumbers
<ButtonGroup>
  <ButtonGroupText>Prefix</ButtonGroupText>
  <Input placeholder="Type something here..." />
  <Button>Button</Button>
</ButtonGroup>
```

### Input Group

Input Group lets you add icons, buttons, and more to your inputs. You know, all those little bits you always need around your inputs.

```tsx
import {
  InputGroup,
  InputGroupAddon,
  InputGroupInput,
} from "@/components/ui/input-group"
```

```tsx showLineNumbers
<InputGroup>
  <InputGroupInput placeholder="Search..." />
  <InputGroupAddon>
    <SearchIcon />
  </InputGroupAddon>
</InputGroup>
```

Here's a preview with icons:


> **Component preview · Base UI**  
> `input-group-icon`


You can also add buttons to the input group.


> **Component preview · Base UI**  
> `input-group-button`


Or text, labels, tooltips, ...


> **Component preview · Base UI**  
> `input-group-text`


It also works with textareas so you can build really complex components with lots of knobs and dials or yet another prompt form.


> **Component preview · Base UI**  
> `input-group-textarea`


Oh here are some cool ones with spinners:


> **Component preview · Base UI**  
> `input-group-spinner`


### Field

Introducing **Field**, a component for building really complex forms. The abstraction here is beautiful.

It took me a long time to get it right but I made it work with all your form libraries: Server Actions, React Hook Form, TanStack Form, Bring Your Own Form.

```tsx
import {
  Field,
  FieldDescription,
  FieldError,
  FieldLabel,
} from "@/components/ui/field"
```

Here's a basic field with an input:

```tsx showLineNumbers
<Field>
  <FieldLabel htmlFor="username">Username</FieldLabel>
  <Input id="username" placeholder="Max Leiter" />
  <FieldDescription>
    Choose a unique username for your account.
  </FieldDescription>
</Field>
```


> **Component preview · Base UI**  
> `field-input`


It works with all form controls. Inputs, textareas, selects, checkboxes, radios, switches, sliders, you name it. Here's a full example:


> **Component preview · Base UI**  
> `field-demo`


Here are some checkbox fields:


> **Component preview · Base UI**  
> `field-checkbox`


You can group fields together using `FieldGroup` and `FieldSet`. Perfect for
multi-section forms.

```tsx showLineNumbers
<FieldSet>
  <FieldLegend />
  <FieldGroup>
    <Field />
    <Field />
  </FieldGroup>
</FieldSet>
```


> **Component preview · Base UI**  
> `field-fieldset`


Making it responsive is easy. Use `orientation="responsive"` and it switches
between vertical and horizontal layouts based on container width. Done.


> **Component preview · Base UI**  
> `field-responsive`


Wait, here's more. Wrap your fields in `FieldLabel` to create a selectable field group. Really easy. And it looks great.


> **Component preview · Base UI**  
> `field-choice-card`


### Item

This one is a straightforward flex container that can house nearly any type of content.

I've built this so many times that I decided to create a component for it. Now I use it all the time. I use it to display lists of items, cards, and more.

```tsx
import {
  Item,
  ItemContent,
  ItemDescription,
  ItemMedia,
  ItemTitle,
} from "@/components/ui/item"
```

Here's a basic item:

```tsx showLineNumbers
<Item>
  <ItemMedia variant="icon">
    <HomeIcon />
  </ItemMedia>
  <ItemContent>
    <ItemTitle>Dashboard</ItemTitle>
    <ItemDescription>Overview of your account and activity.</ItemDescription>
  </ItemContent>
</Item>
```


> **Component preview · Base UI**  
> `item-demo`


You can add icons, avatars, or images to the item.


> **Component preview · Base UI**  
> `item-icon`


> **Component preview · Base UI**  
> `item-avatar`


And here's what a list of items looks like with `ItemGroup`:


> **Component preview · Base UI**  
> `item-group`


Need it as a link? Use the `asChild` prop:

```tsx showLineNumbers
<Item asChild>
  <a href="/dashboard">
    <ItemMedia variant="icon">
      <HomeIcon />
    </ItemMedia>
    <ItemContent>
      <ItemTitle>Dashboard</ItemTitle>
      <ItemDescription>Overview of your account and activity.</ItemDescription>
    </ItemContent>
  </a>
</Item>
```


> **Component preview · Base UI**  
> `item-link`


### Empty

Okay last one: **Empty**. Use this to display empty states in your app.

```tsx
import {
  Empty,
  EmptyContent,
  EmptyDescription,
  EmptyMedia,
  EmptyTitle,
} from "@/components/ui/empty"
```

Here's how you use it:

```tsx showLineNumbers
<Empty>
  <EmptyMedia variant="icon">
    <InboxIcon />
  </EmptyMedia>
  <EmptyTitle>No messages</EmptyTitle>
  <EmptyDescription>You don't have any messages yet.</EmptyDescription>
  <EmptyContent>
    <Button>Send a message</Button>
  </EmptyContent>
</Empty>
```


> **Component preview · Base UI**  
> `empty-demo`


You can use it with avatars:


> **Component preview · Base UI**  
> `empty-avatar`


Or with input groups for things like search results or email subscriptions:


> **Component preview · Base UI**  
> `empty-input-group`


That's it. Seven new components. Works with all your libraries. Ready for your projects.

---

Index of all JGuang resources: https://jiguang132.com/llms.txt
