Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
6cc2dee
feat: added docs for bg gradient
giuliana-gladeye Jul 5, 2026
ecdf2d8
feat: updated cards docs
giuliana-gladeye Jul 5, 2026
e1680e4
feat: updated docs content descriptions
giuliana-gladeye Jul 5, 2026
62b2173
feat: updated card content header docs
giuliana-gladeye Jul 5, 2026
ebaf514
feat: updated checkbox docs
giuliana-gladeye Jul 6, 2026
c912348
feat: updated command docs
giuliana-gladeye Jul 6, 2026
a2cb5fe
feat: update copy button docs
giuliana-gladeye Jul 6, 2026
6a8f564
feat: updated display field and date range picker docs
giuliana-gladeye Jul 6, 2026
b3497d5
feat: updated docs for form and heading components
giuliana-gladeye Jul 6, 2026
881b861
feat: updated docs for icon and icon button
giuliana-gladeye Jul 6, 2026
3e42c93
feat: updated docs for input and info card
giuliana-gladeye Jul 6, 2026
6f912fc
feat: updated label and loading overlay docs
giuliana-gladeye Jul 6, 2026
e3e61e0
feat: updated metric card and motion collapsible content docs
giuliana-gladeye Jul 6, 2026
e9baae2
feat: updated docs for page not found and pagination
giuliana-gladeye Jul 6, 2026
39377e9
feat: updated docs for popover, panel label and progress
giuliana-gladeye Jul 6, 2026
c3d174d
feat: updated radial graph docs
giuliana-gladeye Jul 6, 2026
332d805
feat: updated docs for radio dropdown
giuliana-gladeye Jul 6, 2026
ea97c41
feat: updated radio group docs
giuliana-gladeye Jul 6, 2026
abd69d9
feat: updated scroll area docs
giuliana-gladeye Jul 6, 2026
c2bc841
feat: updated search bar docs
giuliana-gladeye Jul 6, 2026
b9177e7
feat: updated docs for select and section heading components
giuliana-gladeye Jul 6, 2026
fa31248
feat: updated separator docs
giuliana-gladeye Jul 6, 2026
ca3f433
feat: added description to spinner
giuliana-gladeye Jul 6, 2026
5beca9e
feat: updated skeleton docs
giuliana-gladeye Jul 6, 2026
5b0d1c4
feat: updated sort selector docs
giuliana-gladeye Jul 6, 2026
9e402b1
feat: added switch docs
giuliana-gladeye Jul 7, 2026
e41f1a0
feat: update textarea docs
giuliana-gladeye Jul 7, 2026
ef1499b
feat: updated tooltip and truncated description docs
giuliana-gladeye Jul 7, 2026
53a6f2a
feat: touch up copy
giuliana-gladeye Jul 7, 2026
e678435
Merge branch 'main' into feat/docs
giuliana-gladeye Jul 7, 2026
17581bc
feat: added future improvements list
giuliana-gladeye Jul 7, 2026
48ba0bf
feat: update docs table styling
giuliana-gladeye Jul 7, 2026
513649a
feat: small touch ups
giuliana-gladeye Jul 7, 2026
a4e82ce
feat: removed drawer from docs and added note in improvements
giuliana-gladeye Jul 7, 2026
975c3aa
Merge branch 'main' into feat/docs
Shrinks99 Jul 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions FUTURE_IMPROVEMENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Future Improvements

A running list of component improvements surfaced while writing documentation. These are **not** doc issues — the docs describe the components as they behave today. Each item is a candidate enhancement to the `ui` package (or its demos), grouped by theme and roughly ordered by impact.

> Context: compiled from a documentation pass across the component library. Paths point at the relevant source so each can be picked up independently.

## Accessibility

Most components are built on Radix and inherit good accessibility. The items below are where the design system's own additions (or omissions) create gaps.

