reso-ui 3.11.0 → 3.13.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
@@ -36,8 +36,7 @@ A React component library built with TypeScript + SCSS. Ships as tree-shakeable
36
36
  - [Responsive Context](#responsive-context)
37
37
  - [Overriding the Color Palette](#overriding-the-color-palette)
38
38
  - [Utility Classes](#utility-classes)
39
- - [Dev Notes](#dev-notes)
40
- - [CI/CD Notes](#cicd-notes)
39
+ - [Contributing](#contributing)
41
40
 
42
41
  ---
43
42
 
@@ -76,27 +75,29 @@ npm install reso-ui@2.x
76
75
 
77
76
  #### `custom.d.ts` (project root)
78
77
 
79
- Create this file so TypeScript knows how to handle SVG and font file imports:
78
+ Create this file so TypeScript knows how to handle style and reso-ui stylesheet imports:
80
79
 
81
80
  ```ts
82
81
  // custom.d.ts
83
- declare module "*.svg" {
84
- import React from "react";
85
- const SVG: React.FunctionComponent<React.SVGAttributes<SVGElement>>;
86
- export default SVG;
87
- }
88
-
82
+ declare module "*.scss";
83
+ declare module "*.css";
84
+ declare module "reso-ui/styles";
89
85
  declare module "*.ttf" {
90
86
  const content: string;
91
87
  export default content;
92
88
  }
93
89
  ```
94
90
 
95
- Then add it to your `tsconfig.json`:
91
+ #### `tsconfig.json`
92
+
93
+ **`skipLibCheck: true` is required.** Reso UI's compiled type declarations reference SVG imports internally. Without this flag, TypeScript will try to resolve them in your project's module declaration context, causing type errors on icon components.
96
94
 
97
95
  ```json
98
96
  {
99
- "compilerOptions": { ... },
97
+ "compilerOptions": {
98
+ "skipLibCheck": true,
99
+ ...
100
+ },
100
101
  "include": ["src", "custom.d.ts"]
101
102
  }
102
103
  ```
@@ -256,11 +257,11 @@ Reso UI components use React context and hooks internally, so they require a `"u
256
257
 
257
258
  import { ResoUiProvider } from "reso-ui";
258
259
 
259
- export const ResoUiClientProvider = ({ children }: { children: React.ReactNode }) => (
260
- <ResoUiProvider mode="system">
261
- {children}
262
- </ResoUiProvider>
263
- );
260
+ export const ResoUiClientProvider = ({
261
+ children,
262
+ }: {
263
+ children: React.ReactNode;
264
+ }) => <ResoUiProvider mode="system">{children}</ResoUiProvider>;
264
265
  ```
265
266
 
266
267
  Then import the styles and provider in your root layout:
@@ -271,13 +272,15 @@ import "reso-ui/styles";
271
272
  import "./globals.css";
272
273
  import { ResoUiClientProvider } from "@/providers/ResoUiClientProvider";
273
274
 
274
- export default function RootLayout({ children }: { children: React.ReactNode }) {
275
+ export default function RootLayout({
276
+ children,
277
+ }: {
278
+ children: React.ReactNode;
279
+ }) {
275
280
  return (
276
281
  <html lang="en">
277
282
  <body>
278
- <ResoUiClientProvider>
279
- {children}
280
- </ResoUiClientProvider>
283
+ <ResoUiClientProvider>{children}</ResoUiClientProvider>
281
284
  </body>
282
285
  </html>
283
286
  );
@@ -364,7 +367,7 @@ const root = ReactDOM.createRoot(document.getElementById("root"));
364
367
  root.render(
365
368
  <ResoUiProvider>
366
369
  <App />
367
- </ResoUiProvider>
370
+ </ResoUiProvider>,
368
371
  );
369
372
  ```
370
373
 
@@ -376,8 +379,8 @@ Import the Reso UI stylesheet **before** your own application styles so your cus
376
379
 
377
380
  ```ts
378
381
  // index.tsx (or index.ts / index.js)
379
- import "reso-ui/styles"; // ← reso-ui first
380
- import "./index.css"; // ← your app styles after
382
+ import "reso-ui/styles"; // ← reso-ui first
383
+ import "./index.css"; // ← your app styles after
381
384
  ```
382
385
 
383
386
  ---
@@ -415,7 +418,9 @@ import "reso-ui/styles";
415
418
  const ThemeToggle = () => {
416
419
  const { resolvedMode, setMode } = useTheme();
417
420
  return (
418
- <button onClick={() => setMode(resolvedMode === "light" ? "dark" : "light")}>
421
+ <button
422
+ onClick={() => setMode(resolvedMode === "light" ? "dark" : "light")}
423
+ >
419
424
  Switch to {resolvedMode === "light" ? "dark" : "light"} mode
420
425
  </button>
421
426
  );
@@ -431,11 +436,11 @@ const App = () => (
431
436
 
432
437
  ### Mode options
433
438
 
434
- | Mode | Behaviour |
435
- |------|-----------|
436
- | `"light"` (default) | Light theme applied |
437
- | `"dark"` | Dark theme applied |
438
- | `"system"` | Follows the user's OS `prefers-color-scheme` preference and reacts to changes in real time |
439
+ | Mode | Behaviour |
440
+ | ------------------- | ------------------------------------------------------------------------------------------ |
441
+ | `"light"` (default) | Light theme applied |
442
+ | `"dark"` | Dark theme applied |
443
+ | `"system"` | Follows the user's OS `prefers-color-scheme` preference and reacts to changes in real time |
439
444
 
440
445
  ### How it works
441
446
 
@@ -451,7 +456,11 @@ const MyComponent = () => {
451
456
  // resolvedMode is always "light" or "dark" (resolved from "system" if needed)
452
457
  // setMode("light" | "dark" | "system") to change the theme
453
458
  // theme contains the current color and token overrides
454
- return <div className={resolvedMode === "dark" ? "my-dark-style" : ""}>{/* ... */}</div>;
459
+ return (
460
+ <div className={resolvedMode === "dark" ? "my-dark-style" : ""}>
461
+ {/* ... */}
462
+ </div>
463
+ );
455
464
  };
456
465
  ```
457
466
 
@@ -491,13 +500,13 @@ const MyComponent = () => {
491
500
 
492
501
  ### Breakpoints
493
502
 
494
- | Flag | Range |
495
- |------|-------|
496
- | `isMobile` | `width < 640` |
497
- | `isTablet` | `640 <= width < 768` |
498
- | `isMdDesktop` | `768 <= width < 1024` |
499
- | `isLgDesktop` | `1024 <= width < 1280` |
500
- | `isXLgDesktop` | `width >= 1280` |
503
+ | Flag | Range |
504
+ | -------------- | ---------------------- |
505
+ | `isMobile` | `width < 640` |
506
+ | `isTablet` | `640 <= width < 768` |
507
+ | `isMdDesktop` | `768 <= width < 1024` |
508
+ | `isLgDesktop` | `1024 <= width < 1280` |
509
+ | `isXLgDesktop` | `width >= 1280` |
501
510
 
502
511
  ### Container-aware breakpoints (optional)
503
512
 
@@ -532,40 +541,40 @@ When no container is registered (the default), breakpoints work exactly as befor
532
541
 
533
542
  **Top-level (resolved)** — breakpoints computed from `Math.min(viewportWidth, containerWidth)`:
534
543
 
535
- | Field | Type | Description |
536
- |-------|------|-------------|
537
- | `isMobile` | `boolean` | Effective width < 640 |
538
- | `isTablet` | `boolean` | 640 <= effective width < 768 |
539
- | `isMdDesktop` | `boolean` | 768 <= effective width < 1024 |
540
- | `isLgDesktop` | `boolean` | 1024 <= effective width < 1280 |
541
- | `isXLgDesktop` | `boolean` | Effective width >= 1280 |
542
- | `windowWidth` | `number` | Actual viewport width |
543
- | `windowHeight` | `number` | Actual viewport height |
544
+ | Field | Type | Description |
545
+ | ----------------- | ----------------------------------- | --------------------------------------- |
546
+ | `isMobile` | `boolean` | Effective width < 640 |
547
+ | `isTablet` | `boolean` | 640 <= effective width < 768 |
548
+ | `isMdDesktop` | `boolean` | 768 <= effective width < 1024 |
549
+ | `isLgDesktop` | `boolean` | 1024 <= effective width < 1280 |
550
+ | `isXLgDesktop` | `boolean` | Effective width >= 1280 |
551
+ | `windowWidth` | `number` | Actual viewport width |
552
+ | `windowHeight` | `number` | Actual viewport height |
544
553
  | `setContainerRef` | `(el: HTMLElement \| null) => void` | Register/unregister a container element |
545
554
 
546
555
  **`viewport`** — always based on the viewport, ignoring container. Use this for structural layout decisions (e.g., whether to show a sidebar):
547
556
 
548
- | Field | Type | Description |
549
- |-------|------|-------------|
550
- | `viewport.isMobile` | `boolean` | Viewport width < 640 |
551
- | `viewport.isTablet` | `boolean` | 640 <= viewport width < 768 |
552
- | `viewport.isMdDesktop` | `boolean` | 768 <= viewport width < 1024 |
553
- | `viewport.isLgDesktop` | `boolean` | 1024 <= viewport width < 1280 |
554
- | `viewport.isXLgDesktop` | `boolean` | Viewport width >= 1280 |
555
- | `viewport.width` | `number` | Viewport width |
556
- | `viewport.height` | `number` | Viewport height |
557
+ | Field | Type | Description |
558
+ | ----------------------- | --------- | ----------------------------- |
559
+ | `viewport.isMobile` | `boolean` | Viewport width < 640 |
560
+ | `viewport.isTablet` | `boolean` | 640 <= viewport width < 768 |
561
+ | `viewport.isMdDesktop` | `boolean` | 768 <= viewport width < 1024 |
562
+ | `viewport.isLgDesktop` | `boolean` | 1024 <= viewport width < 1280 |
563
+ | `viewport.isXLgDesktop` | `boolean` | Viewport width >= 1280 |
564
+ | `viewport.width` | `number` | Viewport width |
565
+ | `viewport.height` | `number` | Viewport height |
557
566
 
558
567
  **`container`** — breakpoints and dimensions of the tracked container element:
559
568
 
560
- | Field | Type | Description |
561
- |-------|------|-------------|
562
- | `container.isMobile` | `boolean` | Container width < 640 (true when none registered) |
563
- | `container.isTablet` | `boolean` | 640 <= container width < 768 |
564
- | `container.isMdDesktop` | `boolean` | 768 <= container width < 1024 |
565
- | `container.isLgDesktop` | `boolean` | 1024 <= container width < 1280 |
566
- | `container.isXLgDesktop` | `boolean` | Container width >= 1280 |
567
- | `container.width` | `number` | Container width (0 if none registered) |
568
- | `container.height` | `number` | Container height (0 if none registered) |
569
+ | Field | Type | Description |
570
+ | ------------------------ | --------- | ------------------------------------------------- |
571
+ | `container.isMobile` | `boolean` | Container width < 640 (true when none registered) |
572
+ | `container.isTablet` | `boolean` | 640 <= container width < 768 |
573
+ | `container.isMdDesktop` | `boolean` | 768 <= container width < 1024 |
574
+ | `container.isLgDesktop` | `boolean` | 1024 <= container width < 1280 |
575
+ | `container.isXLgDesktop` | `boolean` | Container width >= 1280 |
576
+ | `container.width` | `number` | Container width (0 if none registered) |
577
+ | `container.height` | `number` | Container height (0 if none registered) |
569
578
 
570
579
  ### When to use which
571
580
 
@@ -606,8 +615,8 @@ Pass a partial `theme.colors` object to override semantic color roles. Keys map
606
615
  <ResoUiProvider
607
616
  theme={{
608
617
  colors: {
609
- brandPrimary: "#1a365d", // primary brand (navy)
610
- brandSecondary: "#c53030", // secondary brand (coral/CTA)
618
+ brandPrimary: "#1a365d", // primary brand (navy)
619
+ brandSecondary: "#c53030", // secondary brand (coral/CTA)
611
620
  utilityError: "#e53e3e",
612
621
  utilitySuccess: "#276749",
613
622
  },
@@ -619,54 +628,54 @@ Pass a partial `theme.colors` object to override semantic color roles. Keys map
619
628
 
620
629
  **Full `colors` keys** (`ResoPaletteSemantics`):
621
630
 
622
- | Key | CSS variable |
623
- |-----|-------------|
624
- | `brandPrimaryGhost` | `--resoui-brand-primary-ghost` |
625
- | `brandPrimaryLight` | `--resoui-brand-primary-light` |
626
- | `brandPrimaryMedium` | `--resoui-brand-primary-medium` |
627
- | `brandPrimary` | `--resoui-brand-primary` |
628
- | `brandPrimaryDark` | `--resoui-brand-primary-dark` |
629
- | `brandPrimaryDarkest` | `--resoui-brand-primary-darkest` |
630
- | `brandSecondaryPale` | `--resoui-brand-secondary-pale` |
631
- | `brandSecondaryLight` | `--resoui-brand-secondary-light` |
632
- | `brandSecondary` | `--resoui-brand-secondary` |
633
- | `brandSecondaryDark` | `--resoui-brand-secondary-dark` |
634
- | `brandSecondaryDarker` | `--resoui-brand-secondary-darker` |
631
+ | Key | CSS variable |
632
+ | ------------------------ | ----------------------------------- |
633
+ | `brandPrimaryGhost` | `--resoui-brand-primary-ghost` |
634
+ | `brandPrimaryLight` | `--resoui-brand-primary-light` |
635
+ | `brandPrimaryMedium` | `--resoui-brand-primary-medium` |
636
+ | `brandPrimary` | `--resoui-brand-primary` |
637
+ | `brandPrimaryDark` | `--resoui-brand-primary-dark` |
638
+ | `brandPrimaryDarkest` | `--resoui-brand-primary-darkest` |
639
+ | `brandSecondaryPale` | `--resoui-brand-secondary-pale` |
640
+ | `brandSecondaryLight` | `--resoui-brand-secondary-light` |
641
+ | `brandSecondary` | `--resoui-brand-secondary` |
642
+ | `brandSecondaryDark` | `--resoui-brand-secondary-dark` |
643
+ | `brandSecondaryDarker` | `--resoui-brand-secondary-darker` |
635
644
  | `brandSecondaryGradient` | `--resoui-brand-secondary-gradient` |
636
- | `brandTertiaryPale` | `--resoui-brand-tertiary-pale` |
637
- | `brandTertiaryLight` | `--resoui-brand-tertiary-light` |
638
- | `brandTertiary` | `--resoui-brand-tertiary` |
639
- | `brandTertiaryDark` | `--resoui-brand-tertiary-dark` |
640
- | `brandTertiaryDarker` | `--resoui-brand-tertiary-darker` |
641
- | `brandQuaternaryPale` | `--resoui-brand-quaternary-pale` |
642
- | `brandQuaternaryLight` | `--resoui-brand-quaternary-light` |
643
- | `brandQuaternary` | `--resoui-brand-quaternary` |
644
- | `brandQuaternaryDark` | `--resoui-brand-quaternary-dark` |
645
- | `brandQuaternaryDarker` | `--resoui-brand-quaternary-darker` |
646
- | `utilitySuccessBg` | `--resoui-utility-success-bg` |
647
- | `utilitySuccessLight` | `--resoui-utility-success-light` |
648
- | `utilitySuccess` | `--resoui-utility-success` |
649
- | `utilitySuccessDark` | `--resoui-utility-success-dark` |
650
- | `utilityWarningBg` | `--resoui-utility-warning-bg` |
651
- | `utilityWarningLight` | `--resoui-utility-warning-light` |
652
- | `utilityWarning` | `--resoui-utility-warning` |
653
- | `utilityWarningDark` | `--resoui-utility-warning-dark` |
654
- | `utilityErrorBg` | `--resoui-utility-error-bg` |
655
- | `utilityErrorLight` | `--resoui-utility-error-light` |
656
- | `utilityError` | `--resoui-utility-error` |
657
- | `utilityErrorDark` | `--resoui-utility-error-dark` |
658
- | `utilityInfoBg` | `--resoui-utility-info-bg` |
659
- | `utilityInfoLight` | `--resoui-utility-info-light` |
660
- | `utilityInfo` | `--resoui-utility-info` |
661
- | `utilityInfoDark` | `--resoui-utility-info-dark` |
662
- | `neutralLightest` | `--resoui-neutral-lightest` |
663
- | `neutralLight` | `--resoui-neutral-light` |
664
- | `neutralMedium` | `--resoui-neutral-medium` |
665
- | `neutralDark` | `--resoui-neutral-dark` |
666
- | `neutralDarker` | `--resoui-neutral-darker` |
667
- | `neutralOverlay` | `--resoui-neutral-overlay` |
668
- | `baseWhite` | `--resoui-base-white` |
669
- | `baseBlack` | `--resoui-base-black` |
645
+ | `brandTertiaryPale` | `--resoui-brand-tertiary-pale` |
646
+ | `brandTertiaryLight` | `--resoui-brand-tertiary-light` |
647
+ | `brandTertiary` | `--resoui-brand-tertiary` |
648
+ | `brandTertiaryDark` | `--resoui-brand-tertiary-dark` |
649
+ | `brandTertiaryDarker` | `--resoui-brand-tertiary-darker` |
650
+ | `brandQuaternaryPale` | `--resoui-brand-quaternary-pale` |
651
+ | `brandQuaternaryLight` | `--resoui-brand-quaternary-light` |
652
+ | `brandQuaternary` | `--resoui-brand-quaternary` |
653
+ | `brandQuaternaryDark` | `--resoui-brand-quaternary-dark` |
654
+ | `brandQuaternaryDarker` | `--resoui-brand-quaternary-darker` |
655
+ | `utilitySuccessBg` | `--resoui-utility-success-bg` |
656
+ | `utilitySuccessLight` | `--resoui-utility-success-light` |
657
+ | `utilitySuccess` | `--resoui-utility-success` |
658
+ | `utilitySuccessDark` | `--resoui-utility-success-dark` |
659
+ | `utilityWarningBg` | `--resoui-utility-warning-bg` |
660
+ | `utilityWarningLight` | `--resoui-utility-warning-light` |
661
+ | `utilityWarning` | `--resoui-utility-warning` |
662
+ | `utilityWarningDark` | `--resoui-utility-warning-dark` |
663
+ | `utilityErrorBg` | `--resoui-utility-error-bg` |
664
+ | `utilityErrorLight` | `--resoui-utility-error-light` |
665
+ | `utilityError` | `--resoui-utility-error` |
666
+ | `utilityErrorDark` | `--resoui-utility-error-dark` |
667
+ | `utilityInfoBg` | `--resoui-utility-info-bg` |
668
+ | `utilityInfoLight` | `--resoui-utility-info-light` |
669
+ | `utilityInfo` | `--resoui-utility-info` |
670
+ | `utilityInfoDark` | `--resoui-utility-info-dark` |
671
+ | `neutralLightest` | `--resoui-neutral-lightest` |
672
+ | `neutralLight` | `--resoui-neutral-light` |
673
+ | `neutralMedium` | `--resoui-neutral-medium` |
674
+ | `neutralDark` | `--resoui-neutral-dark` |
675
+ | `neutralDarker` | `--resoui-neutral-darker` |
676
+ | `neutralOverlay` | `--resoui-neutral-overlay` |
677
+ | `baseWhite` | `--resoui-base-white` |
678
+ | `baseBlack` | `--resoui-base-black` |
670
679
 
671
680
  ### Override spacing, typography, and layout tokens
672
681
 
@@ -687,25 +696,25 @@ Pass a partial `theme.colors` object to override semantic color roles. Keys map
687
696
 
688
697
  **Full `tokens` keys** (`ResoTokens`):
689
698
 
690
- | Key | CSS variable | Default |
691
- |-----|-------------|---------|
692
- | `spacing0` … `spacing9` | `--resoui-spacing-0` … `--resoui-spacing-9` | `0px` … `96px` |
693
- | `fontFamily` | `--resoui-font-family` | `"Poppins", "Roboto", sans-serif` |
694
- | `fontSize1` … `fontSize9` | `--resoui-font-size-1` … `--resoui-font-size-9` | `10px` … `26px` |
695
- | `fontWeightNormal` | `--resoui-font-weight-normal` | `400` |
696
- | `fontWeightMedium` | `--resoui-font-weight-medium` | `500` |
697
- | `fontWeightSemibold` | `--resoui-font-weight-semibold` | `600` |
698
- | `fontWeightBold` | `--resoui-font-weight-bold` | `700` |
699
- | `radiusSm` | `--resoui-radius-sm` | `4px` |
700
- | `radiusDefault` | `--resoui-radius-default` | `8px` |
701
- | `radiusLg` | `--resoui-radius-lg` | `16px` |
702
- | `radiusFull` | `--resoui-radius-full` | `9999px` |
703
- | `shadowSm` | `--resoui-shadow-sm` | `0 1px 3px rgba(0,0,0,0.1)` |
704
- | `shadowDefault` | `--resoui-shadow-default` | `0px 2px 15px rgba(34,60,102,0.2)` |
705
- | `shadowLg` | `--resoui-shadow-lg` | `0px 4px 25px rgba(34,60,102,0.15)` |
706
- | `transitionFast` | `--resoui-transition-fast` | `0.125s` |
707
- | `transitionNormal` | `--resoui-transition-normal` | `0.25s` |
708
- | `transitionSlow` | `--resoui-transition-slow` | `0.5s` |
699
+ | Key | CSS variable | Default |
700
+ | ------------------------- | ----------------------------------------------- | ----------------------------------- |
701
+ | `spacing0` … `spacing9` | `--resoui-spacing-0` … `--resoui-spacing-9` | `0px` … `96px` |
702
+ | `fontFamily` | `--resoui-font-family` | `"Poppins", "Roboto", sans-serif` |
703
+ | `fontSize1` … `fontSize9` | `--resoui-font-size-1` … `--resoui-font-size-9` | `10px` … `26px` |
704
+ | `fontWeightNormal` | `--resoui-font-weight-normal` | `400` |
705
+ | `fontWeightMedium` | `--resoui-font-weight-medium` | `500` |
706
+ | `fontWeightSemibold` | `--resoui-font-weight-semibold` | `600` |
707
+ | `fontWeightBold` | `--resoui-font-weight-bold` | `700` |
708
+ | `radiusSm` | `--resoui-radius-sm` | `4px` |
709
+ | `radiusDefault` | `--resoui-radius-default` | `8px` |
710
+ | `radiusLg` | `--resoui-radius-lg` | `16px` |
711
+ | `radiusFull` | `--resoui-radius-full` | `9999px` |
712
+ | `shadowSm` | `--resoui-shadow-sm` | `0 1px 3px rgba(0,0,0,0.1)` |
713
+ | `shadowDefault` | `--resoui-shadow-default` | `0px 2px 15px rgba(34,60,102,0.2)` |
714
+ | `shadowLg` | `--resoui-shadow-lg` | `0px 4px 25px rgba(34,60,102,0.15)` |
715
+ | `transitionFast` | `--resoui-transition-fast` | `0.125s` |
716
+ | `transitionNormal` | `--resoui-transition-normal` | `0.25s` |
717
+ | `transitionSlow` | `--resoui-transition-slow` | `0.5s` |
709
718
 
710
719
  ---
711
720
 
@@ -715,22 +724,22 @@ Reso UI ships utility CSS classes that consumer projects can apply directly via
715
724
 
716
725
  ### Quick Reference
717
726
 
718
- | Class | Category | Dark Mode | Description |
719
- |-------|----------|-----------|-------------|
720
- | [`resoui_section_border`](#section-border) | Layout | Yes | Bordered section container with default border-radius |
721
- | [`resoui_table_base`](#tables) | Tables | Yes | Base `<table>` styling (font, collapse, full width) |
722
- | [`resoui_th_base`](#tables) | Tables | Yes | Table header cell (padding, border, font-weight) |
723
- | [`resoui_tr_base`](#tables) | Tables | Yes | Table row (border, hover highlight) |
724
- | [`resoui_tr_base_selected`](#tables) | Tables | Yes | Selected table row highlight |
725
- | [`resoui_td_base`](#tables) | Tables | No | Table data cell (padding) |
726
- | [`resoui_navItem_base`](#nav-item-base) | Navigation | No | Nav item base layout for custom NavItem renders |
727
- | [`resoui_dropdown_option_base`](#dropdown-option-base) | Forms | Yes | Dropdown option base for custom DropdownSelect options |
728
- | [`resoui_no_select`](#general-utilities) | General | No | Disable text selection |
729
- | [`resoui_component_disabled`](#general-utilities) | General | No | Disabled overlay with pointer-events disabled |
730
- | [`resoui_background_image`](#general-utilities) | General | No | Background image with cover |
731
- | [`resoui_truncate`](#text-utilities) | Text | No | Truncate text with ellipsis |
732
- | [`resoui_text_no_block_margin`](#text-utilities) | Text | No | Remove default block margins |
733
- | [`resoui_text_no_inline_margin`](#text-utilities) | Text | No | Remove default inline margins |
727
+ | Class | Category | Dark Mode | Description |
728
+ | ------------------------------------------------------ | ---------- | --------- | ------------------------------------------------------ |
729
+ | [`resoui_section_border`](#section-border) | Layout | Yes | Bordered section container with default border-radius |
730
+ | [`resoui_table_base`](#tables) | Tables | Yes | Base `<table>` styling (font, collapse, full width) |
731
+ | [`resoui_th_base`](#tables) | Tables | Yes | Table header cell (padding, border, font-weight) |
732
+ | [`resoui_tr_base`](#tables) | Tables | Yes | Table row (border, hover highlight) |
733
+ | [`resoui_tr_base_selected`](#tables) | Tables | Yes | Selected table row highlight |
734
+ | [`resoui_td_base`](#tables) | Tables | No | Table data cell (padding) |
735
+ | [`resoui_navItem_base`](#nav-item-base) | Navigation | No | Nav item base layout for custom NavItem renders |
736
+ | [`resoui_dropdown_option_base`](#dropdown-option-base) | Forms | Yes | Dropdown option base for custom DropdownSelect options |
737
+ | [`resoui_no_select`](#general-utilities) | General | No | Disable text selection |
738
+ | [`resoui_component_disabled`](#general-utilities) | General | No | Disabled overlay with pointer-events disabled |
739
+ | [`resoui_background_image`](#general-utilities) | General | No | Background image with cover |
740
+ | [`resoui_truncate`](#text-utilities) | Text | No | Truncate text with ellipsis |
741
+ | [`resoui_text_no_block_margin`](#text-utilities) | Text | No | Remove default block margins |
742
+ | [`resoui_text_no_inline_margin`](#text-utilities) | Text | No | Remove default inline margins |
734
743
 
735
744
  ### Section Border
736
745
 
@@ -742,7 +751,7 @@ import { Flex, Text } from "reso-ui";
742
751
  <Flex direction="column" rootClassName="resoui_section_border" pa={5}>
743
752
  <Text Element="h3">Section Title</Text>
744
753
  <Text>Section content goes here.</Text>
745
- </Flex>
754
+ </Flex>;
746
755
  ```
747
756
 
748
757
  Light mode: `1px solid` neutral border + default border-radius. Dark mode: border color automatically darkens.
@@ -751,13 +760,13 @@ Light mode: `1px solid` neutral border + default border-radius. Dark mode: borde
751
760
 
752
761
  Base styles for native HTML `<table>` elements. Apply via the `className` attribute. Dark mode is handled automatically.
753
762
 
754
- | Class | Apply to | What it does |
755
- |-------|----------|-------------|
756
- | `resoui_table_base` | `<table>` | Font-family, border-collapse, full width, font size |
757
- | `resoui_th_base` | `<th>` | Padding, bottom border, font-weight 500, left-aligned |
758
- | `resoui_tr_base` | `<tr>` | Bottom border, hover background highlight |
759
- | `resoui_tr_base_selected` | `<tr>` | Selected row highlight (combine with `resoui_tr_base`) |
760
- | `resoui_td_base` | `<td>` | Cell padding |
763
+ | Class | Apply to | What it does |
764
+ | ------------------------- | --------- | ------------------------------------------------------ |
765
+ | `resoui_table_base` | `<table>` | Font-family, border-collapse, full width, font size |
766
+ | `resoui_th_base` | `<th>` | Padding, bottom border, font-weight 500, left-aligned |
767
+ | `resoui_tr_base` | `<tr>` | Bottom border, hover background highlight |
768
+ | `resoui_tr_base_selected` | `<tr>` | Selected row highlight (combine with `resoui_tr_base`) |
769
+ | `resoui_td_base` | `<td>` | Cell padding |
761
770
 
762
771
  ```tsx
763
772
  <table className="resoui_table_base">
@@ -792,8 +801,13 @@ Add custom column-specific styles alongside the utility classes:
792
801
  ```
793
802
 
794
803
  ```scss
795
- .myPage_th_right { text-align: right; }
796
- .myPage_td_mono { font-family: monospace; font-size: 12px; }
804
+ .myPage_th_right {
805
+ text-align: right;
806
+ }
807
+ .myPage_td_mono {
808
+ font-family: monospace;
809
+ font-size: 12px;
810
+ }
797
811
  ```
798
812
 
799
813
  ### Nav Item Base
@@ -833,18 +847,22 @@ import { DropdownSelect } from "reso-ui";
833
847
  import { Link } from "react-router-dom";
834
848
 
835
849
  <DropdownSelect label="Account">
836
- <Link to="/profile" className="resoui_dropdown_option_base">My Profile</Link>
837
- <Link to="/settings" className="resoui_dropdown_option_base">Settings</Link>
838
- </DropdownSelect>
850
+ <Link to="/profile" className="resoui_dropdown_option_base">
851
+ My Profile
852
+ </Link>
853
+ <Link to="/settings" className="resoui_dropdown_option_base">
854
+ Settings
855
+ </Link>
856
+ </DropdownSelect>;
839
857
  ```
840
858
 
841
859
  ### General Utilities
842
860
 
843
- | Class | What it does |
844
- |-------|-------------|
845
- | `resoui_no_select` | Prevent text selection (all browser prefixes) |
861
+ | Class | What it does |
862
+ | --------------------------- | ------------------------------------------------- |
863
+ | `resoui_no_select` | Prevent text selection (all browser prefixes) |
846
864
  | `resoui_component_disabled` | Semi-transparent overlay + disable pointer events |
847
- | `resoui_background_image` | Background image: cover, centered, no-repeat |
865
+ | `resoui_background_image` | Background image: cover, centered, no-repeat |
848
866
 
849
867
  ```tsx
850
868
  <Flex rootClassName={isLocked ? "resoui_component_disabled" : ""}>
@@ -854,11 +872,11 @@ import { Link } from "react-router-dom";
854
872
 
855
873
  ### Text Utilities
856
874
 
857
- | Class | What it does |
858
- |-------|-------------|
859
- | `resoui_truncate` | Truncate with ellipsis (`overflow: hidden; text-overflow: ellipsis; white-space: nowrap`) |
860
- | `resoui_text_no_block_margin` | Remove block margins from headings (`margin-block-start: 0`) |
861
- | `resoui_text_no_inline_margin` | Remove inline margins |
875
+ | Class | What it does |
876
+ | ------------------------------ | ----------------------------------------------------------------------------------------- |
877
+ | `resoui_truncate` | Truncate with ellipsis (`overflow: hidden; text-overflow: ellipsis; white-space: nowrap`) |
878
+ | `resoui_text_no_block_margin` | Remove block margins from headings (`margin-block-start: 0`) |
879
+ | `resoui_text_no_inline_margin` | Remove inline margins |
862
880
 
863
881
  ```tsx
864
882
  <Text rootClassName="resoui_truncate" rootStyles={{ maxWidth: "200px" }}>
@@ -868,176 +886,6 @@ import { Link } from "react-router-dom";
868
886
 
869
887
  ---
870
888
 
871
- ## Dev Notes
872
-
873
- ### Available commands
874
-
875
- | Command | What it does |
876
- |---------|-------------|
877
- | `npm start` | Webpack dev server → serves `src/App.tsx` at `http://localhost:3000` |
878
- | `npm run storybook` | Storybook dev server at `http://localhost:6006` |
879
- | `npm run build` | Rollup production build → `dist/esm/`, `dist/cjs/`, `dist/styles.css` |
880
- | `npm run build-storybook` | Static Storybook build → `storybook-static/` |
881
- | `npm test` | Jest unit tests (all 65 suites) |
882
- | `npm run test-coverage` | Jest with coverage report → `coverage/` |
883
- | `npm run lint` | TSLint check (excludes stories and test files) |
884
-
885
- ### Viewing the App.tsx sandbox
886
-
887
- `npm start` starts a Webpack dev server that hot-reloads `src/App.tsx`. This file is a scratchpad for manually testing components during development — it is **not** the library entry point.
888
-
889
- ```bash
890
- npm start
891
- # → http://localhost:3000
892
- ```
893
-
894
- App.tsx is already wrapped with `<ResoUiProvider>` in `src/index.tsx`, so all components render with the default theme.
895
-
896
- ### Running Storybook
897
-
898
- ```bash
899
- npm run storybook
900
- # → http://localhost:6006
901
- ```
902
-
903
- Storybook is the primary UI for browsing all components, their props, and usage examples.
904
-
905
- ### Library entry point
906
-
907
- The library exports everything from `src/library/index.ts`. When you run `npm run build`, Rollup compiles this to:
908
-
909
- ```
910
- dist/
911
- esm/ ← tree-shakeable ES modules (one file per component)
912
- cjs/ ← CommonJS bundle
913
- styles.css ← single compiled stylesheet for all components
914
- ```
915
-
916
- `dist/` is **not committed to git** — it is built fresh in CI before every npm publish.
917
-
918
- ---
919
-
920
- ## CI/CD Notes
921
-
922
- The pipeline is defined in `.github/workflows/ci-cd.yml`.
923
-
924
- ### What happens on every push / PR
925
-
926
- 1. **Lint** (`npm run lint`)
927
- 2. **Unit tests** (`npm run test-coverage`) on Node 18 and Node 20
928
- 3. **Library build** (`npm run build`)
929
- 4. **Storybook build** (`npm run build-storybook`)
930
-
931
- PRs to `main`, `2.x`, `v3`, or `beta` must pass all four steps.
932
-
933
- ### Branch → npm dist-tag mapping
889
+ ## Contributing
934
890
 
935
- | Branch | npm dist-tag | Version format | Example |
936
- |--------|-------------|----------------|---------|
937
- | `main` | `@latest` | `x.0.0` | `3.1.0` |
938
- | `v3` | `@alpha` | `3.0.0-alpha.n` | `3.0.0-alpha.5` |
939
- | `beta` | `@beta` | `x.0.0-beta.n` | `3.1.0-beta.2` |
940
- | `2.x` | `@2.x` | `2.x.x` | `2.44.0` |
941
-
942
- ### How to make a change and publish a new version
943
-
944
- 1. **Check out `main`** (or `v3` for alpha work):
945
- ```bash
946
- git checkout main # for stable releases
947
- # or
948
- git checkout v3 # for alpha pre-releases
949
- ```
950
-
951
- 2. **Make your changes**, commit using Conventional Commits:
952
- ```bash
953
- git add .
954
- git commit -m "feat: add Tooltip component"
955
- # or: fix: correct Button disabled opacity
956
- # or: chore: update dependencies
957
- ```
958
-
959
- Commit type determines the version bump:
960
- - `fix:` → patch (`3.0.1`)
961
- - `feat:` → minor (`3.1.0`)
962
- - `feat!:` or `BREAKING CHANGE:` footer → major (`4.0.0`)
963
-
964
- 3. **Push** — CI runs automatically. If all checks pass, `semantic-release` determines the next version, publishes to npm, and commits the updated `CHANGELOG.md` and `package.json` back to the branch.
965
- ```bash
966
- git push origin main
967
- ```
968
-
969
- 4. **Pull the release commit** after CI finishes (semantic-release pushes a version bump commit back):
970
- ```bash
971
- git pull origin main
972
- ```
973
-
974
- ### How to publish alpha (pre-release) versions
975
-
976
- Work on the `v3` branch. Every push that contains a `fix:` or `feat:` commit automatically publishes a new `3.0.0-alpha.n` to the `@alpha` dist-tag.
977
-
978
- ```bash
979
- git checkout v3
980
- # make changes
981
- git commit -m "feat: add Paginator component"
982
- git push origin v3
983
- # → publishes 3.0.0-alpha.5 to npm @alpha
984
- ```
985
-
986
- Clients can install alpha builds:
987
- ```bash
988
- npm install reso-ui@alpha
989
- ```
990
-
991
- ### How to publish beta versions
992
-
993
- Push to the `beta` branch. Follows the same Conventional Commit rules; versions are tagged `@beta`.
994
-
995
- ```bash
996
- git checkout beta
997
- git merge v3 # merge alpha work into beta for wider testing
998
- git push origin beta
999
- # → publishes 3.0.0-beta.1 to npm @beta
1000
- ```
1001
-
1002
- ### How to create a breaking change (new major version)
1003
-
1004
- Use the `BREAKING CHANGE` footer in your commit message **or** add `!` after the type:
1005
-
1006
- ```bash
1007
- # Method 1 — exclamation mark
1008
- git commit -m "feat!: remove theme prop from all components"
1009
-
1010
- # Method 2 — footer
1011
- git commit -m "feat: remove theme prop from all components
1012
-
1013
- BREAKING CHANGE: The theme prop has been removed from all components.
1014
- Wrap your app in <ResoUiProvider mode=\"dark\"> instead."
1015
- ```
1016
-
1017
- When pushed to `main`, this bumps the major version (e.g. `3.0.0` → `4.0.0`).
1018
-
1019
- **Before merging a major version to `main`**, create a maintenance branch for the previous major so it can still receive patch releases:
1020
-
1021
- ```bash
1022
- # Preserve current main as a maintenance line before bumping major
1023
- git checkout main
1024
- git checkout -b 3.x # create 3.x maintenance branch
1025
- git push origin 3.x
1026
- # Add "3.x" to release.config.js branches array, then push major change to main
1027
- ```
1028
-
1029
- ### Maintaining an older major (e.g. v2 patches)
1030
-
1031
- The `2.x` branch receives security fixes and critical patches without merging v3 changes.
1032
-
1033
- ```bash
1034
- git checkout 2.x
1035
- git commit -m "fix: correct date selector boundary validation"
1036
- git push origin 2.x
1037
- # → publishes 2.44.1 to npm @2.x
1038
- ```
1039
-
1040
- Clients pinned to v2 install patches with:
1041
- ```bash
1042
- npm install reso-ui@2.x
1043
- ```
891
+ For developer setup, build commands, CI/CD pipeline, and publishing instructions, see [docs/DEVNOTES.md](docs/DEVNOTES.md).