@mucsi96/react-ui 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -119,6 +119,12 @@ const options = [{ id: 'apple', label: 'Apple' }, { id: 'pear', label: 'Pear' }]
119
119
  <Select label="Fruit" options={options} />
120
120
  <ComboBox label="Search fruits" options={options} />
121
121
  <Checkbox defaultSelected>Subscribe</Checkbox>
122
+ <NumberField label="Daily limit" name="limit" minValue={1} maxValue={100} step={1} isRequired />
123
+ <CheckboxGroup label="Card types" name="types" isRequired>
124
+ <Checkbox value="vocabulary">Vocabulary</Checkbox>
125
+ <Checkbox value="grammar">Grammar</Checkbox>
126
+ </CheckboxGroup>
127
+ <MultiSelect label="Fruits" options={options} />
122
128
  <RadioGroup label="Size" defaultValue="medium">
123
129
  <Radio value="small">Small</Radio>
124
130
  <Radio value="medium">Medium</Radio>
@@ -130,6 +136,22 @@ Labels, descriptions, and validation messages are associated with the input auto
130
136
 
131
137
  Select options have `{ id, label, isDisabled? }`; React Aria handles selection, typeahead, and filtering. Checkbox and switch controlled state uses `isSelected`/`onChange`; radio group state uses `value`/`onChange`. React Aria form `name` props support native form submissions.
132
138
 
139
+ `NumberField` uses numeric `value`/`onChange` or `defaultValue`, with `minValue`,
140
+ `maxValue`, `step`, locale-aware `formatOptions`, and increment/decrement buttons.
141
+ An empty field reports `NaN`; validate before persisting rather than substituting
142
+ zero. React Aria commits and clamps typed values on blur. Use `isRequired` to
143
+ prevent empty native form submission. It supports the same `appearance`,
144
+ `description`, `error`, and `validationBehavior` API as the other fields.
145
+
146
+ `CheckboxGroup` owns a string-array `value`/`onChange` or `defaultValue`; each
147
+ child `Checkbox` supplies a `value`. Group labels, descriptions, required
148
+ validation, and errors are associated automatically. `name` submits each selected
149
+ value as a separate form entry. `MultiSelect` provides the same compact field as
150
+ `Select` with `selectionMode="multiple"` fixed internally. Use its React Aria
151
+ `value`/`onChange` or `defaultValue` array API for selection; options remain open
152
+ while selecting, and Escape returns focus to the trigger. Disabled options cannot
153
+ be selected. Both controls accept `description`, `error`, and `isRequired`.
154
+
133
155
  ### Field and button sizing
134
156
 
135
157
  Fields default to `appearance="filled"`, with always-visible floating labels and
@@ -217,6 +239,62 @@ For nested actions, compose `SubmenuTrigger` with a `MenuItem` and another `Menu
217
239
 
218
240
  Dialog focus is trapped while open and restored to the trigger on close. Escape and outside interaction dismiss by default; `isDismissable={false}` disables outside dismissal, and `isKeyboardDismissDisabled` disables Escape. Use `role="alertdialog"` for important confirmations. Dialogs also support controlled `isOpen`/`onOpenChange` without a `DialogTrigger`. Forms and action layouts are composed as ordinary children. Tooltips accept a single pressable child, `content`, optional `placement`, and `delay`.
219
241
 
242
+ Use `size="small" | "medium" | "large"` (24, 32, or 48rem; medium by default)
243
+ to size the outer modal, or `maxWidth` for a CSS width override. All sizes are
244
+ constrained to the viewport with safe-area gutters. The optional `footer` node
245
+ or `({ close }) => ReactNode` keeps actions and the title visible while the body
246
+ scrolls, including in a reduced visual viewport. `className` still styles the
247
+ inner dialog. Keep the form in the body and connect footer submit buttons with
248
+ native `form`/`id` attributes:
249
+
250
+ ```tsx
251
+ <Dialog
252
+ title="Edit source"
253
+ size="large"
254
+ footer={({ close }) => (
255
+ <>
256
+ <Button variant="text" onPress={close}>
257
+ Cancel
258
+ </Button>
259
+ <Button type="submit" form="source-form">
260
+ Save
261
+ </Button>
262
+ </>
263
+ )}
264
+ >
265
+ <form id="source-form" onSubmit={save}>
266
+ <TextField label="Source name" isRequired />
267
+ </form>
268
+ </Dialog>
269
+ ```
270
+
271
+ ## Tabs and empty states
272
+
273
+ ```tsx
274
+ <Tabs defaultSelectedKey="items">
275
+ <TabList aria-label="Collection views">
276
+ <Tab id="items">Items</Tab>
277
+ <Tab id="summary">Summary</Tab>
278
+ </TabList>
279
+ <TabPanel id="items">
280
+ <EmptyState
281
+ title="No items yet"
282
+ description="Create an item to get started."
283
+ action={<Button onPress={create}>Add item</Button>}
284
+ />
285
+ </TabPanel>
286
+ <TabPanel id="summary">Summary content</TabPanel>
287
+ </Tabs>
288
+ ```
289
+
290
+ Tabs support controlled `selectedKey`/`onSelectionChange`, disabled tabs,
291
+ `orientation="vertical"`, and React Aria's keyboard activation and focus
292
+ behavior. Match tab and panel IDs. Panels unmount by default; use
293
+ `shouldForceMount` on `TabPanel` to preserve state in an inactive, hidden panel.
294
+ `EmptyState` owns no business behavior: supply the title, description, action,
295
+ and optional children. Its heading defaults to level 2; set `headingLevel` to
296
+ match the surrounding document.
297
+
220
298
  ## Notifications
221
299
 
222
300
  ```tsx