- **Spinner** — renders bare `<div>`s with no `role="status"` or `aria-label`, so loading is conveyed only visually and is invisible to screen readers. Add `role="status"` + an accessible label (e.g. "Loading").
`packages/ui/src/components/spinner/spinner.tsx`
- **Loading Overlay** — no `role="status"`/`aria-live`, no focus trap, and no `aria-busy` on the blocked content. Screen reader users may not be told loading started, and keyboard focus can still reach content behind the overlay. Add a live region and focus management.
`packages/ui/src/components/loading-overlay/loading-overlay.tsx`
- **Command** — keyboard navigation works, but there is no visual highlight for the active item. cmdk marks it with `data-selected="true"`, but `.command-item` only styles `:hover`/`:focus`. Add a `data-[selected=true]` rule mirroring the hover colors:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Visual highlight Looks fine to me on in-app nav search, selects as expected but may need to check how the tab order works on the command component itself?

```css
@apply data-[selected=true]:text-lilac-700! data-[selected=true]:bg-lilac-300/50!;
@apply dark:data-[selected=true]:bg-lilac-600/50! dark:data-[selected=true]:text-lilac-100!;
```
`packages/ui/src/components/command/command.module.css`
- **Pagination** — numbered page buttons convey the current page only via color (`primary` vs `tertiary`), with no `aria-current="page"`; the control group isn't wrapped in a `<nav aria-label="Pagination">` landmark.
`packages/ui/src/components/pagination/pagination.tsx`
- **Icon Button** — `label` (which becomes `aria-label`) is optional, but an icon-only button with no label is unlabeled for screen readers. Consider making `label` required.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional to prevent double labels when used with tooltips

`packages/ui/src/components/icon-button/icon-button.tsx`
- **Copy Button** — on success the label swaps to "Copied!" but there's no `aria-live` region, so the confirmation isn't announced. Add a visually-hidden live region.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add tooltip that appears on copy that says "Copied!"

`packages/ui/src/components/copy-button/copy-button.tsx`
- **Form / FormMessage** — the validation message isn't a live region (`aria-live`/`role="alert"`), so an error appearing while focus stays in the field isn't announced.
`packages/ui/src/components/form/form.tsx`
- **Radial Graph** — purely visual; the percentage is only in the label text and bar fills, with no `role="progressbar"`/`aria-valuenow`. If the value is meaningful data (e.g. compliance scores), expose ARIA progressbar semantics.
`packages/ui/src/components/radial-graph/radial-graph.tsx`
- **Date Range Picker** — calendar day buttons render only the day number (no `aria-label` for the full date), selected/today cells have no `aria-selected`/`aria-current`, and the grid has no arrow-key navigation (relies on tab/click).
`packages/ui/src/components/date-range-picker/date-range-picker.tsx`
- **Info Card** — `label` and `description` have no programmatic association. If read as standalone data points, a `<dl>`/`<dt>`/`<dd>` structure would convey the label→value relationship.
`packages/ui/src/components/info-card/info-card.tsx`
- **Skeleton** — no built-in loading semantics. Document/encourage the consumer pattern of `aria-busy` on the loading container with the skeletons `aria-hidden`, or provide a labelled wrapper.
`packages/ui/src/components/skeleton/skeleton.tsx`
- **Motion Collapsible Content** — no `prefers-reduced-motion` handling; it always animates. Honor the media query for motion-sensitive users. (Trigger↔region `aria-expanded`/`aria-controls` wiring is left to consumers — worth documenting.)
`packages/ui/src/components/motion-collapsible/motion-collapsible.tsx`

## Correctness / Bugs

- **Truncated Description** — truncation decides _whether_ to clip using plain-text length but slices the _raw HTML_ string (`description.slice(0, maxLength)`). With any markup this can cut mid-tag or leave unclosed tags, which is then fed to `dangerouslySetInnerHTML` — producing malformed output and inconsistent visible length.
`packages/ui/src/components/truncated-description/truncated-description.tsx`
- **Search Bar** — the clear button uses `name="XIcon"`. Lucide's canonical icon is `X` (`XIcon` is an alias that exists only in newer versions). If the installed lucide version lacks the alias, `IconButton` warns and renders `null`, so the clear button silently disappears. Prefer `name="X"`.
`packages/ui/src/components/search-bar/search-bar.tsx`
- **Checkbox** — stray trailing space / `{' '}` inside the indicator markup. Harmless, minor cleanup.
`packages/ui/src/components/checkbox/checkbox.tsx`

