@usefidel/design-system 0.17.0 → 0.19.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/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as react from 'react';
2
- import { ButtonHTMLAttributes, ReactNode, AnchorHTMLAttributes, HTMLAttributes, InputHTMLAttributes } from 'react';
2
+ import { ButtonHTMLAttributes, ReactNode, AnchorHTMLAttributes, HTMLAttributes, InputHTMLAttributes, ReactElement } from 'react';
3
3
 
4
4
  type ButtonVariant = 'primary' | 'outlined' | 'text' | 'neutral' | 'link'
5
5
  /** High-contrast near-black, for a page's main create action ("New comparison"). */
@@ -221,8 +221,10 @@ declare function DiffPropertyList({ properties, className, ...rest }: DiffProper
221
221
  interface SelectOption {
222
222
  value: string;
223
223
  label: string;
224
- /** Secondary line, e.g. an @handle. */
224
+ /** Secondary text beside the label, e.g. an @handle. */
225
225
  secondary?: string;
226
+ /** Line under the label explaining the option, e.g. what a role can do. */
227
+ description?: string;
226
228
  /** Leading node (avatar / icon) shown in the option and, when selected, the trigger. */
227
229
  avatar?: ReactNode;
228
230
  disabled?: boolean;
@@ -246,6 +248,16 @@ interface SelectProps {
246
248
  name?: string;
247
249
  className?: string;
248
250
  containerClassName?: string;
251
+ /** `field` is the bordered form control; `inline` is a borderless trigger
252
+ * that sits inside another control, e.g. an Input's `trailing`. @default 'field' */
253
+ variant?: 'field' | 'inline';
254
+ /** `small` is a 32px trigger for table rows and inline use. @default 'medium' */
255
+ size?: 'medium' | 'small';
256
+ /** Which edge of the trigger the list lines up with; `end` lets a short
257
+ * trigger open a wider list leftwards. @default 'start' */
258
+ align?: 'start' | 'end';
259
+ /** Accessible name when there is no visible `label`. */
260
+ 'aria-label'?: string;
249
261
  }
250
262
  /**
251
263
  * Fidel design-system Select — a listbox (optionally searchable) with avatar +
@@ -372,6 +384,10 @@ interface SegmentedControlProps<T extends string> {
372
384
  onChange: (value: T) => void;
373
385
  /** Names the group for screen readers. */
374
386
  'aria-label': string;
387
+ /** `underline` sits on a baseline like TabNav; `pill` is a grey track with
388
+ * the selected option raised, for a two- or three-way switch inside a
389
+ * form or above content. @default 'underline' */
390
+ variant?: 'underline' | 'pill';
375
391
  className?: string;
376
392
  }
377
393
  /**
@@ -380,7 +396,7 @@ interface SegmentedControlProps<T extends string> {
380
396
  * move and select; Tab leaves the group. When the options don't fit, the row
381
397
  * scrolls sideways instead of widening the page.
382
398
  */
383
- declare function SegmentedControl<T extends string>({ options, value, onChange, 'aria-label': ariaLabel, className, }: SegmentedControlProps<T>): react.JSX.Element;
399
+ declare function SegmentedControl<T extends string>({ options, value, onChange, 'aria-label': ariaLabel, variant, className, }: SegmentedControlProps<T>): react.JSX.Element;
384
400
 
385
401
  /**
386
402
  * Layout breakpoints, in px, used as `max-width` media queries.
@@ -462,6 +478,8 @@ declare function Badge({ tone, icon, className, children, ...rest }: BadgeProps)
462
478
  interface TagProps extends HTMLAttributes<HTMLSpanElement> {
463
479
  /** Colour of the leading dot. Leave out for no dot. */
464
480
  dot?: Tone;
481
+ /** Leading icon, drawn at 14px, e.g. a repository or branch mark. */
482
+ icon?: ReactNode;
465
483
  children: ReactNode;
466
484
  }
467
485
  /**
@@ -469,7 +487,7 @@ interface TagProps extends HTMLAttributes<HTMLSpanElement> {
469
487
  * optional coloured dot. Measured from Figma "✅Project" comparison-type chip
470
488
  * (node 231:59808).
471
489
  */
472
- declare function Tag({ dot, className, children, ...rest }: TagProps): react.JSX.Element;
490
+ declare function Tag({ dot, icon, className, children, ...rest }: TagProps): react.JSX.Element;
473
491
 