@@ -287,6 +365,20 @@ This is a semantic HTML table. Columns with `compare` have three-state sorting (
287
365
 
288
366
  All loading animations respect reduced motion. `Card` supports `outlined` and `elevated`; `Badge` accepts semantic tones and `neutral`. `Heading` supports semantic levels 1–6, `Text` supports `muted`, and `Code` provides inline monospace styling.
289
367
 
368
+ Compose stable placeholders with `Skeleton` (`variant="text" | "image" | "row"`,
369
+ optional `width`/`height` CSS values). Each shape is decorative and hidden from
370
+ assistive technology. Wrap a set in `SkeletonGroup label="Loading collection"`
371
+ for one visually hidden status label. Place row placeholders inside table cells,
372
+ not directly inside a `tbody`. Animations stop under reduced motion.
373
+
374
+ ```tsx
375
+ <SkeletonGroup label="Loading collection">
376
+ <Skeleton variant="image" />
377
+ <Skeleton width="70%" />
378
+ <Skeleton variant="row" />
379
+ </SkeletonGroup>
380
+ ```
381
+
290
382
  ## Customize with CSS Modules
291
383
 
292
384
  ```css
@@ -1,4 +1,4 @@
1
- import type { ReactNode } from 'react';
1
+ import type { CSSProperties, ReactNode } from 'react';
2
2
  import type { ModalOverlayProps } from 'react-aria-components';
3
3
  export { DialogTrigger } from 'react-aria-components';
4
4
  export interface DialogProps extends Omit<ModalOverlayProps, 'children' | 'className'> {
@@ -9,5 +9,10 @@ export interface DialogProps extends Omit<ModalOverlayProps, 'children' | 'class
9
9
  }) => ReactNode);
10
10
  role?: 'dialog' | 'alertdialog';
11
11
  className?: string;
12
+ size?: 'small' | 'medium' | 'large';
13
+ maxWidth?: CSSProperties['maxWidth'];
14
+ footer?: ReactNode | ((props: {
15
+ close: () => void;
16
+ }) => ReactNode);
12
17
  }
13
- export declare function Dialog({ title, description, children, role, className, isDismissable, ...props }: DialogProps): import("react").JSX.Element;
18
+ export declare function Dialog({ title, description, children, role, className, size, maxWidth, footer, isDismissable, ...props }: DialogProps): import("react").JSX.Element;
@@ -0,0 +1,9 @@
1
+ import type { ComponentPropsWithRef, ReactNode } from 'react';
2
+ import type { HeadingProps } from '../surface/surface';
3
+ export interface EmptyStateProps extends Omit<ComponentPropsWithRef<'section'>, 'title'> {
4
+ title: string;
5
+ description?: ReactNode;
6
+ action?: ReactNode;
7
+ headingLevel?: HeadingProps['level'];
8
+ }
9
+ export declare function EmptyState({ title, description, action, headingLevel, children, className, ...props }: EmptyStateProps): import("react").JSX.Element;
@@ -1,10 +1,18 @@
1
- import type { CheckboxProps as AriaCheckboxProps, RadioGroupProps as AriaRadioGroupProps, RadioProps as AriaRadioProps, SwitchProps as AriaSwitchProps } from 'react-aria-components';
1
+ import type { CheckboxProps as AriaCheckboxProps, CheckboxGroupProps as AriaCheckboxGroupProps, RadioGroupProps as AriaRadioGroupProps, RadioProps as AriaRadioProps, SwitchProps as AriaSwitchProps } from 'react-aria-components';
2
2
  import type { ReactNode } from 'react';
3
3
  export interface CheckboxProps extends Omit<AriaCheckboxProps, 'children' | 'className'> {
4
4
  children: ReactNode;
5
5
  className?: string;
6
6
  }
7
7
  export declare function Checkbox({ children, className, ...props }: CheckboxProps): import("react").JSX.Element;
8
+ export interface CheckboxGroupProps extends Omit<AriaCheckboxGroupProps, 'children' | 'className'> {
9
+ label: string;
10
+ children: ReactNode;
11
+ description?: ReactNode;
12
+ error?: ReactNode;
13
+ className?: string;
14
+ }
15
+ export declare function CheckboxGroup({ label, children, description, error, className, ...props }: CheckboxGroupProps): import("react").JSX.Element;
8
16
  export interface RadioGroupProps extends Omit<AriaRadioGroupProps, 'children' | 'className'> {
9
17
  label: string;
10
18
  children: ReactNode;
@@ -0,0 +1,11 @@
1
+ import type { NumberFieldProps as AriaNumberFieldProps } from 'react-aria-components';
2
+ import type { ReactNode, Ref } from 'react';
3
+ export interface NumberFieldProps extends Omit<AriaNumberFieldProps, 'children' | 'className'> {
4
+ label: string;
5
+ description?: ReactNode;
6
+ error?: ReactNode;
7
+ appearance?: 'outlined' | 'filled';
8
+ className?: string;
9
+ ref?: Ref<HTMLDivElement>;
10
+ }
11
+ export declare function NumberField({ label, description, error, appearance, className, ref, ...props }: NumberFieldProps): import("react").JSX.Element;
@@ -14,10 +14,12 @@ interface FieldProps {
14
14
  appearance?: 'outlined' | 'filled';
15
15
  className?: string;
16
16
  }
17
- export interface SelectProps extends Omit<AriaSelectProps<SelectOption>, keyof FieldProps | 'children' | 'items'>, FieldProps {
17
+ export interface SelectProps<M extends 'single' | 'multiple' = 'single'> extends Omit<AriaSelectProps<SelectOption, M>, keyof FieldProps | 'children' | 'items'>, FieldProps {
18
18
  }
19
- export declare function Select({ label, options, description, error, placeholder, appearance, className, ...props }: SelectProps): import("react").JSX.Element;
19
+ export declare function Select<M extends 'single' | 'multiple' = 'single'>({ label, options, description, error, placeholder, appearance, className, ...props }: SelectProps<M>): import("react").JSX.Element;
20
20
  export interface ComboBoxProps extends Omit<AriaComboBoxProps<SelectOption>, keyof FieldProps | 'children' | 'items' | 'defaultItems'>, FieldProps {
21
21
  }
22
+ export type MultiSelectProps = Omit<SelectProps<'multiple'>, 'selectionMode' | 'selectedKey' | 'defaultSelectedKey' | 'onSelectionChange'>;
23
+ export declare function MultiSelect(props: MultiSelectProps): import("react").JSX.Element;
22
24
  export declare function ComboBox({ label, options, description, error, placeholder, appearance, className, ...props }: ComboBoxProps): import("react").JSX.Element;
23
25
  export {};
@@ -0,0 +1,11 @@
1
+ import type { ComponentPropsWithRef, CSSProperties } from 'react';
2
+ export interface SkeletonProps extends Omit<ComponentPropsWithRef<'div'>, 'children'> {
3
+ variant?: 'text' | 'image' | 'row';
4
+ width?: CSSProperties['width'];
5
+ height?: CSSProperties['height'];
6
+ }
7
+ export declare function Skeleton({ variant, width, height, className, style, ...props }: SkeletonProps): import("react").JSX.Element;
8
+ export interface SkeletonGroupProps extends ComponentPropsWithRef<'div'> {
9
+ label: string;
10
+ }
11
+ export declare function SkeletonGroup({ label, children, className, ...props }: SkeletonGroupProps): import("react").JSX.Element;
@@ -0,0 +1,17 @@
1
+ import type { TabsProps as AriaTabsProps, TabListProps as AriaTabListProps, TabProps as AriaTabProps, TabPanelProps as AriaTabPanelProps } from 'react-aria-components';
2
+ export interface TabsProps extends Omit<AriaTabsProps, 'className'> {
3
+ className?: string;
4
+ }
5
+ export interface TabListProps<T extends object> extends Omit<AriaTabListProps<T>, 'className'> {
6
+ className?: string;
7
+ }
8
+ export interface TabProps extends Omit<AriaTabProps, 'className'> {
9
+ className?: string;
10
+ }
11
+ export interface TabPanelProps extends Omit<AriaTabPanelProps, 'className'> {
12
+ className?: string;
13
+ }
14
+ export declare function Tabs({ className, ...props }: TabsProps): import("react").JSX.Element;
15
+ export declare function TabList<T extends object>({ className, ...props }: TabListProps<T>): import("react").JSX.Element;
16
+ export declare function Tab({ className, ...props }: TabProps): import("react").JSX.Element;
17
+ export declare function TabPanel({ className, ...props }: TabPanelProps): import("react").JSX.Element;
package/dist/index.d.ts CHANGED
@@ -4,10 +4,12 @@ export { Button, LinkButton } from './components/button/button';
4
4
  export type { ButtonProps, ButtonVariant, LinkButtonProps } from './components/button/button';
5
5
  export { TextField } from './components/forms/text-field';
6
6
  export type { TextFieldProps } from './components/forms/text-field';
7
- export { Select, ComboBox } from './components/forms/select';
8
- export type { SelectProps, ComboBoxProps, SelectOption } from './components/forms/select';
9
- export { Checkbox, Radio, RadioGroup, Switch } from './components/forms/controls';
10
- export type { CheckboxProps, RadioProps, RadioGroupProps, SwitchProps, } from './components/forms/controls';
7
+ export { NumberField } from './components/forms/number-field';
8
+ export type { NumberFieldProps } from './components/forms/number-field';
9
+ export { Select, MultiSelect, ComboBox } from './components/forms/select';
10
+ export type { SelectProps, MultiSelectProps, ComboBoxProps, SelectOption, } from './components/forms/select';
11
+ export { Checkbox, CheckboxGroup, Radio, RadioGroup, Switch } from './components/forms/controls';
12
+ export type { CheckboxProps, CheckboxGroupProps, RadioProps, RadioGroupProps, SwitchProps, } from './components/forms/controls';
11
13
  export { DonutSlider } from './components/donut-slider/donut-slider';
12
14
  export type { DonutSliderProps } from './components/donut-slider/donut-slider';
13
15
  export { Menu, MenuItem, MenuPopover, MenuSeparator, MenuTrigger, SubmenuTrigger, } from './components/menu/menu';
@@ -27,3 +29,9 @@ export type { BarLoaderProps, ProgressBarProps } from './components/loader/loade
27
29
  export { Card, Badge, Heading, Text, Code, Divider } from './components/surface/surface';
28
30
  export type { CardProps, BadgeProps, HeadingProps, TextProps } from './components/surface/surface';
29
31
  export type { Tone } from './types';
32
+ export { Tabs, TabList, Tab, TabPanel } from './components/tabs/tabs';
33
+ export type { TabsProps, TabListProps, TabProps, TabPanelProps } from './components/tabs/tabs';
34
+ export { Skeleton, SkeletonGroup } from './components/skeleton/skeleton';
35
+ export type { SkeletonProps, SkeletonGroupProps } from './components/skeleton/skeleton';
36
+ export { EmptyState } from './components/empty-state/empty-state';
37
+ export type { EmptyStateProps } from './components/empty-state/empty-state';