## Security

- **Truncated Description** — renders `description` via `dangerouslySetInnerHTML` with no sanitization. If any description can originate from user input, this is an XSS vector. Sanitize (e.g. DOMPurify) or document a hard "trusted content only" contract.
`packages/ui/src/components/truncated-description/truncated-description.tsx`

## API Consistency

- **Icon** — an unknown Lucide string name **throws** (`Icon "<name>" not found`), crashing the render, whereas **Icon Button** with an unknown name only warns and returns `null`. Align the two: either both throw or both degrade gracefully.
`packages/ui/src/components/icon/icon.tsx` · `packages/ui/src/components/icon-button/icon-button.tsx`
- **Tooltip vs Popover — arrow** — Tooltip always renders an arrow (hardcoded), while Popover makes it an opt-in `arrow` prop. Consider making them consistent.
`packages/ui/src/components/tooltip/tooltip.tsx` · `packages/ui/src/components/popover/popover.tsx`
- **Tooltip — provider footgun** — a `Tooltip` without a `TooltipProvider` ancestor silently doesn't work. Consider a pre-composed export or a default provider to make it foolproof.
`packages/ui/src/components/tooltip/tooltip.tsx`
- **Switch — thumb icon** — only a single `thumbIcon` is supported; showing a different icon per state requires the consumer to swap it based on `checked`. A `thumbIconChecked` prop (as the demo simulates) could be a first-class feature.
`packages/ui/src/components/switch/switch.tsx`
- **Section Heading** — `renderRightContent` is a render prop (`() => ReactNode`) though the content isn't parameterized; most sibling components (Card Content Header, Display Field `actions`) take a `ReactNode` directly. Consider accepting a plain node for consistency.
`packages/ui/src/components/section-heading/section-heading.tsx`
- **Card Content Header** — the "See All" button label is hardcoded and not configurable; there's also a `TODO` to make the icon a slot so elevation can be set independently.
`packages/ui/src/components/card-content-header/card-content-header.tsx`
- **Scroll Area** — hardcodes a single vertical `ScrollBar`, so horizontal scrolling isn't supported through the `ScrollArea` API (the `ScrollBar` export exists for manual composition). Consider accepting an `orientation`.
`packages/ui/src/components/scroll-area/scroll-area.tsx`
- **Bg Gradient** — an unrecognized `theme` falls back to black (invisible-ish), which is easy to miss. Consider failing loudly or falling back to `primary`. (Currently guarded by the `Theme` type, so only reachable via unsafe casts.)
`packages/ui/src/components/bg-gradient/bg-gradient.tsx`
- **Page Not Found** — the component is exported as `NotFound` but the doc/page is titled "Page Not Found". Not a bug, just a naming mismatch to be aware of.
`packages/ui/src/components/page-not-found/page-not-found.tsx`

## Incomplete / Undocumented Components

- **Drawer** — appears unfinished. Its documentation page has been **removed from the docs site only** (the component still exists in the `ui` package) pending a decision to either complete and document it, or deprecate and remove it. If other components have superseded it (e.g. [Sheet](packages/ui/src/components/sheet), Dialog), lean toward deprecation to avoid a half-supported component in the public API.
`packages/ui/src/components/drawer/`

## Notes

