@fpkit/acss 1.0.0 → 2.0.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 +60 -0
- package/libs/{chunk-7XPFW7CB.js → chunk-43TK2ICH.js} +2 -2
- package/libs/chunk-5PJYLVFY.cjs +17 -0
- package/libs/chunk-5PJYLVFY.cjs.map +1 -0
- package/libs/chunk-E4OSROCA.cjs +17 -0
- package/libs/chunk-E4OSROCA.cjs.map +1 -0
- package/libs/chunk-KVKQLRJG.js +10 -0
- package/libs/chunk-KVKQLRJG.js.map +1 -0
- package/libs/{chunk-QVW6W76L.cjs → chunk-MGPWZRBX.cjs} +3 -3
- package/libs/chunk-NNTBIHSD.js +8 -0
- package/libs/chunk-NNTBIHSD.js.map +1 -0
- package/libs/{chunk-X3JCTEPD.js → chunk-QKHPHMG2.js} +2 -2
- package/libs/{chunk-T4T6GWYQ.cjs → chunk-R7NLLZU2.cjs} +3 -3
- package/libs/{chunk-X5LGFCWG.js → chunk-UJAQVHWC.js} +3 -3
- package/libs/{chunk-DKTHCQ5P.cjs → chunk-X5RKCLDC.cjs} +3 -3
- package/libs/components/breadcrumbs/breadcrumb.cjs +5 -5
- package/libs/components/breadcrumbs/breadcrumb.d.cts +1 -1
- package/libs/components/breadcrumbs/breadcrumb.d.ts +1 -1
- package/libs/components/breadcrumbs/breadcrumb.js +2 -2
- package/libs/components/button.cjs +3 -3
- package/libs/components/button.d.cts +1 -1
- package/libs/components/button.d.ts +1 -1
- package/libs/components/button.js +1 -1
- package/libs/components/dialog/dialog.cjs +4 -4
- package/libs/components/dialog/dialog.js +2 -2
- package/libs/components/link/link.cjs +11 -3
- package/libs/components/link/link.d.cts +131 -3
- package/libs/components/link/link.d.ts +131 -3
- package/libs/components/link/link.js +1 -1
- package/libs/components/modal.cjs +3 -3
- package/libs/components/modal.js +2 -2
- package/libs/hooks.cjs +3 -3
- package/libs/hooks.d.cts +1 -1
- package/libs/hooks.d.ts +1 -1
- package/libs/hooks.js +2 -2
- package/libs/index.cjs +12 -12
- package/libs/index.d.cts +237 -2
- package/libs/index.d.ts +237 -2
- package/libs/index.js +5 -5
- package/package.json +2 -2
- package/src/components/breadcrumbs/breadcrumb.test.tsx +1 -2
- package/src/components/buttons/README.mdx +19 -9
- package/src/components/buttons/button.tsx +19 -15
- package/src/components/link/link.stories.tsx +205 -8
- package/src/components/link/link.test.tsx +1 -1
- package/src/components/link/link.tsx +22 -0
- package/src/components/link/link.types.ts +11 -3
- package/src/docs/fpkit-developer.mdx +131 -53
- package/libs/chunk-33PNJ4LO.cjs +0 -15
- package/libs/chunk-33PNJ4LO.cjs.map +0 -1
- package/libs/chunk-GT77BX4L.cjs +0 -17
- package/libs/chunk-GT77BX4L.cjs.map +0 -1
- package/libs/chunk-OVWLQYMK.js +0 -10
- package/libs/chunk-OVWLQYMK.js.map +0 -1
- package/libs/chunk-UEPAWMDF.js +0 -8
- package/libs/chunk-UEPAWMDF.js.map +0 -1
- package/libs/link-5192f411.d.ts +0 -323
- /package/libs/{chunk-7XPFW7CB.js.map → chunk-43TK2ICH.js.map} +0 -0
- /package/libs/{chunk-QVW6W76L.cjs.map → chunk-MGPWZRBX.cjs.map} +0 -0
- /package/libs/{chunk-X3JCTEPD.js.map → chunk-QKHPHMG2.js.map} +0 -0
- /package/libs/{chunk-T4T6GWYQ.cjs.map → chunk-R7NLLZU2.cjs.map} +0 -0
- /package/libs/{chunk-X5LGFCWG.js.map → chunk-UJAQVHWC.js.map} +0 -0
- /package/libs/{chunk-DKTHCQ5P.cjs.map → chunk-X5RKCLDC.cjs.map} +0 -0
package/libs/index.d.cts
CHANGED
|
@@ -4,7 +4,7 @@ export { default as Field, FieldProps } from './components/form/fields.cjs';
|
|
|
4
4
|
export { default as Input } from './components/form/inputs.cjs';
|
|
5
5
|
export { default as Icon, IconProps } from './components/icons/icon.cjs';
|
|
6
6
|
import React, { ReactNode } from 'react';
|
|
7
|
-
export {
|
|
7
|
+
export { default as Link, default as To } from './components/link/link.cjs';
|
|
8
8
|
export { List } from './components/list/list.cjs';
|
|
9
9
|
export { Modal, ModalProps } from './components/modal.cjs';
|
|
10
10
|
export { default as Popover, PopoverProps } from './components/popover/popover.cjs';
|
|
@@ -328,6 +328,241 @@ declare const Img: {
|
|
|
328
328
|
displayName: string;
|
|
329
329
|
};
|
|
330
330
|
|
|
331
|
+
/**
|
|
332
|
+
* Props for the Link component.
|
|
333
|
+
*
|
|
334
|
+
* The Link component renders accessible anchor elements with enhanced security,
|
|
335
|
+
* styling variants, and WCAG 2.1 AA compliance. It supports both traditional
|
|
336
|
+
* text links and button-styled links for call-to-action scenarios.
|
|
337
|
+
*
|
|
338
|
+
* ## Accessibility Considerations
|
|
339
|
+
*
|
|
340
|
+
* - External links automatically include `rel="noopener noreferrer"` for security
|
|
341
|
+
* - Links should have descriptive text or `aria-label` for screen readers
|
|
342
|
+
* - Focus indicators must meet WCAG 2.4.7 contrast requirements (3:1 minimum)
|
|
343
|
+
* - Button-styled links maintain semantic `<a>` element for proper navigation
|
|
344
|
+
*
|
|
345
|
+
* @example
|
|
346
|
+
* ```tsx
|
|
347
|
+
* // Basic link
|
|
348
|
+
* <Link href="/about">About Us</Link>
|
|
349
|
+
*
|
|
350
|
+
* // External link with prefetch
|
|
351
|
+
* <Link href="https://example.com" target="_blank" prefetch>
|
|
352
|
+
* Visit Example
|
|
353
|
+
* </Link>
|
|
354
|
+
*
|
|
355
|
+
* // Button-styled link
|
|
356
|
+
* <Link href="/signup" btnStyle="primary">
|
|
357
|
+
* <b>Sign Up Now</b>
|
|
358
|
+
* </Link>
|
|
359
|
+
* ```
|
|
360
|
+
*/
|
|
361
|
+
type LinkProps = {
|
|
362
|
+
/**
|
|
363
|
+
* The URL that the hyperlink points to.
|
|
364
|
+
* Can be relative or absolute, internal or external.
|
|
365
|
+
*
|
|
366
|
+
* @example
|
|
367
|
+
* ```tsx
|
|
368
|
+
* href="/products"
|
|
369
|
+
* href="https://example.com"
|
|
370
|
+
* href="mailto:hello@example.com"
|
|
371
|
+
* href="tel:+1234567890"
|
|
372
|
+
* ```
|
|
373
|
+
*/
|
|
374
|
+
href?: string;
|
|
375
|
+
/**
|
|
376
|
+
* Where to display the linked URL.
|
|
377
|
+
*
|
|
378
|
+
* - `_self` (default): Current browsing context
|
|
379
|
+
* - `_blank`: New tab/window (automatically adds security attributes)
|
|
380
|
+
* - `_parent`: Parent browsing context
|
|
381
|
+
* - `_top`: Top-level browsing context
|
|
382
|
+
*
|
|
383
|
+
* Note: When `target="_blank"`, `rel="noopener noreferrer"` is automatically
|
|
384
|
+
* added for security unless explicitly overridden.
|
|
385
|
+
*
|
|
386
|
+
* @example
|
|
387
|
+
* ```tsx
|
|
388
|
+
* target="_blank" // Opens in new tab with security
|
|
389
|
+
* ```
|
|
390
|
+
*/
|
|
391
|
+
target?: string;
|
|
392
|
+
/**
|
|
393
|
+
* Relationship between current document and linked URL.
|
|
394
|
+
*
|
|
395
|
+
* Common values:
|
|
396
|
+
* - `noopener`: Prevents window.opener access (security)
|
|
397
|
+
* - `noreferrer`: Prevents referrer header (privacy)
|
|
398
|
+
* - `nofollow`: Hints search engines not to follow (SEO)
|
|
399
|
+
* - `prefetch`: Hints to prefetch the resource (performance)
|
|
400
|
+
*
|
|
401
|
+
* Note: For `target="_blank"`, this component automatically merges
|
|
402
|
+
* `noopener noreferrer` with any user-provided values for security.
|
|
403
|
+
*
|
|
404
|
+
* @example
|
|
405
|
+
* ```tsx
|
|
406
|
+
* rel="nofollow noopener"
|
|
407
|
+
* rel="author"
|
|
408
|
+
* ```
|
|
409
|
+
*/
|
|
410
|
+
rel?: string;
|
|
411
|
+
/**
|
|
412
|
+
* Content to display inside the link.
|
|
413
|
+
*
|
|
414
|
+
* For accessibility, ensure link text is descriptive and meaningful.
|
|
415
|
+
* Avoid generic text like "click here" or "read more" without context.
|
|
416
|
+
*
|
|
417
|
+
* @example
|
|
418
|
+
* ```tsx
|
|
419
|
+
* // ✅ Good: Descriptive link text
|
|
420
|
+
* <Link href="/products">View all products</Link>
|
|
421
|
+
*
|
|
422
|
+
* // ❌ Bad: Generic link text without context
|
|
423
|
+
* <Link href="/products">Click here</Link>
|
|
424
|
+
*
|
|
425
|
+
* // ✅ Good: Icon with accessible label
|
|
426
|
+
* <Link href="/home" aria-label="Return to homepage">
|
|
427
|
+
* <HomeIcon aria-hidden="true" />
|
|
428
|
+
* </Link>
|
|
429
|
+
* ```
|
|
430
|
+
*/
|
|
431
|
+
children: React.ReactNode;
|
|
432
|
+
/**
|
|
433
|
+
* Inline CSS styles to apply to the link element.
|
|
434
|
+
* Can be used to override CSS custom properties.
|
|
435
|
+
*
|
|
436
|
+
* @example
|
|
437
|
+
* ```tsx
|
|
438
|
+
* styles={{
|
|
439
|
+
* '--link-color': '#ff0000',
|
|
440
|
+
* '--link-decoration': 'underline',
|
|
441
|
+
* }}
|
|
442
|
+
* ```
|
|
443
|
+
*/
|
|
444
|
+
styles?: React.CSSProperties;
|
|
445
|
+
/**
|
|
446
|
+
* Hints to the browser to prefetch the linked resource.
|
|
447
|
+
*
|
|
448
|
+
* When `true` and `target="_blank"`, adds `rel="prefetch"` along with
|
|
449
|
+
* security attributes. This can improve perceived performance but should
|
|
450
|
+
* be used judiciously as it consumes bandwidth.
|
|
451
|
+
*
|
|
452
|
+
* Note: Browser support varies. Modern browsers may ignore this hint.
|
|
453
|
+
*
|
|
454
|
+
* @default false
|
|
455
|
+
* @example
|
|
456
|
+
* ```tsx
|
|
457
|
+
* <Link href="/next-page" prefetch>Next Page</Link>
|
|
458
|
+
* ```
|
|
459
|
+
*/
|
|
460
|
+
prefetch?: boolean;
|
|
461
|
+
/**
|
|
462
|
+
* Applies button-like styling to the link.
|
|
463
|
+
*
|
|
464
|
+
* When set, the link renders with button styling including padding,
|
|
465
|
+
* borders, and hover effects while maintaining semantic anchor behavior.
|
|
466
|
+
*
|
|
467
|
+
* Common values:
|
|
468
|
+
* - `"btn"`: Standard button styling
|
|
469
|
+
* - `"pill"`: Rounded pill button styling
|
|
470
|
+
*
|
|
471
|
+
* Alternative: Wrap children in `<b>` or `<i>` tags for automatic styling:
|
|
472
|
+
* - `<b>`: Applies button styling
|
|
473
|
+
* - `<i>`: Applies pill styling
|
|
474
|
+
*
|
|
475
|
+
* @example
|
|
476
|
+
* ```tsx
|
|
477
|
+
* // Using btnStyle prop
|
|
478
|
+
* <Link href="/signup" btnStyle="btn">Sign Up</Link>
|
|
479
|
+
*
|
|
480
|
+
* // Using child wrapper (automatic detection)
|
|
481
|
+
* <Link href="/signup"><b>Sign Up</b></Link>
|
|
482
|
+
* <Link href="/signup"><i>Pill Button</i></Link>
|
|
483
|
+
* ```
|
|
484
|
+
*/
|
|
485
|
+
btnStyle?: string;
|
|
486
|
+
/**
|
|
487
|
+
* Event handler called when the link is clicked or activated.
|
|
488
|
+
*
|
|
489
|
+
* **Recommended for most use cases**, especially analytics and tracking.
|
|
490
|
+
* This event fires for:
|
|
491
|
+
* - Mouse clicks
|
|
492
|
+
* - Touch/tap interactions
|
|
493
|
+
* - Keyboard activation (Enter key)
|
|
494
|
+
* - Assistive technology activation
|
|
495
|
+
*
|
|
496
|
+
* Use `onClick` when you need to track ALL user activations, including
|
|
497
|
+
* keyboard users. This ensures full accessibility coverage.
|
|
498
|
+
*
|
|
499
|
+
* @param event - The mouse event
|
|
500
|
+
* @example
|
|
501
|
+
* ```tsx
|
|
502
|
+
* // ✅ RECOMMENDED: onClick tracks all activation methods
|
|
503
|
+
* <Link
|
|
504
|
+
* href="/products"
|
|
505
|
+
* onClick={(e) => {
|
|
506
|
+
* trackEvent('link_click', { href: '/products' });
|
|
507
|
+
* }}
|
|
508
|
+
* >
|
|
509
|
+
* Products
|
|
510
|
+
* </Link>
|
|
511
|
+
* ```
|
|
512
|
+
*/
|
|
513
|
+
onClick?: (event: React.MouseEvent<HTMLAnchorElement>) => void;
|
|
514
|
+
/**
|
|
515
|
+
* Event handler called when a pointer device button is pressed on the link.
|
|
516
|
+
*
|
|
517
|
+
* Use this for specific pointer interactions like:
|
|
518
|
+
* - Drag-and-drop detection
|
|
519
|
+
* - Touch gesture recognition
|
|
520
|
+
* - Distinguishing input types (mouse vs touch vs pen)
|
|
521
|
+
* - Providing early visual feedback before click completes
|
|
522
|
+
*
|
|
523
|
+
* **⚠️ Accessibility Note**: Unlike `onClick`, this does NOT fire for
|
|
524
|
+
* keyboard activation (Enter key). If you need to track all user interactions
|
|
525
|
+
* including keyboard users, use `onClick` instead.
|
|
526
|
+
*
|
|
527
|
+
* @param event - The pointer event
|
|
528
|
+
* @example
|
|
529
|
+
* ```tsx
|
|
530
|
+
* // Use onPointerDown for pointer-specific interactions
|
|
531
|
+
* <Link
|
|
532
|
+
* href="/products"
|
|
533
|
+
* onPointerDown={(e) => {
|
|
534
|
+
* // Distinguish between mouse (2), touch (5), and pen (3)
|
|
535
|
+
* console.log('Pointer type:', e.pointerType);
|
|
536
|
+
* }}
|
|
537
|
+
* >
|
|
538
|
+
* Products
|
|
539
|
+
* </Link>
|
|
540
|
+
* ```
|
|
541
|
+
*
|
|
542
|
+
* @example
|
|
543
|
+
* ```tsx
|
|
544
|
+
* // ✅ Use both handlers together for comprehensive tracking
|
|
545
|
+
* <Link
|
|
546
|
+
* href="/products"
|
|
547
|
+
* onClick={(e) => trackAllActivations(e)}
|
|
548
|
+
* onPointerDown={(e) => provideFeedback(e)}
|
|
549
|
+
* >
|
|
550
|
+
* Products
|
|
551
|
+
* </Link>
|
|
552
|
+
* ```
|
|
553
|
+
*/
|
|
554
|
+
onPointerDown?: (event: React.PointerEvent<HTMLAnchorElement>) => void;
|
|
555
|
+
/**
|
|
556
|
+
* Icon element to display in the link (used by IconLink).
|
|
557
|
+
*
|
|
558
|
+
* @example
|
|
559
|
+
* ```tsx
|
|
560
|
+
* <IconLink href="/home" icon={<HomeIcon />} />
|
|
561
|
+
* ```
|
|
562
|
+
*/
|
|
563
|
+
icon?: React.ReactNode;
|
|
564
|
+
} & Omit<React.ComponentPropsWithoutRef<"a">, 'style'>;
|
|
565
|
+
|
|
331
566
|
/**
|
|
332
567
|
* Props for the TextToSpeechComponent.
|
|
333
568
|
* @interface TextToSpeechComponentProps
|
|
@@ -955,4 +1190,4 @@ type FPComponent = {
|
|
|
955
1190
|
*/
|
|
956
1191
|
declare const FP: FPComponent;
|
|
957
1192
|
|
|
958
|
-
export { Article, Aside, Badge, BadgeProps, FP as Box, Caption, ComponentProps$1 as ComponentProps, Details, FP, Footer, Header, Img, ImgProps, Landmarks, Main, Section, Table, Tag, TagProps, TagVariant, Tbody, Td, TextToSpeech, Thead, Tr };
|
|
1193
|
+
export { Article, Aside, Badge, BadgeProps, FP as Box, Caption, ComponentProps$1 as ComponentProps, Details, FP, Footer, Header, Img, ImgProps, Landmarks, LinkProps, Main, Section, Table, Tag, TagProps, TagVariant, Tbody, Td, TextToSpeech, Thead, Tr };
|
package/libs/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export { default as Field, FieldProps } from './components/form/fields.js';
|
|
|
4
4
|
export { default as Input } from './components/form/inputs.js';
|
|
5
5
|
export { default as Icon, IconProps } from './components/icons/icon.js';
|
|
6
6
|
import React, { ReactNode } from 'react';
|
|
7
|
-
export {
|
|
7
|
+
export { default as Link, default as To } from './components/link/link.js';
|
|
8
8
|
export { List } from './components/list/list.js';
|
|
9
9
|
export { Modal, ModalProps } from './components/modal.js';
|
|
10
10
|
export { default as Popover, PopoverProps } from './components/popover/popover.js';
|
|
@@ -328,6 +328,241 @@ declare const Img: {
|
|
|
328
328
|
displayName: string;
|
|
329
329
|
};
|
|
330
330
|
|
|
331
|
+
/**
|
|
332
|
+
* Props for the Link component.
|
|
333
|
+
*
|
|
334
|
+
* The Link component renders accessible anchor elements with enhanced security,
|
|
335
|
+
* styling variants, and WCAG 2.1 AA compliance. It supports both traditional
|
|
336
|
+
* text links and button-styled links for call-to-action scenarios.
|
|
337
|
+
*
|
|
338
|
+
* ## Accessibility Considerations
|
|
339
|
+
*
|
|
340
|
+
* - External links automatically include `rel="noopener noreferrer"` for security
|
|
341
|
+
* - Links should have descriptive text or `aria-label` for screen readers
|
|
342
|
+
* - Focus indicators must meet WCAG 2.4.7 contrast requirements (3:1 minimum)
|
|
343
|
+
* - Button-styled links maintain semantic `<a>` element for proper navigation
|
|
344
|
+
*
|
|
345
|
+
* @example
|
|
346
|
+
* ```tsx
|
|
347
|
+
* // Basic link
|
|
348
|
+
* <Link href="/about">About Us</Link>
|
|
349
|
+
*
|
|
350
|
+
* // External link with prefetch
|
|
351
|
+
* <Link href="https://example.com" target="_blank" prefetch>
|
|
352
|
+
* Visit Example
|
|
353
|
+
* </Link>
|
|
354
|
+
*
|
|
355
|
+
* // Button-styled link
|
|
356
|
+
* <Link href="/signup" btnStyle="primary">
|
|
357
|
+
* <b>Sign Up Now</b>
|
|
358
|
+
* </Link>
|
|
359
|
+
* ```
|
|
360
|
+
*/
|
|
361
|
+
type LinkProps = {
|
|
362
|
+
/**
|
|
363
|
+
* The URL that the hyperlink points to.
|
|
364
|
+
* Can be relative or absolute, internal or external.
|
|
365
|
+
*
|
|
366
|
+
* @example
|
|
367
|
+
* ```tsx
|
|
368
|
+
* href="/products"
|
|
369
|
+
* href="https://example.com"
|
|
370
|
+
* href="mailto:hello@example.com"
|
|
371
|
+
* href="tel:+1234567890"
|
|
372
|
+
* ```
|
|
373
|
+
*/
|
|
374
|
+
href?: string;
|
|
375
|
+
/**
|
|
376
|
+
* Where to display the linked URL.
|
|
377
|
+
*
|
|
378
|
+
* - `_self` (default): Current browsing context
|
|
379
|
+
* - `_blank`: New tab/window (automatically adds security attributes)
|
|
380
|
+
* - `_parent`: Parent browsing context
|
|
381
|
+
* - `_top`: Top-level browsing context
|
|
382
|
+
*
|
|
383
|
+
* Note: When `target="_blank"`, `rel="noopener noreferrer"` is automatically
|
|
384
|
+
* added for security unless explicitly overridden.
|
|
385
|
+
*
|
|
386
|
+
* @example
|
|
387
|
+
* ```tsx
|
|
388
|
+
* target="_blank" // Opens in new tab with security
|
|
389
|
+
* ```
|
|
390
|
+
*/
|
|
391
|
+
target?: string;
|
|
392
|
+
/**
|
|
393
|
+
* Relationship between current document and linked URL.
|
|
394
|
+
*
|
|
395
|
+
* Common values:
|
|
396
|
+
* - `noopener`: Prevents window.opener access (security)
|
|
397
|
+
* - `noreferrer`: Prevents referrer header (privacy)
|
|
398
|
+
* - `nofollow`: Hints search engines not to follow (SEO)
|
|
399
|
+
* - `prefetch`: Hints to prefetch the resource (performance)
|
|
400
|
+
*
|
|
401
|
+
* Note: For `target="_blank"`, this component automatically merges
|
|
402
|
+
* `noopener noreferrer` with any user-provided values for security.
|
|
403
|
+
*
|
|
404
|
+
* @example
|
|
405
|
+
* ```tsx
|
|
406
|
+
* rel="nofollow noopener"
|
|
407
|
+
* rel="author"
|
|
408
|
+
* ```
|
|
409
|
+
*/
|
|
410
|
+
rel?: string;
|
|
411
|
+
/**
|
|
412
|
+
* Content to display inside the link.
|
|
413
|
+
*
|
|
414
|
+
* For accessibility, ensure link text is descriptive and meaningful.
|
|
415
|
+
* Avoid generic text like "click here" or "read more" without context.
|
|
416
|
+
*
|
|
417
|
+
* @example
|
|
418
|
+
* ```tsx
|
|
419
|
+
* // ✅ Good: Descriptive link text
|
|
420
|
+
* <Link href="/products">View all products</Link>
|
|
421
|
+
*
|
|
422
|
+
* // ❌ Bad: Generic link text without context
|
|
423
|
+
* <Link href="/products">Click here</Link>
|
|
424
|
+
*
|
|
425
|
+
* // ✅ Good: Icon with accessible label
|
|
426
|
+
* <Link href="/home" aria-label="Return to homepage">
|
|
427
|
+
* <HomeIcon aria-hidden="true" />
|
|
428
|
+
* </Link>
|
|
429
|
+
* ```
|
|
430
|
+
*/
|
|
431
|
+
children: React.ReactNode;
|
|
432
|
+
/**
|
|
433
|
+
* Inline CSS styles to apply to the link element.
|
|
434
|
+
* Can be used to override CSS custom properties.
|
|
435
|
+
*
|
|
436
|
+
* @example
|
|
437
|
+
* ```tsx
|
|
438
|
+
* styles={{
|
|
439
|
+
* '--link-color': '#ff0000',
|
|
440
|
+
* '--link-decoration': 'underline',
|
|
441
|
+
* }}
|
|
442
|
+
* ```
|
|
443
|
+
*/
|
|
444
|
+
styles?: React.CSSProperties;
|
|
445
|
+
/**
|
|
446
|
+
* Hints to the browser to prefetch the linked resource.
|
|
447
|
+
*
|
|
448
|
+
* When `true` and `target="_blank"`, adds `rel="prefetch"` along with
|
|
449
|
+
* security attributes. This can improve perceived performance but should
|
|
450
|
+
* be used judiciously as it consumes bandwidth.
|
|
451
|
+
*
|
|
452
|
+
* Note: Browser support varies. Modern browsers may ignore this hint.
|
|
453
|
+
*
|
|
454
|
+
* @default false
|
|
455
|
+
* @example
|
|
456
|
+
* ```tsx
|
|
457
|
+
* <Link href="/next-page" prefetch>Next Page</Link>
|
|
458
|
+
* ```
|
|
459
|
+
*/
|
|
460
|
+
prefetch?: boolean;
|
|
461
|
+
/**
|
|
462
|
+
* Applies button-like styling to the link.
|
|
463
|
+
*
|
|
464
|
+
* When set, the link renders with button styling including padding,
|
|
465
|
+
* borders, and hover effects while maintaining semantic anchor behavior.
|
|
466
|
+
*
|
|
467
|
+
* Common values:
|
|
468
|
+
* - `"btn"`: Standard button styling
|
|
469
|
+
* - `"pill"`: Rounded pill button styling
|
|
470
|
+
*
|
|
471
|
+
* Alternative: Wrap children in `<b>` or `<i>` tags for automatic styling:
|
|
472
|
+
* - `<b>`: Applies button styling
|
|
473
|
+
* - `<i>`: Applies pill styling
|
|
474
|
+
*
|
|
475
|
+
* @example
|
|
476
|
+
* ```tsx
|
|
477
|
+
* // Using btnStyle prop
|
|
478
|
+
* <Link href="/signup" btnStyle="btn">Sign Up</Link>
|
|
479
|
+
*
|
|
480
|
+
* // Using child wrapper (automatic detection)
|
|
481
|
+
* <Link href="/signup"><b>Sign Up</b></Link>
|
|
482
|
+
* <Link href="/signup"><i>Pill Button</i></Link>
|
|
483
|
+
* ```
|
|
484
|
+
*/
|
|
485
|
+
btnStyle?: string;
|
|
486
|
+
/**
|
|
487
|
+
* Event handler called when the link is clicked or activated.
|
|
488
|
+
*
|
|
489
|
+
* **Recommended for most use cases**, especially analytics and tracking.
|
|
490
|
+
* This event fires for:
|
|
491
|
+
* - Mouse clicks
|
|
492
|
+
* - Touch/tap interactions
|
|
493
|
+
* - Keyboard activation (Enter key)
|
|
494
|
+
* - Assistive technology activation
|
|
495
|
+
*
|
|
496
|
+
* Use `onClick` when you need to track ALL user activations, including
|
|
497
|
+
* keyboard users. This ensures full accessibility coverage.
|
|
498
|
+
*
|
|
499
|
+
* @param event - The mouse event
|
|
500
|
+
* @example
|
|
501
|
+
* ```tsx
|
|
502
|
+
* // ✅ RECOMMENDED: onClick tracks all activation methods
|
|
503
|
+
* <Link
|
|
504
|
+
* href="/products"
|
|
505
|
+
* onClick={(e) => {
|
|
506
|
+
* trackEvent('link_click', { href: '/products' });
|
|
507
|
+
* }}
|
|
508
|
+
* >
|
|
509
|
+
* Products
|
|
510
|
+
* </Link>
|
|
511
|
+
* ```
|
|
512
|
+
*/
|
|
513
|
+
onClick?: (event: React.MouseEvent<HTMLAnchorElement>) => void;
|
|
514
|
+
/**
|
|
515
|
+
* Event handler called when a pointer device button is pressed on the link.
|
|
516
|
+
*
|
|
517
|
+
* Use this for specific pointer interactions like:
|
|
518
|
+
* - Drag-and-drop detection
|
|
519
|
+
* - Touch gesture recognition
|
|
520
|
+
* - Distinguishing input types (mouse vs touch vs pen)
|
|
521
|
+
* - Providing early visual feedback before click completes
|
|
522
|
+
*
|
|
523
|
+
* **⚠️ Accessibility Note**: Unlike `onClick`, this does NOT fire for
|
|
524
|
+
* keyboard activation (Enter key). If you need to track all user interactions
|
|
525
|
+
* including keyboard users, use `onClick` instead.
|
|
526
|
+
*
|
|
527
|
+
* @param event - The pointer event
|
|
528
|
+
* @example
|
|
529
|
+
* ```tsx
|
|
530
|
+
* // Use onPointerDown for pointer-specific interactions
|
|
531
|
+
* <Link
|
|
532
|
+
* href="/products"
|
|
533
|
+
* onPointerDown={(e) => {
|
|
534
|
+
* // Distinguish between mouse (2), touch (5), and pen (3)
|
|
535
|
+
* console.log('Pointer type:', e.pointerType);
|
|
536
|
+
* }}
|
|
537
|
+
* >
|
|
538
|
+
* Products
|
|
539
|
+
* </Link>
|
|
540
|
+
* ```
|
|
541
|
+
*
|
|
542
|
+
* @example
|
|
543
|
+
* ```tsx
|
|
544
|
+
* // ✅ Use both handlers together for comprehensive tracking
|
|
545
|
+
* <Link
|
|
546
|
+
* href="/products"
|
|
547
|
+
* onClick={(e) => trackAllActivations(e)}
|
|
548
|
+
* onPointerDown={(e) => provideFeedback(e)}
|
|
549
|
+
* >
|
|
550
|
+
* Products
|
|
551
|
+
* </Link>
|
|
552
|
+
* ```
|
|
553
|
+
*/
|
|
554
|
+
onPointerDown?: (event: React.PointerEvent<HTMLAnchorElement>) => void;
|
|
555
|
+
/**
|
|
556
|
+
* Icon element to display in the link (used by IconLink).
|
|
557
|
+
*
|
|
558
|
+
* @example
|
|
559
|
+
* ```tsx
|
|
560
|
+
* <IconLink href="/home" icon={<HomeIcon />} />
|
|
561
|
+
* ```
|
|
562
|
+
*/
|
|
563
|
+
icon?: React.ReactNode;
|
|
564
|
+
} & Omit<React.ComponentPropsWithoutRef<"a">, 'style'>;
|
|
565
|
+
|
|
331
566
|
/**
|
|
332
567
|
* Props for the TextToSpeechComponent.
|
|
333
568
|
* @interface TextToSpeechComponentProps
|
|
@@ -955,4 +1190,4 @@ type FPComponent = {
|
|
|
955
1190
|
*/
|
|
956
1191
|
declare const FP: FPComponent;
|
|
957
1192
|
|
|
958
|
-
export { Article, Aside, Badge, BadgeProps, FP as Box, Caption, ComponentProps$1 as ComponentProps, Details, FP, Footer, Header, Img, ImgProps, Landmarks, Main, Section, Table, Tag, TagProps, TagVariant, Tbody, Td, TextToSpeech, Thead, Tr };
|
|
1193
|
+
export { Article, Aside, Badge, BadgeProps, FP as Box, Caption, ComponentProps$1 as ComponentProps, Details, FP, Footer, Header, Img, ImgProps, Landmarks, LinkProps, Main, Section, Table, Tag, TagProps, TagVariant, Tbody, Td, TextToSpeech, Thead, Tr };
|
package/libs/index.js
CHANGED
|
@@ -2,24 +2,24 @@ import { b } from './chunk-IRLFZ3OL.js';
|
|
|
2
2
|
export { a as Textarea } from './chunk-IRLFZ3OL.js';
|
|
3
3
|
export { a as Field } from './chunk-HRRHPLER.js';
|
|
4
4
|
export { a as Caption, i as TBL, f as Table, c as Tbody, e as Td, b as Thead, d as Tr } from './chunk-Y2PFDELK.js';
|
|
5
|
-
export { a as Dialog } from './chunk-
|
|
5
|
+
export { a as Dialog } from './chunk-QKHPHMG2.js';
|
|
6
6
|
export { c as Nav, b as NavItem, a as NavList } from './chunk-FVROL3V5.js';
|
|
7
7
|
export { b as List } from './chunk-IEB64SWY.js';
|
|
8
8
|
export { b as Popover } from './chunk-23ANBDCR.js';
|
|
9
9
|
export { a as Text } from './chunk-IQ76HGVP.js';
|
|
10
10
|
export { b as Heading, a as Title } from './chunk-ZFJ4U45S.js';
|
|
11
|
-
export { b as Breadcrumb, a as useBreadcrumbSegments } from './chunk-
|
|
11
|
+
export { b as Breadcrumb, a as useBreadcrumbSegments } from './chunk-UJAQVHWC.js';
|
|
12
12
|
import './chunk-GCGKYLDG.js';
|
|
13
13
|
import { b as b$1 } from './chunk-5QD3DWFI.js';
|
|
14
14
|
export { a as Icon } from './chunk-5QD3DWFI.js';
|
|
15
15
|
export { d as Card, b as CardContent, c as CardFooter, a as CardTitle } from './chunk-KK47SYZI.js';
|
|
16
|
-
export { a as Modal } from './chunk-
|
|
17
|
-
export { a as Button } from './chunk-
|
|
16
|
+
export { a as Modal } from './chunk-43TK2ICH.js';
|
|
17
|
+
export { a as Button } from './chunk-KVKQLRJG.js';
|
|
18
18
|
export { a as Input } from './chunk-F5EYMVQM.js';
|
|
19
19
|
export { a as Box, a as FP } from './chunk-6SAHIYCZ.js';
|
|
20
20
|
import './chunk-BFK62VX5.js';
|
|
21
21
|
import './chunk-75QHTLFO.js';
|
|
22
|
-
export { a as Link,
|
|
22
|
+
export { a as Link, d as To } from './chunk-NNTBIHSD.js';
|
|
23
23
|
import { a } from './chunk-HHLNOC5T.js';
|
|
24
24
|
import u, { useCallback, useMemo, useState, useEffect } from 'react';
|
|
25
25
|
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@fpkit/acss",
|
|
3
3
|
"description": "A lightweight React UI library for building modern and accessible components that leverage CSS custom properties for reactive Styles.",
|
|
4
4
|
"private": false,
|
|
5
|
-
"version": "
|
|
5
|
+
"version": "2.0.0",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": ">=22.12.0",
|
|
8
8
|
"npm": ">=8.0.0"
|
|
@@ -126,5 +126,5 @@
|
|
|
126
126
|
"publishConfig": {
|
|
127
127
|
"access": "public"
|
|
128
128
|
},
|
|
129
|
-
"gitHead": "
|
|
129
|
+
"gitHead": "c26374b7d65656bf57e002cbf44dab95ce8f0197"
|
|
130
130
|
}
|
|
@@ -342,12 +342,11 @@ describe("Breadcrumb", () => {
|
|
|
342
342
|
currentRoute="/products/shirts"
|
|
343
343
|
linkProps={{
|
|
344
344
|
onClick: handleClick,
|
|
345
|
-
"data-testid": "breadcrumb-link",
|
|
346
345
|
}}
|
|
347
346
|
/>
|
|
348
347
|
);
|
|
349
348
|
|
|
350
|
-
const links = screen.
|
|
349
|
+
const links = screen.getAllByRole("link");
|
|
351
350
|
expect(links.length).toBeGreaterThan(0);
|
|
352
351
|
|
|
353
352
|
// Click first link
|
|
@@ -93,30 +93,38 @@ export default AdvancedButton;
|
|
|
93
93
|
|
|
94
94
|
### Overview
|
|
95
95
|
|
|
96
|
-
The Button component now uses an **optimized disabled state implementation**
|
|
96
|
+
The Button component now uses an **optimized disabled state implementation**
|
|
97
|
+
that follows WCAG 2.1 Level AA accessibility guidelines. This update brings
|
|
98
|
+
significant performance improvements and better accessibility compliance.
|
|
97
99
|
|
|
98
100
|
### Key Improvements
|
|
99
101
|
|
|
100
102
|
#### 1. **ARIA-Disabled Pattern**
|
|
101
103
|
|
|
102
|
-
Instead of using the native `disabled` attribute, the button uses
|
|
104
|
+
Instead of using the native `disabled` attribute, the button uses
|
|
105
|
+
`aria-disabled`:
|
|
103
106
|
|
|
104
|
-
- **Stays in tab order** - Screen reader users can discover and navigate to
|
|
105
|
-
|
|
106
|
-
- **
|
|
107
|
+
- **Stays in tab order** - Screen reader users can discover and navigate to
|
|
108
|
+
disabled buttons
|
|
109
|
+
- **Allows focus** - Users can still focus disabled buttons to read tooltips or
|
|
110
|
+
help text
|
|
111
|
+
- **Prevents interactions** - All click/keyboard events are blocked when
|
|
112
|
+
disabled
|
|
107
113
|
- **Better styling control** - Meets WCAG AA contrast requirements more easily
|
|
108
114
|
|
|
109
115
|
#### 2. **Performance Optimizations**
|
|
110
116
|
|
|
111
117
|
The new `useDisabledState` hook provides:
|
|
112
118
|
|
|
113
|
-
- **~90% reduction in unnecessary re-renders** compared to previous
|
|
119
|
+
- **~90% reduction in unnecessary re-renders** compared to previous
|
|
120
|
+
implementation
|
|
114
121
|
- **Stable handler references** - Event handlers don't recreate on every render
|
|
115
122
|
- **Optimized memoization** - Single memoization pass for all props and handlers
|
|
116
123
|
|
|
117
124
|
#### 3. **Automatic className Merging**
|
|
118
125
|
|
|
119
|
-
The disabled state now automatically merges your custom classes with the
|
|
126
|
+
The disabled state now automatically merges your custom classes with the
|
|
127
|
+
`.is-disabled` class:
|
|
120
128
|
|
|
121
129
|
```tsx
|
|
122
130
|
// Before: You had to manage className manually
|
|
@@ -188,10 +196,12 @@ This implementation follows:
|
|
|
188
196
|
### Related
|
|
189
197
|
|
|
190
198
|
- See [useDisabledState Hook](/docs/hooks/use-disabled-state) for advanced usage
|
|
191
|
-
- See [Accessibility Guide](/docs/guides/accessibility) for WCAG compliance
|
|
199
|
+
- See [Accessibility Guide](/docs/guides/accessibility) for WCAG compliance
|
|
200
|
+
details
|
|
192
201
|
|
|
193
202
|
## Additional Notes
|
|
194
203
|
|
|
195
204
|
- Ensure the `type` prop is set to one of `'button'`, `'submit'`, or `'reset'`.
|
|
196
205
|
- The `styles` prop can be used to apply inline styles to the button.
|
|
197
|
-
- The `disabled` prop uses the accessible `aria-disabled` pattern instead of
|
|
206
|
+
- The `disabled` prop uses the accessible `aria-disabled` pattern instead of
|
|
207
|
+
native `disabled` attribute.
|