474
492
  interface MultiSelectOption {
475
493
  value: string;
@@ -481,8 +499,17 @@ interface MultiSelectOption {
481
499
  disabled?: boolean;
482
500
  }
483
501
  interface MultiSelectProps {
484
- /** Trigger text, e.g. "Status". Also the list's accessible name. */
502
+ /** Trigger text, e.g. "Status", or the field's label in the `field`
503
+ * variant. Also the list's accessible name. */
485
504
  label: string;
505
+ /** `filter` is a compact trigger with an "n/m" count; `field` is a
506
+ * full-width form field with its label above and the chosen options as
507
+ * removable chips. @default 'filter' */
508
+ variant?: 'filter' | 'field';
509
+ /** `field` only: text in the box while nothing is chosen. */
510
+ placeholder?: string;
511
+ /** Show Select all / Clear under the list. @default true for `filter`, false for `field` */
512
+ showActions?: boolean;
486
513
  options: MultiSelectOption[];
487
514
  /** Selected values. An empty list means nothing is ticked. */
488
515
  value: string[];
@@ -496,11 +523,12 @@ interface MultiSelectProps {
496
523
  /**
497
524
  * Fidel design-system MultiSelect: a filter menu of checkbox options, each
498
525
  * with an optional dot and count, and Select all / Clear in the footer. The
499
- * trigger shows "n/m" once anything is ticked. Keyboard: Enter/Space/↓ open;
526
+ * trigger shows "n/m" once anything is ticked. The `field` variant is a form
527
+ * field instead: label above, chosen options as chips you can remove. Keyboard: Enter/Space/↓ open;
500
528
  * ↑/↓/Home/End move; Enter/Space toggle; Esc closes. Measured from Figma
501
529
  * "✅Project" filter Select (node 231:60682).
502
530
  */
503
- declare function MultiSelect({ label, options, value, onChange, disabled, selectAllLabel, clearLabel, id, className, }: MultiSelectProps): react.JSX.Element;
531
+ declare function MultiSelect({ label, variant, placeholder, showActions, options, value, onChange, disabled, selectAllLabel, clearLabel, id, className, }: MultiSelectProps): react.JSX.Element;
504
532
 
505
533
  interface SearchInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'> {
506
534
  /** Keyboard hint shown at the end while the field is empty, e.g. "/". */
@@ -540,13 +568,16 @@ interface EmptyStateProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'>
540
568
  action?: ReactNode;
541
569
  /** Secondary line under the action, e.g. a help link. */
542
570
  footer?: ReactNode;
571
+ /** `compact` for an empty list inside a card or table: smaller title and
572
+ * spacing, and the illustration (usually an icon) keeps its own size. @default 'default' */
573
+ size?: 'default' | 'compact';
543
574
  }
544
575
  /**
545
576
  * Fidel design-system EmptyState: a centred illustration, title, description,
546
577
  * action and footer, for a list or page with nothing in it yet. Measured from
547
578
  * Figma "✅Project" Empty State Container (node 231:59661).
548
579
  */
549
- declare function EmptyState({ illustration, title, description, action, footer, className, ...rest }: EmptyStateProps): react.JSX.Element;
580
+ declare function EmptyState({ illustration, title, description, action, footer, size, className, ...rest }: EmptyStateProps): react.JSX.Element;
550
581
  /**
551
582
  * Two tilted cards with a search badge: "nothing found yet". Drawn from the
552
583
  * Figma "Stacked Cards" layers (node 80:49887), 240×160.
@@ -603,4 +634,229 @@ interface SkeletonGroupProps extends HTMLAttributes<HTMLDivElement> {
603
634
  /** Wraps a skeleton layout and announces it once as loading (role="status"). */
604
635
  declare function SkeletonGroup({ label, className, children, ...rest }: SkeletonGroupProps): react.JSX.Element;
605
636
 
606
- export { AppNav, type AppNavProps, Avatar, type AvatarProps, type AvatarSize, Badge, type BadgeProps, type Breakpoint, Button, ButtonLink, type ButtonLinkProps, type ButtonProps, type ButtonSize, type ButtonVariant, Callout, type CalloutProps, type CalloutTone, type DiffElement, type DiffPropertyLine, DiffPropertyList, type DiffPropertyListProps, DiffSection, type DiffSectionProps, EmptyState, type EmptyStateProps, MismatchCard, type MismatchCardProps, type MismatchProperty, Modal, type ModalProps, type ModalSize, type ModalTone, MultiSelect, type MultiSelectOption, type MultiSelectProps, Pagination, type PaginationProps, SearchInput, type SearchInputProps, SectionHeader, type SectionHeaderProps, SegmentedControl, type SegmentedControlProps, type SegmentedOption, Select, type SelectOption, type SelectProps, SettingsSection, type SettingsSectionProps, Skeleton, SkeletonGroup, type SkeletonGroupProps, type SkeletonProps, type SkeletonShape, Split, type SplitProps, StackedCardsIllustration, TabNav, type TabNavProps, Tag, type TagProps, Toggle, type ToggleProps, type ToggleSize, type Tone, breakpoints };
637
+ /** Surface colour. `subtle` is the grey panel, `default` white with a border, `plain` white without one. */
638
+ type CardTone = 'subtle' | 'default' | 'plain';
639
+ type CardPadding = 'none' | 'md' | 'lg';
640
+ interface CardProps extends HTMLAttributes<HTMLDivElement> {
641
+ /** @default 'default' */
642
+ tone?: CardTone;
643
+ /** Inner spacing: 24px (`md`) or 40px (`lg`, 24px on phones). @default 'md' */
644
+ padding?: CardPadding;
645
+ children?: ReactNode;
646
+ }
647
+ /**
648
+ * Fidel design-system Card: a rounded surface that groups related content.
649
+ * It has no layout of its own; put anything inside. Measured from Figma
650
+ * "Integrations" frames (nodes 231:66631, 231:67267, 231:67335).
651
+ */
652
+ declare function Card({ tone, padding, className, children, ...rest }: CardProps): react.JSX.Element;
653
+
654
+ interface StatProps extends HTMLAttributes<HTMLDivElement> {
655
+ /** What the number counts, e.g. "Tokens found". */
656
+ label: ReactNode;
657
+ /** The figure itself. */
658
+ value: ReactNode;
659
+ /** Detail under the figure, e.g. a row of Tags. */
660
+ children?: ReactNode;
661
+ }
662
+ /**
663
+ * Fidel design-system Stat: a caption, a large figure and optional detail.
664
+ * Has no surface; wrap it in a Card. Measured from Figma "Design System
665
+ * connected" (node 231:67335).
666
+ */
667
+ declare function Stat({ label, value, children, className, ...rest }: StatProps): react.JSX.Element;
668
+
669
+ interface CheckboxProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type' | 'size'> {
670
+ /** Text beside the box. Without one, pass `aria-label`. */
671
+ label?: ReactNode;
672
+ /** Secondary line under the label. */
673
+ description?: ReactNode;
674
+ /** Shows a dash for "some of these"; screen readers announce it as mixed. */
675
+ indeterminate?: boolean;
676
+ }
677
+ /**
678
+ * Fidel design-system Checkbox. Renders a native checkbox, visually hidden
679
+ * over a drawn box, so checked/indeterminate/disabled/focus come from the
680
+ * input itself and every standard input attribute passes through. Built like
681
+ * Toggle; checked is ink-filled to match the Integrations frames.
682
+ */
683
+ declare const Checkbox: react.ForwardRefExoticComponent<CheckboxProps & react.RefAttributes<HTMLInputElement>>;
684
+
685
+ interface RadioProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type' | 'size'> {
686
+ /** Text beside the circle. Without one, pass `aria-label`. */
687
+ label?: ReactNode;
688
+ /** Secondary line under the label. */
689
+ description?: ReactNode;
690
+ }
691
+ /**
692
+ * Fidel design-system Radio: one choice of several. Give every Radio in a
693
+ * set the same `name`, and wrap the set in a `role="radiogroup"` element (or
694
+ * a fieldset) with a label. Built like Checkbox: a native input over a drawn
695
+ * circle, ink-filled when chosen.
696
+ */
697
+ declare const Radio: react.ForwardRefExoticComponent<RadioProps & react.RefAttributes<HTMLInputElement>>;
698
+
699
+ interface AccordionProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {
700
+ /** Header content, always visible. Clicking it opens and closes the body. */
701
+ summary: ReactNode;
702
+ /**
703
+ * Controls in the header that do their own thing, e.g. a Retry button.
704
+ * Kept outside the toggle so they stay separate keyboard stops.
705
+ */
706
+ actions?: ReactNode;
707
+ /** Controlled open state. */
708
+ open?: boolean;
709
+ /** Initial open state when uncontrolled. @default false */
710
+ defaultOpen?: boolean;
711
+ onOpenChange?: (open: boolean) => void;
712
+ /** Body, shown while open. */
713
+ children?: ReactNode;
714
+ }
715
+ /**
716
+ * Fidel design-system Accordion: one row that expands to show more. Stack
717
+ * several for a list. The header is a button with `aria-expanded`; the
718
+ * chevron on the right points down when closed and up when open.
719
+ */
720
+ declare function Accordion({ summary, actions, open: openProp, defaultOpen, onOpenChange, children, className, ...rest }: AccordionProps): react.JSX.Element;
721
+
722
+ type StepStatus = 'done' | 'active' | 'pending' | 'failed';
723
+ interface Step {
724
+ id: string;
725
+ label: ReactNode;
726
+ status: StepStatus;
727
+ }
728
+ interface StepListProps extends Omit<HTMLAttributes<HTMLOListElement>, 'children'> {
729
+ steps: Step[];
730
+ }
731
+ /**
732
+ * Fidel design-system StepList: an ordered list of steps, each done, in
733
+ * progress, not started or failed. The in-progress step is marked
734
+ * `aria-current="step"`. Measured from Figma "Scanning" (node 231:67267).
735
+ */
736
+ declare function StepList({ steps, className, ...rest }: StepListProps): react.JSX.Element;
737
+
738
+ interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size'> {
739
+ /** Text above the field. Without one, pass `aria-label`. */
740
+ label?: ReactNode;
741
+ /** Muted line under the field, e.g. why it is locked. */
742
+ hint?: ReactNode;
743
+ /** Replaces the hint and marks the field invalid. */
744
+ error?: ReactNode;
745
+ /** Icon before the value, e.g. a lock on a read-only field. */
746
+ leadingIcon?: ReactNode;
747
+ /** Control inside the field after the value, e.g. a compact Select. */
748
+ trailing?: ReactNode;
749
+ /** Classes for the outer field (label + box + message). */
750
+ containerClassName?: string;
751
+ }
752
+ /**
753
+ * Fidel design-system Input: a labelled text field with an optional leading
754
+ * icon, a trailing control inside the box, and a hint or error underneath.
755
+ * Read-only and disabled fields render on the grey surface. Every standard
756
+ * input attribute passes through, so it works with react-hook-form's
757
+ * `register`. Measured from Figma Settings · General and Team frames.
758
+ */
759
+ declare const Input: react.ForwardRefExoticComponent<InputProps & react.RefAttributes<HTMLInputElement>>;
760
+
761
+ type IconButtonVariant = 'outlined' | 'ghost';
762
+ type IconButtonSize = 'small' | 'medium';
763
+ interface IconButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'children'> {
764
+ /** The icon; drawn at 18px (`medium`) or 16px (`small`). */
765
+ icon: ReactNode;
766
+ /** Names the action for screen readers, since there is no visible text. */
767
+ 'aria-label': string;
768
+ /** @default 'outlined' */
769
+ variant?: IconButtonVariant;
770
+ /** 44px (`medium`, matches Button medium) or 28px (`small`). @default 'medium' */
771
+ size?: IconButtonSize;
772
+ }
773
+ /**
774
+ * Fidel design-system IconButton: a square button holding only an icon, for
775
+ * actions like regenerate, edit, delete or "more". Measured from Figma
776
+ * Settings · Team (regenerate link) and Privacy & Security (row menu).
777
+ */
778
+ declare function IconButton({ icon, variant, size, type, className, ...rest }: IconButtonProps): react.JSX.Element;
779
+
780
+ interface MenuItem {
781
+ label: ReactNode;
782
+ onSelect: () => void;
783
+ /** `danger` for destructive actions, e.g. "Sign out of this device". */
784
+ tone?: 'default' | 'danger';
785
+ icon?: ReactNode;
786
+ disabled?: boolean;
787
+ }
788
+ interface MenuProps {
789
+ /** The button that opens the menu, usually an IconButton. It gets the click and ARIA wiring. */
790
+ trigger: ReactElement;
791
+ items: MenuItem[];
792
+ /** Which edge of the trigger the menu lines up with. @default 'end' */
793
+ align?: 'start' | 'end';
794
+ className?: string;
795
+ }
796
+ /**
797
+ * Fidel design-system Menu: a short list of actions opened from a button,
798
+ * e.g. a row's "more" menu. Keyboard: Enter/Space/↓ on the trigger open it;
799
+ * ↑/↓/Home/End move; Enter/Space choose; Esc and Tab close; clicking outside
800
+ * closes.
801
+ */
802
+ declare function Menu({ trigger, items, align, className }: MenuProps): react.JSX.Element;
803
+
804
+ interface TableColumn<Row> {
805
+ key: string;
806
+ header: ReactNode;
807
+ /** Renders this column's cell for a row. */
808
+ cell: (row: Row) => ReactNode;
809
+ /** @default 'start' */
810
+ align?: 'start' | 'end';
811
+ /** CSS width, e.g. '120px' or '40%'. */
812
+ width?: string;
813
+ }
814
+ interface TableProps<Row> extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
815
+ columns: TableColumn<Row>[];
816
+ rows: Row[];
817
+ /** Stable key for each row. */
818
+ rowKey: (row: Row) => string;
819
+ /** Shown under the header when `rows` is empty, e.g. an EmptyState. */
820
+ empty?: ReactNode;
821
+ /** Names the table for screen readers. */
822
+ 'aria-label': string;
823
+ }
824
+ /**
825
+ * Fidel design-system Table: a grey header row over hairline-divided rows,
826
+ * for records people scan by column, like payments. With no rows it keeps
827
+ * the header and shows `empty` beneath it. Scrolls sideways on narrow
828
+ * screens instead of squashing columns. Measured from Figma Settings ·
829
+ * Billing history.
830
+ */
831
+ declare function Table<Row>({ columns, rows, rowKey, empty, className, 'aria-label': ariaLabel, ...rest }: TableProps<Row>): react.JSX.Element;
832
+
833
+ interface PricingCardProps extends Omit<HTMLAttributes<HTMLElement>, 'title'> {
834
+ /** Small label above the name, e.g. "Current plan". */
835
+ eyebrow?: ReactNode;
836
+ /** Plan name, rendered as an `h3`. */
837
+ title: ReactNode;
838
+ /** Beside the name, e.g. a "Beta" tag. */
839
+ badge?: ReactNode;
840
+ /** Formatted price, e.g. "$29". */
841
+ price: ReactNode;
842
+ /** After the price, e.g. "/ month". */
843
+ period?: ReactNode;
844
+ description?: ReactNode;
845
+ /** Usually a full-width Button. */
846
+ action?: ReactNode;
847
+ /** Heading over the feature list. @default 'Features' */
848
+ featuresTitle?: ReactNode;
849
+ /** Line above the list, e.g. "Everything in Free, plus". */
850
+ featuresIntro?: ReactNode;
851
+ features?: ReactNode[];
852
+ /** Accent outline and tint, for the plan you're recommending. */
853
+ highlighted?: boolean;
854
+ }
855
+ /**
856
+ * Fidel design-system PricingCard: one plan's name, price, action and
857
+ * features. The top sits on a raised panel; the feature list sits below it on
858
+ * the card's tint. Measured from Figma Settings · Plan (node 384:14395).
859
+ */
860
+ declare function PricingCard({ eyebrow, title, badge, price, period, description, action, featuresTitle, featuresIntro, features, highlighted, className, ...rest }: PricingCardProps): react.JSX.Element;
861
+
862
+ export { Accordion, type AccordionProps, AppNav, type AppNavProps, Avatar, type AvatarProps, type AvatarSize, Badge, type BadgeProps, type Breakpoint, Button, ButtonLink, type ButtonLinkProps, type ButtonProps, type ButtonSize, type ButtonVariant, Callout, type CalloutProps, type CalloutTone, Card, type CardPadding, type CardProps, type CardTone, Checkbox, type CheckboxProps, type DiffElement, type DiffPropertyLine, DiffPropertyList, type DiffPropertyListProps, DiffSection, type DiffSectionProps, EmptyState, type EmptyStateProps, IconButton, type IconButtonProps, type IconButtonSize, type IconButtonVariant, Input, type InputProps, Menu, type MenuItem, type MenuProps, MismatchCard, type MismatchCardProps, type MismatchProperty, Modal, type ModalProps, type ModalSize, type ModalTone, MultiSelect, type MultiSelectOption, type MultiSelectProps, Pagination, type PaginationProps, PricingCard, type PricingCardProps, Radio, type RadioProps, SearchInput, type SearchInputProps, SectionHeader, type SectionHeaderProps, SegmentedControl, type SegmentedControlProps, type SegmentedOption, Select, type SelectOption, type SelectProps, SettingsSection, type SettingsSectionProps, Skeleton, SkeletonGroup, type SkeletonGroupProps, type SkeletonProps, type SkeletonShape, Split, type SplitProps, StackedCardsIllustration, Stat, type StatProps, type Step, StepList, type StepListProps, type StepStatus, TabNav, type TabNavProps, Table, type TableColumn, type TableProps, Tag, type TagProps, Toggle, type ToggleProps, type ToggleSize, type Tone, breakpoints };