- Items were identified during documentation and have **not** been verified with tests. Confirm each before acting.
- The list is a prompt for review, not a defect log.
4 changes: 2 additions & 2 deletions packages/demo/src/components/demo/avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
const sizes = ["sm", "md", "lg", "xl"] as const;
const labels = { sm: "SM", md: "MD", lg: "LG", xl: "XL" };
return (
<div className="flex items-end gap-4">
<div className="mb-4 flex items-end gap-4">
{sizes.map((s) => (
<Avatar key={s} size={s} shape={shape}>
<AvatarImage
Expand All @@ -48,14 +48,14 @@
};

export const AvatarShapeDemo = ({
variant = "fallback",

Check warning on line 51 in packages/demo/src/components/demo/avatar.tsx

View workflow job for this annotation

GitHub Actions / quality

'variant' is assigned a value but never used. Allowed unused args must match /^_/u
shape,
}: {
variant?: "default" | "fallback";
shape: "circle" | "square";
}) => {
return (
<div className="flex items-center gap-4">
<div className="mb-4 flex items-center gap-4">
<Avatar shape={shape}>
<AvatarFallback>RG</AvatarFallback>
</Avatar>
Expand Down
6 changes: 6 additions & 0 deletions packages/demo/src/components/demo/checkbox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { Checkbox } from "@eqtylab/equality";
import { Minus } from "lucide-react";

export const CheckboxCustomIconDemo = () => {
return <Checkbox checked icon={Minus} />;
};
30 changes: 17 additions & 13 deletions packages/demo/src/components/demo/command.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,33 @@
import {
Command,
CommandInput,
CommandList,
CommandEmpty,
CommandGroup,
CommandItem,
} from "@eqtylab/equality";
import { Check } from "lucide-react";
import { useState } from "react";

const options = ["Option 1", "Option 2", "Option 3"];

export const CommandDemo = () => {
const [selected, setSelected] = useState("Option 1");

return (
<Command>
<CommandInput placeholder="Search repositories..." />
<CommandEmpty>No repositories found.</CommandEmpty>
<CommandGroup heading="Repositories">
<CommandItem value="Option 1" onSelect={() => {}}>
Option 1
<Check />
</CommandItem>
<CommandItem value="Option 2" onSelect={() => {}}>
Option 2
</CommandItem>
<CommandItem value="Option 3" onSelect={() => {}}>
Option 3
</CommandItem>
</CommandGroup>
<CommandList>
<CommandEmpty>No repositories found.</CommandEmpty>
<CommandGroup heading="Repositories">
{options.map((option) => (
<CommandItem key={option} value={option} onSelect={setSelected}>
{option}
{selected === option && <Check />}
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
);
};
51 changes: 0 additions & 51 deletions packages/demo/src/components/demo/drawer.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion packages/demo/src/components/demo/icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const CustomIcon = ({ className, ...props }: React.SVGProps<SVGSVGElement>) => {

export const IconDemo = () => {
return (
<div>
<div style={{ marginBottom: "1rem" }}>
<Icon icon={<CustomIcon />} background="circle" />
</div>
);
Expand Down
12 changes: 12 additions & 0 deletions packages/demo/src/components/demo/info-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { InfoCard } from "@eqtylab/equality";

export const InfoCardClickableDemo = () => {
return (
<InfoCard
label="Policy Type"
description="Custom"
icon="Shield"
onClick={() => alert("Clicked!")}
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ export const MotionCollapsibleContentDemo = () => {

return (
<div className="flex flex-col space-y-6">
<Button onClick={() => setIsOpen(!isOpen)}>Click me</Button>
<Button onClick={() => setIsOpen(!isOpen)} className="w-max">
Click me
</Button>
<MotionCollapsibleContent isOpen={isOpen}>
<div>
<h3 className="text-lg font-medium">Motion Collapsible Content</h3>
Expand Down
6 changes: 1 addition & 5 deletions packages/demo/src/components/demo/pagination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ const generateItems = (count: number) => {
return Array.from({ length: count }, (_, i) => ({
id: i + 1,
name: `Item ${i + 1}`,
description: `Description for item ${i + 1}`,
}));
};

Expand Down Expand Up @@ -38,12 +37,9 @@ export const PaginationDemo = () => {
{paginatedItems.map((item) => (
<div
key={item.id}
className="border-border bg-muted/50 rounded-md border p-3"
className="border-border bg-muted/50 rounded-md border px-3 py-2"
>
<div className="font-medium">{item.name}</div>
<div className="text-text-secondary text-sm">
{item.description}
</div>
</div>
))}
</div>
Expand Down
20 changes: 12 additions & 8 deletions packages/demo/src/components/demo/popover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,21 @@ import {

export function PopoverDemo({
align = "center",
arrow = false,
}: {
align?: "start" | "end" | "center";
arrow?: boolean;
}) {
return (
<Popover>
<PopoverTrigger asChild>
<Button size="sm">Click me</Button>
</PopoverTrigger>
<PopoverContent align={align}>
<p>This is a popover</p>
</PopoverContent>
</Popover>
<div style={{ marginBottom: "1rem" }}>
<Popover>
<PopoverTrigger asChild>
<Button size="sm">Click me</Button>
</PopoverTrigger>
<PopoverContent align={align} arrow={arrow}>
<p>This is a popover</p>
</PopoverContent>
</Popover>
</div>
);
}
6 changes: 3 additions & 3 deletions packages/demo/src/components/demo/radio-group.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ export const RadioGroupDemo = () => {
onValueChange={(value) => setSelectedValue(value)}
>
<div className="flex items-center gap-2">
<RadioGroupItem value="none" />
<RadioGroupItem value="none" id="none" />
<Label htmlFor="none">No Access</Label>
</div>
<div className="flex items-center gap-2">
<RadioGroupItem value="read" />
<RadioGroupItem value="read" id="read" />
<Label htmlFor="read">Read Only</Label>
</div>
<div className="flex items-center gap-2">
<RadioGroupItem value="write" />
<RadioGroupItem value="write" id="write" />
<Label htmlFor="write">Read & Write</Label>
</div>
</RadioGroup>
Expand Down
16 changes: 16 additions & 0 deletions packages/demo/src/components/demo/select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,22 @@ export function SelectDemo({
<SelectItem value="option12">Option 12</SelectItem>
<SelectItem value="option13">Option 13</SelectItem>
<SelectItem value="option14">Option 14</SelectItem>
<SelectItem value="option15">Option 15</SelectItem>
<SelectItem value="option16">Option 16</SelectItem>
<SelectItem value="option17">Option 17</SelectItem>
<SelectItem value="option18">Option 18</SelectItem>
<SelectItem value="option19">Option 19</SelectItem>
<SelectItem value="option20">Option 20</SelectItem>
<SelectItem value="option21">Option 21</SelectItem>
<SelectItem value="option22">Option 22</SelectItem>
<SelectItem value="option23">Option 23</SelectItem>
<SelectItem value="option24">Option 24</SelectItem>
<SelectItem value="option25">Option 25</SelectItem>
<SelectItem value="option26">Option 26</SelectItem>
<SelectItem value="option27">Option 27</SelectItem>
<SelectItem value="option28">Option 28</SelectItem>
<SelectItem value="option29">Option 29</SelectItem>
<SelectItem value="option30">Option 30</SelectItem>
</SelectContent>
</Select>
);
Expand Down
10 changes: 1 addition & 9 deletions packages/demo/src/content/components/alert.mdx
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
---
layout: "@demo/layouts/mdx-layout.astro"
heading: "Alert"
description: "Alert with sizes and variants"
description: "Message for communicating status, warnings, or errors"
---

import { Alert } from "@eqtylab/equality";

## Overview

---

The Alert component displays important messages to users, usually as a result of an action they took. Use alerts to communicate status, warnings, errors, or success states.

- **Primary:** General information.
Expand All @@ -20,8 +18,6 @@ The Alert component displays important messages to users, usually as a result of

## Usage

---

Import the component:

```tsx
Expand All @@ -36,8 +32,6 @@ Basic usage with title and description:

## Variants

---

<div className="mt-4 flex max-w-[50%] flex-col gap-4">
<Alert
variant="primary"
Expand Down Expand Up @@ -109,8 +103,6 @@ The `success`, `warning`, and `danger` variants apply a default icon automatical

## Props

---

### Alert

| Name | Description | Type | Default | Required |
Expand Down
2 changes: 1 addition & 1 deletion packages/demo/src/content/components/avatar.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
layout: "@demo/layouts/mdx-layout.astro"
heading: "Avatar"
description: "Avatar with sizes and variants"
description: "Visual representation of a user or entity"
---

import {
Expand Down
2 changes: 1 addition & 1 deletion packages/demo/src/content/components/badge.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
layout: "@demo/layouts/mdx-layout.astro"
heading: "Badge"
description: "Badge with sizes and variants"
description: "Compact label for communicating status or context"
---

import { Badge, PanelLabel } from "@eqtylab/equality";
Expand Down
Loading
Loading